Values and types¶
The LSP language is strongly typed. In other words, there
is only a limited set of implicit conversions between values of different types.
For example, it is not possible to multiply an integer and a string, even if the
string itself represents a number (for exemple 4 * "40.3"
is not allowed).
As already mentionned, the LSP is also a dynamic language. Thus, the type is hold by the value, not by the variable. Every value has a type, and the type itself is also a value. This is particulary important since almost everything is a value in LSP (included classes, functions and modules).
Standard & common types¶
Nil¶
Nil is a particular type. The single value of this type is accessed through
the keyword nil
. It is used to signify the absence of a value.
Nil is the default returned value for functions that don’t explicitly
return anything. It’s also the default value assigned by the modeler to every
global and local variable. Caution should be taken when dealing with nil
:
Indeed, only a very small subset of operations is allowed on nil
.
Every forbidden operation performed on nil
will throw an exception.
Booleans¶
Booleans are written as true
and false
. Booleans are loosely typed and
behave like the integers 1 and 0 in numeric context. Thus, true + 1
is a
valid expression equal to 2
. Conversely, the integers 1
and 0
are
automatically and transparently converted to true
and false
when a
boolean is expected. In other words, when a function expects a boolean value,
you can call it with true
, false
, 1
or 0
. Any other integer
used as a boolean will throw an error:
if (1) println("foo"); // display "foo". 1 is automatically converted to true when a boolean is expected.
if (-38) println("bar"); // will throw the error "Cannot use a branch instruction with type 'int'."
c = (true + 1)*4; // c will receive 8 : true is automatically converted to 1.
Integers¶
Integers are positive and negative integral numbers stored on 64 bits. They are created by integer literals or returned as results of arithmetic operations. Integers are immutable.
The smallest possible integer is -9,223,372,036,854,775,808
and the largest integer is +9,223,372,036,854,775,807
. The modeler do not
perform any range check: if the result of an operation fall outside of this
range, the modeler won’t throw any exception but an integer overflow will occur.
Floats¶
Floats are double precision floating point numbers (stored on 64 bits) in IEEE 754 binary floating point representation. They are created by floating point literals or returned as results of arithmetic operations. Floats are immutable.
Objects¶
All values that are not numbers, booleans or nil are objects. The most commonly used objects are strings, maps, files and LSExpressions, for example.
Strings¶
A string is an immutable sequence of unicode characters stored in UTF-8 format. There is no character type. A character is represented as a string of length 1. See section String module for a description of built-in functions for string management.
Maps¶
Maps are data structure matching some values to some keys. Keys and values
can be of any type except nil
that has a special meaning. The value
associated to a key is set or retrieved by using the “bracket” notation.
For instance, a[k]
returns the value associated to the key k
from the
map a
. If there is no value associated to the given key, nil
is returned. Setting the value of an existing key will overwrite the previous
value associated to the key.
A map is both an associative table and an array. A map is implicitly declared
when inserting its first element. Alternatively, an empty map can be defined
using map()
function or a pair of braces {}
. Braces also allow defining
a map by giving a sequence of values. In this case these values will be assigned
to integer keys 0,1,2,...
(see section Map declaration).
See section Map module for a description of built-in functions for map management.
LSExpressions¶
LSExpressions are the variables and the expressions of the mathematical model
defined by the LSP program. They can only be introduced and manipulated with
the “link” operator <-
. Only expressions introduced or manipulated with
this operator are passed to the solver for a resolution.
In the following example x_0
, x_1
and knapsackWeight
are LS expressions:
x_0 <- bool();
x_1 <- bool();
knapsackWeight <- 10*x_0 + 60*x_1
These expressions are directly passed to the LocalSolver APIs. Consequently, they must follow the rules of the solver. For example, the solver forbids declaring a non-boolean number as a constraint and requires logical operators to apply on boolean values only.
Functions¶
The LSP language treats functions as first-class citizens. In other words, a function is a value with a particular type. Thus, functions can be passed as arguments to other functions, can be assigned to variables or returned by other functions.
There are two kinds of functions in the LSP language:
Native functions. These functions are directly provided by the underlying LSP virtual machine. They are written in a native language like C or C++.
User functions. These functions are written with the LSP language. User functions are the only place where local variables can be declared.
The section Functions describes the behavior of functions and how to declare them.
Modules¶
A module is a collection of classes, functions and global variables. Modules are used to group classes and functions together and import them dynamically at runtime. The I/O library is an example of a module. Each LSP file is a module.
Like functions, LSP treats modules as first-class citizens. Thus, modules can be passed as arguments, assigned to variables…
Other types¶
The modeler comes with many other types. Please refer to the documentation of each module to have a description of their characteristics.