Re: An IDL for SCXML interpreters
Jacob Beard <[email protected]> Tue, 14 Jul 2015 09:38:13 -0400
| Newsgroups | gmane.comp.web.voice |
|---|---|
| Message-ID | <[email protected]> |
--Apple-Mail=_21B62C63-F893-4F3D-B1C3-F2DAFA8685F6 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hi Stefan, Please excuse the delay in my reply. > On Jul 3, 2015, at 10:01 AM, Stefan Radomski = <[email protected]> wrote: >=20 > Hey there, >=20 > [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: >=20 > 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. >=20 > 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: >=20 > import namespace scxml; > try { > Interpreter session =3D Implementation.fromURI("http://www = <http://www/>.example.com/foo.scxml"); > for(;;) { > int state =3D session.step(); > if (state =3D=3D FINISHED) > break; > if (state =3D=3D AFTER_MACROSTEP && session.configuration.in('foo')) > session.receive('bar.baz'); > } > } catch (Exception e) { > print e; > } >=20 Here are my comments on this. In SCION, there=E2=80=99s a notion of compiling the SCXML into a = =E2=80=9Cmodel=E2=80=9D object, which is a native object used to create = the session (scxml.urlToModel = <https://github.com/jbeard4/SCION#scxmlurltomodelurlfunctionerr-model>). = This gives the client a way to create multiple sessions without = reparsing/recompiling the SCXML into its object representation, which is = a relatively expensive operation.=20 Additionally, the model can be can be parsed from a DOM object = (scxml.documentToModel = <https://github.com/jbeard4/SCION#scxmldocumenttomodelscxmldocumentfunctio= nerr-model>), which provides opportunities for model transformation = using XML DOM API. Finally, in SCION there are convenience methods for = parsing SCXML from filesystem (scxml.pathToModel = <https://github.com/jbeard4/SCION#scxmlpathtomodelpathfunctionerr-model>),= and from a string representation (scxml.documentStringToModel = <https://github.com/jbeard4/SCION#scxmldocumentstringtomodelscxmldocstring= functionerr-model>). After that, can you instantiate the session using the model object: = scxml.scion.Statechart(model, options) It=E2=80=99s useful to have a mechanism to specify the SCXML _sessionid. = This is passed in on the options argument. session.step() seems equivalent to session.start() in SCION. This causes = the state machine to enter its initial state. Currently in SCION, the return value of session.start() is a basic = configuration (set of basic states), encoded as a JavaScript array = containing state id strings. In SCION, the basic configuration is kept = as an internal data structure, so this cheap to return.=20 In terms of querying the session for current state, you can use = session.getConfiguration() to get the basic configuration, and use = regular JavaScript semantics to query the array (e.g. = "configuration.indexOf(=E2=80=99stateId') > -1=E2=80=9D). You can a can = also use session.isIn(=E2=80=99stateId') to query the session for basic = and composite states. In SCION, session.gen() is equivalent to session.receive(). I chose the = name =E2=80=9Cgen" from Harel=E2=80=99s paper The Rhapsody Semantics of = Statecharts = <http://research.microsoft.com/apps/pubs/default.aspx?id=3D148785>. In = SCION, the return value is the same as session.start(): a basic = configuration. Finally, you can use session.isFinal() to check if the session is in a = final state. Altogether, here is an example of the SCION API: scxml.urlToModel(url,function(err, model){ if(err) throw err; //you can inspect the generated code if you like using = JavaScript's Function.prototype.toString console.log(model.toString()); =20 //instantiate the interpreter var statechart1 =3D new scxml.scion.Statechart(model); //you can instantiate a second interpreter using the same model var statechart2 =3D new scxml.scion.Statechart(model); //start the interpreter var initialConfiguration =3D statechart1.start(); //send events statechart1.gen({name : 'foo', data : 'bar'}); }); > A couple of notes and possible variations: >=20 > =3D=3D 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. >=20 I agree with this. A blocking API for interpret/receive/gen works well = with the notion of =E2=80=9CFast Computation=E2=80=9D for big-step = modeling languages described in section 2.3 of Big-Step Semantics = <https://cs.uwaterloo.ca/~sesmaeil/publications/2009/CS-2009-05.pdf> by = Nancy Day, et al. gen() should be a fast, synchronous, blocking = operation. > =3D=3D 2. Exceptions > Similarly I want to avoid any assumption about the availability of = exceptions, therefore step() might return FAULT and set the lastError = attribute: >=20 > int state; > for(;;) { > state - session.step(); > switch(state) { > case FAULT: > print session.lastError; > break; > case FINISHED: > return; > } > } >=20 I=E2=80=99ve been considering this. The SCXML spec says that scripting = errors should be put on the internal queue as error.execution events. = However, from a developer perspective, I often find this behavior = surprising. The developer needs to remember to add a top-level = <transition event=3D=E2=80=9Cerror.*=E2=80=9D> to catch execution errors = exposed as events. So by default, in SCXML, JavaScript errors are = suppressed. I therefore think it could be useful if the interpreter API = could provide better visibility so that execution errors are by default = not suppressed.=20 > =3D=3D 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. >=20 In SCION, the datamodel is kept fully private, and not exposed = externally, except via the session.getSnapshot() method, which returns a = copy of the full datamodel. This is a relatively cheap operation. > =3D=3D 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. I agree that receive() should be able to accommodate both internal and = external events. It should be possible to inspect the _event.origin = field and compare it to _ioprocessors to determine whether an event = originating internal or external to the session. >=20 > =3D=3D 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. >=20 Right now, in SCION, datamodel elements that are =E2=80=9Ctransient=E2=80=9D= (not serializable) are initialized in the top-level <script> tag, which = is executed every time a session is instantiated. Rather than put them = in the datamodel, they are declared in the <script> tag using JavaScript = =E2=80=9Cvar=E2=80=9D. I think this is a bit ugly, and could be = improved. To improve this, two things would be needed: 1. An explicit notion of transient attributes on the datamodel. This is = similar to the =E2=80=9Ctransient" attribute modifier in Java. These = datamodel elements would not be serialized on hibernate. 2. Explicitly recognizing that top-level script tag is a code block that = will executed on resume. This allows transient datamodel elements to be = re-initialized.=20 State machine hibernation is useful for developing scalable cloud = applications, as it allows your SCXML session data to be persisted to = secondary storage, rather than kept in memory. This is needed for = horizontal scalability. > =3D=3D 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) >=20 I think it would be useful to explicitly capture these interpreter = states as a meta-state machine. It may be interesting to look at the states in the docker container = lifecycle, as docker provides a generic container API for linux = applications. These concepts could carry over to modeling the SCXML = interpreter lifecycle. I created an SCXML to model this here: = http://examples.scxml.io/e/docker-manager/ = <http://examples.scxml.io/e/docker-manager/> > =3D=3D 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? >=20 I think we should consider an API for <send>. I=E2=80=99m currently = working on improving the SCION <send> implementation, including support = for custom send types, and will follow up on this item shortly. >=20 > 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? Thank you for getting this process started. Please let me know your = feedback, and I can take a pass at iterating on the proposed IDL. Regards, Jacob Beard >=20 > Regards > Stefan >=20 > [1] = http://scxmlworkshop.de/eics2014/submissions/A%20Debugger%20for%20SCXML%20= Documents.pdf >=20 >=20 >=20 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D >=20 > module scxml { >=20 > exception Exception { > const unsigned short PARSE_ERR =3D 1; // Given string could not be = parsed as an xml document > const unsigned short SCHEMA_ERR =3D 2; // XML DOM not a valid SCXML = document > const unsigned short IMPL_ERR =3D 4; // Unknown datamodel, ioproc, = executable content or invoker used >=20 > unsigned short code; > String cause; > }; >=20 >=20 > // 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); > } >=20 > interface Event { > const unsigned short PLATFORM_EVENT =3D 1; > const unsigned short INTERNAL_EVENT =3D 2; > const unsigned short EXTERNAL_EVENT =3D 3; >=20 > String name; > unsigned short type; > String origin; > String originType; > String sendid; > Data data; > }; >=20 > interface Data { > set(in String value); // atom > String get(); >=20 > setNode(in Node node); // XML node > Node getNode(); >=20 > setKey(in String key, in Data value); // compound > Data getKey(in String key); >=20 > setItemAt(in String index, in Data value); // array > Data getItemAt(in String index); > }; >=20 > interface Configuration { > boolean in(in String state); > String item(in unsigned long index); > readonly attribute unsigned long length; > }; >=20 > interface Interpreter { > const unsigned int FAULT =3D 0; // something bad happened, look into = lastError > const unsigned int AFTER_MICROSTEP =3D 1; // step finished with a = single microstep > const unsigned int AFTER_MACROSTEP =3D 2; // step finished with a = single macrostep and interpreter is stable > const unsigned int SCXML_IDLE =3D 3; // interpreter is stable with no = pending events on queues > const unsigned int SCXML_FINISHED =3D 4; // interpreter reached = top-level final state >=20 > 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 >=20 > receive(in Event event); > receive(in String event); // convenience >=20 > readonly attribute Exception lastError; > readonly attribute Configuration configuration; > readonly attribute Configuration basicConfiguration; > } > } >=20 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --Apple-Mail=_21B62C63-F893-4F3D-B1C3-F2DAFA8685F6 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 <html><head><meta http-equiv=3D"Content-Type" content=3D"text/html = charset=3Dutf-8"></head><body style=3D"word-wrap: break-word; = -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" = class=3D""><span style=3D"font-family: -apple-system-font; line-height: = 16px;" class=3D"">Hi Stefan,</span><div style=3D"font-family: = -apple-system-font; line-height: 16px;" class=3D""><br = class=3D""></div><div style=3D"font-family: -apple-system-font; = line-height: 16px;" class=3D"">Please excuse the delay in my = reply.</div><div style=3D"font-family: -apple-system-font; line-height: = 16px;" class=3D""><br class=3D""></div><div><blockquote type=3D"cite" = class=3D""><div class=3D"">On Jul 3, 2015, at 10:01 AM, Stefan Radomski = <<a href=3D"mailto:[email protected]" = class=3D"">[email protected]</a>> = wrote:</div><br class=3D"Apple-interchange-newline"><div class=3D""> <meta http-equiv=3D"Content-Type" content=3D"text/html; = charset=3Dus-ascii" class=3D""> <div style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; = -webkit-line-break: after-white-space;" class=3D""> Hey there,<br class=3D""> <br class=3D""> [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:<br class=3D""> <br class=3D""> 1. An Interface Description Language (IDL) for SCXML interpreters.<br = class=3D""> 1.1 For simple life-cycle and interpretation of state-charts.<br = class=3D""> 1.2 A set of hooks for (on-line) visualisation.<br class=3D""> 1.3 A set of hooks for (on-line) modelling / debugging.<br class=3D""> <br class=3D""> 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:<br class=3D""> <br class=3D""> import namespace scxml;<br class=3D""> try {<br class=3D""> <span class=3D"Apple-tab-span" = style=3D"white-space:pre"></span>Interpreter session =3D = Implementation.fromURI("<a href=3D"http://www/" = class=3D"">http://www</a>.<a href=3D"http://example.com/foo.scxml" = class=3D"">example.com/foo.scxml</a>");<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>for(;;) = {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>int = state =3D session.step();<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>if = (state =3D=3D FINISHED)<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>break;<br = class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>if = (state =3D=3D AFTER_MACROSTEP && = session.configuration.in('foo'))<br class=3D""> <span class=3D"Apple-tab-span" = style=3D"white-space:pre"></span>session.receive('bar.baz');<br = class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>}<br = class=3D""> } catch (Exception e) {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>print = e;<br class=3D""> }<br class=3D""> <br class=3D""></div></div></blockquote><div><br = class=3D""></div><div><div style=3D"font-family: -apple-system-font; = line-height: 16px; direction: ltr;" class=3D"">Here are my comments on = this.</div><div style=3D"font-family: -apple-system-font; line-height: = 16px; direction: ltr;" class=3D""><br class=3D""></div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D""><div class=3D"">In SCION, there=E2=80=99s a notion of = compiling the SCXML into a =E2=80=9Cmodel=E2=80=9D object, which is a = native object used to create the session (<a = href=3D"https://github.com/jbeard4/SCION#scxmlurltomodelurlfunctionerr-mod= el" class=3D"">scxml.urlToModel</a>). This gives the client a way to = create multiple sessions without reparsing/recompiling the SCXML into = its object representation, which is a relatively expensive = operation. </div><div class=3D""><br class=3D""></div><div = class=3D"">Additionally, the model can be can be parsed from a DOM = object (<a = href=3D"https://github.com/jbeard4/SCION#scxmldocumenttomodelscxmldocument= functionerr-model" class=3D"">scxml.documentToModel</a>), which provides = opportunities for model transformation using XML DOM API. Finally, in = SCION there are convenience methods for parsing SCXML from filesystem = (<a = href=3D"https://github.com/jbeard4/SCION#scxmlpathtomodelpathfunctionerr-m= odel" class=3D"">scxml.pathToModel</a>), and from a string = representation (<a = href=3D"https://github.com/jbeard4/SCION#scxmldocumentstringtomodelscxmldo= cstringfunctionerr-model" = class=3D"">scxml.documentStringToModel</a>).</div><div class=3D""><br = class=3D""></div><div class=3D"">After that, can you instantiate the = session using the model object: scxml.scion.Statechart(model, = options)</div><div class=3D""><br class=3D""></div><div class=3D"">It=E2=80= =99s useful to have a mechanism to specify the SCXML _sessionid. This is = passed in on the options argument.</div><div class=3D""><br = class=3D""></div><div class=3D"">session.step() seems equivalent to = session.start() in SCION. This causes the state machine to enter its = initial state.</div><div class=3D""><br class=3D""></div><div = class=3D"">Currently in SCION, the return value of session.start() is a = basic configuration (set of basic states), encoded as a JavaScript array = containing state id strings. In SCION, the basic configuration is kept = as an internal data structure, so this cheap to return. </div><div = class=3D""><br class=3D""></div><div class=3D"">In terms of querying the = session for current state, you can use session.getConfiguration() to get = the basic configuration, and use regular JavaScript semantics to query = the array (e.g. "configuration.indexOf(=E2=80=99stateId') > -1=E2=80=9D= ). You can a can also use session.isIn(=E2=80=99stateId') to query the = session for basic and composite states.</div><div class=3D""><br = class=3D""></div><div class=3D"">In SCION, session.gen() is equivalent = to session.receive(). I chose the name =E2=80=9Cgen" from Harel=E2=80=99s = paper <a = href=3D"http://research.microsoft.com/apps/pubs/default.aspx?id=3D148785" = class=3D"">The Rhapsody Semantics of Statecharts</a>. In SCION, the = return value is the same as session.start(): a basic = configuration.</div><div class=3D""><br class=3D""></div><div = class=3D"">Finally, you can use session.isFinal() to check if the = session is in a final state.</div><div class=3D""><br = class=3D""></div><div class=3D"">Altogether, here is an example of the = SCION API:</div><div class=3D""><br class=3D""></div><div class=3D""><pre = style=3D"box-sizing: border-box; overflow: auto; font-family: Consolas, = 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; = margin-top: 0px; margin-bottom: 0px; line-height: 1.45; padding: 16px; = background-color: rgb(247, 247, 247); border-top-left-radius: 3px; = border-top-right-radius: 3px; border-bottom-right-radius: 3px; = border-bottom-left-radius: 3px; word-wrap: normal; word-break: normal; = color: rgb(51, 51, 51);" class=3D""> scxml.urlToModel(url,<span = class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, 29, = 93);">function</span>(<span class=3D"pl-smi" style=3D"box-sizing: = border-box;">err</span>, <span class=3D"pl-smi" style=3D"box-sizing: = border-box;">model</span>){ <span class=3D"pl-k" style=3D"box-sizing: border-box; color: = rgb(167, 29, 93);">if</span>(err) <span class=3D"pl-k" = style=3D"box-sizing: border-box; color: rgb(167, 29, 93);">throw</span> = err; <span class=3D"pl-c" style=3D"box-sizing: border-box; color: = rgb(150, 152, 150);">//you can inspect the generated code if you like = using JavaScript's Function.prototype.toString</span> <span class=3D"pl-en" style=3D"box-sizing: border-box; color: = rgb(121, 93, 163);">console</span><span class=3D"pl-c1" = style=3D"box-sizing: border-box; color: rgb(0, 134, = 179);">.log</span>(model.<span class=3D"pl-c1" style=3D"box-sizing: = border-box; color: rgb(0, 134, 179);">toString</span>()); =20 <span class=3D"pl-c" style=3D"box-sizing: border-box; color: = rgb(150, 152, 150);">//instantiate the interpreter</span> <span class=3D"pl-k" style=3D"box-sizing: border-box; color: = rgb(167, 29, 93);">var</span> statechart1 <span class=3D"pl-k" = style=3D"box-sizing: border-box; color: rgb(167, 29, 93);">=3D</span> = <span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, = 29, 93);">new</span> <span class=3D"pl-en" style=3D"box-sizing: = border-box; color: rgb(121, 93, = 163);">scxml.scion</span>.Statechart(model); <span class=3D"pl-c" style=3D"box-sizing: border-box; color: = rgb(150, 152, 150);">//you can instantiate a second interpreter using = the same model</span> <span class=3D"pl-k" style=3D"box-sizing: border-box; color: = rgb(167, 29, 93);">var</span> statechart2 <span class=3D"pl-k" = style=3D"box-sizing: border-box; color: rgb(167, 29, 93);">=3D</span> = <span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, = 29, 93);">new</span> <span class=3D"pl-en" style=3D"box-sizing: = border-box; color: rgb(121, 93, = 163);">scxml.scion</span>.Statechart(model); <span class=3D"pl-c" style=3D"box-sizing: border-box; color: = rgb(150, 152, 150);">//start the interpreter</span> <span class=3D"pl-k" style=3D"box-sizing: border-box; color: = rgb(167, 29, 93);">var</span> initialConfiguration <span class=3D"pl-k" = style=3D"box-sizing: border-box; color: rgb(167, 29, 93);">=3D</span> = statechart1.<span class=3D"pl-c1" style=3D"box-sizing: border-box; = color: rgb(0, 134, 179);">start</span>(); <span class=3D"pl-c" style=3D"box-sizing: border-box; color: = rgb(150, 152, 150);">//send events</span> statechart1.gen({name <span class=3D"pl-k" style=3D"box-sizing: = border-box; color: rgb(167, 29, 93);">:</span> <span class=3D"pl-s" = style=3D"box-sizing: border-box; color: rgb(24, 54, 145);"><span = class=3D"pl-pds" style=3D"box-sizing: border-box;">'</span>foo<span = class=3D"pl-pds" style=3D"box-sizing: border-box;">'</span></span>, data = <span class=3D"pl-k" style=3D"box-sizing: border-box; color: rgb(167, = 29, 93);">:</span> <span class=3D"pl-s" style=3D"box-sizing: border-box; = color: rgb(24, 54, 145);"><span class=3D"pl-pds" style=3D"box-sizing: = border-box;">'</span>bar<span class=3D"pl-pds" style=3D"box-sizing: = border-box;">'</span></span>}); });</pre><div class=3D""><br class=3D""></div></div></div></div><br = class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div = style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; = -webkit-line-break: after-white-space;" class=3D""> A couple of notes and possible variations:<br class=3D""> <br class=3D""> =3D=3D 1. Threads<br class=3D""> 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.<br class=3D""> <br class=3D""></div></div></blockquote><div><br = class=3D""></div><div><span style=3D"font-family: -apple-system-font; = line-height: 16px;" class=3D"">I agree with this. A blocking API for = interpret/receive/gen works well with the notion of =E2=80=9CFast = Computation=E2=80=9D for big-step modeling languages described in = section 2.3 of </span><a = href=3D"https://cs.uwaterloo.ca/~sesmaeil/publications/2009/CS-2009-05.pdf= " style=3D"font-family: -apple-system-font; line-height: 16px;" = class=3D"">Big-Step Semantics</a><span style=3D"font-family: = -apple-system-font; line-height: 16px;" class=3D""> by Nancy Day, = et al. gen() should be a fast, synchronous, blocking = operation.</span></div><br class=3D""><blockquote type=3D"cite" = class=3D""><div class=3D""><div style=3D"word-wrap: break-word; = -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" = class=3D""> =3D=3D 2. Exceptions<br class=3D""> Similarly I want to avoid any assumption about the availability of = exceptions, therefore step() might return FAULT and set the lastError = attribute:<br class=3D""> <br class=3D""> int state;<br class=3D""> for(;;) {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>state - = session.step();<br class=3D""> <span class=3D"Apple-tab-span" = style=3D"white-space:pre"></span>switch(state) {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>case = FAULT:<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>print = session.lastError;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>break;<br = class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>case = FINISHED:<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>return;<br= class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>}<br = class=3D""> }<br class=3D""> <br class=3D""></div></div></blockquote><div><br = class=3D""></div><div><span style=3D"font-family: -apple-system-font; = line-height: 16px;" class=3D"">I=E2=80=99ve been considering this. The = SCXML spec says that scripting errors should be put on the internal = queue as error.execution events. However, from a developer perspective, = I often find this behavior surprising. The developer needs to remember = to add a top-level <transition event=3D=E2=80=9Cerror.*=E2=80=9D> = to catch execution errors exposed as events. So by default, in SCXML, = JavaScript errors are suppressed. I therefore think it could be useful = if the interpreter API could provide better visibility so that execution = errors are by default not suppressed. </span></div><div><br = class=3D""></div><br class=3D""><blockquote type=3D"cite" class=3D""><div = class=3D""><div style=3D"word-wrap: break-word; -webkit-nbsp-mode: = space; -webkit-line-break: after-white-space;" class=3D""> =3D=3D 3. Data<br class=3D""> 0. If nothing in a Data object is set, its value is undefined<br = class=3D""> 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.<br = class=3D""> 2. If a node is given and 1. is not the case, the field is to be = represented as a DOM Node<br class=3D""> 3. If a key in a compound is set and 1. and 2. are not the case, the = respective field is a map<br class=3D""> 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.<br class=3D""> <br class=3D""></div></div></blockquote><div><br = class=3D""></div><div><span style=3D"font-family: -apple-system-font; = line-height: 16px;" class=3D"">In SCION, the datamodel is kept fully = private, and not exposed externally, except via the = session.getSnapshot() method, which returns a copy of the full = datamodel. This is a relatively cheap operation.</span></div><br = class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div = style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; = -webkit-line-break: after-white-space;" class=3D""> =3D=3D 4. Event<br class=3D""> 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.<br class=3D""></div></div></blockquote><div><br = class=3D""></div><span style=3D"font-family: -apple-system-font; = line-height: 16px;" class=3D"">I agree that receive() should be able to = accommodate both internal and external events. It should be possible to = inspect the _event.origin field and compare it to _ioprocessors to = determine whether an event originating internal or external to the = session.</span></div><div><font face=3D"-apple-system-font" = class=3D""><span style=3D"line-height: 16px;" class=3D""><br = class=3D""></span></font><blockquote type=3D"cite" class=3D""><div = class=3D""><div style=3D"word-wrap: break-word; -webkit-nbsp-mode: = space; -webkit-line-break: after-white-space;" class=3D""> <br class=3D""> =3D=3D 5. Hibernating<br class=3D""> 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.<br = class=3D""> <br class=3D""></div></div></blockquote><div><br = class=3D""></div><div><div style=3D"font-family: -apple-system-font; = line-height: 16px; direction: ltr;" class=3D"">Right now, in SCION, = datamodel elements that are =E2=80=9Ctransient=E2=80=9D (not = serializable) are initialized in the top-level <script> tag, which = is executed every time a session is instantiated. Rather than put them = in the datamodel, they are declared in the <script> tag using = JavaScript =E2=80=9Cvar=E2=80=9D. I think this is a bit ugly, and could = be improved. To improve this, two things would be needed:</div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D""><br class=3D""></div><div style=3D"font-family: = -apple-system-font; line-height: 16px; direction: ltr;" class=3D"">1. An = explicit notion of transient attributes on the datamodel. This is = similar to the =E2=80=9Ctransient" attribute modifier in Java. These = datamodel elements would not be serialized on hibernate.</div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D"">2. Explicitly recognizing that top-level script tag is = a code block that will executed on resume. This allows transient = datamodel elements to be re-initialized. </div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D""><br class=3D""></div><div style=3D"font-family: = -apple-system-font; line-height: 16px; direction: ltr;" class=3D"">State = machine hibernation is useful for developing scalable cloud = applications, as it allows your SCXML session data to be persisted to = secondary storage, rather than kept in memory. This is needed for = horizontal scalability.</div></div><br class=3D""><blockquote = type=3D"cite" class=3D""><div class=3D""><div style=3D"word-wrap: = break-word; -webkit-nbsp-mode: space; -webkit-line-break: = after-white-space;" class=3D""> =3D=3D 6. Naming<br class=3D""> 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)<br class=3D""> <br class=3D""></div></div></blockquote><div><br = class=3D""></div><div><div style=3D"font-family: -apple-system-font; = line-height: 16px; direction: ltr;" class=3D"">I think it would be = useful to explicitly capture these interpreter states as a meta-state = machine.</div><div style=3D"font-family: -apple-system-font; = line-height: 16px; direction: ltr;" class=3D""><br class=3D""></div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D"">It may be interesting to look at the states in the = docker container lifecycle, as docker provides a generic container API = for linux applications. These concepts could carry over to modeling the = SCXML interpreter lifecycle. I created an SCXML to model this = here: <a href=3D"http://examples.scxml.io/e/docker-manager/" = class=3D"">http://examples.scxml.io/e/docker-manager/</a></div></div><br = class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div = style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; = -webkit-line-break: after-white-space;" class=3D""> =3D=3D 7. Events *from* the interpreter<br class=3D""> 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?<br class=3D""> <br class=3D""></div></div></blockquote><div><br class=3D""></div><span = style=3D"font-family: -apple-system-font; line-height: 16px;" class=3D"">I= think we should consider an API for <send>. I=E2=80=99m currently = working on improving the SCION <send> implementation, including = support for custom send types, and will follow up on this item = shortly.</span></div><div><font face=3D"-apple-system-font" = class=3D""><span style=3D"line-height: 16px;" class=3D""><br = class=3D""></span></font><blockquote type=3D"cite" class=3D""><div = class=3D""><div style=3D"word-wrap: break-word; -webkit-nbsp-mode: = space; -webkit-line-break: after-white-space;" class=3D""> <br class=3D""> 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?<br = class=3D""></div></div></blockquote><div><br class=3D""></div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D"">Thank you for getting this process started. Please let = me know your feedback, and I can take a pass at iterating on the = proposed IDL.</div><div style=3D"font-family: -apple-system-font; = line-height: 16px; direction: ltr;" class=3D""><br class=3D""></div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D"">Regards,</div><div style=3D"font-family: = -apple-system-font; line-height: 16px; direction: ltr;" class=3D""><br = class=3D""></div><div style=3D"font-family: -apple-system-font; = line-height: 16px; direction: ltr;" class=3D"">Jacob Beard</div><div = style=3D"font-family: -apple-system-font; line-height: 16px; direction: = ltr;" class=3D""><br class=3D""></div><blockquote type=3D"cite" = class=3D""><div class=3D""><div style=3D"word-wrap: break-word; = -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" = class=3D""> <br class=3D""> Regards<br class=3D""> Stefan<br class=3D""> <br class=3D""> [1] <a = href=3D"http://scxmlworkshop.de/eics2014/submissions/A%20Debugger%20for%20= SCXML%20Documents.pdf" = class=3D"">http://scxmlworkshop.de/eics2014/submissions/A%20Debugger%20for= %20SCXML%20Documents.pdf</a><br class=3D""> <br class=3D""> <br class=3D""> <br class=3D""> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br class=3D""> <br class=3D""> <font face=3D"Courier" class=3D"">module scxml {<br class=3D""> <br class=3D""> exception Exception {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned short PARSE_ERR =3D 1; // Given string could not be parsed as = an xml document<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned short SCHEMA_ERR =3D 2; // XML DOM not a valid SCXML = document<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned short IMPL_ERR =3D 4; // Unknown datamodel, ioproc, executable = content or invoker used<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>unsigned = short code;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>String = cause;<br class=3D""> };<br class=3D""> <br class=3D""> <br class=3D""> // central place to get interpreter instances<br class=3D""> interface Implementation {<br class=3D""> <span class=3D"Apple-tab-span" = style=3D"white-space:pre"></span>Interpreter fromURI(in String uri) = raises(Exception);<br class=3D""> <span class=3D"Apple-tab-span" = style=3D"white-space:pre"></span>Interpreter fromXML(in String = xmlString) raises(Exception);<br class=3D""> <span class=3D"Apple-tab-span" = style=3D"white-space:pre"></span>Interpreter fromDOM(in Node scxmlRoot) = raises(Exception);<br class=3D""> }<br class=3D""> <br class=3D""> interface Event {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned short PLATFORM_EVENT =3D 1;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned short INTERNAL_EVENT =3D 2;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned short EXTERNAL_EVENT =3D 3;<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>String = name;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>unsigned = short type;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>String = origin;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>String = originType;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>String = sendid;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>Data = data;<br class=3D""> };<br class=3D""> <br class=3D""> interface Data {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>set(in = String value); // atom<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>String = get();<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>setNode(in= Node node); // XML node<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>Node = getNode();<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>setKey(in = String key, in Data value); // compound<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>Data = getKey(in String key);<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" = style=3D"white-space:pre"></span>setItemAt(in String index, in Data = value); // array<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>Data = getItemAt(in String index);<br class=3D""> };<br class=3D""> <br class=3D""> interface Configuration {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>boolean = in(in String state);<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>String = item(in unsigned long index);<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>readonly = attribute unsigned long length;<br class=3D""> };<br class=3D""> <br class=3D""> interface Interpreter {<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned int FAULT =3D 0; // something bad happened, look into = lastError<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned int AFTER_MICROSTEP =3D 1; // step finished with a single = microstep<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned int AFTER_MACROSTEP =3D 2; // step finished with a single = macrostep and interpreter is stable<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned int SCXML_IDLE =3D 3; // interpreter is stable with no pending = events on queues<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned int SCXML_FINISHED =3D 4; // interpreter reached top-level = final state<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned int step() raises(Exception) raises(Exception); // blocking per = default<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>const = unsigned int step(in int timeOutMs) raises(Exception); // block at most = for given duration, 0 for non-blocking<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>receive(in= Event event);<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>receive(in= String event); // convenience<br class=3D""> <br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>readonly = attribute Exception lastError;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>readonly = attribute Configuration configuration;<br class=3D""> <span class=3D"Apple-tab-span" style=3D"white-space:pre"></span>readonly = attribute Configuration basicConfiguration;<br class=3D""> }<br class=3D""> }<br class=3D""> </font><br class=3D""> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D </div> </div></blockquote></div><br class=3D""></body></html>= --Apple-Mail=_21B62C63-F893-4F3D-B1C3-F2DAFA8685F6--