Jump to content

BSL:Manual: Difference between revisions

332 bytes removed ,  24 April 2023
m
implemented new template SectionLink for nice-looking section links
m (→‎Variables: brought in some points from BSL:Variables)
m (implemented new template SectionLink for nice-looking section links)
Line 38: Line 38:
  dmsg("Statement 2")
  dmsg("Statement 2")


The third example is partly in old-style syntax, which is discussed under the [[#Old vs. new syntax|Old vs. new syntax]] section.
The third example is partly in old-style syntax, which is discussed under {{SectionLink||Old vs. new syntax}}.


===Compound statements===
===Compound statements===
Line 49: Line 49:
  <b>}</b>
  <b>}</b>


The purpose of doing this is to place statements under either a function declaration (see the [[#Declaration|Declaration]] section) or an "if" statement (see the [[#Conditional|Conditional]] section). Such a group of statements is referred to as a "block", and sometimes also defines a "scope". Traditionally in programming, anything inside a certain scope can be seen from elsewhere within that scope, or from within a scope inside that scope, but not from a scope outside that scope. This allows careful management of which code can alter which data. In BSL's case, however, there are certain issues with scope not being respected (see the [[#if|if statement]] section). Variables outside of all scopes (including functions) are referred to as "globals".
The purpose of doing this is to place statements under either a function declaration (see {{SectionLink||Declaration}}) or an "if" statement (see {{SectionLink||Conditional}}). Such a group of statements is referred to as a "block", and sometimes also defines a "scope". Traditionally in programming, anything inside a certain scope can be seen from elsewhere within that scope, or from within a scope inside that scope, but not from a scope outside that scope. This allows careful management of which code can alter which data. In BSL's case, however, there are certain issues with scope not being respected (see {{SectionLink||if}}). Variables outside of all scopes (including functions) are referred to as "globals".


===Comments===
===Comments===
Line 64: Line 64:
  }
  }


Do not use a trailing comment unless you end the statement with a semicolon (see the [[#Old vs. new syntax|Old vs. new syntax]] section for explanation).
Do not use a trailing comment unless you end the statement with a semicolon (see {{SectionLink||Old vs. new syntax}} for explanation).


In documentation outside of source code or script files, such as this page's BSL samples, comments are sometimes used to tell the reader something in a way that won't break the actual code if the user copies the whole block of text into a script file, comments and all.
In documentation outside of source code or script files, such as this page's BSL samples, comments are sometimes used to tell the reader something in a way that won't break the actual code if the user copies the whole block of text into a script file, comments and all.
Line 96: Line 96:


===Coding style===
===Coding style===
There are other aspects of the language which are flexible, and yet not connected to the old-style/new-style division. For instance, the quotes around "Hello" can be left out in both syntax versions of the above calls to dprint() and dmsg(). You can also omit stating the type and parameters of a function, with "void" being assumed in their absence (see the [[#Functions|Functions]] section if you need further explanation). You also do not need to use curly braces to enclose code that falls under an if/else statement if there is only a single line of code intended to be in that scope (see the [[#Conditional|Conditional]] section for examples). None of these syntax choices are in conflict with the "new style" syntax.
There are other aspects of the language which are flexible, and yet not connected to the old-style/new-style division. For instance, the quotes around "Hello" can be left out in both syntax versions of the above calls to dprint() and dmsg(). You can also omit stating the type and parameters of a function, with "void" being assumed in their absence (see {{SectionLink||Functions}} if you need further explanation). You also do not need to use curly braces to enclose code that falls under an if/else statement if there is only a single line of code intended to be in that scope (see {{SectionLink||Conditional}} for examples). None of these syntax choices are in conflict with the "new style" syntax.


Additionally, you can use whitespace and newlines in different ways:
Additionally, you can use whitespace and newlines in different ways:
Line 135: Line 135:


==Data types==
==Data types==
When declaring a variable or a function (more on this under the [[#Functions|Functions]] and [[#Variables|Variables]] sections), you must specify the type of data it contains, accepts, or returns. You can choose from "bool" (can be "true" or "false", but see warning under the "bool" section), "int" (can be any whole number), "float" (a value with a decimal point), or "string" (some text).
When declaring a variable or a function (more on this under {{SectionLink||Functions}} and {{SectionLink||Variables}}), you must specify the type of data it contains, accepts, or returns. You can choose from "bool" (can be "true" or "false", but see warning under the "bool" section), "int" (can be any whole number), "float" (a value with a decimal point), or "string" (some text).


  var '''int''' x;
  var '''int''' x;
Line 147: Line 147:


===void===
===void===
See the [[#Functions|Functions]] section. Variables cannot be type "void".
See {{SectionLink||Functions}}. Variables cannot be type "void".


===bool===
===bool===
Line 244: Line 244:


===Arithmetical===
===Arithmetical===
These operations do not change the numbers that the operators act upon; they merely provide a resulting number for your use. Note that there is no operator for multiplication or division. Bungie West was only concerned with creating enough scripting power to drive Oni, and they did not need "higher math" for this. See the [[#Data types|Data types]] section to learn the details of how math works between different data types.
These operations do not change the numbers that the operators act upon; they merely provide a resulting number for your use. Note that there is no operator for multiplication or division. Bungie West was only concerned with creating enough scripting power to drive Oni, and they did not need "higher math" for this. See {{SectionLink||Data types}} to learn the details of how math works between different data types.


{| class="wikitable"   
{| class="wikitable"   
Line 326: Line 326:
|}
|}


Note: These operators are intended for use with numbers; strings cannot make reliable use of comparators, as explained in the [[#string|string]] section.
Note: These operators are intended for use with numbers; strings cannot make reliable use of comparators, as explained under {{SectionLink||string}}.


===Logical===
===Logical===
Line 347: Line 347:
|}
|}


See the [[#if|"if" statement]] section to learn how to use the logical operators.
See {{SectionLink||if}} to learn how to use the logical operators.


==Reserved words==
==Reserved words==
Line 358: Line 358:
  '''var''' int a = 0;
  '''var''' int a = 0;


After this, you can refer to the variable merely as "a". See the [[#Variables|Variables]] section for details on declaring variables.
After this, you can refer to the variable merely as "a". See {{SectionLink||Variables}} for details on declaring variables.


====func====
====func====
Line 366: Line 366:
  }
  }


Besides this, you can call the function merely by writing "spawn_team", but the proper new-style syntax is "spawn_team();". See the [[#Functions|Functions]] section for details on declaring functions.
Besides this, you can call the function merely by writing "spawn_team", but the proper new-style syntax is "spawn_team();". See {{SectionLink||Functions}} for details on declaring functions.


===Type specification===
===Type specification===
Line 378: Line 378:
  }
  }


Besides "void", which is only used in function definitions (indicating that no data is returned), these are the types of data that can be assigned to variables, passed into functions, and returned by functions. See the [[#Data types|Data types]] section for details.
Besides "void", which is only used in function definitions (indicating that no data is returned), these are the types of data that can be assigned to variables, passed into functions, and returned by functions. See {{SectionLink||Data types}} for details.


===Conditional===
===Conditional===
Line 389: Line 389:
  }
  }


For examples of operators, see the [[#Operators|Operators]] section. A typical example would be:
For examples of operators, see {{SectionLink||Operators}}. A typical example would be:


  if (kills < 10)
  if (kills < 10)
Line 412: Line 412:
That indentation on "spawn_considered" is misleading; when glancing at this code, you might expect that "spawn_considered" only is changed if "a" is greater than zero. It could be the script's writer really did want that line to be subject to the "if" statement, but he forgot to add braces. Always using braces around an "if" statement's body, even when it's one line long, will prevent that mistake.
That indentation on "spawn_considered" is misleading; when glancing at this code, you might expect that "spawn_considered" only is changed if "a" is greater than zero. It could be the script's writer really did want that line to be subject to the "if" statement, but he forgot to add braces. Always using braces around an "if" statement's body, even when it's one line long, will prevent that mistake.


Unfortunately, even ''with'' braces, BSL does not always respect scope for blocks of code under "if" statements; for instance, a "return" statement will fire even when the surrounding "if" condition is false (see the [[#Flow interrupt|Flow interrupt]] section for an example). An even more alarming example of bad scoping is this:
Unfortunately, even ''with'' braces, BSL does not always respect scope for blocks of code under "if" statements; for instance, a "return" statement will fire even when the surrounding "if" condition is false (see {{SectionLink||Flow interrupt}} for an example). An even more alarming example of bad scoping is this:


  func void broken_if(void)
  func void broken_if(void)
Line 526: Line 526:
  }
  }


Yes, "return" is also subject to the scope bug discussed in the [[#Conditional|Conditional]] section above. The statements under "else" will never run. The "return" will actually kick in and the function will exit, even though the surrounding control statement did not evaluate to true.
Yes, "return" is also subject to the scope bug discussed under {{SectionLink||Conditional}}. The statements under "else" will never run. The "return" will actually kick in and the function will exit, even though the surrounding control statement did not evaluate to true.


However, "return" is still useful at the end of a function for returning data to the function that called that one; see the section on [[#Returning|returning function values]].
However, "return" is still useful at the end of a function for returning data to the function that called that one; see {{SectionLink||Returning}}.


====sleep====
====sleep====
Line 540: Line 540:


===Loop===
===Loop===
It is generally desirable in any program to be able to run the same code over and over, such as repeatedly spawning enemies. This is one of BSL's biggest limitations, as it has no conventional loop statement like C's "for" or "while", but there are two indirect methods for looping: (1) use "fork" on a function (see the section on [[#Looping|looping functions]]), and (2) "schedule-at"/"schedule-repeat-every" (see the [[#Concurrency|Concurrency]] section).
It is generally desirable in any program to be able to run the same code over and over, such as repeatedly spawning enemies. This is one of BSL's biggest limitations, as it has no conventional loop statement like C's "for" or "while", but there are two indirect methods for looping: (1) use "fork" on a function (see {{SectionLink||Looping}}), and (2) "schedule-at"/"schedule-repeat-every" (see {{SectionLink||Concurrency}}).


===Multi-threading===
===Multi-threading===
====fork, schedule-at, schedule-repeat-every====
====fork, schedule-at, schedule-repeat-every====
See the [[#Concurrency|Concurrency]] section for the use of these keywords.
See {{SectionLink||Concurrency}} for the use of these keywords.


===Obsolete===
===Obsolete===
Line 554: Line 554:


==Functions==
==Functions==
A function is a block of code that can be accessed repeatedly whenever you want to perform a certain task. As in mathematics, functions can be passed input and can return output, though unlike in mathematics, they do not need to do either of those things in order to be useful, as BSL functions can affect external data by modifying global variables and by calling built-in functions which affect the game environment (see the [[#Built-in commands|Built-in commands]] section).
A function is a block of code that can be accessed repeatedly whenever you want to perform a certain task. As in mathematics, functions can be passed input and can return output, though unlike in mathematics, they do not need to do either of those things in order to be useful, as BSL functions can affect external data by modifying global variables and by calling built-in functions which affect the game environment (see {{SectionLink||Built-in commands}}).


===Defining===
===Defining===
Line 604: Line 604:


===Recursive calling===
===Recursive calling===
A function can call itself, which is useful for various looping behavior, but a function can only call itself recursively up to about four times. Note that this limit is bypassed if you use "[[#fork|fork]]" to call a function from within itself, but this no longer counts as recursing because the logic will not complete in a predictable inside-to-outside order. For a non-recursive way to loop a function, see the [[#Looping|Looping]] section.
A function can call itself, which is useful for various looping behavior, but a function can only call itself recursively up to about four times. Note that this limit is bypassed if you use "[[#fork|fork]]" to call a function from within itself, but this no longer counts as recursing because the logic will not complete in a predictable inside-to-outside order. For a non-recursive way to loop a function, see {{SectionLink||Looping}}.


===Returning===
===Returning===
As mentioned under the [[#Flow interrupt|Flow interrupt]] section, "return" exits the function at that point. Because of the bug documented in that section, you cannot exit early from a function under some logical condition. Since "return" can thus only be placed at the end of a function, there is no point in using it at all unless you are going to pass back a value by placing a variable name after "return":
As mentioned under {{SectionLink||Flow interrupt}}, "return" exits the function at that point. Because of the bug documented in that section, you cannot exit early from a function under some logical condition. Since "return" can thus only be placed at the end of a function, there is no point in using it at all unless you are going to pass back a value by placing a variable name after "return":


  func int add_ten(int input)
  func int add_ten(int input)