====== Comment ======
// single line
----
====== Branch definition ======
branch name( [param1 [, param2 [, param3 …]]] )
statement
[statement]
[...]
[return [value]]
end
Parameter definition
* ** param_name [=deflt]**\\ Parameter by value
* **[ &] param_name**\\ Parameter by reference
The type of the parameter passed by reference is not guaranteed; it strictly depends on the calling parameter. Therefore, type declaration of such parameter is for info purposes only, and is not required. Also, default value with parameter by reference is not supported.
----
====== Eval definition ======
eval name( [param1 [, param2 [,…]]] ) expression [; expression [; ..]]
eval name( [param1 [, param2 [,…]]] )
expression
[expression]
[...]
end
Evals are similar to branches, with the following differences:
* Evals are lists of expressions, not statements.
* Flow control statements are not allowed
* A list of expressions in eval is executed identically to a list of expressions separated by comma operators
* Evals may be compiled and linked to database objects in runtime
* Evals have no stack, so no local variables (except for parameters) are allowed
* Only parameters passed by reference are allowed
* Execution of evals is faster than execution of branches
* Result of the last expression is returned (return is not needed and may not be used)
* Result is always by reference:
branch access(prp)
return $.(prp)
end
eval access2(prp) $.(prp)
branch test()
ATOM $.A = 'A' //A == 'A'
access('A') = 'B' //A == 'A'
access2('A') = 'C' //A == 'C'
end
Parameter definition
* **[ &] param_name**\\ Parameter by reference
The type of the parameter passed by reference is not guaranteed; it strictly depends on the calling parameter. Therefore, type declaration of such parameter is for info purposes only, and is not required.
----
====== Expressions overview ======
* **name**
local variable or local property ($.name)
* **ref.name**
property
* **ref.func( p1 [, ..])**
multiparam func result
* **ref.func()**
void param func result
* **ref.(expression)**
property by indirection
* **ref.(func)()**
void param func result (call by indirection)
* **ref.(func()).name** \\ **ref_foo().name**
call to a function as reference to object
* **ref.name**
equals to ref.('name')
* **ref.({func1 func2 func3})()**
call to multiple functions
* **integer.prop** \\ **integer.(prop_name)** \\ **integer.(prop_name)**
engine object property
* **integer.func(…)** \\ **integer.(func)(…)** \\ **integer_list.func()**
engine object call
----
====== Variable declaration expression ======
TYPE variable [= expression]
* ** name [= expression ]**
name is a local variable.if expression is ommited, the initial value of the variable is undefined.
* ** ref.name [= .. ]**
name is an object property
* ** $.name [= .. ]**
for this
* ** *.name [= .. ]**
for caller
* Multiobject declaration:
REFERENCES refs = ...
VECTOR refs.vec // no assignment possible
* Indirect declaration:
ATOM name = 'var1'
ATOMS names = { 'var2' 'var3' 'var4' }
ATOM ref.(name) // no assignment possible
INTEGER ref.(names) // no assignment possible
----
====== Assignment expression ======
variable = expression
property = expression //equivalent to:
$.property = expression
*.property = expression
reference.property = expression
* Regular assignment x = obj.prop
* x gets the value of obj.prop
* obj.prop is a property of the object
* Assign into (overwrite)x := ... \\ [x] = ...
----
===== Examples =====
Example 1:
ARRAY props = reference.({ 'x' 'y' 'z' })
props := 0.0
or:
ARRAY props = reference.({ 'x' 'y' 'z' })
[props] = 0.0
//or:
[reference . ({'x' 'y' 'z'})] = 0.0
Example 2:
INTEGERS list = {1 2 3 4 5 6 7 8 9 10}
[list[{1 2 4 6}]] = {201 311}
//or:
ARRAY{list}[{1 2 4 6}] := {201 311}
//result:
list == {201 311 3 201 5 311 7 8 9 10}
----
====== Operators ======
For list operators: if a is a list, operation is done on all members of a. If b is also a list, the values in b are cycled through, otherwise, the single value b is repeated on all elements of list a. The exception to this rule are the logical operators. In this case, the list is evaluated as a single bool (false for an empty list, true for a list with at least one item). To emulate the regular behavior with logical operators, binary logical functions can be used in combination with the bool operator. (eg. **and(bool a, bool b)** instead of **a and b**).
When comparison operators are used on a list, the result is a list of integers - indexes to items that satisfy the condition.
Between operators of the same precedence, expression is evaluated left to right. The exception to this rule are unary and assignment operators, which are evaluated right to left.
* **a - b - c** is equivalent to **(a - b) - c**
* **a ; b ; c** is equivalent to **(a ; b) ; c**
* **a = b = c** is equivalent to **a = (b = c)**
* **a *= b + c** is equivalent to **a *= (b + c)**
* **a += b += c** is equivalent to **(a += b) += c**
* **a - b + c - d** is equivalent to **(a - b) + (c - d)**
* **neg sgn a** is equivalent to **neg (sgn a)**
All unary operators hold precedence to all binary operators, thus:
* **neg a + neg b** is equivalent to **(neg a) + (neg b)**
----
====== Database objects as lists ======
A database object has similar behavior to a list.
The **list**, **last** and **count** operators may be used directly on a reference:
clear($) // properties on the object are destroyed
count $ // 0
ATOM $.prop1 = 'atom1'
INTEGER $.prop2 = 11
ATOMS $.prop3 = {'atom2' 'atom3' 'atom4'}
$[0] // nul
$[1] // 'atom1'
$[2] = 15.1 // rounds to INTEGER, 15
$[3][1] // 'atom2'
$[3][2] = 'atom5'
$.prop3 // {'atom2' 'atom5' 'atom4'}
$[15] = 'atom5' //no effect
last last $ // 'atom4'
[$[1 .. 3]] = nul // clear first three properties
count $ // 3
The names of properties may be read and altered using a system function. This way, the same name may be shared among multiple properties. In such case, regular access to properties by using their name is not guaranteed to always return the first property with that name:
pname($, 1) // 'prop1'
pname($, 3, 'prop1') // 1st and 3rd property share the name ‘prop1’
$.prop1 // might return either 1st or 3rd
// prop - unpredictable but not random
The type of a property may be read or altered, or a range of properties may be read and altered using an operator and system functions:
$.prop1|type // 'ATOM'
$[1]|type // 'ATOM'
pdeclare(1, 'INTEGER') // $.prop1 is now INTEGER, value undefined
pdeclare(1, 'FLOAT') = 0.0
count $ // 3
pdeclareset(2, 50, 'ATOM')
count $ // 50
Functions **pname** (only when setting, not reading a name), **pdeclare** and **pdeclareset** implicitely call **presize** when the number of properties allocated on the database object is less than required. The newly added properties have no type or name (all names are nul).
presize($, 50) // items 1 .. 50 may now be accessed
presize($, 0) // all properties are deleted, equivalent to clear($)
Reading typeless properties is safe (nul is always returned). Assignment into typeless properties is also safe (no effect).
----
====== Compiler directives ======
All compiler modes are reset for each branch / eval.
* **compiler array loop**
sets array compiler mode: (for multicalls) to loop (default) {1 2 3} = {1 2 3 1 2 3 1 2 3...}
* **compiler array last**
sets array compiler mode to last: {1 2 3} = {1 2 3 3 3 3 3 3 3...}
* **compiler array nul**
sets array compiler mode to nul: {1 2 3} = {1 2 3}