Statements¶
Assignment statements¶
Assignments are used to assign values to variables. There are many kind of assignments in LSP depending on the type of the variable (local or global) and the operation you want to perform.
assignment_operator
: "="
| "<-"
| "+="
| "-="
| "/="
| "*="
| "%="
local_assignment_operator
: "="
| "<-"
assignment_statement
: `identifier` `assignment_operator` `expression` ";"
| `identifier` `assg_compositor` `assignment_operator` `expression` ";"
local_assignment_statement
: "local" `identifier` `local_assignment_operator` `expression` ";"
| "local" `identifier` `assg_compositor` `local_assignment_operator` `expression` ";"
local_statement
: "local" `identifier` ";"
assg_compositor
: "[" `filter_iterator` "]"
| "[" `expression` "]"
| '.' `expression`
| `assg_compositor` "[" `filter_iterator` ']'
| `assg_compositor` "[" `expression` "]"
| `assg_compositor` "." `identifier`
Simple statements¶
The simple statement is the classical variable = value;
that assigns the
given value to the specified variable, overriding the previous value. The
variable can be local or global. If the variable was not previously declared as
local, the variable is considered as global by default and is implicitly
declared if necessary.
This statement cannot be used to add an LSExpression to the mathematical model. See Link statements for that.
Examples:
a = true; // a = 1
b = 9; // b = 9
c = a + b; // c = 10
c = a * b; // c = 9
c = (a == b); // c = 0
c = a < b; // c = 1
Coumpound assignment statements¶
A coumpound assignment (also called “augmented assignment”) is the combination of an arithmetic operation and an assignment. The arithmetic operations allowed with coumpound assignment statements are:
+
addition-
substraction*
multiplication/
division%
modulo
Thus, an assignment like a = a + b
can be rewritten as a += b;
with the
coumpound assignment syntax.
Exemples:
a += 2; // a = a + 2
a /= 2; // a = a/2
a *= b + c; // a = a*(b + c)
Link statements¶
The link statement is a particular assignment that only applies to LSExpression or values that can be casted to LSExpression. This statement is used to add expressions to the mathematical model. If the assigned value is not an LSExpression or cannot be cast to an LSExpression, an exception is thrown. Only integers, floating point numbers and in certain circonstances maps, can be casted to LS expressions.
Examples:
a = true; // a = 1
b = 9; // b = 9
c = a + b; // c = 10
c = a * b; // c = 9
c = a == b; // c = 0
c = a < b; // c = 1
x <- 1; // 1 is transformed to a constant LS expression and is added to the mathematical model
y <- bool(); // y is a new decision variable and is added to the mathematical model
z <- x+y; // z is an LS expression and is added to the mathematical model
// This assignment will throw an exception: strings cannot be casted to LSExpression.
z <- "a string";
Local assignment and local statements¶
Local statements local variable
, local variable = value
or local variable <- value
introduce a new local variable with the given
name and set its value to nil or to the specified value.
If a global variable with the same name was already defined, then the global variable will be masked while this local variable is visible. If a local variable with the same name was already defined an error is thrown. See Variables for the differences between local and global variables and for details on the visibility scopes of variables.
Examples:
local i; // Declare i as local and set its value to nil.
local j = 2; // Declare j as local and set its value to 2.
for[z in 1..10] {
// This assignment will throw an exception since z was already implicitly
// declared as local in the for loop.
local z = "foo";
}
Iterated assignment statements¶
a[v in V] = f(v);
is an iterated assignment which is strictly equivalent
to for [v in V] a[v] = f(v);
Similarly a[v in V] <- f(v);
is an
iterated assignment which is strictly equivalent to for [v in V] a[v] <- f(v);
These iterated assignment features will help you will help you to make your
models shorter and clearer. Similarly to the for statement introduced in
the previous section, iterations can be nested and filtered:
for[i in 0..9][j in i+1..9][k in j+2..9]
a[i][j][k] = i + j + k;
a[i in 0..9][j in i+1..9][k in j+2..9] = i + j + k; // compact
If statements¶
The if statement is used for conditional execution.
if_condition
: 'if' '(' expression ')'
;
if_else_statement
: if_condition statement
| if_condition statement 'else' statement
;
if the if_condition
is true (equals to 1), then the first statement is
executed. Otherwise, the second statement after the else is executed. Note
that the else branch is optional and a block of statements can be declared
instead of a sole statement by using the braces {}
.
If the expression is not an integer equal to 0 or 1 an error will be thrown.
Note
The conditional ternary operator ? :
can also be used as shortcut.
Examples:
if (0) c = "ok";
if (true) c = "ok";
if (2) c = "error"; // ERROR: invalid condition
For statements¶
The for statement is used to iterate over a range, the elements of a map or any other iterable value. The for statements can be nested with a compact syntax and can be filtered with an optional conditionnal statement.
for_statement
: 'for' for_compositor statement
;
for_compositor
: '[' filter_iterator ']'
| for_compositor '[' filter_iterator ']'
;
filter_iterator
: identifier 'in' expression ':' expression
| identifier ',' identifier 'in' expression ':' expression
| identifier 'in' expression '..' expression ':' expression
| identifier 'in' expression
| identifier ',' identifier 'in' expression
| identifier 'in' expression '..' expression
| expression '..' expression
;
Simple for-loops¶
for [v in A] S;
is a simple for-loop where the statement S
is
iteratively executed with v
taking all values in A
, where A
can be a
range or an iterable value like a map. Variable v
is implicitly declared as
a local variable visible within this for statement and in nested blocks only.
When a range is given, it is declared with the from..to
syntax where both
from and to are included.
When an iterable object is given, the iteration is performed on the sub-values of the object. The iteration order is specific to the type of the value. For the maps, the order is defined as follows:
Iterates on number keys (integer or floats) in ascending order.
Iterates on strings in ascending order.
Iterates on other types in an implementation specific way.
It is also possible to iterate on the pairs (key, value) using
the syntax for [k,v in M]
. In that case, k
and v
are both declared
implicitly as local variables and contain respectively the current key and
the current value of the loop.
Example:
s = { -44, 12, 14 };
for [i in 0..2] a[i] = i + 1; // a[0] = 1, a[1] = 2, a[2] = 3
for [v in s] println(v/2); // prints -22, 6 and 7.
for [k, v in s] println(k, ":", v); // prints 0:-44, 1:12 and 2:14
Filtered for-loops¶
for [v in V : C]
is a filtered iteration loop: v takes only the values in
V satisfying the condition C.
Compact for-loops¶
Filtered and non filtered for-loops can be nested in a compact way, as follows:
// Non compact
for[i in 0..9]
for [j in i+1..9 : j % 2 == 0]
for [k in j+2..9]
a[i][j][k] = i + j + k;
// Compact
for[i in 0..9][j in i+1..9 : j % 2 == 0][k in j+2..9]
a[i][j][k] = i + j + k;
The behavior of these 2 examples is similar except that the language considers the non-compact case as the association of 3 enclosing loops, while the compact example is solely a loop with 3 iterated indexes. This semantic difference is particularly important for break statement: a break statement stops the most inner loop, regardless of the number of iterated indexes.
For all kinds of loops, a block of statements can be declared instead of a sole
statement by using the braces {}
:
for[i in 0..9][j in i+1..9][k in j+2..9] {
a[i][j][k] = i + j + k;
b[i][j][k] = i * j * k;
}
for-loops can contain ‘break’ and ‘continue’ statement to respectively terminate the loop unconditionnaly or to go back to testing the condition of the loop whitout executing the rest of the statement suite.
While/do-while statements¶
while_statement
: 'while' '(' expression ')' statement
;
dowhile_statement
: 'do' statement 'while' '(' expression ')' ';'
;
While or do-while loops are used for repeating a section of code as long as an expression is true.
For the ‘while’ loop, the expression is tested first. If it is true, the statement is executed. The loop terminates otherwise.
For the ‘do-while’ loop, the statement is executed first, then the expression is tested. Contrary to the ‘while’ loop, the ‘do-while’ loop ensures that at least one statement suite is executed.
While or do-while loops can contain ‘break’ and ‘continue’ statement to respectively terminate the loop unconditionnaly or to go back to testing the condition of the loop whitout executing the rest of the statement.
Continue statement¶
continue_statement
: 'continue' ';'
;
The continue statement, when encountered, goes back to testing the condition of the nearest enclosing loop, whitout executing the rest of the block code.
Continue statements can only take place in for/while/do-while loops. Use of this statement outside of these loops will throw an error.
Break statement¶
break_statement
: 'break' ';'
;
Break statement terminates the nearest enclosing loop. Please note that for ‘for’ loops, the entire loop is stopped, regardless of the number of iterated indexes.
Break statements can only take place in for/while/do-while loops. Use of this statement outside of these loops will throw an error.
Try-catch statement¶
In the LSP Language, all errors, faults or exceptionnal situations are handled with an exception mechanism.
trycatch_statement
: 'try' statement
'catch' '(' identifier ')' statement
;
Throw statement¶
throw_statement
: 'throw' expression ';'
| 'throw' ';'
;
With statement¶
The with statement is used for resource management. It ensures that a system or a native object like files or solver instances are correctly freed at the end of the statement, whatever flow the code follows (return, exception).
The with statement in LSP is similar to the with statement in Python, the try-with-resource in Java or the using statement in C#.
with_statement
: 'with' '(' with_resource ')' statement
;
with_resource
: identifier
| identifier '=' expression
Examples:
// f is a local variable whose scope is limited to the "with" statement
with(f = io.openRead("/path/to/file")) {
local a = f.readInt();
...
}
// The file is automatically closed at the end of the "with" statement,
// even if an exception is thrown.
Constraint/minimize/maximize statements¶
modifier
: 'minimize'
| 'maximize'
| 'constraint'
;
modifier_statement
: modifier expression ';'
;
These statements modify expressions of the mathematical model (LSExpression) to add them to the constraints list or the objectives list. These statements can also be applied on integers or doubles.
constraint c;
adds the LSExpressionc
as a constraint to the mathematical model. An error will be thrown is c is not a boolean LSExpression (introduced with a logical or relational operator) or a constant equals to 0 or 1.minimize c;
adds the LSExpressionc
as an objective to be minimized by the mathematical model.maximize c;
adds the LS expressionc
as an objective to be maximized by the mathematical model.
Note
At least one objective must be defined in the mathematical model.