Port and action conditions

The core model requires expressions for port and action conditions. Besides simple values such as integers, floats, expressions can also be function calls (including operator expressions such as 1 + 2), or can access paths to reference symbols, struct fields or array elements.

Note

Array indices start with 1 to be consistent with Lua.

Besides basic boolean and arithmetic expressions, the core evaluates expressions in a node context (i.e. specific function calls and symbols can be used in expressions). Basically, a node context contains bindings for the following symbols:

  • result: The result value of a state or link.

  • parameter: The parameter value of a state or link.

  • port(<name>): A function to get the activation state of a port.

For instance, a port condition that checks if a (scaled) result value field a is above a specific threshold specified in a parameter expression can be written as follows:

result.a / 1000.0  > parameter.threshold

In addition, the evaluation context of expressions contains a binding of the child(<name>) function which returns the node context of the corresponding child node. For instance, a port condition that activates when the port condition of a port "Success" owned by the child node "foo" holds or if the child node "bar" has a result value field a that evaluates to 123 can be written as follows:

child("foo").port("Success") || child("bar").result.a == 123

Please note that the top-level evaluation context contains a binding to child while the context returned by child does not in order to prevent access to children of children of children. Also note that parameter expressions are evaluated in the context of the owning (i.e. the parent) state while condition expressions are evaluated in the state containing the actions and ports. Please refer to the section on Parameter Evaluation for better understanding.

Built-in operators and functions

The following operators and functions can currently be used in expressions:

Symbol

Example

Description

Supported types

+

+2

+ prefix operator

int -> int
float -> float

+

1 + 2

+ operator

(int, int) -> int
(float, float) -> float

-

-2

- prefix operator

int -> int
float -> float

-

1 - 2

- operator

(int, int) -> int
(float, float) -> float

*

1 * 2

* operator

(int, int) -> int
(float, float) -> float

/

1 / 2

/ operator

(int, int) -> int
(float, float) -> float

#

#a

Array Length

[a] -> int, for all possible types a

and

a and b

Logical and

(bool, bool) -> bool

or

a or b

Local or

(bool, bool) -> bool

not

not a

Logical not

bool -> bool

<

a < b

Smaller than

(int, int) -> bool
(float, float) -> bool

<=

a <= b

Smaller or equal

(int, int) -> bool
(float, float) -> bool

==

a == b

Equality

(a, a) -> bool, for all possible types a

~=

a ~= b

Inequality

(a, a) -> bool, for all possible types a

>

a > b

Greater than

(int, int) -> bool
(float, float) -> bool

>=

a >= b

Greater or equal

(int, int) -> bool
(float, float) -> bool

any

any([true, false])

Any element equal to true

[bool] -> bool

all

all([true, false])

All elements equal to true

[bool] -> bool

float

float(1)

Convert to float

int -> float

int

int(1.5)

Convert to int

float -> int

child

child("foo")

Access child context.

string -> <node context>

port

port("foo")

Access port state.

string -> bool

if

if a==b then 1 else 2

Ternary operator.

(bool, a, a) -> a, for all types a

Mathematical standard library

The following table shows a list of the current mathematical standard library supported by scripts and condition expressions.

Symbol

Description

Supported types

min

Find the smallest element in an array. Empty lists lead to a runtime error.

[int] -> int
[float] -> float

max

Finds the greatest element in an array. Empty lists lead to a runtime error.

[int] -> int
[float] -> float

abs

Returns the absolute value of the parameter.

int -> int
float -> float

sin

Returns the sine of the parameter.

float -> float

asin

Returns the inverse sine of the parameter

float -> float

cos

Returns the cosine of the parameter.

float -> float

acos

Returns the inverse cosine of the parameter.

float -> float

tan

Returns the tangent of the parameter.

float -> float

atan

Returns the arctangent of the parameter.

float -> float

atan2

Returns the arctangent. Takes two parameters

(float, float) -> float

exp

Computes the exponential function.

float -> float

log

Computes the natural logarithm.

float -> float

pow

Computes x^y.

(float, float) -> float

sqrt

Computes the square root of the parameter.

float -> float

dot

Returns the dot product of two vectors.

(vec3, vec3) -> float

cross

Returns the cross product of two vectors.

(vec3, vec3) -> vec3

vnorm

Returns the vector norm (i.e. the length) of the parameter

vec3 -> float

vdist

Returns the distance between two vectors.

(vec3, vec3) -> float

vadd

Adds two vectors.

(vec3, vec3) -> vec3

vsub

Subtracts two vectors.

(vec3, vec3) -> vec3

vmul

Scales a vector with a given scalar.

(vec3, float) -> vec3

The vector functions in the above table require a vector type. The vector type is defined as a struct with the following layout:

{
    float x;
    float y;
    float z;
}

Services

To access services (i.e. event values, operation results and the status of operation calls), the function service is provided. It takes a single string argument that names the service to be accessed. The service object returned by the service function contains two functions, operation and event. operation allows to query operation results, errors and the status of an operation call while event allows to access event values. Both functions take a single string parameter identifying the operation or event to access. The return value of a call to operation is similar to a struct with the following layout:

{
    <result type> result;
    <error type> error;
    string status;
}

The result and error types are defined by the service that is accessed. Possible values for the status string are:

  • "unknown": The operation has not been called yet.

  • "pending": The operation has been called by no result has been received yet.

  • "success": The operation succeeded and the result value is bound to the result field.

  • "error": The operation failed and the result value is bound to the error field.

The result of a call to the event function is a value that matches the declared event type.

Expression type inference

The core is able to infer the type of expressions and performs type validation on all RPC calls that change either condition expressions, parameter and result types or parameter expressions. If such an RPC call would lead to type mismatches in expressions, the call is rejected with an error message. Expression types are computed according to the following rules:

  • Plain expressions (i.e. int, string, bool and float expressions) have the corresponding base type.

  • Array expressions result in an array type with the element being the result of a recursive application of these typing rules.

  • Struct expressions result in a struct type with the field types being computed by recursive application of these typing rules.

  • Function call types result in the return type of the corresponding function as shown in the above table.

  • Access paths result in the corresponding type of the access path entry.

    • Access paths into structs result in the corresponding struct field type.

    • Access paths into parameter result in the corresponding parameter field type.

    • Access paths into result result in the corresponding result field type.