This is the documentation of the compiled executable format of ScalarIQ expressions.
Presentation
ScalarIQ Executable is a tree format data structure of executable nodes. The structure is typically contained in a JSON encoded string when transported over network.
Alternative compact binary form representation is in planning state.
Executable Node
All nodes have two properties - op and
av.
{
"op": <op-code-string>,
"av": [ <arguments> ... ]
}
Supported op values are: "expression",
"add", "sub", "mul",
"div", "mod", "not",
"or", "and", "eq",
"ne", "lt", "le",
"ge", "gt", "condition",
"call", "lookup", "scope",
"coalesce", "isnull", and
"typeof".
Array av is always present in the node. If the node does
not have arguments, then av is set to an empty array
[].
All arguments in the av array are either other
executable nodes or simple scalar values of number (NaN or Inf are not
allowed), string, boolean type, or null.
| Op | Args | Description |
|---|---|---|
expression |
1 | Reduces to the value of the argument,
which can be either a scalar or another node. The root node of the
ScalarIQ executable tree, must not be a scalar. If the expression
directly reduces to a constant scalar value, it must be wrapped into
expression node. There are no other beneficial use cases
for this node type. |
add |
1 .. n | Reduces to the sum of all arguments. All
arguments must reduce to number before summation. If there are arguments
that reduce to other types, add operation will reduce to
null. |
sub |
2..n | Reduces to the subtraction of all
arguments i.e. the sum of all subsequent arguments is subtracted from
the first argument. All arguments must reduce to number before
calculation. If there are arguments that reduce to other types,
sub operation will reduce to null. |
mul |
1 .. n | Reduces to the product of all arguments.
All arguments must reduce to number before multiplication. If there are
arguments that reduce to other types, mul operation will
reduce to null. |
div |
2 | Reduces to the result of the division of
operation’s two arguments. Both arguments must reduce to number before
division and the latter one must not be zero. If either argument reduce
to other types, div operation will reduce to null. |
mod |
2 | Reduces to the result of the modulo of
operation’s two arguments. Both arguments must reduce to number before
calculation and the latter one must not be zero. If either argument
reduce to other types, mod operation will reduce to
null. |
not |
1 | Reduces to the logical negation (i.e. NOT)
of the argument. If the argument is TRUE it reduces to FALSE, and FALSE
reduces to TRUE. If the argument is or reduces to non-boolean scalar, it
will first be booleanized with following rules: non-zero number and
non-empty string booleanizes to TRUE and number zero and empty string
booleanizes to FALSE. null does not booleanize and with null argument,
not operation reduces to null |
or |
1 .. n | Reduces to the logical OR of arguments.
Non-boolean arguments are booleanized like in and
operation. If any of the arguments is null, or operation
reduces to null |
and |
1 .. n | Reduces to the logical ANF of arguments.
Non-boolean arguments are booleanized like in and
operation. If any of the arguments is null, or operation
reduces to null |
eq |
2 | Reduces to TRUE if both arguments reduce
to identical scalars, and FALSE otherwise. However, if either of the
arguments is null, eq operation reduces to null. |
ne |
2 | Reduces to FALSE if both arguments reduce
to identical scalars, and TRUE otherwise. However, if either of the
arguments is null, nq operation reduces to null. |
lt |
2 | Requires two arguments that reduce to a
number or null. If either is null, then lt reduces to null.
Otherwise it reduces to TRUE if the first argument’s value is less than
the second arguments value, and FALSE otherwise. |
le |
2 | Requires two arguments that reduce to a
number or null. If either is null, then lt reduces to null.
Otherwise it reduces to TRUE if the first argument’s value is less or
equal than the second arguments value, and FALSE otherwise. |
ge |
2 | Requires two arguments that reduce to a
number or null. If either is null, then lt reduces to null.
Otherwise it reduces to TRUE if the first argument’s value is greater or
equal than the second arguments value, and FALSE otherwise. |
gt |
2 | Requires two arguments that reduce to a
number or null. If either is null, then lt reduces to null.
Otherwise it reduces to TRUE if the first argument’s value is greater
than the second arguments value, and FALSE otherwise. |
condition |
2n + 1 | Requires an odd number of arguments.
Arguments before the last one are evaluated in pairs, if the first
argument of the pair reduces to TRUE (or is booleanized to TRUE), then
condition operation reduces to the next argument, otherwise
the execution proceeds to the next pair. If no positive case is found
before the last argument, condition reduces to the last
argument (i.e. default value). |
call |
1 .. n | Requires a string literal as a first
argument. Other arguments are reduced to scalar before proceeding.
Operation call reduces to the return value of the
externally provided function identified by the first argument. Other
arguments are passed as parameters to this external call. The external
function must return a scalar value (number, string, boolean, or
null). |
scope |
2n + 1 | Requires an odd number of arguments.
Creates a new scope. Arguments before the last one are evaluated in
pairs. First argument of each pair must be a string literal, which is
used as a name, and the second argument is reduced to a scalar value and
stored to the scope with the name. All names must be unique in a single
scope, but the same name can be used again in the inner scope, in which
case the inner definition shadows the outer one. After the scope has
been formed, scope operation will evaluate the last
argument within the defined scope and reduce to the value to which this
last argument reduces to. Scopes can be nested arbitrarily. |
lookup |
1 | Requires a string literal as an argument. Reduces to the scalar value that is looked up from the scope of the operation with the name identified by the argument string. If the value is not found from the current scope, also the enclosing outer scopes are checked in order. |
coalesce |
0 .. n | Reduces to the first non-null argument. If there are no non-null arguments, reduces to null. |
isnull |
1 | Reduces to TRUE, if the argument reduces to null, otherwise FALSE |
typeof |
1 | Reduces to string "number",
"boolean", "string", or "null"
according to the type of the value to which the argument reduces
to. |
Examples
{
"op": "expression",
"av": [ 1 ]
}
Reduces to number 1. Should be used only as a root node. If any item
in any av array is a number, boolean, or string literal or
null, they should be inserted into av as is and not
enclosed to expression operation.
{
"op": "sub",
"av": [ { "op": "add", "av": [ 1, 1 ] }, 2 ]
}
1 + 1 - 2
Reduces to 0.
{
"op": "scope",
"av": [ "a", 1,
"b", 2,
{
"op": "add",
"av": [ { "op": "lookup", "av": [ "a" ] },
{ "op": "lookup", "av": [ "b" ] } ]
} ]
}
Defines a scope, where a is 1 and b is 2
and evaluates the sum a+b which reduces to 3.
{
"op": "scope",
"av": [ "temperature", { "op": "call", "av": [ "sensor" ] },
{ "op": "condition",
"av": [ { "op": "lt", "av": [ { "op": "lookup", "av": [ "temperature" ] },
0 ] },
"cold",
{ "op": "gt", "av": [ { "op": "lookup", "av": [ "temperature" ] },
30 ] },
"hot",
"ok" ] } ]
}
Defines a scope, where temperature is set to the return
value of the external function sensor() and returns string
"cold" if temperature is less than zero, or
"hot" if tempeature is greater than 30 and
"ok" otherwise.
Final Note
It is noteworthy that if there are no call operation
nodes present in the executable tree, the tree reduces always to the
same constant scalar value.