S-SCXML Web Laboratory

S-SCXML Web Laboratory is a web interface to an implementation of a simplified version of State Chart XML (SCXML). You may want to start by looking at something which is more in the spirit of the January Draft, namely SCXML Web Laboratory, and then return here to study our change proposals.

Synergy S-SCXML v. 0.5.1

Based on our experiences trying to implement the current draft we would like to propose a number of changes to SCXML. We think they would make SCXML simpler and more intuitive to use, as well as easier to implement.

Proposed syntax changes

  1. Remove <initial> and introduce a new (optional) attribute 'target' (with value of type namelist) for <state>. Make 'target' incompatible with 'final'.
  2. Allow a mixture of <state> and <parallel> as children of <state> and <parallel>. Also, allow <transition> as children of <parallel>.
  3. Treat <scxml> as a variant of <state>, allowed only on the toplevel. That is, use (optional) 'target' instead of 'initialstate', allow 'final', etc..
  4. Use the 'target' attribute for <history> as well.

As a consequence of 1)

<state id="s0">
    <initial>
        <transition target="s1" >
    </initial>
    <state id="s1" ... />
    <state id="s2" ... />
<state>

can be written as

<state id="s0" target="s1">
    <state id="s1" ... />
    <state id="s2" ... />
<state>

As a consequence of 2)

<state id="s0" target="s1">
    <state id="s1" ... />
    <state id="s2">
        <parallel ... />
    </state>
<state>

can be replaced with

<state id="s0" target="s1">
    <state id="s1" ... />
    <parallel ... />
<state>

As a consequence of 3), the Hello world example can now be written as

<?xml version="1.0"?>
<scxml version="1.0" final="true">
    <onentry>
        <log expr="'Hello world'"/>
    </onentry>
<scxml>

In the current implementation, a source to source (or rather DOM to DOM) transformation takes place, transforming the above to

<state id="main" final="true">
    <onentry>
        <log expr="'Hello world'"/>
    </onentry>
    <transition event="error.*">
        <exit/>
    </transition>
<state>

That is...

  1. The element changes names from <scxml> to <state> and the <scxml>-specific attributes are removed.
  2. The <state> is given an attribute 'id' (value "main" by default).
  3. An implicit transition over the event error.* is inserted as the last child of the state element. Note that this also means that it is possible to tailor e.g. error handling further, by inserting other transitions as children of the scxml element.

This also has consequences for how the 'src' attribute of <state> and <parallel> is handled. If the file "hello.scxml" contains

<?xml version="1.0"?>
<scxml version="1.0" final="true">
    <onentry>
        <log expr="'Hello world'"/>
    </onentry>
<scxml>

then

...
<state id="s1" src="hello.scxml"/>
...

is transformed into

...
<state id="s1" final="true">
    <onentry>
        <log expr="'Hello world'"/>
    </onentry>
<state>
...

Proposed semantics changes

Generation of completion events

Note: This may not be a change proposal proper. The January draft is a bit vague when it comes to the generation of completion events. What I propose here may be exactly what they meant!

In Synergy SCXML, completion events of the form ID.done are generated for

  1. final states
  2. parallel states (AND-states)
  3. sequential states (OR-states)

Note that completion events are not generated for states that are neither final, parallel or sequential.

The completion events of children are used to detect when the completion events of their parents should be generated.

A completion event of the form ID.done is generated

  1. upon entry into a final state SID
  2. when a parallel state SID has children SID1,..,SIDn and ID1.done,..,IDn.done have been generated
  3. when a sequential state SID has children SID1,..,SIDn and IDi.done has been generated

That is:

  1. A final state has completed upon entry, when its onentry handlers have executed
  2. A parallel state has completed when all its children states have completed
  3. A sequential state has completed when any of its children states has completed

An scxml process completes (terminates) when any of the toplevel states (children of <scxml>) generates a completion event.

A perhaps surprising consequence of this semantics is that the following scxml does not reach the state named "Final".

<scxml xmlns="http://www.w3.org/2005/07/SCXML"
       version="1.0"
       target="S">
    <state id="S" target="S1">
        <state id="S1" final="true"/>
        <transition event="S1.done" target="Final"/>
    </state>
    <state id="Final" final="true"/>
</scxml>

The events generated for this example are

S1.done
S.done
main.done

and the trace looks like so:

main:<s> ==> S:<s>
S:<s> ==> S1:<s>(final)

However, the following scxml does reach "Final":

<scxml xmlns="http://www.w3.org/2005/07/SCXML"
       version="1.0"
       target="P">
    <parallel id="P">
        <state id="S1" final="true"/>
        <state id="S2">
            <transition event="S1.done" target="Final"/>
        </state>
    </parallel>
    <state id="Final" final="true"/>
</scxml>

Here the generated events are

S1.done
Final.done
main.done

and the trace:

main:<s> ==> P:<p>
P:<p> ==> S1:<s>(final)
P:<p> ==> S2:<s>
S2:<s> = [S1.done] => Final:<s>(final)

The morale, and fortunately rather simple rule-of-thumb, is that if you want a state to listen to the *.done event of another state, then these states need to run in parallel, i.e. they have to be active at the same time.

Another way to implement (what is presumably) the intended behavior is to listen for a user defined 'done event' rather than the system generated one. Like so:

<scxml xmlns="http://www.w3.org/2005/07/SCXML"
       version="1.0"
       target="S">
    <state id="S" target="S1">
        <state id="S1">
            <onentry>
                <send event="S1.mydone"/>
            </onentry>
        </state>
        <transition event="S1.mydone" target="Final"/>
    </state>
    <state id="Final" final="true"/>
</scxml>

This works like a charm, placing the following events in the queue:

S1.mydone
send.successful
Final.done
main.done

and taking the following route through the chart:

main:<s> ==> S:<s>
S:<s> ==> S1:<s>
S1:<s> = [S1.mydone] => Final:<s>(final)

Finally, note that there is an example in the January draft section F.1 where a state tries to listen to its own *.done event. That won't work under the proposed semantics either, for the reasons stated above. Here's the significant part of this example:

<!-- Really simple state showing the basic syntax. -->
<state id="Test1">
  <initial>
    <transition target="Test1Sub1"/>
  </initial>
  <!-- Runs before we go into the substate -->
  <onentry>
    <log expr="'Inside Test1'"/>
  </onentry>
  <!-- Here is our first substate -->
  <state id="Test1Sub1">
    <onentry>
      <log expr="'Inside Test1Sub1.'"/>
    </onentry>
    <onexit>
      <log expr="'Leaving Test1Sub1'"/>
    </onexit>
    <!-- Go to Sub2 on Event1 -->
    <transition event="Event1" target="Test1Sub2"/>
  </state>
  <!-- Here is the second substate
       -    It is final, so Test1 is done when we get here -->
  <state id="Test1Sub2" final="true">
    <onentry>
      <log expr="'Inside Test1Sub2...'"/>
    </onentry>
    <onexit>
      <log expr="'Leaving Test1Sub2'"/>
    </onexit>
  </state>
  <!-- We get this event when we reach Test1Sub2. -->
  <transition event="Test1.done" target="Test2"/>
   <!-- We run this on the way out of Test1 -->
  <onexit>
    <log expr="'Leaving Test1...'"/>
  </onexit>
</state>

Changes

Acknowledgements

Torbjörn Lager wrote this particular version, based on discussions with Fredrik Kronlid and based on a previous version written by Fredrik Kronlid and Torbjörn Lager.

Availability

The source code will be made available as soon as we've cleaned it up a bit.

Contact

We'll appreciate your feedback! Please write to the Synergy Team.

eXTReMe Tracker