.. include:: alias.rst

.LF file format
===============

Introduction
------------

The ``.lf`` file format is a human-readable format for representing |rcm|'s semantics
for state machines and all their properties. Its intended use case is the
creation and manipulation of state machines using light-weight
tools such as a text editor and a command line interface to read, validate and
upload state machines to the |core|.

.lf files
---------

A ``.lf`` file holds a single root state, all its hierarchical child
states, as well as all ports, barriers, actions, parameters, variables and results. The
name of the file directly acts as the name of that state, e.g. a file called
``Wiggle.lf`` is interpreted as a state machine called 'Wiggle'.

State machines can also contain script code, e.g. for actions. Scripts are stored
within ``.lf`` files as well, but they are enclosed in special tags (``@{`` as
the opening tag and ``}@`` as the closing tag).

An example of a state machine representing a simple timer module is given
below:

.. code-block:: lf

  Timer {
    port done service("timer").operation("wait").status == "success"

    parameterType {
      float duration;
    }

    entry @{
      service("timer").operation("wait").call(parameter.duration)
    }@

    clientData {
      type : "app";
    }
  }

Note that the script language for actions (including entry and exit actions) is Lua.

In the following sections, we will go over the grammar of the individual elements.

Elements of a state machine
---------------------------

A state machine consists of several elements. The following figure shows an
overview of them. For a simple state only the name of the state machine and the
ports are mandatory, all the other elements can be used if necessary. If you
want to build a Desk app, a few more elements are necessary which are explained
later in the tutorial.

.. figure:: _static/statemachine_structure.png
    :align: center

The next code block displays these elements in |lf|. The order of the
elements inside the state does not matter. The structure of the child states is
similar to the parent state. All the elements can be used, except of the
clientData block.

.. code-block:: lf

  App {
    port Success child("child_state_2").port("success")
    port Error child("child_state_1").port("error") or
               child("child_state_2").port("error")

    clientData { ... }

    parameterType { ... }

    resultType { ... }

    variableType { ... }

    entry @{ ... }@

    action ..condition.. @{ ... }@

    action ..condition.. @{ ... }@

    exit @{ ... }@

    --> child_state_1 {
      port success ..condition.. -> child_state_2
      port error ..condition..

      parameterType { ... }
      resultType { ... }
      variableType { ... }
      entry @{ ... }@
      action ..condition.. @{ ... }@
      action ..condition.. @{ ... }@
      exit @{ ... }@

    } where { ... }

    child_state_2 {
      port success ..condition..
      port error ..condition..

      parameterType { ... }
      resultType { ... }
      variableType { ... }
      entry @{ ... }@
      action ..condition.. @{ ... }@
      action ..condition.. @{ ... }@
      exit @{ ... }@

    } where { ... }

  } where { ... }

Root states
-----------

A single ``.lf`` file contains a single root state. Its name must match the
filename without the ``.lf`` suffix.

The grammar for a root state (i.e. for a complete ``.lf`` file) is given as follows:

.. code-block:: bnf

  <root-state> ::= <state-name> <state-block>

The rules for ``<state-name>`` and ``<state-block>`` will be defined in the next section.

States
------

A state is a named entity in a hierarchical state machine that can contain
other states or barriers. It can be connected to sibling states via ports, and
contain actions that are executed upon certain triggers.

In |rcm|, the state holds a reference to a single child state or barrier which it
treats as its "first" child, i.e. upon executing the state, this "first" child
element gets activated. In ``.lf`` files, this attribute is not expressed at the
parent state, but the "first" child element is marked by a ``-->`` arrow,
marking it as the entry state.

A state can be a link state and reference a library, i.e. another state machine, which it links to. Such a
link state cannot contain states, barriers, nor actions as these elements are inherited
from the linked library. The only elements the link state can contain are ports without
a condition that must also be present within the library.

.. code-block:: bnf

  <state> ::= <entry-symbol> <state-name> <state-block>
  <link> ::= <entry-symbol> <state-name> "<-" <library-name> <link-block>
  <dynamic-link> ::= <entry-symbol> <state-name> "<-" <value> <link-block>
  <entry-symbol> ::= epsilon | "-->"
  <parameter-value> ::= epsilon | "where" <value>

  <state-block> ::= "{" <state-contents> "}" <parameter-value>
  <state-contents> ::= <state-elem> *
  <state-elem> ::=  <state> | <link> | <barrier> | <action> | <port> | <client-data> |
                    <parameter> | <variable> | <result>

  <link-block> ::= "{" <link-contents> "}" <parameter-value>
  <link-contents> ::= <link-elem> *
  <link-elem> ::=  <link-port> | <client-data>

  <state-name> ::= <identifier>
  <library-name> ::= <identifier>
  <identifier> ::= <alpha> <identifier-component>
  <identifier-component> ::= <alpha-num> *
  <alpha> ::= A-Za-z
  <alpha-num> ::= <alpha> | 0-9 | "_"

Valid state or library identifiers start with a letter and are
followed by any number of letters, numbers or underscore. Identifiers
are case-sensitive.

The ``epsilon`` represents an empty symbol.

The rules for ``<barrier>``, ``<action>``, ``<port>``, ``<link-port>``,
``<parameter>``, ``<variable>``, ``<value>``, ``<result>`` and ``<client-data>``
are given in the following sections.

Barriers
--------

Barriers are child elements of states and represent either:

- a synchronization point where incoming port connections from multiple states
  can be merged onto a single destination state. Execution waits for all
  incoming ports to activate and transitions to the destination state. This is
  akin to a ``join`` operation in multi-threaded programs.
- a branching point where a single incoming port is mapped onto a number of
  destination states. In this case, execution starts the execution of the
  destination states in parallel. This is similar to a ``fork`` operation in
  multi-threaded programs. Barriers can also be entry nodes of the containing
  state, i.e. they are the first element to activate when the parent activates.

The grammar for barriers is defined as follows:

.. code-block:: bnf

  <barrier> ::= <entry-symbol> "barrier" <barrier-name> <barrier-block>
  <barrier-name> ::= <identifier>

  <barrier-block> ::= "{" <barrier-connections> "}"
  <barrier-connections> ::= <barrier-connection> *
  <barrier-connection> ::= "->" <state-name>

Actions
-------

Actions are functions written in Lua that are executed based on trigger
conditions during the execution of the state machines. Special cases are the
``entry`` and ``exit`` actions, which are executed upon entering and leaving a
state, respectively. More general ``actions`` have an additional condition expression which
must evaluate to true to be executed.

The grammar for actions is defined as follows:

.. code-block:: bnf

  <action> ::= <entry-action> | <exit-action> | <condition-action>
  <entry-action> ::= 'entry' <script>
  <exit-action> ::= 'exit' <script>
  <condition-action> ::= 'action' <value> <script>
  <script> ::= '@{' String '}@' | '"' EscapedString '"'


In this grammar and the following ones in this document, ``String`` represents
any string, and ``EscapedString`` represents any string where quotes are
escaped (``\"``).
The ``<value>`` in the ``<condition-action>`` must evaluate to a ``<bool-value>``.

.. note::

   Actions are executed synchronously and should therefore not contain any
   long running computations, since this might block the execution of parallel
   branches. Any long running computation should be extracted to a separate
   service and integrated using an operation call.

Ports
-----

Ports are named entities that allow the transition from the port's parent (the
source state) to the port's destination (the destination state). A port also
has a condition attached that must evaluate to true for the port (and thus the
transition) to be activated. Ports are not necessarily connected to a
destination state.

The grammar for ports is defined as follows:

.. code-block:: bnf

  <port> ::= "port" <port-name> <value> <connection>
  <port-name> ::= <identifier>
  <connection> ::= epsilon | "->" <destination-name>
  <destination-name> ::= <state-name>

The ``<value>`` in the ``<condition-action>`` must evaluate to a ``<bool-value>``.

Link ports
----------

Libraries also can have ports, and instantiations of libraries ("link" states)
inherit the library's ports such that they can be connected. As such, link ports
are less complex since they do not contain the condition expression. The
condition is already defined within the library.

The grammar for link ports is thus defined as follows, using the same rules as
the regular port grammar:

.. code-block:: bnf

  <link-port> ::= "port" <port-name> <connection>

It is therefore possible to define a link port without connecting it to a
destination state or barrier. In this case, the statement merely acts as an
explicit statement that the linked library must provide the corresponding port
``<port-name>``, however this is currently not checked when compiling the bundle.

Parameter, result and variable
------------------------------

States can have parameters, results and variables, which are simple or composite
data structures representing a configuration, outcome or private data of a state,
respectively. Parameters, results and variables are strongly typed.
Parameters and results can be augmented with metadata for specifying default values,
value ranges, units but also information about which widgets to use for allowing the
user to specify them. Variables can be used to store state private data which is
persistent even if a (child) state is deactivated.

The definition of parameters, results and variables is split into two aspects: types and values.

Parameter, result and variable types
````````````````````````````````````
A parameter/result/variable type can consist of the following entities:

- basic types
    - **float**: The `float` data type is a double precision 64-bit floating point.
    - **int**: The `int` data type is a 32-bit signed integer.
    - **bool**: The `bool` data type has two possible values: `true` and `false`.
    - **string**: The `string` data type represents character strings.
- **array type**: An array is a container holding a fixed or unbounded number of values of a single type.
- **struct type**: A struct is a container holding a set of named fields with potentially different types.
- **state interface type**: A state interface describes the public interface of
  a state, namely its ports, parameter type and result type. A state fulfills a
  state interface if both contain the same ports, and if all parameter fields
  and result fields are contained in the parameter fields and result fields of
  the interface, respectively.
- **comments**: everything from the '--' sign until the end of the line is
  considered a comment and will not be parsed.

The following grammar defines the structure of parameter/result/variable types:

.. code-block:: bnf

    <parameter> ::= "parameterType" <type>
    <variable> ::= "variableType" <type>
    <result> ::= "resultType" <type>
    <type> ::= <base-type> | <array> | <struct> | <state-interface>
    <base-type> ::= 'int' | 'float' | 'bool' | 'string'
    <array> ::= '[]' <type> | '[' Integer ']' <type>
    <field> ::= <type> <identifier> ';'
    <fields> ::= <field> *
    <struct> ::= '{' <fields> '}'
    <state-interface> ::= '{' <state-interface-elem> <state-interface-contents> '}'
    <state-interface-contents> ::= <state-interface-elem> *
    <state-interface-elem> ::= <state-interface-port> | <parameter> | <result> |
                               "parameterType" "any" | "resultType" "any"
    <state-interface-port> ::= 'port' <port-name>

The following example shows a simple parameter type that contains a pose matrix
and linear and angular velocities:

.. code-block:: lua

  {
    [4][4]float goal_pose;
    -- this is a comment
    {
      [3]float linear;
      [3]float angular;
    } velocities;
  }

Here is another example containing two state interfaces:

.. code-block:: lua

  {
    compute_goal_pose: {
      port done
      resultType {
        [4][4]float goal_pose;
      }
    };
    move_to_goal_pose: {
      port success
      port error
      parameterType {
        [4][4]float goal_pose;
      }
    };
  }

Since both structs and state interfaces are enclosed with curly braces, state
interfaces must contain at least one element to distinguish between an empty
struct and an empty state interface. Specifying parameter and result type in a
state interface is optional. Both default to the special `any` type, meaning
all types will match. It is possible to explicitly write this as follows:

.. code-block:: lf
  
  {
    port done
    parameterType any
    resultType any
  }

This is equivalent to:

.. code-block:: lf
  
  {
    port done
  }

.. _lf-values:

Parameter, result, variable values
``````````````````````````````````

In the preceding section, the grammar for parameter, result and variable types was given.
The grammar for assigning values to these parameters is a separate aspect and
defined as follows:

.. code-block:: bnf

  <value> ::= <int-value> | <float-value> | <string-value> | <bool-value> |
              <nil-value> | <array-value> | <struct-value> |
              <anonymous-state> | <exp> | "(" <value> ")"
  <int-value> ::= Integer
  <float-value> ::= Float
  <string-value> ::= "'" String "'"
  <bool-value> ::= "true" | "false"
  <nil-value> ::= "nil"
  <array-value> ::= "[" <elements> "]"
  <struct-value> ::= "{" <field-values> "}"
  <elements> ::= <value> | <value> "," <elements>
  <field-values> ::= <field-value> *
  <field-value> ::= <identifier> ":" <value> ";"
  <anonymous-state> ::= <state-block>
  <exp> ::= <fun-app> | <access-path> | <exp> "[" Integer "]"
  <fun-app> ::= <access-path> "(" <elements> ")" | <access-path> "(" ")" |
                <unary-operator> <value> | <value> <binary-operator> <value> |
                "if" <value> "then" <value> "else" <value>
  <unary-operator> ::= "not" | "#" | "-"
  <binary-operator> ::= "and" | "or" | "*" | "/" | "%" | "+" | "-" |
                        "==" | "~=" | "<=" | ">=" | "<" | ">"
  <access-path> ::= <identifier> "." <access-path> | <identifier>

See :ref:`builtin_operators_and_functions` for a list of available operators
and functions and and their meaning.

An instantiation of the above parameter type follows as:

.. code-block:: python

  {
    goal_pose : [[1.0, 0.0, 0.0, 0.0],
                 [0.0, 1.0, 0.0, 0.0],
                 [0.0, 0.0, 1.0, 0.0],
                 [0.0, 0.0, 0.0, 1.0]];
    velocities : { linear : [ 1.0, 0.0, 0.0 ]; angular : [ 0.0, 0.0, 0.0 ]; };
  }

Note that omission of the "where" clause results in an empty parameter struct value.

The value for a state interface can be specified via a struct with exactly two
fields `{ string state; any parameter; }`, where `state` and `parameter` mean
the same as `<library-name>` and `<parameter-value>` in links. E.g.

.. code-block:: lf

  {
    state: "some_root_state";
    parameter: {
      a: "Hello";
      b: 42;
    };
  }

references the root state "some_root_state" and sets a default value for its
parameter value. A state reference **must** specify values for all parameter
fields that are not contained in the parameter type of the state interface.

Client data
-----------

States can hold arbitrary client data in a key-value store. This allows for
clients to store e.g. human-readable state names or the app's
context menus. While client data is stored in the |core|, no semantics
are attached to them, i.e. their interpretation resides fully client-side.
It is possible to provide some extra data that you might want to use
later using :ref:`ElementAPI <elementAPI>`. Every key in ``clientData`` that is
prefixed with ``X_`` will be available in ``extraClientData`` property of ``model``
object with ``X_`` prefix omitted. For example the following ``clientData`` block

.. code-block:: lua

    clientData {
      X_myCustomProperty: "hello"
    }

will look like this when accessed via :ref:`ElementAPI <elementAPI>`

.. code-block:: js

    model: {
      extraClientData: {
        myCustomProperty: "hello"
      }
    }

The grammar for client-data is defined as follows:

.. code-block:: bnf

  <client-data> ::= "clientData" "{" <client-data-block> "}"
  <client-data-block> ::= <key-value> *
  <key-value> ::= <key> ":" <value> ";"
  <key> ::= <identifier>
  <value> ::= '@{' String '}@' | '"' EscapedString '"'
