.. include:: alias.rst

Port and action conditions
==========================

The |rcm| 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:

.. code-block:: lua

   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:

.. code-block:: lua

   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 <core_model.html#parameter-evaluation>`_
for better understanding.

.. _builtin_operators_and_functions:

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  | [bool] -> bool                           |
|           |                           | true                  |                                          |
+-----------+---------------------------+-----------------------+------------------------------------------+
| ``all``   | ``all([true, false])``    | All elements equal to | [bool] -> bool                           |
|           |                           | true                  |                                          |
+-----------+---------------------------+-----------------------+------------------------------------------+
| ``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.       | | [int] -> int          |
|           | Empty lists lead to a runtime error.         | | [float] -> float      |
+-----------+----------------------------------------------+-------------------------+
| ``max``   | Finds the greatest element in an array.      | | [int] -> int          |
|           | Empty lists lead to a runtime error.         | | [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 | vec3 -> float           |
|           | the parameter                                |                         |
+-----------+----------------------------------------------+-------------------------+
| ``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:

.. code-block:: none

   {
       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:

.. code-block:: none

   {
       <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.
