Преглед изворни кода

Guard conditions are parsed as expressions, currently supporting: literals, identifiers, function calls, arrays. Initial (very minimal) data model.

Joeri Exelmans пре 5 година
родитељ
комит
9831860870

+ 51 - 0
src/sccd/runtime/expression.py

@@ -0,0 +1,51 @@
+from abc import *
+from typing import *
+from dataclasses import *
+
+class Variable:
+    def __init__(self, value):
+        self.value = value
+
+class DataModel:
+    def __init__(self, instance, names: Dict[str, Variable]):
+        self.instance = instance
+        self.names = names
+
+@dataclass
+class Expression(ABC):
+    pass
+
+    @abstractmethod
+    def eval(self, datamodel):
+        pass
+
+@dataclass
+class Identifier(Expression):
+    identifier: str
+
+    def eval(self, datamodel):
+        return datamodel.names[self.identifier].value
+
+@dataclass
+class FunctionCall(Expression):
+    function: Expression
+    parameters: List[Expression]
+
+    def eval(self, datamodel):
+        f = self.function.eval(datamodel)
+        p = [p.eval(datamodel) for p in self.parameters]
+        return f(*p)
+
+@dataclass
+class StringLiteral(Expression):
+    string: str
+
+    def eval(self, datamodel):
+        return self.string
+
+@dataclass
+class Array(Expression):
+    elements: List[Any]
+
+    def eval(self, datamodel):
+        return [e.eval(datamodel) for e in self.elements]

+ 37 - 3
src/sccd/runtime/grammar.g

@@ -2,8 +2,11 @@
 // At this time is only used for parsing target state references of transitions.
 // In the future will contain rules for anything else that needs to be parsed, including our action language
 
-WHITESPACE: (" " | "\t" | "\n")+
-%ignore WHITESPACE
+%import common.WS
+%ignore WS
+
+%import common.SIGNED_NUMBER
+%import common.ESCAPED_STRING
 
 _PATH_SEP: "/" 
 PARENT_NODE: ".." 
@@ -11,9 +14,40 @@ CURRENT_NODE: "."
 IDENTIFIER: /[A-Za-z_][A-Za-z_0-9]*/ 
 
 // target of a transition
-target_expr: _path | "(" _path ("," _path)+ ")" 
+state_ref: _path | "(" _path ("," _path)+ ")" 
 
 _path: absolute_path | relative_path 
 absolute_path: _PATH_SEP _path_sequence
 relative_path: _path_sequence
 _path_sequence: (CURRENT_NODE | PARENT_NODE | IDENTIFIER) (_PATH_SEP _path_sequence)?
+
+
+
+
+?expr: or_expr
+
+?or_expr: and_expr
+       | or_expr "||" and_expr -> or
+
+?and_expr: atom
+        | and_expr "&&" atom   -> and
+
+?atom: IDENTIFIER               -> identifier
+    | "-" atom                 -> neg
+    | "(" expr ")"             -> group
+    | literal                 
+    | func_call
+    | array
+
+array: "[" (expr ("," expr)*)? "]"
+
+?literal: ESCAPED_STRING -> string
+        | SIGNED_NUMBER -> number
+        | bool_literal -> bool
+?bool_literal: TRUE | FALSE
+
+func_call: atom "(" param_list ")"
+param_list: ( expr ("," expr)* )?  -> params
+
+TRUE: "true"
+FALSE: "false"

+ 15 - 9
src/sccd/runtime/statechart_instance.py

@@ -17,6 +17,10 @@ class StatechartInstance(Instance):
         self.model = model
         self.object_manager = object_manager
 
+        self.data_model = DataModel(self, {
+            "INSTATE": Variable(self.inState),
+        })
+
         # these 2 fields have the same information
         self.configuration = []
         self.configuration_bitmap = 0
@@ -47,7 +51,7 @@ class StatechartInstance(Instance):
             self._perform_actions(state.enter)
             self._start_timers(state.after_triggers)
         stable = not self.eventless_states
-        print_debug(termcolor.colored('completed initialization (time=%d)'%now, 'red'))
+        print_debug(termcolor.colored('completed initialization (time=%d)'%now+("(stable)" if stable else ""), 'red'))
         return (stable, self._big_step.output_events)
 
     # perform a big step. generating a set of output events
@@ -62,11 +66,14 @@ class StatechartInstance(Instance):
             if self.model.semantics.big_step_maximality == BigStepMaximality.TAKE_ONE:
                 break # Take One -> only one combo step allowed
 
+        # can the next big step still contain transitions, even if there are no input events?
+        stable = not self.eventless_states or (not input_events and not self._big_step.has_stepped)
+
         if self._big_step.has_stepped:
-            print_debug(termcolor.colored('completed big step (time=%d)'%now, 'red'))
+            print_debug(termcolor.colored('completed big step (time=%d)'%now+(" (stable)" if stable else ""), 'red'))
+        else:
+            print_debug(termcolor.colored("(stable)" if stable else "", 'red'))
 
-        # can the next big step still contain transitions, even if there are no input events?
-        stable = not self.eventless_states or (not filtered and not self._big_step.has_stepped)
         return (stable, self._big_step.output_events)
 
     def combo_step(self):
@@ -183,7 +190,7 @@ class StatechartInstance(Instance):
             self.configuration = self.config_mem[self.configuration_bitmap]
         except:
             self.configuration = self.config_mem[self.configuration_bitmap] = sorted([s for s in list(self.model.states.values()) if 2**s.state_id & self.configuration_bitmap], key=lambda s: s.state_id)
-        t.enabled_event = None
+        # t.enabled_event = None
         
 
     # def getChildren(self, link_name):
@@ -224,18 +231,17 @@ class StatechartInstance(Instance):
         enabled_transitions = []
         for t in transitions:
             if self._is_transition_enabled(t, enabled_events, enabled_transitions):
-            # if t.isEnabled(self, enabled_events, enabled_transitions):
                 enabled_transitions.append(t)
         return enabled_transitions
 
     def _is_transition_enabled(self, t, events, enabled_transitions) -> bool:
         if t.trigger is None:
-            t.enabled_event = None
-            return (t.guard is None) or (t.guard == ELSE_GUARD and not enabled_transitions) or t.guard(self, [])
+            # t.enabled_event = None
+            return (t.guard is None) or (t.guard == ELSE_GUARD and not enabled_transitions) or t.guard.eval(self.data_model)
         else:
             for event in events:
                 if (t.trigger.name == event.name and (not t.trigger.port or t.trigger.port == event.port)) and ((t.guard is None) or (t.guard == ELSE_GUARD and not enabled_transitions) or t.guard(event.parameters)):
-                    t.enabled_event = event
+                    # t.enabled_event = event
                     return True
 
     def _perform_actions(self, actions: List[Action]):

+ 4 - 8
src/sccd/runtime/statechart_syntax.py

@@ -1,8 +1,10 @@
 from dataclasses import dataclass, field
 from typing import *
 from sccd.runtime.event_queue import Timestamp
+from sccd.runtime.expression import *
 from sccd.compiler.utils import FormattedWriter
 
+
 @dataclass
 class Action:
     pass
@@ -139,12 +141,12 @@ class AfterTrigger(Trigger):
 
 class Transition:
     def __init__(self, source, targets: List[State]):
-        self.guard = None
+        self.guard: Optional[Expression] = None
         self.actions: List[Action] = []
         self.trigger: Optional[Trigger] = None
         self.source = source
         self.targets = targets
-        self.enabled_event = None # the event that enabled this transition
+        # self.enabled_event = None # the event that enabled this transition <_ huh?
         self.optimize()
                     
     def setGuard(self, guard):
@@ -174,12 +176,6 @@ class Transition:
     def __repr__(self):
         return "Transition(%s, %s)" % (self.source, self.targets[0])
 
-
-@dataclass
-class Expression:
-    pass
-
-
 @dataclass
 class RaiseEvent(Action):
     name: str

+ 37 - 14
src/sccd/runtime/xml_loader.py

@@ -15,7 +15,7 @@ schema_path = os.path.join(
 schema = ET.XMLSchema(ET.parse(schema_path))
 
 grammar = open(os.path.join(os.path.dirname(os.path.abspath(__file__)),"grammar.g"))
-l = Lark(grammar, parser="lalr", start=["target_expr"])
+l = Lark(grammar, parser="earley", start=["state_ref", "expr"])
 
 
 # Some types immitating the types that are produced by the compiler
@@ -74,11 +74,11 @@ def load_model(src_file) -> Tuple[Model, Optional[Test]]:
         value = aspect.type[key.upper()]
         setattr(semantics, aspect.name, value)
 
-    class_ = Class(class_name, None)
-    statechart = Statechart(class_, root_state, states, semantics)
-    class_.statechart = statechart
+    _class = Class(class_name, None)
+    statechart = Statechart(_class=_class, root=root_state, states=states, semantics=semantics)
+    _class.statechart = statechart
 
-    model.classes[class_name] = lambda: class_
+    model.classes[class_name] = lambda: _class
     if default:
       model.default_class = class_name
 
@@ -119,7 +119,7 @@ def load_model(src_file) -> Tuple[Model, Optional[Test]]:
 
   return (model, test)
 
-class InvalidTag(Exception):
+class SkipTag(Exception):
   pass
 
 def load_tree(scxml_node) -> Tuple[State, Dict[str, State]]:
@@ -144,7 +144,7 @@ def load_tree(scxml_node) -> Tuple[State, Dict[str, State]]:
       else:
         state = ShallowHistoryState(name)
     else:
-      raise InvalidTag()
+      raise SkipTag()
 
     initial = xml_node.get("initial", "")
     for xml_child in xml_node.getchildren():
@@ -153,7 +153,7 @@ def load_tree(scxml_node) -> Tuple[State, Dict[str, State]]:
         state.addChild(child)
         if child.short_name == initial:
           state.default_state = child
-      except InvalidTag:
+      except SkipTag:
         pass # skip non-state tags
 
     if not initial and len(state.children) == 1:
@@ -182,7 +182,7 @@ def load_tree(scxml_node) -> Tuple[State, Dict[str, State]]:
   for xml_t, source in transitions:
     # Parse and find target state
     target_string = xml_t.get("target", "")
-    parse_tree = l.parse(target_string, start="target_expr")
+    parse_tree = l.parse(target_string, start="state_ref")
     def find_state(sequence) -> State:
       if sequence.data == "relative_path":
         el = source
@@ -212,8 +212,14 @@ def load_tree(scxml_node) -> Tuple[State, Dict[str, State]]:
     # Actions
     actions = load_actions(xml_t)
     transition.setActions(actions)
-    # todo: set guard
-
+    # Guard
+    cond = xml_t.get("cond")
+    if cond is not None:
+      parse_tree = l.parse(cond, start="expr")
+      # print(parse_tree)
+      # print(parse_tree.pretty())
+      cond_expr = load_expression(parse_tree)
+      transition.setGuard(cond_expr)
     source.addTransition(transition)
 
   return (root, states)
@@ -228,7 +234,7 @@ def load_action(action_node) -> Optional[Action]:
     else:
       return RaiseOutputEvent(name=event, parameters=[], outport=port, time_offset=0)
   else:
-    raise InvalidTag()
+    raise SkipTag()
 
 # parent_node: XML node containing 0 or more action nodes as direct children
 def load_actions(parent_node) -> List[Action]:
@@ -238,6 +244,23 @@ def load_actions(parent_node) -> List[Action]:
       a = load_action(node)
       if a:
         actions.append(a)
-    except InvalidTag:
+    except SkipTag:
       pass # skip non-action tags
-  return actions
+  return actions
+
+class UnknownExpressionType(Exception):
+  pass
+
+def load_expression(parse_node) -> Expression:
+  if parse_node.data == "func_call":
+    function = load_expression(parse_node.children[0])
+    parameters = [load_expression(e) for e in parse_node.children[1].children]
+    return FunctionCall(function, parameters)
+  elif parse_node.data == "string":
+    return StringLiteral(parse_node.children[0].value[1:-1])
+  elif parse_node.data == "identifier":
+    return Identifier(parse_node.children[0].value)
+  elif parse_node.data == "array":
+    elements = [load_expression(e) for e in parse_node.children]
+    return Array(elements)
+  raise UnknownExpressionType()

+ 37 - 45
test/test_files/semantics/order/document_order+c.svg

@@ -4,95 +4,87 @@
 <!-- Generated by graphviz version 2.40.1 (20161225.0304)
  -->
 <!-- Title: state transitions Pages: 1 -->
-<svg width="386pt" height="241pt"
- viewBox="0.00 0.00 385.50 241.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 237)">
+<svg width="224pt" height="221pt"
+ viewBox="0.00 0.00 223.50 221.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 217)">
 <title>state transitions</title>
-<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-237 381.5,-237 381.5,4 -4,4"/>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-217 219.5,-217 219.5,4 -4,4"/>
 <!-- __initial -->
 <g id="node1" class="node">
 <title>__initial</title>
-<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="229" cy="-227.5" rx="5.5" ry="5.5"/>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="148.5" cy="-207.5" rx="5.5" ry="5.5"/>
 </g>
 <!-- _a -->
 <g id="node2" class="node">
 <title>_a</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="298,-194 160,-194 160,-148 298,-148 298,-194"/>
-<text text-anchor="start" x="225.6646" y="-177.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">a</text>
-<text text-anchor="start" x="165.8272" y="-157.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.entered_a</text>
-<polygon fill="#000000" stroke="#000000" points="160,-171 160,-171 298,-171 298,-171 160,-171"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M173,-149C173,-149 285,-149 285,-149 291,-149 297,-155 297,-161 297,-161 297,-181 297,-181 297,-187 291,-193 285,-193 285,-193 173,-193 173,-193 167,-193 161,-187 161,-181 161,-181 161,-161 161,-161 161,-155 167,-149 173,-149"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="176.5,-174 120.5,-174 120.5,-138 176.5,-138 176.5,-174"/>
+<text text-anchor="start" x="145.1646" y="-152.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">a</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M132.8333,-139C132.8333,-139 164.1667,-139 164.1667,-139 169.8333,-139 175.5,-144.6667 175.5,-150.3333 175.5,-150.3333 175.5,-161.6667 175.5,-161.6667 175.5,-167.3333 169.8333,-173 164.1667,-173 164.1667,-173 132.8333,-173 132.8333,-173 127.1667,-173 121.5,-167.3333 121.5,-161.6667 121.5,-161.6667 121.5,-150.3333 121.5,-150.3333 121.5,-144.6667 127.1667,-139 132.8333,-139"/>
 </g>
 <!-- __initial&#45;&gt;_a -->
 <g id="edge1" class="edge">
 <title>__initial&#45;&gt;_a</title>
-<path fill="none" stroke="#000000" d="M229,-221.876C229,-217.5252 229,-211.1081 229,-204.286"/>
-<polygon fill="#000000" stroke="#000000" points="232.5001,-204.1947 229,-194.1947 225.5001,-204.1947 232.5001,-204.1947"/>
-<text text-anchor="middle" x="230.3895" y="-205" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M148.5,-201.9886C148.5,-197.6293 148.5,-191.1793 148.5,-184.4801"/>
+<polygon fill="#000000" stroke="#000000" points="152.0001,-184.0122 148.5,-174.0122 145.0001,-184.0122 152.0001,-184.0122"/>
+<text text-anchor="middle" x="149.8895" y="-185" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _b -->
 <g id="node3" class="node">
 <title>_b</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="218,-120 80,-120 80,-74 218,-74 218,-120"/>
-<text text-anchor="start" x="145.6646" y="-103.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">b</text>
-<text text-anchor="start" x="85.8272" y="-83.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.entered_b</text>
-<polygon fill="#000000" stroke="#000000" points="80,-97 80,-97 218,-97 218,-97 80,-97"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M93,-75C93,-75 205,-75 205,-75 211,-75 217,-81 217,-87 217,-87 217,-107 217,-107 217,-113 211,-119 205,-119 205,-119 93,-119 93,-119 87,-119 81,-113 81,-107 81,-107 81,-87 81,-87 81,-81 87,-75 93,-75"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="137.5,-110 81.5,-110 81.5,-74 137.5,-74 137.5,-110"/>
+<text text-anchor="start" x="106.1646" y="-88.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">b</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M93.8333,-75C93.8333,-75 125.1667,-75 125.1667,-75 130.8333,-75 136.5,-80.6667 136.5,-86.3333 136.5,-86.3333 136.5,-97.6667 136.5,-97.6667 136.5,-103.3333 130.8333,-109 125.1667,-109 125.1667,-109 93.8333,-109 93.8333,-109 88.1667,-109 82.5,-103.3333 82.5,-97.6667 82.5,-97.6667 82.5,-86.3333 82.5,-86.3333 82.5,-80.6667 88.1667,-75 93.8333,-75"/>
 </g>
 <!-- _a&#45;&gt;_b -->
 <g id="edge2" class="edge">
 <title>_a&#45;&gt;_b</title>
-<path fill="none" stroke="#000000" d="M204.126,-147.9916C196.9707,-141.3729 189.058,-134.0537 181.5138,-127.0753"/>
-<polygon fill="#000000" stroke="#000000" points="183.8518,-124.4702 174.1341,-120.2491 179.0985,-129.6089 183.8518,-124.4702"/>
-<text text-anchor="middle" x="195.3895" y="-131" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M137.4285,-137.8314C133.9182,-132.0709 129.9567,-125.57 126.1441,-119.3134"/>
+<polygon fill="#000000" stroke="#000000" points="128.9272,-117.1544 120.7346,-110.4363 122.9496,-120.797 128.9272,-117.1544"/>
+<text text-anchor="middle" x="133.8895" y="-121" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _c -->
 <g id="node4" class="node">
 <title>_c</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="377.5,-120 240.5,-120 240.5,-74 377.5,-74 377.5,-120"/>
-<text text-anchor="start" x="306.5" y="-103.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">c</text>
-<text text-anchor="start" x="246.6626" y="-83.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.entered_c</text>
-<polygon fill="#000000" stroke="#000000" points="241,-97 241,-97 378,-97 378,-97 241,-97"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M253.5,-75C253.5,-75 364.5,-75 364.5,-75 370.5,-75 376.5,-81 376.5,-87 376.5,-87 376.5,-107 376.5,-107 376.5,-113 370.5,-119 364.5,-119 364.5,-119 253.5,-119 253.5,-119 247.5,-119 241.5,-113 241.5,-107 241.5,-107 241.5,-87 241.5,-87 241.5,-81 247.5,-75 253.5,-75"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="215.5,-110 159.5,-110 159.5,-74 215.5,-74 215.5,-110"/>
+<text text-anchor="start" x="184.5" y="-88.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">c</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M171.8333,-75C171.8333,-75 203.1667,-75 203.1667,-75 208.8333,-75 214.5,-80.6667 214.5,-86.3333 214.5,-86.3333 214.5,-97.6667 214.5,-97.6667 214.5,-103.3333 208.8333,-109 203.1667,-109 203.1667,-109 171.8333,-109 171.8333,-109 166.1667,-109 160.5,-103.3333 160.5,-97.6667 160.5,-97.6667 160.5,-86.3333 160.5,-86.3333 160.5,-80.6667 166.1667,-75 171.8333,-75"/>
 </g>
 <!-- _a&#45;&gt;_c -->
 <g id="edge3" class="edge">
 <title>_a&#45;&gt;_c</title>
-<path fill="none" stroke="#000000" d="M253.874,-147.9916C261.0293,-141.3729 268.942,-134.0537 276.4862,-127.0753"/>
-<polygon fill="#000000" stroke="#000000" points="278.9015,-129.6089 283.8659,-120.2491 274.1482,-124.4702 278.9015,-129.6089"/>
-<text text-anchor="middle" x="275.3895" y="-131" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M159.5715,-137.8314C163.0818,-132.0709 167.0433,-125.57 170.8559,-119.3134"/>
+<polygon fill="#000000" stroke="#000000" points="174.0504,-120.797 176.2654,-110.4363 168.0728,-117.1544 174.0504,-120.797"/>
+<text text-anchor="middle" x="171.8895" y="-121" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _d -->
 <g id="node5" class="node">
 <title>_d</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="298,-46 160,-46 160,0 298,0 298,-46"/>
-<text text-anchor="start" x="225.6646" y="-29.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">d</text>
-<text text-anchor="start" x="165.8272" y="-9.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.entered_d</text>
-<polygon fill="#000000" stroke="#000000" points="160,-23 160,-23 298,-23 298,-23 160,-23"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M173,-1C173,-1 285,-1 285,-1 291,-1 297,-7 297,-13 297,-13 297,-33 297,-33 297,-39 291,-45 285,-45 285,-45 173,-45 173,-45 167,-45 161,-39 161,-33 161,-33 161,-13 161,-13 161,-7 167,-1 173,-1"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="191.5,-41 135.5,-41 135.5,-5 191.5,-5 191.5,-41"/>
+<text text-anchor="start" x="160.1646" y="-19.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">d</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M147.8333,-6C147.8333,-6 179.1667,-6 179.1667,-6 184.8333,-6 190.5,-11.6667 190.5,-17.3333 190.5,-17.3333 190.5,-28.6667 190.5,-28.6667 190.5,-34.3333 184.8333,-40 179.1667,-40 179.1667,-40 147.8333,-40 147.8333,-40 142.1667,-40 136.5,-34.3333 136.5,-28.6667 136.5,-28.6667 136.5,-17.3333 136.5,-17.3333 136.5,-11.6667 142.1667,-6 147.8333,-6"/>
 </g>
 <!-- _b&#45;&gt;_d -->
 <g id="edge5" class="edge">
 <title>_b&#45;&gt;_d</title>
-<path fill="none" stroke="#000000" d="M173.874,-73.9916C181.0293,-67.3729 188.942,-60.0537 196.4862,-53.0753"/>
-<polygon fill="#000000" stroke="#000000" points="198.9015,-55.6089 203.8659,-46.2491 194.1482,-50.4702 198.9015,-55.6089"/>
-<text text-anchor="middle" x="195.3895" y="-57" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M123.6879,-73.8711C129.5938,-66.3245 136.5645,-57.4175 143.0091,-49.1828"/>
+<polygon fill="#000000" stroke="#000000" points="145.8126,-51.2796 149.2194,-41.2474 140.3,-46.9654 145.8126,-51.2796"/>
+<text text-anchor="middle" x="139.8895" y="-57" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 <!-- _e -->
 <g id="node6" class="node">
 <title>_e</title>
-<polygon fill="transparent" stroke="transparent" stroke-width="2" points="138,-46 0,-46 0,0 138,0 138,-46"/>
-<text text-anchor="start" x="65.6646" y="-29.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">e</text>
-<text text-anchor="start" x="5.8272" y="-9.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.entered_e</text>
-<polygon fill="#000000" stroke="#000000" points="0,-23 0,-23 138,-23 138,-23 0,-23"/>
-<path fill="none" stroke="#000000" stroke-width="2" d="M13,-1C13,-1 125,-1 125,-1 131,-1 137,-7 137,-13 137,-13 137,-33 137,-33 137,-39 131,-45 125,-45 125,-45 13,-45 13,-45 7,-45 1,-39 1,-33 1,-33 1,-13 1,-13 1,-7 7,-1 13,-1"/>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="113,-46 0,-46 0,0 113,0 113,-46"/>
+<text text-anchor="start" x="53.6646" y="-29.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">e</text>
+<text text-anchor="start" x="6.1668" y="-9.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">onentry/ ^out.bingo</text>
+<polygon fill="#000000" stroke="#000000" points=".5,-23 .5,-23 113.5,-23 113.5,-23 .5,-23"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M13,-1C13,-1 100,-1 100,-1 106,-1 112,-7 112,-13 112,-13 112,-33 112,-33 112,-39 106,-45 100,-45 100,-45 13,-45 13,-45 7,-45 1,-39 1,-33 1,-33 1,-13 1,-13 1,-7 7,-1 13,-1"/>
 </g>
 <!-- _b&#45;&gt;_e -->
 <g id="edge4" class="edge">
 <title>_b&#45;&gt;_e</title>
-<path fill="none" stroke="#000000" d="M124.126,-73.9916C116.9707,-67.3729 109.058,-60.0537 101.5138,-53.0753"/>
-<polygon fill="#000000" stroke="#000000" points="103.8518,-50.4702 94.1341,-46.2491 99.0985,-55.6089 103.8518,-50.4702"/>
-<text text-anchor="middle" x="115.3895" y="-57" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+<path fill="none" stroke="#000000" d="M95.5749,-73.8711C91.0031,-67.9192 85.7814,-61.1211 80.6756,-54.4739"/>
+<polygon fill="#000000" stroke="#000000" points="83.1952,-52.0085 74.328,-46.21 77.6439,-56.2726 83.1952,-52.0085"/>
+<text text-anchor="middle" x="90.8895" y="-57" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
 </g>
 </g>
 </svg>

+ 4 - 27
test/test_files/semantics/order/document_order.xml

@@ -10,32 +10,18 @@
   <class name="c" default="true">
     <scxml initial="a" big_step_maximality="take_one">
       <state id="a">
-        <onentry>
-          <raise event="entered_a" port="out"/>
-        </onentry>
         <transition target="../b"/>
         <transition target="../c"/>
       </state>
       <state id="b">
-        <onentry>
-          <raise event="entered_b" port="out"/>
-        </onentry>
         <transition target="../e"/>
         <transition target="../d"/>
       </state>
-      <state id="c">
-        <onentry>
-          <raise event="entered_c" port="out"/>
-        </onentry>
-      </state>
-      <state id="d">
-        <onentry>
-          <raise event="entered_d" port="out"/>
-        </onentry>
-      </state>
+      <state id="c"/>
+      <state id="d"/>
       <state id="e">
         <onentry>
-          <raise event="entered_e" port="out"/>
+          <raise event="bingo" port="out"/>
         </onentry>
       </state>
     </scxml>
@@ -43,16 +29,7 @@
   <test>
     <expected>
       <slot>
-        <!-- initialization -->
-        <event name="entered_a" port="out"/>
-      </slot>
-      <slot>
-        <!-- big step -->
-        <event name="entered_b" port="out"/>
-      </slot>
-      <slot>
-        <!-- big step -->
-        <event name="entered_e" port="out"/>
+        <event name="bingo" port="out"/>
       </slot>
     </expected>
   </test>

+ 2 - 2
test/test_files/semantics/order/parallel_document_order.xml

@@ -12,7 +12,7 @@
       <parallel id="p">
         <state id="region1" initial="s1">
           <state id="s1">
-            <transition target="../s2" cond="INSTATE('/p/region2/s1')">
+            <transition target="../s2" cond='INSTATE(["/p/region2/s1"])'>
               <raise port="out" event="t1"/>
             </transition>
           </state>
@@ -20,7 +20,7 @@
         </state>
         <state id="region2" initial="s1">
           <state id="s1">
-            <transition target="../s2" cond="INSTATE('/p/region1/s1')">
+            <transition target="../s2" cond='INSTATE(["/p/region1/s1"])'>
               <raise port="out" event="t2"/>
             </transition>
           </state>