Control Flow Statements
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 _
STORE statement assigns a value to a variable.
STORE <NUMBER-VAR or NUMBER or TEXT-VAR or TEXT> IN <NUMBER-VAR or TEXT-VAR>
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
"15a") the conversion
will fail and 0 will be stored in the NUMBER variable. If the TEXT contains a
proper number, though, for example
"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
IF _ IS _ THEN
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.
1 2 3 4 5
IF <CONDITION> THEN #Code goes here (positive branch) ELSE #Code goes here (negative branch) END IF
1 2 3
IF <CONDITION> THEN #Code goes here (positive branch) END IF
<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-B> <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
NOT EQUAL TO
GREATER THAN OR EQUAL TO
LESS THAN OR EQUAL TO
Possible values of
NOT EQUAL TO
You can also write compound conditions using
OR and parenthesis:
<CONDITION> AND <CONDITION>is positive if both conditions are positive
<CONDITION> OR <CONDITION>is positive if both conditions are positive
( <CONDITION> )is positive if the condition is positive, it's used to alter the default precedence
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 ).
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.
1 2 3 4 5 6 7 8
DATA: names IS TEXT LIST length IS NUMBER PROCEDURE: GET LENGTH OF names IN length IF length IS GREATER THAN 0 AND ( names:0 IS EQUAL TO "Alice" OR names:0 IS EQUAL TO "Bob" ) THEN #Code END IF
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
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
All the different
IF variants of the IF statement apply, just with
ELSE added before them.
1 2 3 4 5 6 7 8 9 10 11 12 13
DATA: name IS TEXT PROCEDURE: STORE "Mike" IN name IF name IS equal to "John" THEN DISPLAY "Hello there, John!" CRLF ELSE IF name IS equal to "Mike" THEN DISPLAY "Hello there, Mike!" CRLF ELSE IF name IS equal to "Robert" THEN DISPLAY "Hello there, Robert!" CRLF ELSE DISPLAY "I don't know you, " name CRLF END IF
WHILE _ IS _ DO
WHILE statement evaluates if the condition given is positive. While it is, the code between the
REPEAT statements is repeatedly ran.
1 2 3
WHILE <CONDITION> DO #Code goes here REPEAT
<CONDITION> that you can use are the same as the IF statement ones.
FOR _ FROM _ TO _ STEP _ DO
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
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).
1 2 3
FOR <NUMBER-VAR> FROM <NUMBER-VAR or NUMBER> TO <NUMBER-VAR or NUMBER> STEP <NUMBER-VAR or NUMBER> DO #Code goes here REPEAT
1 2 3 4 5 6 7
DATA: i IS NUMBER PROCEDURE: FOR i FROM 0 TO 10 STEP 2 DO DISPLAY i " " REPEAT # Will display "0 2 4 6 8 10"
FOR EACH _ IN _ DO
FOR EACH statement repeatedly run the code in its body for every element in a given
MAP. At the start of each iteration an element of the collection is assigned to a scalar variable matching its type.
As the variable must be a scalar variable, the for each statement doens't support multicontainers.
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.
1 2 3
FOR EACH <NUMBER-VAR> IN <NUMBER-LIST or NUMBER-MAP> DO #Code goes here REPEAT
1 2 3
FOR EACH <TEXT-VAR> IN <TEXT-LIST or TEXT-MAP> DO #Code goes here REPEAT
1 2 3 4 5 6 7 8 9 10 11 12
DATA: letter IS TEXT letters IS TEXT LIST PROCEDURE: PUSH "L" TO letters PUSH "D" TO letters PUSH "P" TO letters PUSH "L" TO letters FOR EACH letter IN letters DO DISPLAY letter REPEAT # Will display "LDPL"
1 2 3 4 5 6 7 8 9 10 11
DATA: number IS NUMBER numbers IS NUMBER MAP PROCEDURE: STORE 1 IN numbers:"One" STORE 2 IN numbers:"Two" STORE 3 IN numbers:"Three" FOR EACH number IN numbers DO DISPLAY number REPEAT # Will display "312" or any permutation
BREAK statement breaks the execution of the innermost
FOR EACH loop. Will throw a compiler error if used outside one.
CONTINUE statement jumps to the next iteration of the innermost
FOR loop. Will throw a compiler error if used outside one.
CALL SUB-PROCEDURE statement executes a SUB-PROCEDURE. Once the SUB-PROCEDURE returns, the execution continues from the line following the
CALL SUB-PROCEDURE <sub-procedure name> CALL SUB-PROCEDURE <sub-procedure name> WITH <multiple NUMBER, TEXT, TEXT-VAR, NUMBER-VAR, MAP or LIST>
CALL <sub-procedure name> CALL <sub-procedure name> WITH <multiple NUMBER, TEXT, TEXT-VAR, NUMBER-VAR, MAP or LIST>
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 statement returns from a SUB-PROCEDURE. Will throw a compiler error if used outside one.
EXIT statement ends execution of the program.
WAIT _ MILLISECONDS
WAIT statement pauses the execution of a program for the given number of milliseconds.
WAIT <NUMBER or NUMBER-VAR> MILLISECONDS
GOTO & LABEL
"If you want to go somewhere, goto is the best way to get there." -- Ken Thompson
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.
Label names follow the naming rules stated in the Identifier Naming Schemes section of this documentation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
PROCEDURE: GOTO start LABEL start display "> starting..." crlf GOTO ending LABEL middle display "> entering the middle section..." crlf sub cool-code GOTO cool display "hmm... is this cool?" crlf LABEL cool display "wow, yeah! cool code!" crlf end sub LABEL ending CALL cool-code display "> that's the end" crlf
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
> starting... wow, yeah! cool code! > that's the end
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 _
CREATE STATEMENT statement lets you add custom statements to LDPL that execute SUB-PROCEDUREs.
CREATE STATEMENT <TEXT> EXECUTING <sub-procedure name>
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
"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.
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
PROCEDURE: SUB-PROCEDURE displayNValueTimes PARAMETERS: value is number times is number LOCAL DATA: i is number PROCEDURE: FOR i FROM 0 TO times STEP 1 DO DISPLAY value " " REPEAT END SUB-PROCEDURE CREATE STATEMENT "DISPLAY $ $ TIMES" EXECUTING displayNValueTimes # Syntax for this new statement: DISPLAY <NUMBER or NUMBER-VAR> <NUMBER or NUMBER-VAR> TIMES SUB-PROCEDURE displayTValueTimes PARAMETERS: value is text times is number LOCAL DATA: i is number PROCEDURE: FOR i FROM 0 to times STEP 1 DO DISPLAY value " " REPEAT END SUB-PROCEDURE CREATE STATEMENT "DISPLAY $ $ TIMES" EXECUTING displayTValueTimes # Syntax for this new statement: DISPLAY <TEXT or TEXT-VAR> <NUMBER or NUMBER-VAR> TIMES # We can imagine that we have only one new statement: # DISPLAY <NUMBER or NUMBER-VAR or TEXT or TEXT-VAR> <NUMBER or NUMBER-VAR> TIMES DISPLAY 100 2 TIMES # This executes: CALL displayNValueTimes with 100 2 DISPLAY "Hi!" 3 TIMES # This executes: CALL displayTValueTimes with "Hi!" 3 # This program displays "100 100 Hi! Hi! "
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
DATA: times is number PROCEDURE: SUB-PROCEDURE displayTValueTimes PARAMETERS: value is text times is number LOCAL DATA: i is number PROCEDURE: FOR i FROM 0 to times STEP 1 DO DISPLAY value " " REPEAT END SUB-PROCEDURE CREATE STATEMENT "DISPLAY $ $ TIMES" EXECUTING displayTValueTimes # Syntax for this new statement: DISPLAY <TEXT or TEXT-VAR> <NUMBER or NUMBER-VAR> TIMES DISPLAY "Hi!" 3 TIMES # This executes the LDPL DISPLAY statement! # This program displays "Hi!30" because times is equal to 0
CALL EXTERNAL _
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.
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.
CALL EXTERNAL <external sub-procedure name>
CALL EXTERNAL http-get