V4 Replacement for SNL
Warning: The following is work in progress.
Deficiencies of current SNL
The current version of SNL (State Notation Language) has a number of severe deficiencies that should be addressed in a new version for EPICS R4.
- No Abstraction Facilities
- SNL doesn't support factoring common functionality. Functions cannot be defined in SNL, only by escaping to C, loosing all the features SNL adds (for instance easy access to PVs via 'assigned' variables). A typical workaround is to create additional state sets as a kind of subroutine. However, parameter passing and start/done communication must be simulated via PV-assigned global variables.
- State Change is Determined by When Clause
- In SNL the next state is already determined by the when-condition. This means that a condition for when to *do* something is coupled to a commitment for what to do next. This is often very inconvenient and to work around this limitation leads to a proliferation of artificial states that have nothing to do with the original state machine model.
- Weak Support for Introspection
- SNL supports querying internal state via the iocShell, but this is rather inconvenient and doesn't cover continous monitoring of the current state of a state set. In order to achieve this, the programmer has to (1) create a record to contain the value representing the current state, and (2) manually pvPut a value corresponding to the state into the PV on entry to the state, which clutters the code with extremely repetitive code, maintained via cut & paste.
Proposal for a new SNL
We propose a redesign of SNL, building on good and bad experiences with the current version. The goal is to remedy the deficiencies mentioned above, without throwing away what is good and proven to work. The syntax and semantics should be similar, although we adopt a somewhat different viewpoint. This viewpoint naturally leads to a number of new features that, taken together, solve the above mentioned problems.
Preliminary Observation
It is widely known that closures (procedure + environment) can be implemented as objects in a language that natively supports objects. It is less well known, that objects can be implemented as closures in languages where closures are a native feature. The two concepts are quite similar. In what follows we will often switch from viewing things as objects to viewing them as closures and vice versa.
Overview of Concepts
The new SNL will still be a programming language in its own right. It will still be based on the notions of "state" and "state set"; it will still support a subset of C for "normal" imperative programming (statements, if/then/else, assignment, etc.).
However, we introduce a new view on the concepts of "state set" and "state". A state set is regarded as a (special form of) closure resp. object.
- State sets can be asynchronously "spawned" to run as an independent task. But they can also be synchronously "called", like a normal procedure, where the caller stops and waits for the state set to return.
- State sets can receive arguments on creation. In the OO view, this corresponds to constructor arguments.
- State sets can also return a value. Returning from a state set always destroys the underlying state set object. If a value was returned and the state set was created with a "call", the caller receives this value. Otherwise the returned value is lost.
- State sets can have local variables. These are not visible from the outside.
- Individual states in a state set can also have local variables, as well as parameters. Both are not visible outside the state. The general syntax for a state change is state state_name(arg,...);.
- The lifetime of asynchronously (via spawn) created state sets is always limited to the enclosing block. For state sets created at the top-level, this means forever (or rather as long as the underlying task doesn't get killed).
- Waiting on a condition to become true is done with the traditional when-clause. However, the clause does determine a new state. Instead 'state x;' is treated like an ordinary SNL action statement and can be used freely inside a when-block.
Creation of State Sets
There are two ways to specify creation and execution of a state set:
- Synchronous
- call state_set_class_name(arg1, arg2, ...)
- An object of the given state set class is created with the given parameters and started. The calling state set waits (blocks execution) until the called state set returns. A state set can stop execution at any time, returning any number of values back to the caller, with a return(ret1, ret2, ...); statement.
- Asynchronous
- spawn state_set_class_name(arg1, arg2, ...)
- An object of the given state set class is created with the given parameters and started. The calling state set does not block execution and cannot receive any return values. Instead spawn returns a handle to the newly created state set.
In the old SNL, a state set declaration implied creation of a global top-level state set object. This is no longer the case. Instead, state set objects must be explicitly created at the top-level. If a top-level state set is supposed to run permanently, it must be created with a spawn statement.
A side-effect of this is that the programmer has control over the sequence of initialization.
Access from the Outside
Each SNL program will be presented to the outside world as a Data Access property catalog. Available properties include diagnostics such as the number of connected/available member variables (if assigned to a PV), a list of all global variables assigned to PVs, and all existing (life) state set objects as subproperties. Properties of a state set include the current state (including the state's parameters), and member variables.
PVs
We are currently evaluating the idea to introduce a special data type to represent references to PVs. This would replace how PVs are handled now (i.e. with assign, monitor, etc).
Syntax
to be continued
Implementation
We think that the implementation could be quite similar to the current one.
to be continued