Control Flow Statements
Note
While this section is up-to-date and complete, it has to be reformated to be easier on the eyes. All UPPERCASE statement names and code should be changed to lowercase.
STORE _ IN _
The STORE statement assigns a value to a variable.
Syntax:
1 | |
Type Conversion Notes:
If the value to be stored is NUMBER and it's to be stored in a TEXT variable,
the value will be converted to text, so 15 will be turned into "15". If the
value to be stored is a TEXT value two things can happen. If it contains any
non-numeric characters (for example letters, or more than one minus sign or
more than one decimal point, for example "--1.2" or "15a") the conversion
will fail and 0 will be stored in the NUMBER variable. If the TEXT contains a
proper number, though, for example "-416.419" or "89" it will be converted
to its number equivalent and stored in the variable. If a string literal depicting
a number is preceded by leading zeros, these will be trimmed (turning 0005
into 5, -0002.3 into -2.3 and 00.23 into 0.23).
IF _ IS _ THEN
The IF statement evaluates if the condition given is positive. If it is, the code in the positive branch is executed. If it is not, the code in the negative branch is executed (if available). Execution then continues normally.
Syntax:
1 2 3 4 5 | |
or
1 2 3 | |
The <CONDITION> may be a relational operator between two values with the same type:
<NUMBER-VAR or NUMBER> IS <REL-OP-A> <NUMBER-VAR or NUMBER><TEXT-VAR or TEXT> IS <REL-OP-A> <TEXT-VAR or TEXT><NUMBER LIST> IS <REL-OP-B> <NUMBER LIST><TEXT LIST> IS <REL-OP-B> <TEXT LIST><NUMBER MAP> IS <REL-OP-B> <NUMBER MAP><TEXT MAP> IS <REL-OP-B> <TEXT MAP>
Possible values of REL-OP-A:
EQUAL TONOT EQUAL TOGREATER THANLESS THANGREATER THAN OR EQUAL TOLESS THAN OR EQUAL TO
Possible values of REL-OP-B:
EQUAL TONOT EQUAL TO
For containers, both values must have the same type. You cannot compare, for example,
a list of lists of numbers with a list of lists of lists of numbers or a number map
with a text map.
The <CONDITION> may also be a membership operator:
<NUMBER-VAR or NUMBER or TEXT-VAR or TEXT> IN <LIST><NUMBER-VAR or NUMBER or TEXT-VAR or TEXT> IN <MAP>
When using a membership operator, if the second value is a list, it checks if the first value is contained within that list. If the second value is a map, however, it checks if the first value is contained within the keys of that map.
The first value must always be a scalar value, you cannot check if, for example, a
map of numbers is contained within a list of maps of numbers.
You can also write compound conditions using AND, OR and parenthesis:
<CONDITION> AND <CONDITION>is positive if both conditions are positive<CONDITION> OR <CONDITION>is positive if any of the conditions is positive( <CONDITION> )is positive if the condition is positive and it's used to alter the default precedence
The AND has higher precedence than OR, and the conditions inside parenthesis will be evaluated first. That means that C1 AND C2 OR C3 is the same as ( C1 AND C2 ) OR C3, but you can make the OR evaluate first if you write C1 AND ( C2 OR C3 ). Mind the spaces surrounding the parenthesis: (<CONDITION>) is not a
valid condition, while ( <CONDITION> ) is.
Both AND and OR perform short-circuit evaluation: If the first operand of an AND is negative the second will not be evaluated and the AND condition is determined as negative. If the first operand of an OR is positive the second will not be evaluated and the OR condition is determined as positive.
For example:
1 2 3 4 5 6 7 8 | |
The names list is empty, so the length is greater than 0 condition is negative, and the second one is not evaluated (and the execution continues after the END IF). Thanks to short-circuit evaluation names:0 is not evaluated and we don`t get an index out of range runtime error!
ELSE IF _ IS _ THEN
The ELSE IF statement is equivalent to writing an IF statement inside the ELSE statement of another IF statement, but shorter. Must be used after an IF statement and before END IF or ELSE.
Syntax:
All the different IF variants of the IF statement apply, just with ELSE added before them.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
WHILE _ IS _ DO
The WHILE statement evaluates if the condition given is positive. While it is, the code between the WHILE and REPEAT statements is repeatedly ran.
Syntax:
1 2 3 | |
The <CONDITION> that you can use are the same as the IF statement ones.
FOR _ FROM _ TO _ STEP _ DO
The FOR statement repeatedly run the code in its body a number of times, given a counter variable, the start of the range, its end and a step.
When the loop starts, start is assigned to counter and starts an iteration, evaluating a condition. The condition is counter < end if step >= 0 and counter > end if step < 0. If the condition passes, the code in the body of the FOR is executed, otherwise the loop will end. After the code is ran the counter is incremeted by step and a new iteration is started (checking the condition and so on).
Syntax:
1 2 3 | |
Example:
1 2 3 4 5 6 7 | |
FOR EACH _ IN _ DO
The FOR EACH statement repeatedly run the code in its body for every element in a given LIST or MAP. At the start of each iteration an element of the collection is assigned to a variable matching its type. This even works with multicontainers. For example, you can iterate a NUMBER MAP LIST using a NUMBER MAP as the iteration variable.
If the collection is a LIST, its elements will be iterated increasingly from index 0, while in the case of a MAP all the elements will be iterated in no particular order.
Info
Starting from LDPL 5 Groovy Gualicho, FOR EACH iterates over the may keys, instead of its elements. The iteration variable type must thus be TEXT.
Syntax:
1 2 3 | |
Example:
1 2 3 4 5 6 7 8 9 10 11 12 | |
BREAK
The BREAK statement breaks the execution of the innermost WHILE, FOR or FOR EACH loop. Will throw a compiler error if used outside one.
Syntax:
1 | |
CONTINUE
The CONTINUE statement jumps to the next iteration of the innermost WHILE or FOR loop. Will throw a compiler error if used outside one.
Syntax:
1 | |
CALL SUB-PROCEDURE
The CALL SUB-PROCEDURE statement executes a SUB-PROCEDURE. Once the SUB-PROCEDURE returns, execution continues from the line following the CALL SUB-PROCEDURE.
Syntax:
1 2 | |
Or
1 2 | |
Of course, a SUB-PROCEDURE must be declared somewhere in your program for you to call it.
If the SUB-PROCEDURE you call doesn't have any declared parameters, you must call it without the WITH keyword, otherwise you must include it and pass all required parameters after it, in the same order declared in the PARAMETERS section of the SUB-PROCEDURE.
RETURN
The RETURN statement returns from a SUB-PROCEDURE. Will throw a compiler error if used outside one.
Syntax:
1 | |
EXIT
The EXIT statement ends execution of the program.
Syntax:
1 | |
GOTO and LABEL
"If you want to go somewhere, goto is the best way to get there." -- Ken Thompson
The GOTO statement performs a one-way transfer of control to a line of code marked by a LABEL statement. In lame man terms, the execution jumps to the line where the wanted LABEL is found and continues from there.
While maligned by Edsger W. Dijkstra and his cohorts, GOTO is very useful in many situations. Its reputation is undeserved and mostly perpetuated by people that don't understand the origins of the criticism or how the statement can be used.
You also can't make a COBOL-esque language without GOTO, so (due to popular request) we've added it to the language.
Syntax:
1 | |
1 | |
Hint
Label names follow the naming rules stated in the Identifier Naming Schemes section of this documentation.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
In the output of this program you can see the middle LABEL and the start of the cool-code SUB-PROCEDURE are skipped:
1 2 3 | |
In order to keep GOTO from turning your source into unmaintainable spaghetti code, both your GOTO statements and the LABELs they jump to have to be declared together in the same sub-procedure or in the main code body of an LDPL program. You can't goto across sub-procedures or into them, or anything like that.
CREATE STATEMENT _ EXECUTING _
The CREATE STATEMENT statement lets you add custom statements to LDPL that execute SUB-PROCEDUREs.
Syntax:
1 | |
The TEXT describes the new statement syntax and must contain tokens separated by whitespace. Each token can be a keyword, which is a word with A-Z characters (preferably in English), or "$", a character that marks where parameters are passed. At least one keyword token is required and the number of "$" tokens must be the same as the number of parameters of the SUB-PROCEDURE you pass after EXECUTING. For example, a valid TEXT is "DISPLAY $ $ TIMES" if the SUB-PROCEDURE has exactly two parameters. The SUB-PROCEDURE must be declared before creating the statement.
After a statement is created you can use it like any other LDPL statement in PROCEDURE sections, just write a line with all the tokens of the TEXT in the same order but placing values instead of "$". The types of the values must be the same as the parameter types of the SUB-PROCEDURE the statement executes following the same order. Using the new statement will produce the same effect as CALLing the SUB-PROCEDURE (parameters are passed by reference too).
You can create two different statements with same TEXT and use both if at least one of the parameter types are different in each SUB-PROCEDURE, because the resulting syntaxes will differ from each other. Using this you can create two versions of the same statements dealing with different parameter types, like the first example shows.
Bear in mind that a line in your program could match more than one statement: If all of them were created with CREATE STATEMENT, the one that was created first will be executed. If one of the them is a LDPL built-in statement, this will be executed. For example, if you create "DISPLAY $ $ TIMES", declare a variable TIMES and use the line DISPLAY "Hi!" 3 TIMES, the LDPL DISPLAY statement will be executed, because the line matches its syntax. This is illustrated in the second example.
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
Example 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
CALL EXTERNAL _
Hint
This section talks about external sub-procedure calling for C++ Extensions. If you have not read the section on C++ Extensions yet, ignore this and then come back later.
The CALL EXTERNAL statement executes a SUB-PROCEDURE defined in an extension to LDPL, typically in C++. It otherwise operates the same as CALL SUB-PROCEDURE, except that external SUB-PROCEDURES do not receive parameters.
Syntax:
1 | |
Example:
1 | |