KL flow control

## "If/Else" Commands

The "If" command can be used to conditionally skip some commands. The "If" command has 1 parameter, the condition. An expression is usually supplied. Following the "If" command, the command(s) to be conditionally skipped should appear, followed by an "EndIf" command that indicates the end of the "If" section.

If the condition evaluates to true, then the commands within the "If" section will be executed. If the condition evaluates to false, then the commands within the "If" section will be skipped.

In the following example, the 2 "Set" commands will only be executed if the value of the variable "a" is equal to 5. If it is not equal to 5, the 2 "Set" commands are skipped (not executed).

```
If a == 5;
    Set a, 6;
    Set b, 11;
EndIf;

```

Using the "Else" command, it is possible to provide alternate commands that will be executed in the event of the condition evaluating to false. In the following example, if "a" is equal to 5, then "b" is set to 11, but if "a" is NOT equal to 5, then "b" is set to 66. Only 1 of the 2 "Set" commands will be executed, depending on whether "a" equals 5.

```
If a == 5;
    Set b, 11;
Else;
    Set b, 66;
EndIf;

```

Using the "ElseIf" command, it is possible to provide alternate conditions (and associated alternate commands to be executed). If the condition in the "If" command evaluates to false, then the next "ElseIf" command will be executed, and if the condition in the "ElseIf" command evaluates to true, then the commands associated with the "ElseIf" command will be executed.

In the following example, if "a" equals 5, then "b" is set to 11. If "a" does NOT equal 5, then it checks whether "a" equals 7, and if it does, then "b" is set to 22. If "a" does NOT equal 7 (and does not equal 5), then "b" is set to 66. Only 1 of the 3 "Set" commands will be executed.

```
If a == 5;
    Set b, 11;
ElseIf a == 7;
    Set b, 22;
Else;
    Set b, 66;
EndIf;

```

The "Else" command is optional, but if it is present in an "If" sequence then there can be no more than 1 and it must be last (after all/any "ElseIf" commands).

Multiple "ElseIf" commands can be present in an "If" sequence, as in the following example. The first "If" or "ElseIf" with a condition that evaluates to true will have its associated commands executed. The conditions are evaluated sequentially in the same order as they appear (top to bottom). Thus in the following example, if "a" equals 30, then 3 comparisons/checks are performed ("a == 10", then "a == 20", then "a == 30").

```
{Assume "a" equals 30.}
If a == 10;       {EXECUTED}
    Set a, 1111;  {NOT EXECUTED}
ElseIf a == 20;   {EXECUTED}
    Set a, 2222;  {NOT EXECUTED}
ElseIf a == 30;   {EXECUTED}
    Set a, 3333;  {EXECUTED}
ElseIf a == 40;   {NOT EXECUTED}
    Set a, 4444;  {NOT EXECUTED}
ElseIf a == 50;   {NOT EXECUTED}
    Set a, 5555;  {NOT EXECUTED}
EndIf;

```

The "==" operator/function tests whether 2 values are equal. It is also possible to test whether a value is less than another value, etc. The main operators are summarized below. For more information, see the Expressions section of this documentation.

To write a condition for an "If" command that is satisfied (true) if either of 2 other conditions are true, use the "Or" operator/function. In the following example, "q" will be set to 123 if "a" is equal to "b", or if "x" is equal to "y".

```
If (a == b) || (x == y);
    Set q, 123;
EndIf;

```

In the following example, "q" is set to 123 if "n" is in the range 100 to 200 (inclusive), or if "n" is zero.

```
If ((n >= 100) && (n <= 200)) || (n == 0);
    Set q, 123;
EndIf;

```

Note that expressions are evaluated simply left-to-right. Therefore, the following 2 commands are equivalent:

```
If a == b && x == y;
If ((a == b) && x) == y;

```

Here is a Truth Table for the logical operators, displaying the result of "a $ b" where "$" is one the logical operators such as "AND":

 False
 True
 True

"If" commands can be nested, meaning an "If" sequence can appear inside another "If" sequence (either alone or amongst other commands). The nested inner "If" sequence operates in exactly the same manner as if it were not nested. However, the outer "If" sequence controls whether the inner "If" sequence will be executed. For example:

```
If n < 0;  {if "n" is negative}
    If n < -1000;
        DoSplendidThings;
    EndIf;
    Set n, -1;
Else;  {"n" is positive}
    If n > 1000;
        DoWonderfulThings;
    EndIf;
    Set n, 1;
EndIf;

```

When using a nested "If" sequence, ensure that you do not forget to provide an "EndIf" command for both the nested inner "If" sequence and the outer "If" sequence. Accidentally omitting an "EndIf" command can result in a confusing/ambiguous/invalid interpretation.

"If" commands can be nested to at least 10 levels deep.

The "IfNot" command operates the same as the "If" command except with the opposite interpretation of the boolean condition. The following 2 examples are equivalent. The second uses the function "Not".

```
IfNot condition;
   {...}
EndIf;
If Not[condition];
   {...}
EndIf;

```

The "If" and other commands have shortcut names that are easier to type. You can use either the full name or the shortcut name.

 IfNot
 ElseIf
 Else
 EndIf

Here is an example using shortcut names:

```
if a == 5;
    set b, 11;
elif a == 7;
    set b, 22;
else;
    set b, 66;
eif;

```

## Unconditional Goto

The "goto" command can be used to cause execution of the program to jump to (go to) a different location within the current Command Implementation, either forwards or backwards. The goto command has 1 parameter, the name of the location to jump to. The location is separately defined using the "loc" (location) command. The "loc" command has 1 parameter, a name to assign to this location (the location is where the "loc" command is). For example:

```
goto test;
set a, 123; {this is skipped}
loc test;   {the destination}

```

The goto command cannot be used to jump to a location in a different Command Implementation. The goto command and its corresponding named destination location must be within the same Command Implementation, with either appearing first.

There can be multiple goto commands in different places (within the same Command Implementation) that jump to the same named destination location. There cannot be 2 locations with the same name. Location names have the same restrictions as variable names (no spaces, symbols, etc).

Some people have claimed that goto commands/statements in programming languages are harmful and should not be used. This nonsense originates from a letter written to a magazine/journal by a man named Edsger Dijkstra in 1968:

> "Letters to the editor: go to statement considered harmful" by Edsger W. Dijkstra, Communications of the ACM, Volume 11, Issue 3 (March 1968), pages 147-148.
>
>

However, Dijkstra issued handwritten manuscripts and rarely used computers, and owned only 1 computer late in his life, and did not do any programming on it. He never did any real programming (meaning he never created a real-world software product used for real-world non-theoretical tasks).

> "Dijkstra eschewed the use of computers in his own work for many decades. Even after he succumbed to his UT [University of Texas] colleagues' encouragement and acquired a Macintosh computer, he used it only for e-mail and for browsing the World Wide Web. He had no use for word processors, believing that one should be able to write a letter or article without rough drafts, rewriting, or any significant editing."
> ("In Memoriam of Edsger Wybe Dijkstra" by Jayadev Misra and Hamilton Richards, University of Texas at Austin, 3 Nov 2003.)
>
>

Certainly "goto" can be abused, but so can kitchen knives. That is no reason to ban kitchen knives. Almost anything in a programming language can be abused. If we removed all the features that can be abused, there would be nothing remaining in the language.

It is clear to experienced competent software engineers involved in the production of real-world software that "goto" is useful and helpful in some situations, and is only harmful if abused or used excessively.

## Repeat

One or more commands can be executed repeatedly using the "repeat" command. Following is an example of an infinite loop (never-ending repetition):

```
var msg, TText;
var counter, uint, 0;
repeat;
    incr counter;  {add 1 to counter}
    MText.Set msg, "Never say die ";
    MText.AppendDecInt msg, counter;
    MCLI.Output msg;
erepeat;

```

To exit/abort a repetition from inside the repetition, either the "goto" or "break" command can be used. The "break" command causes execution to jump to the command after the "erepeat" command. For example:

```
var msg, TText;
var sq, uint, 2;
repeat;
    MText.Set msg, "sq contains ";
    MText.AppendDecInt msg, sq;
    MCLI.Output msg;
    if sq == 65536;
        break;
    eif;
    set sq, sq * sq;
erepeat;
MCLI.Output "The end.";

```

To repeat a certain number of times (to perform a certain number of iterations), supply a count for the first parameter of the "repeat" command. The following example performs the commands 5 times:

```
var n, uint;
set n, 3 + 2;
repeat n;
    MCLI.Output "I have MPD.";
    MCLI.Output "No I don't!";
erepeat;

```

In the above example, the variable "n" is not modified by the "repeat" command, and any modification of "n" within the repeat section (during the repetition) does not change the number of repetitions performed.

The count supplied to the "repeat" command can be zero. In that case, the commands within the repeat section are not executed. (Whereas if the count parameter is omitted entirely, the repetition count defaults to infinity.)

The first parameter of the "repeat" command (the repetition count) can be an expression. The expression is calculated once when the repetition starts, not recalculated with each iteration. The repetition count is typecast to an unsigned integer. If it is negative, an error is generated.

"repeat" commands can be nested, meaning a repeat section can be inside another repeat section. For example:

```
var rowCount, uint, 3;
var columnCount, uint, 6;
var msg, TText;
repeat rowCount;
    MText.AppendChar msg, '|';
    repeat columnCount;
        MText.AppendChar msg, '*';
    erepeat;
    MText.AppendChar msg, '|';
    MText.AppendLineBreak msg;
erepeat;
MCLI.Output msg;

```

That produces this output text:

```

```

When using nested repeats, multiple repeat sections can be aborted simultaneously by providing a parameter to the "break" command -- a constant number indicating the number of repeat sections to abort (if no parameter is supplied, it defaults to 1). For example:

```
repeat 10;
    repeat 15;
        repeat 25;
            break 2;
            MCLI.Output "Innermost";  {NOT EXECUTED}
        erepeat;
        MCLI.Output "Middle";  {NOT EXECUTED}
    erepeat;
    {The "break 2" jumps to here.}
    MCLI.Output "Outermost";  {EXECUTED}
erepeat;

```

To end the current iteration early and immediately begin the next iteration, use the "continue" command. It causes execution to jump to the end of the repeat section (but without aborting the repetition) and from there execution will return to the beginning of the repeat section for the next iteration (unless the current iteration is the last iteration). It does not change the total number of iterations performed, it affects only the current iteration. Example:

```
repeat 10;
    MCLI.Output "Apples";   {EXECUTED}
    continue;
    MCLI.Output "Oranges";  {NOT EXECUTED}
erepeat;

```

That is equivalent to:

```
repeat 10;
    MCLI.Output "Apples";   {EXECUTED}
    goto bottom;
    MCLI.Output "Oranges";  {NOT EXECUTED}
    loc bottom;
erepeat;

```

A "repeat" command is equivalent to a certain arrangement of goto commands. Consider this example:

```
repeat n * 3;
    MCLI.Output "Say hello";
    MCLI.Output "to my little friend";
erepeat;

```

That is equivalent to:

```
var countDown, uint;
set countDown, n * 3;
goto bottom;
loc top;
MCLI.Output "Say hello";
MCLI.Output "to my little friend";
loc bottom;
GotoIfDecr countDown, top;

```

## Switch

\*\*\*\* MORE INFO TO BE WRITTEN \*\*\*\*

### Multi-Value Switch

This proposed feature allows multiple values to be used with a "switch" command. If you have nested switch commands (switch commands inside the cases of a switch commands, or if/else commands inside the cases of a switch command), then you might use a multi-value switch instead. For example, consider this example with nested switch commands:

```
switch a;
    case 1;
        switch b;
            case 60;
                {...}
            case 70;
                {...}
        eswitch;
    case 2;
        switch b;
            case 880;
                {...}
            case 881;
                {...}
        eswitch;
    case 3;
        switch b;
            case 70;
                {...}
            case 80;
                {...}
        eswitch;
eswitch;

```

It could be rewritten as a multi-value switch like this:

```
switch a, b;
    case 1, 60;
        {...}
    case 1, 70;
        {...}
    case 2, 880;
        {...}
    case 2, 881;
        {...}
    case 3, 70;
        {...}
    case 3, 80;
        {...}
eswitch;

```

Consider the following example using if/else and goto commands.

```
if b && c;
    goto doX3;
eif;
if a;
    set x, 1;
elif b || c;
    set x, 2;
else;
    loc doX3;
    set x, 3;
eif;

```

It could potentially be rewritten as a multi-value switch like this:

```
switch a, b, c;
    case true, false, false;
    case true, false, true;
    case true, true, false;
        set x, 1;
    case false, true, false;
    case false, false, true;
        set x, 2;
    default;
        set x, 3;
eswitch;

```

### Action Switch

When using a complex if/else sequence, sometimes it is good to separate the actions/results from the logic testing of the conditions, especially when there are multiple conditions that should be directed to the same lengthy chunk of code.

In the following example, the actions are not performed within the complex if/else sequence. Instead the if/else sequence merely determines which action to perform, and then the lengthy action is performed after the entire if/else sequence using a switch to perform only the selected action.

```
if b && c;
    set action, 3;
elif a;
    set action, 1;
elif b || c;
    set action, 2;
elif !d;
    set action, 1;
else;
    set action, 3;
eif;

switch action;
    case 1;
        {...}
    case 2;
        {...}
    case 3;
        {...}
eswitch;

```

## Conditional Goto

The conditional goto commands perform a goto operation only if a certain condition is satisfied. They have 2 parameters. The first parameter is the value, variable, condition, or expression. The second parameter is the name of the destination location.

 GotoIfNot
 GotoIfEQZ
 GotoIfNEQZ
 GotoIfDecr

A decompiler or disassembler may emit a "GotoIf", or "GotoIfDecr", etc., command instead of trying to reconstruct/guess the original higher-level "If", "Repeat", or other command. (A decompiler is a utility that converts compiled code back to source code, or rather compiled code to degraded source code.)

Following is an example of using the "GotoIf" command:

```
loc test;
{...}
GotoIf a == b, test;

```

That is equivalent to:

```
loc test;
{...}
if a == b;
    goto test;
eif;

```

Following is an example of using the "GotoIfEQZ" command:

```
loc test;
{...}
GotoIfEQZ n, test;

```

That is equivalent to:

```
loc test;
{...}
if n == 0;
    goto test;
eif;

```

Consider this if/else sequence of commands:

```
if n == 1;
    DoInterestingThings;
elif n == 2;
    DoGreatThings;
else;
    DoSplendidThings;
eif;

```

That is equivalent to:

```
GotoIfNot n == 1, secondTest;
DoInterestingThings;
goto theEnd;

loc secondTest;
GotoIfNot n == 2, defaultSection;
DoGreatThings;
goto theEnd;

loc defaultSection;
DoSplendidThings;
loc theEnd;

```