Flow Control

From HLKitWiki
Revision as of 20:45, 17 November 2008 by Rob (Talk | contribs) (New page: Category:Basic Concepts and Terminology [Context: HL Kit … Basic Concepts and Terminology … Scripting Language] The scripting language supports a variety of...)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

[Context: HL KitBasic Concepts and TerminologyScripting Language]

The scripting language supports a variety of basic flow control mechanisms, and each is described in the sections below.

Label and Goto Statements

The most primitive form of flow control is the use of "label" and "goto" statements. Label statements are defined with the form "name:", where "name" follows the same naming rules as variables. To transfer control to a label statement, a goto statement is used. The syntax for a goto statement is "goto name", where name corresponds to an existing label within the script. When a goto statement is executed, control passes to the label statement, and the next line executed in the script is the one immediately following the label statement. It is perfectly valid to issue a goto statement prior to the definition of the label statement, allowing you to skip over a section of the script if you wish. An example code block demonstrating the use of labels and gotos is given below.

var foo as number
foo = 10
goto mylabel
foo = 20
mylabel:
~The value of foo is still 10, since we skipped over the assignment to 20.

If/Then Blocks

A more traditional form of control flow is with the "if/then" block. Within an if/then block, a test of some sort is performed. Based on the results of that test, the following block of code may or may not be executed. The if/then block consists of two separate statements. The first statement is the test to be performed and uses the syntax "if (expr1 comparison expr2) then". The values of "expr1" and "expr2" can be any valid arithmetic expression. The valid values for "comparison" are the various relationship operators: '<', '<=', '=', '>=', '>', and '<>'. The first five of these comparison operators should be familiar, while the last one implies "not equal".

The "if" statement evaluates the two expressions and then compares them with the relationship indicated. If the comparison is satisfied, then execution continues with the line immediately following the "if" statement.

The second statement identifies the end of the if/then block and has the simple syntax "endif". If the comparison is failed, then execution skips over the if/then block until the "endif" statement is reached, at which point execution resumes. An example if/then block is shown below.

var foo as number
foo = 10
if (foo + 3 > 20) then
  foo = 1
  endif
~The value of foo is still 10, since we skipped over the assignment above.

If/Then/Else Blocks

The if/then block can be extended to be an if/then/else block. This form is useful when you need to execute one block of code if the condition is true and another block of code if it fails. The if/then/else block is identical to the if/then block, except that an additional "else" statement is inserted. This new statement demarcates where the block of code to execute on success ends and the block of code to execute on failure begins. If the conditional test is true, then execution continues with the next line, but when the "else" statement is encountered, execution jumps to the line following the "endif" statement. If the conditional test fails, then execution jumps to the line following the "else" statement. An example if/then/else block is shown below.

var foo as number foo = 10 if (foo + 3 > 20) then

 foo = 1

else

 foo = foo + 10
 endif

~The value of foo is now 20, since we executed the "else" clause only.

If/Then/Elseif/Else Blocks

To handle the situation where multiple value ranges need to be handled, the if/then/else block also supports an "elseif" statement. The "elseif" statement allows a separate condition to be tested, with its own block of code to be executed if the condition is satisfied. All condition blocks are tested in sequence, with only the first one that is satisfied having its code executed.

var foo as number foo = 8 if (foo <= 5) then

 foo = 1

elseif (foo <= 10) then

 foo = 2

elseif (foo <= 15) then

 foo = 3

else

 foo = 4
 endif

~The value of foo is now 2, since we executed the first "elseif" clause only.

While/Loop Blocks

Another control flow mechanism provided within scripting is the while/loop block. The while/loop block executes a block of code repeatedly as long as a particular conditional test remains true. The while/loop block begins with a statement of the form "while (expr1 comparison expr2)", where expr1, expr2, and comparison all behave identically to an "if" statement. The end of a while/loop block is identified by a "loop" statement, which consists solely of the keyword "loop" on a line. When the "loop" statement is encountered, the conditional test is evaluated again. As long as the condition remains true, execution continues with the line following the "while" statement. Once the condition fails, execution jumps to the line following the "loop" statement. This loop will continue until the conditional test finally fails. An example while/loop block is shown below.

var foo as number foo = 1 while (foo <= 10)

 foo = foo + 1
 loop

~The value of foo is now 11.

Done Statement

If you reach a point in the execution of a script where all necessary processing is completed, you can utilize the "done" statement to immediately exit the current script. Judicious use of "done" can simplify scripts and make them easier to maintain by eliminating a great deal of nesting and matching of if/then/else statements. Two examples are shown below, where the second script accomplishes the same as the first. The key difference is that the second script utilizes the "done" statement. Use of the "done" statement is a matter of personal style, but it can be very handy for scripts with both simple and complex conditions.

if (foo <= 3) then

 ~do something

else

 ~lots of code
 if (for <= 6) then
   ~lots of code
 else
   ~lots of code
   endif
 ~lots of code
 endif

if (foo <= 3) then

 ~do something
 done
 endif

~lots of code if (for <= 6) then

 ~lots of code

else

 ~lots of code
 endif

~lots of code

For/Next Blocks

The final control flow mechanism available is the for/next block. Like the while/loop block, the for/next block executes a block of code repeatedly, linked to the value of a variable (the "loop index"). The for/next block is identified by "for varname = expr1 to expr2", where varname is the name of the numeric variable to be used as the loop index and expr1 and expr2 are complex expressions. The variable is initialized with a given value and incremented by 1 every iteration of the loop. After the second value has been reached and processed, the iteration stops (so looping from 1 to 5 will run through the loop 5 times, the index taking values of 1, 2, 3, 4 and 5 in succession before stopping). The loop index is incremented by the for/next construct itself, and does not have to be maintained by the script writer.

var x as number var text as string text = "A list of some numbers: " for x = 0 to (100 / 20 * 2)

 text = text & x
 next

~The string 'text' will now contain an ascending list of the numbers from 0 up to 10.

Limitations

All conditional statements (if/then, if/then/else, while/loop and for/next) can be safely nested within each other. The only limitation is a maximum nesting depth of 20, which ought to be significantly more than any script should ever need.

The scripting mechanism is designed to handle scripts of only moderate size and complexity. If a script is too large or complex, an error will be reported when compiling the script. In general, a given script can utilize dozens of flow control constructs without becoming too complex, so the complexity limit should not be reached under normal conditions.