An IDL for SCXML interpreters

Hey there,

[explicitly bcc'ing David, Jacob and Zjnue for I know that they maintain SCXML implementations] - this post is pertaining to action point 1 from my previous mail:

1. An Interface Description Language (IDL) for SCXML interpreters.
1.1 For simple life-cycle and interpretation of state-charts.
1.2 A set of hooks for (on-line) visualisation.
1.3 A set of hooks for (on-line) modelling / debugging.

For now, I'd like to focus on point 1.1, but we ought to keep the others in mind and maybe eventually extend our ambitions. At least 1.2 is very useful as it would allow or a common visualisation. I hereby propose a first sketch for an Interface Description Language (IDL) for SCXML (see below). It will only allow to instantiate interpreters, run them and deliver events. A typical session would look like this:

import namespace scxml;
try {
Interpreter session = Implementation.fromURI("http://www.example.com/foo.scxml");
for(;;) {
int state = session.step();
if (state == FINISHED)
break;
if (state == AFTER_MACROSTEP && session.configuration.in('foo'))
session.receive('bar.baz');
}
} catch (Exception e) {
print e;
}

A couple of notes and possible variations:

== 1. Threads
I want to avoid any assumptions about the availability of threads in the embedding platform. As such, there is e.g. no non-blocking interpret(). It would be the responsibility of the target platform to emulate something like this by embedding the block above in a thread.

== 2. Exceptions
Similarly I want to avoid any assumption about the availability of exceptions, therefore step() might return FAULT and set the lastError attribute:

int state;
for(;;) {
state - session.step();
switch(state) {
case FAULT:
print session.lastError;
break;
case FINISHED:
return;
}
}

== 3. Data
0. If nothing in a Data object is set, its value is undefined
1. If an atom is given, the respective field is to be interpreted as the evaluation of that atom, e.g. "3" is a string, 3 is an integer.
2. If a node is given and 1. is not the case, the field is to be represented as a DOM Node
3. If a key in a compound is set and 1. and 2. are not the case, the respective field is a map
4. If an index is set and none of the above applies, the respective field is an array. Setting a an item at an index N will cause the array to behave as if it has N fields for the largest N. With all unset fields undefined.

== 4. Event
Having most fields visible will allow for interpreters where all i/o processors are external by simply delivering respective Event entities via receive. The distinction between internal and external events ought to happen in receive(Event) itself depending on the event's type field. I am not sure if we need the PLATFORM class though.

== 5. Hibernating
We might want to include a way to serialise a complete interpreter and instantiate it again from its serialised representation. I do know that Jacob was working on a respective feature. We dropped our ambitions for now as most of the datamodels we employed via 3rd party libraries would not support something like that.

== 6. Naming
AFTER_MACROSTEP might just as well be called STABLE. I choose the former for its more explicit reference to the runtime semantics of SCXML, which might play a role if we were to specify a bunch of hooks for 1.2 and 1.3 (see debugger paper[1], table 1)

== 7. Events *from* the interpreter
While point 4 allows an embedding platform to send arbitrary events *into* the interpreter, maybe we ought to have something similar for everything <send> from the interpreter?


Maybe anyone who is interested in pursuing the idea of this basic IDL could speak up and comment about the proposal? What is missing, what is superfluous for a basic IDL?

Regards
Stefan

[1] http://scxmlworkshop.de/eics2014/submissions/A%20Debugger%20for%20SCXML%20Documents.pdf



============

module scxml {

exception Exception {
const unsigned short PARSE_ERR = 1; // Given string could not be parsed as an xml document
const unsigned short SCHEMA_ERR = 2; // XML DOM not a valid SCXML document
const unsigned short IMPL_ERR = 4; // Unknown datamodel, ioproc, executable content or invoker used

unsigned short code;
String cause;
};


// central place to get interpreter instances
interface Implementation {
Interpreter fromURI(in String uri) raises(Exception);
Interpreter fromXML(in String xmlString) raises(Exception);
Interpreter fromDOM(in Node scxmlRoot) raises(Exception);
}

interface Event {
const unsigned short PLATFORM_EVENT  = 1;
const unsigned short INTERNAL_EVENT  = 2;
const unsigned short EXTERNAL_EVENT  = 3;

String name;
unsigned short type;
String origin;
String originType;
String sendid;
Data data;
};

interface Data {
set(in String value); // atom
String get();

setNode(in Node node); // XML node
Node getNode();

setKey(in String key, in Data value); // compound
Data getKey(in String key);

setItemAt(in String index, in Data value); // array
Data getItemAt(in String index);
};

interface Configuration {
boolean in(in String state);
String item(in unsigned long index);
readonly attribute unsigned long length;
};

interface Interpreter {
const unsigned int FAULT = 0; // something bad happened, look into lastError
const unsigned int AFTER_MICROSTEP = 1; // step finished with a single microstep
const unsigned int AFTER_MACROSTEP = 2; // step finished with a single macrostep and interpreter is stable
const unsigned int SCXML_IDLE = 3; // interpreter is stable with no pending events on queues
const unsigned int SCXML_FINISHED = 4; // interpreter reached top-level final state

const unsigned int step() raises(Exception) raises(Exception); // blocking per default
const unsigned int step(in int timeOutMs) raises(Exception); // block at most for given duration, 0 for non-blocking

receive(in Event event);
receive(in String event); // convenience

readonly attribute Exception lastError;
readonly attribute Configuration configuration;
readonly attribute Configuration basicConfiguration;
}
}

============

Received on Friday, 3 July 2015 14:03:08 UTC