Lua logo

Preface

This is the reference manual of MoonSC, which is a Lua execution environment for Harel statecharts, following the State Chart XML (SCXML) recommendation. [1]

It is assumed that the reader is familiar with both SCXML and the Lua programming language.

For convenience of reference, this document contains external (deep) links to the Lua Reference Manual and to the SCXML Recommendation.

Getting and installing

For installation intructions, refer to the README file in the MoonSC official repository on GitHub.

Module organization

The MoonSC module is loaded using Lua’s require() and returns a table containing the functions it provides (as usual with Lua modules). This manual assumes that such table is named moonsc, i.e. that it is loaded with:

 moonsc = require("moonsc")

but nothing forbids the use of a different name.

Examples

Complete examples can be found in the examples/ directory of the release package.

License

MoonSC is released under the MIT/X11 license (same as Lua, and with the same only requirement to give proper credits to the original author). The copyright notice is in the LICENSE file in the base directory of the official repository on GitHub.

See also

MoonSC is part of MoonLibs, a collection of Lua libraries for graphics and audio programming.

Overview

A MoonSC application executes one or more concurrent SCXML sessions each defined by a SCXML statechart, as shown in the sketched example below:

MoonSC application (sketch)
 local moonsc = require("moonsc")
 -- ...
 -- Optionally set callbacks to control the execution:
 moonsc.set_log_callback(mylogfunc)
 -- ...
 -- Create and start any initial session:
 moonsc.create('mysessionid', mystatechart)
 moonsc.start('mysessionid')
 -- ...
 -- Enter the main loop:
 while moonsc.trigger() do
   -- ...
 end

The application code first sets a few callbacks to control some aspects of the execution (e.g. logs, event routing, invocations), then it creates and starts any initial session, and finally it enters its main loop, from which at each iteration it is expected to call the trigger( ) function that executes any enabled transitions in the sessions that are running.

Any session running in the application is created by the application itself using the create( ) function, passing it an unique session identifier, the statechart defining the session’s behavior, and possibly a set of parameters in case the session is created because of the execution of an <invoke> element in an already existing session (the 'parent session').

When created, a session is by default still not running. It can be started either by passing start=true when creating it, or later by calling the start( ) function.

The statechart is passed in form of a Lua table equivalent to an SCXML document, as described in the 'Statecharts' section. A statechart in this form may be either written directly in Lua or produced as a result of parsing an actual SCXML document [2]. The same statechart can be used to execute multiple sessions, i.e. one or more independent instances of the same state machine, either concurrently running or otherwise.

Each session has a dedicated Lua environment (_ENV), that represents its Data Model and provides it with encapsulation. The 'lua' Data Model is the only data model supported by MoonSC. Any chunk of Lua code contained in the statechart’s elements (cond, expr, <script>, etc) is executed in the session’s dedicated environment. System variables as per the SCXML recommendation and any <data> variables are also defined there as global variables.

The application and sessions communicate with each other by standard means, i.e. via SCXML events as described in the 'Events' section.

Statecharts

An SCXML element is represented in MoonSC by a Lua table having the format shown below. A statechart is just the Lua-table representation of an element of the <scxml> type (i.e. having element.tag="scxml").

Lua-table representation of a SCXML element
 element = {}
 element.tag  -- the SCXML tag (a string, e.g. _'scxml'_, _'state'_, etc.)
 element.xxx  -- the value of the attribute named 'xxx' (a string),
 element.yyy  -- the value of the attribute named 'yyy' (a string),
 -- ...
 element[1]   -- 1-st SCXML child element, in document order (a table),
 element[2]   -- 2-nd SCXML child element, in document order (a table),
 -- ...
 element[N]   -- N-th SCXML child element, in document order (a table),
 element.text -- embedded text and/or markup content (a string).

The rules dictated by the SCXML recommendation apply to their Lua-table equivalent as well, specifying which attributes an element may have and their admitted values, which types of children it may have and how many, and so on, with a few caveats (see 'Elements' for more details).

To enhance expressivity, MoonSC provides for each element a element constructor, which is a function that takes a table as parameter and simply adds to it the element’s tag field. Table constructors can be imported using the following function:

  • import_tags([t])
    Adds the element constructors to the table t, which defaults to the current _ENV (this implies that calling this function with no arguments has the effect of defining the constructors as global functions in the current environment). For each generic SCXML element <tag>, its element constructor is a function named _tag( ) with the leading underscore (e.g. _state( ) for <state>, _parallel( ) for <parallel>, and so on).

The examples below shows a simple SCXML statechart and its representation in MoonSC, first with the tags added manually, and then using element constructors:

A simple SCXML statechart
 <scxml version="1.0" name="Hello" initial="s1">
   <state id="s1">
     <transition event="go" target="s2">
       <log expr="'Hello, World!'" />
     </transition>
   </state>
   <final id="s2">
   </final>
 </scxml>
Lua-table representation
 local moonsc = require("moonsc")

 local helloworld = {
    tag='scxml', version="1.0", name="Hello", initial="s1",
    { tag='state', id = "s1",
      { tag='transition', event="go", target="s2",
         { tag="log", expr="'Hello, World!'" },
      },
    },
    { tag='final', id="s2" },
 }
Lua-table representation using constructors
 local moonsc = require("moonsc")
 moonsc.import_tags() -- adds the element constructors to this environment

 local helloworld = _scxml{ version="1.0", name="Hello", initial="s1",
    _state{ id="s1",
       _transition{ event="go", target="s2", _log{ expr="'Hello, World!'" } },
    },
    _final{ id="s2" },
 }

Note that since constructors accept a table as single parameter, the parentheses can be omitted.

Also note that the statechart need not be constructed in one single shot, by defining all the nested elements in-line. That is, the Lua-table representation allows for composability and possibly reuse of elements definitions, as shown in the following (equivalent) re-elaboration of the previous example:

Composability of Lua-table representations
 local moonsc = require("moonsc")
 moonsc.import_tags() -- adds the element constructors to this environment

 -- This could be reused at different points in the statechart,
 -- and also in other statecharts:
 local salute = _log{ expr="'Hello, World!'" }
 local s1 = _state{ id="s1", _transition{ event="go", target="s2", salute } }
 local s2 = _final{ id="s2" }
 local helloworld = _scxml{ version="1.0", name="Hello", initial="s1", s1, s2 }

Sessions

An SCXML session is an executable instance of an SCXML statechart.

A MoonSC application is capable of running multiple concurrent sessions, which it creates and starts with the create( ) and the start( ) functions. The application may create sessions at any time, on its own initiative, or to serve requests from other entities (other sessions, or whatever).

When creating a session, the application must assign it a session identifier (sessionid). This is a NMTOKEN string that is required to univoquely identify the session within those currently being executed by the application itself. The application designer may use whatever scheme she likes to assign session identifiers, or just use the generate_sessionid( ) function. [3]

After it is started, a session evolves as defined by its statechart, transitioning between its states in reaction to events or triggering conditions, and executing the actions contained in any enabled transition. The application controls the execution of transitions via the trigger( ) function, which it is expected to call repeatedly in its main loop. Transitions are executed only within calls of this function. [4]

A session terminates when it reaches a top-level <final> state, or when it is cancelled by the application with cancel( ), e.g. upon a cancellation request from the parent session because it exited the state containing the <invoke>. When it terminates, it is deleted from the internal database of sessions.

The application can track the termination of sessions by setting the 'exit callback', and by setting the 'error callback' it can also track errors of execution or communication.

  • create(sessionid, statechart, start, [invokeinfo])
    Creates a new SCXML session and possibly starts its execution.
    sessionid: the session identifier for this session (a string).
    statechart: the root <scxml> element defining the session’s behavior,
    start: if true, also starts the execution of the session,
    invokeinfo: <invoke > information, in case this session is requested by another entity.

  • start(sessionid)
    Starts the execution of the given session. If the session is already running, a call of this function has no effects. Note that any event sent to the session while not running is still delivered to it, but it is not processed until the session is started.

  • sessionid = generate_sessionid( )
    Returns a new sessionid that is not currently used in the application.

  • cancel(sessionid)
    Cancels the session, stopping it (if running) and deleting it from the internal database. If the session is not running it is deleted immediately, otherwise it is sent a special 'external' event that causes it to exit without triggering any transition (note that this implies that the session is actually cancelled only when this special event is processed, after any other event that was already enqueued).

  • tnext = trigger( )
    Executes an iteration of the SCXML algorithm’s main loop for each session that is currently running in the system. Statecharts' transitions are executed only within calls of this function, that the application is expected to call repeatedly, e.g. at each iteration of its own main loop.
    Returns nil if there are no more sessions running in the system, otherwise returns the next time at which this function needs to be called, unless in the meanwhile other events are sent to any session with send( ) and raise( ) or other sessions are created, in which case this function should be called immediately after. The tnext time value is on the same time base of the values returned by the now( ) function.
    Note: This function is executed in protected mode. This means that the application does not exit if an error occurs during its execution. Instead, an error event is sent back to the session where the error occurred (if the SCXML Recommendation says so) and the 'error callback' is called (if set).

  • {stateid} = active_states(sessionid)
    Returns the current state configuration for the given session, i.e. the list of ids of the currently active states (in document order). The root <scxml> is not included in the list, although it is implicitly always active.

  • boolean = is_active(sessionid, stateid)
    Returns true if the state whose id is stateid is currently active in the given session, otherwise returns false.

  • env = get_env(sessionid)
    Returns the Lua environment (_ENV) dedicated to the session, or nil if the session doesn’t exist (or doesn' exist anymore).

Events

The application and the running sessions communicate with each other via SCXML events.

Sessions receive events as part of the standard transition triggering mechanism, and, by executing <send> and <raise> elements they may send events to other sessions, to external entities (through the application), or to themselves.

The application can send( ) external events to sessions, it can raise( ) internal or platform events in them, and by setting the 'send callback' it can receive any session-originated <send> that MoonSC does not know how (or if) to route.

MoonSC by itself directly supports only the SCXML Event I/O Processor, and is able to route automatically only events exchanged by local sessions using <send> elements having 'type'="scxml", and the special 'target' attributes prescribed by the SCXML Recommendation ('#_internal', '#_scxml_sessionid', '#_parent', and '#_invokeid').

Any <send> issued by a local session having a 'type' different than "scxml" or a 'target' that is not a special one (or that is not recognized as targeting a local session), causes MoonSC to call the 'send callback' and delegate to the application the routing of the message.

  • send(sessionid, eventinfo)
    send(sessionid, name, [data])
    Sends an event to the given session, by inserting it in the session’s external or internal event queue, depending on the value of eventinfo.type. The second version of this function inserts an 'external' event with the given name (a string) and optional data in the external event queue.

  • raise(sessionid, eventinfo)
    raise(sessionid, name, [data])
    Raises an event in the given session, by inserting it in the session’s internal queue. The second version of this function inserts a 'platform' event with the given name (a string) and optional data in the external event queue.

Data Model

MoonSC supports a Data Model based on the Lua language (version >= 5.3), by assigning to each SCXML session a dedicated Lua environment (_ENV) where to define data and execute content. The dedicated _ENV is customizable by providing a template via the set_env_template( ) function.

MoonSC assumes that the "lua" value for the 'datamodel' attribute in the <scxml> element refers to this Data Model, and assumes this same value as the default if the 'datamodel' attribute is omitted.

The Lua Data Model is described here, loosely following the specification given in appendix B.2 of the SCXML Recommendation for the ECMAScript Data Model.

  1. <datamodel>, <data> - For each <data> element in the statechart, MoonSC creates in _ENV a global variable whose name is the value of the 'id' attribute of <data>. By default, the variable is assigned the nil value. If the <data> element has a 'expr' attribute, the Lua chunk "return "..expr is executed in _ENV and the returned value is assigned to the variable. Otherwise if the <data> element has a 'src' attribute, or contains an inline specification, the 'data callback' is called to resolve it and the returned value is assigned to the variable. The evaluation and assignment take place at the time indicated by the 'binding' attribute on the <scxml> element.

  2. Scoping - All <data> elements are defined as global variables in the _ENV dedicated to the session, and thus are accessible from any state. <data> elements are guaranteed to be created in document order only if they are children of the same <datamodel> element, otherwise they are not. When early binding is selected, all <data> elements are created and bound to their values at initialization time. When late binding is selected, <data> elements are created at initialization time but bound to their values only when the state containing them is first entered.

  3. Conditional expressions - Conditional expressions are executed as "return "..cond in the _ENV, and their returned value is interpreted as a boolean value using Lua standard rules on the matter (false and nil are falsy, true and any other value are truthy).

  4. In( ) predicate - The In(stateid) predicate is predefined as a global function in the dedicated _ENV. It returns true if the state having the passed id is active, otherwise it returns false.

  5. Location expressions - Any Lua left-hand-side expression is accepted as location expression.

  6. Value expressions - Any Lua expression is accepted as value expression.

  7. <content> - If a <content> element has a 'expr' attribute, the Lua chunk "return "..expr is executed in _ENV and the returned value is used as the content value. Otherwise if the <content> element contains inline text, the 'content callback' is called to resolve it and the returned value is used as the content value. In both cases the evaluation is done at the time the <content> element is executed.

  8. <assign> - When an <assign> element is executed, the 'expr' or inline content are treated in the same way as for <data> elements (see point 1), and the obtained value is assigned to the global variable (in _ENV) specified by the 'location' attribute.

  9. System variables - MoonSC defines a Lua global variable in the session’s dedicated _ENV for each variable defined in section 5.10 of the SCML Recommendation. Such variables are to be intended as read-only by the statechart code authors and care should be taken not to overwrite them. See the System Variables section for more details.

  10. Serialization - The serialization of events to/from other message formats in order to communicate with remote entities is a concern of the application and outside the scope of MoonSC.

  11. <script> - If a <script> element has a 'src' attribute, this is resolved by calling the 'script callback' and interpreting the returned value (a string) as Lua code. Otherwise if it has textual content, this is interpreted as the Lua code for the script. In both cases, the execution of the <script> element causes the Lua code to be executed in the sessions’s _ENV.

  12. <foreach> - A <foreach> element is executed in the _ENV iterating with the standard Lua pairs( ) function, over a shallow copy of the value returned by evaluating the 'array' attribute (that thus must result in a Lua table).

  13. <log> - When a <log> element is executed, its attributes are evaluated and passed to the 'log callback', together with the session identifier. If the log callback is not set, no action is taken. The 'expr' attribute is evaluated in the same way as for the <data> element (see point 1). The nil value is passed to the callback for any omitted attribute.

  14. time intervals - The 'delay' attribute in <send> elements may be either a string composed by a number immediately followed by a 's' (for seconds) or 'ms' (for milliseconds), or simply as a number, in which case it is interpreted as seconds.

  15. Now( ) and Since( ) - The Now() and Since() functions are predefined on the dedicated _ENV to give to statecharts access to the MoonSC now( ) and since( ) functions (note that these functions are platform-specific, i.e. they are not dictated by the SCXML Recommendation).

Callbacks

MoonSC virtually supports all SCXML elements, although for some of them (or for some of their attributes) it needs assistance from the application and requires it via the callbacks described in this section. [5] A few callbacks are also provided to track the execution of the sessions and detect errors without the need of adding guards and logs in their statecharts using standard SCXML elements (this is useful expecially when developing and debugging statecharts).

Callbacks are optional, and set with the functions listed below. Each of them, when called with a nil or omitted func argument, unsets the corresponding callback (if it was previously set).

Note that all callbacks that are expected to fetch values must return them synchronously, thus they block the execution of all running sessions for the whole duration of the fetch operation (this may be a problem if the data has to be fetched over a network and the application is running multiple concurrent sessions).

Also note that callbacks are usually executed within calls of the trigger( ) function, so they are protected calls [6] This means that any error occurring in them - either an unintentional bug or an intentional call of standard Lua assert( ) or error( ) - will not cause the application to exit but will instead result in an error event being sent to the session being executed.

  • set_log_callback(func)
    Registers the function func as the 'log callback', which is called as func(sessionid, label, expr) each time a <log> element is executed in the session identified by sessionid. The label argument is the value of the 'label' attribute (or nil, if omitted), while expr is the value resulting from evaluating the 'expr' attribute in the session’s dedicated _ENV (or nil, if omitted). If the callback is not set, no action is taken when a <log> element is executed.

  • set_script_callback(func)
    Registers the function func as the 'script callback', which is called as code=func(src) each time a <script> element is initialized, if it has a 'src' attribute. In this case the callback is called passing it the src value (a string containing an URI) and is expected to fetch and return the corresponding script (a string containing valid Lua code), or nil if it is unable to do so.

  • set_data_callback(func)
    Registers the function func as the 'data callback', which is called as value=func(text, src) each time a <data> or <assign> element having a 'src' attribute or inline data specification is executed. The callback is expected to fetch and return the data value corresponding to the passed text or src argument, or return nil if it is unable to do it. The text argument, if not nil, is the inner content of the <data> or <assign> element being executed (a string that should contain inline data specification, possibly markup). The src argument, if not nil, is the value of the 'src' attribute of the element (a string containing a URI). Only one of text and src is not nil.

  • set_content_callback(func)
    Registers the function func as the 'content callback', which is called as value=func(text) each time a <content> element having inline specification is executed. The callback is expected to fetch and return the content value corresponding to the passed text argument (a string that should contain inline specification, possibly markup), or return nil if it is unable to do it.

  • set_send_callback(func)
    Registers the function func as the 'send callback', which is called as success=_func(sendinfo) each time a <send> element with a valid 'type' is executed that MoonSC does not know how to route.
    The callback receives as argument a sendinfo table with information from the <send> element, and is expected to route the message. The destination of the message may be either a local session or a remote entity. In the former case the application must translate the sendinfo to a eventinfo and send( ) the event to the destination session. In the latter case it must serialize the message properly and send it to the destination by appropriate means.
    If the routing succeeds, the callback must return true. If it fails, the callback may either return false (or nil) or raise a Lua error, causing an 'error.communication' or an 'error.execution' (respectively) to be sent back to the sender session.
    Note: the 'send callback' is called for a <send> element only if its 'type' attribute has a value for which an entry exists in the _ioprocessors system variable. If not, an error event is sent back to the sender session, signalling that the I/O processor type is not supported. To add an entry, use the add_ioprocessor( ) function.

  • set_invoke_callback(func)
    Registers the function func as the 'invoke callback', which is called as childid=func(invokeinfo) each time a <invoke> element is executed.
    The callback receives as argument a invokeinfo table with information from the <invoke> element, and is expected to invoke the requested service.
    The service may be provided either by a new local session or by a remote entity. If the service provider is a local session, the callback is expected to create it with create( ) passing it the invokeinfo, and return the sessionid assigned to it (MoonSC will use this to automatically route events generated with <send> of the 'scxml' type). If the service provider is remote, the callback is expected to deliver the request to it in the appropriate format and by appropriate means, and return nil (in this case the application is also in charge of properly routing any message subsequently exchanged by the parent session and the invoked service, which it can do with the 'send callback' and the send( ) function).

  • set_cancel_callback(func)
    Registers the function func as the 'cancel callback', which is called as func(invokeinfo, childid) each time a <invoke> element is cancelled due to its containing state being exited while the invocation is still ongoing.
    The callback receives as argument the same invokeinfo that was passed to the 'invoke callback', and the childid returned by it (if any), and it is expected to cancel( ) the child, if it is a local session, or to signal the need for cancellation to the remote service provider.

  • set_exit_callback(func)
    Registers the function func as the 'exit callback', which is called as func(sessionid, reason, invokeinfo) when a session exits. The reason argument is a string that may be either 'done' (normal exit) or 'cancelled' (session cancelled via the cancel( ) function), and invokeinfo argument is the value passed at session creation via create( ).

  • set_error_callback(func)
    Registers the function func as the 'exit callback', which is called as func(sessionid, name, errmsg) when an execution or communication error occurs during the execution of an SCXML element in a running session. The name argument is either 'error.execution' or 'error.communication', and errmsg is a message indicating the occurred error and the offending element. (Note that by default MoonSC is robust with respect to these kind of errors, i.e. when an error occurs in a session it just raises an error event and continues the execution as dictated by the SCXML Recommendation. By setting this callback, the application may additionally track these errors and possibly exit as soon as one is detected).

The following callbacks are added mainly as an aid to debug and visualization tools. They are not expected to affect the execution of the sessions (except for slowing them down, since callbacks are time-consuming):

  • set_trace_callback(func)
    Registers the function func as the 'trace callback', which is called as func(sessionid, message) when something of interest happens during the execution of a running session (e.g. a change of state configuration). Mainly for debug and test purposes.

  • set_event_callback(func)
    Registers the function func as the 'event callback', which is called as func(sessionid, eventinfo) when an event is about to be processed. The eventinfo argument may be nil, meaning the 'null event'.

  • set_transition_callback(func)
    Registers the function func as the 'transition callback', which is called as func(sessionid, source, event, cond, target) when a transition is about to be taken. The source argument is the id of the source state, while the event, cond, and target arguments are the values of the corresponding attributes in the <transition> element being executed.

  • set_exit_states_callback(func)
    Registers the function func as the 'exit states callback', which is called as func(sessionid, states) when a set of states is about to be exited. The states argument is a table containing the ids of the states, in exit order.

  • set_enter_states_callback(func)
    Registers the function func as the 'enter states callback', which is called as func(sessionid, states) when a set of states is about to be entered. The states argument is a table containing the ids of the states, in entry order.

Additional utilities

  • set_env_template(env)
    Sets the template for the Lua environments dedicated to sessions (e.g. for sandboxing).
    By default, the template environment is a shallow copy of the main environment (_ENV) as it is when the MoonSC module is loaded with require().

  • timestamp = now( )
    Returns the current system time, in seconds. The system time is relative to an unspecified point in the past, that depends on the underlying function used to retrieve time from the operating system.
    Session can access this same function from their dedicated _ENV, where it is global and defined as Now( ).

  • dt = since(timestamp)
    Returns the time elapsed from the point in time given by timestamp.
    Session can access this same function from their dedicated _ENV, where it is global and defined as Since( ).

  • sleep(seconds)
    Sleeps for the given amount of seconds (returns immediately if seconds is less than or equal to zero).

  • string = tostring(sessionid)
    Returns a printable description of the statechart for the session identified by sessionid, with all its elements arranged in a tree, and their attributes and values.

System variables

The following system variables are defined as global variables in each session’s dedicated _ENV:

  • _sessionid: the session identifier (a string).

  • _name: the value of the 'name' attribute n the root <scxml> element (a string, or nil).

  • _event: the event being processed (a eventinfo table, or nil when no event is being processed).

  • _ioprocessors: a table, with an entry for each supported I/O Processor type (indexed by the type string), containing related information. By default contains only an entry for the "scxml" value (SCXML I/O Processors). Other entries can be added using the add_ioprocessor( ))function.

  • _x: a table, for platform-dependent system variables.

The following are defined only if the session is a 'child session', i.e. created by passing a non-nil invokeinfo argument to the create( ) function:

  • _invokeid: the invokeid assigned to this session by the parent (a string).

  • _x.invokeinfo: the invokeinfo passed at the creation of the session.

The following function can be used to add entries to the _ioprocessors variable for processors other than the default SCXML I/O Processor (type="scxml"):

  • add_ioprocessor(type, location, [info])
    Adds to the _ioprocessors system variable the entry for the I/O Processor of the given type (a string). The location parameter will be used as value for the entry[type].location field. The optional info parameter, is a table whose fields will be shallow-copied with the same names in the entry[type] table.

Note: all the system variables are intended to be read-only, but MoonSC does little to enforce this rule (it just checks that they are not used as 'location' attributes) so it is up to the authors of the statecharts to take care not to alter or erase them.

Elements

For reference, below is the list of SCXML elements, with links to the relevant sections in the SCXML Recommendation.

All elements are supported, with a few caveats:

  • MoonSC ignores any attribute whose name it does not recognize for the given element type.

  • In the root <scxml> element, the 'xmlns' attribute is not supported, the 'version' attribute is optional and defaults to "1.0", and the 'datamodel' attribute defaults to "lua", which is the only admitted value (the "lua" datamodel is described in the Data Model section of this document).

  • A 'text' attribute, which doesn’t exist in pure SCXML elements, is added in their Lua-table form to contain any embedded textual or markup content. The 'text' attribute may occur in <script>, <data>, <assign>, and <content> elements.

  • The only value recognized for the <send>.type attribute is "scxml", short form for "http://www.w3.org/TR/scxml/#SCXMLEventProcessor", that is not recognized. Any other value is either handled via callbacks (see below) or causes an error event.

  • The only value recognized for the <invoke>.type attribute is "scxml" (short form for "http://www.w3.org/TR/scxml/", that is not recognized). Any other value is either handled via callbacks (see below) or causes an error event.

  • Assistance is required from the application (via callbacks) to fully support the following elements or attributes:

    • The <log> element requires assistance via the 'log callback'.

    • The <data>.src, <data>.text, and <assign>.text attributes require assistance via the 'data callback'.

    • The <content>.text attribute requires assistance via the 'content callback'.

    • The <script>.src attribute requires assistance via the 'script callback'.

    • The <invoke> element requires assistance via the 'invoke callback' and possibly the 'cancel callback'.

    • The <send> element requires assistance via the 'send callback' to support I/O Processors other than "scxml", or targets other that the special ones, or remote destinations.

Structs

  • eventinfo = {
    type: 'external' | 'internal' | 'platform',
    name: event name (a string),
    sendid: id assigned by sender (a string, opt.),
    origin: URI to be used as <send>.target in replies (a string, opt.),
    origintype: I/O processor to be used as <send>.type in replies (a string, opt.),
    invokeid: the invokeid assigned by the parent session (a string, only in child-to-parent messages),
    data: the contained data (opt.),
    } (rfr. 5.10.1 The Internal Structure of Events)

  • sendinfo = {
    sourceid: the sessionid of the sending session (a string),
    type: the value of 'type', or resulting from evaluating 'typeexpr' (a string),
    target: the value of 'target', or resulting from evaluating 'targetexpr' (a string, opt.),
    event: the value of 'event', or resulting from evaluating 'eventexpr' (a string, opt.),
    sendid: the 'id' of the send (opt.),
    data: the contained data (opt.),
    } (rfr. 6.2 <send>)

  • invokeinfo = {
    parentid: the sessionid of the parent session, if local (a string, opt.),
    invokeid: the 'id' assigned by the parent session (a string, opt.),
    type: the value of 'type', or resulting from evaluating 'typeexpr' (a string),
    autoforward: the value of 'autoforward' (a boolean),
    src: the value of 'src', or resulting from evaluating 'srcexpr' (a string, opt.),
    data: the contained data (opt.),
    } (rfr. 6.4 <invoke>)

  • data = a table with name-value pairs (data[name]=value).
    When used to represent the data contained in a <send> or <invoke> element, the data table may contain the name-value pair for the 'content' attribute (data.content, a string) and/or all those for the names in the 'namelist' attribute and for the variables in any <param> children. In case of duplicate names, the last encountered value is used ('content' is evaluated before 'namelist', which is evaluated before <param> children, which are evaluated in document order, so the last <param> wins).

Note: all these 'structs' (tables, actually) are passed around by reference, so care must be taken not to alter a struct after having passed it - e.g. a data table after having passed it to the send( ) function - nor to alter a struct received as argument - e.g. the invokeinfo table received as argument in the 'invoke callback'.


1. This manual is written in AsciiDoc, rendered with AsciiDoctor and a CSS from the AsciiDoctor Stylesheet Factory.
2. The parsing of actual SCXML documents to produce statecharts in form of Lua tables is outside the scope of MoonSC and, if needed, delegated to external tools.
3. MoonSC does not assign session ids automatically by default, because the designer may want to cluster the sessions running in different OS processes into a single set of 'local' sessions, having ids unique in the same domain (or, to put it in another way, she may want to execute local sessions in different OS processes, e.g. to run them in parallel). By having control on the assignment of session ids, she can ensure that those of sessions running in different processes do not collide.
4. A call of the trigger( ) function executes, for every running session, an iteration of the main loop of the SCXML algorithm.
5. In particular, by design MoonSC does not create new sessions autonomously, it does not support any I/O processor other than the SCXML Event I/O Processor, it does not have built-in networking capabilities, and it doesn’t understand markup other than SCXML in its Lua-table equivalent representation. So, any time a service is invoked by a running session, or an event has to be routed to a remote destination, or a value must be retrieved from an URI, or some markup content must be interpreted, MoonSC invokes the intervention of the application via a callback.
6. The exception being the case of callbacks called at initialization time, when the create( ) function is called outside the trigger( ) function (for example, when the application creates an initial session before entering the main loop).