Quellcode durchsuchen

Entering a history state whose parent hasn't been exited before should exit the parent's default state.

Joeri Exelmans vor 5 Jahren
Ursprung
Commit
9a65f34293

+ 5 - 4
src/sccd/cd/cd.py

@@ -28,22 +28,23 @@ class SingleInstanceCD(AbstractCD):
     return self.statechart
 
   def print(self):
+    print("%d states. %d transitions." % (len(self.statechart.tree.state_list), len(self.statechart.tree.transition_list)))
     for inport, events in self.statechart.inport_events.items():
       print("Inport \"%s\" events:" % inport)
       for event_id in events:
         print("  %s" % self.globals.events.get_name(event_id))
-    print()
+    # print()
     for outport in self.globals.outports.names:
       print("Outport \"%s\" events:" % outport)
       for event_name, port in self.statechart.event_outport.items():
         if port == outport:
           print("  %s" % event_name)
-    print()
+    # print()
     print("Internal events:")
     for event_id in bm_items(self.statechart.internal_events):
       print("  %s" % self.globals.events.get_name(event_id))
-    print()
+    # print()
     print("All event triggers:")
     for event_id in bm_items(self.statechart.events):
       print("  %s" % self.globals.events.get_name(event_id))
-    print()
+    # print()

+ 7 - 9
src/sccd/statechart/dynamic/statechart_execution.py

@@ -10,9 +10,8 @@ from sccd.util import timer
 # Set of current states etc.
 class StatechartExecution:
 
-    def __init__(self, statechart: Statechart, instance):
+    def __init__(self, statechart: Statechart):
         self.statechart = statechart
-        self.instance = instance
 
         self.gc_memory = None
         self.rhs_memory = None
@@ -22,8 +21,9 @@ class StatechartExecution:
         # set of current states
         self.configuration: Bitmap = Bitmap()
 
-        # mapping from history_id to set of states to enter if history is target of transition
-        self.history_values: List[Bitmap] = {}
+        # Mapping from history_id to set of states to enter if history is target of transition
+        # By default, if the parent of a history state has never been exited before, the parent's default states should be entered.
+        self.history_values: List[Bitmap] = [h.parent.opt.ts_static for h in statechart.tree.history_states]
 
         # For each AfterTrigger in the statechart tree, we keep an expected 'id' that is
         # a parameter to a future 'after' event. This 'id' is incremented each time a timer
@@ -63,14 +63,12 @@ class StatechartExecution:
             # Sequence of exit states is the intersection between set of current states and the arena's descendants.
             timer.start("exit set")
             exit_ids = self.configuration & t.opt.arena.opt.descendants
-            timer.stop("exit set")
             exit_set = self._ids_to_states(bm_reverse_items(exit_ids))
+            timer.stop("exit set")
 
 
             timer.start("enter set")
             # Sequence of enter states is more complex but has for a large part already been computed statically.
-            if t.opt.enter_states_dynamic:
-                print(t.opt.enter_states_dynamic)
             enter_ids = t.opt.enter_states_static | reduce(lambda x,y: x|y, (self.history_values[s.history_id] for s in t.opt.enter_states_dynamic), Bitmap())
             enter_set = self._ids_to_states(bm_items(enter_ids))
             timer.stop("enter set")
@@ -91,11 +89,13 @@ class StatechartExecution:
             timer.stop("exit states")
 
             # execute transition action(s)
+            timer.start("actions")
             self.rhs_memory.push_frame(t.scope) # make room for event parameters on stack
             if t.trigger:
                 t.trigger.copy_params_to_stack(ctx)
             self._perform_actions(ctx, t.actions)
             self.rhs_memory.pop_frame()
+            timer.stop("actions")
 
             timer.start("enter states")
             # enter states...
@@ -144,10 +144,8 @@ class StatechartExecution:
 
     @staticmethod
     def _perform_actions(ctx: EvalContext, actions: List[Action]):
-        timer.start("actions")
         for a in actions:
             a.exec(ctx)
-        timer.stop("actions")
 
     def _start_timers(self, triggers: List[AfterTrigger]):
         for after in triggers:

+ 1 - 1
src/sccd/statechart/dynamic/statechart_instance.py

@@ -27,7 +27,7 @@ class StatechartInstance(Instance):
     def __init__(self, statechart: Statechart, object_manager):
         self.object_manager = object_manager
 
-        self.execution = StatechartExecution(statechart, self)
+        self.execution = StatechartExecution(statechart)
 
         semantics = statechart.semantics
 

+ 1 - 1
test/test_files/UNTESTED

@@ -1,3 +1,3 @@
 Missing tests (=TODO):
 
- - History target of a transition, but parent of history state has not yet been exited before. (will probably crash at the moment)
+ - Priority and order of small steps semantic aspect

+ 3 - 3
test/test_files/features/history/test_history.svg

@@ -32,7 +32,7 @@
 <title>_state_3</title>
 <polygon fill="transparent" stroke="transparent" stroke-width="2" points="123,-348 0,-348 0,-302 123,-302 123,-348"/>
 <text text-anchor="start" x="42.3236" y="-331.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">state_3</text>
-<text text-anchor="start" x="6.4994" y="-311.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">entry ^out.in_state_3</text>
+<text text-anchor="start" x="6.164" y="-311.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">enter ^out.in_state_3</text>
 <polygon fill="#000000" stroke="#000000" points=".5,-325 .5,-325 123.5,-325 123.5,-325 .5,-325"/>
 <path fill="none" stroke="#000000" stroke-width="2" d="M13,-303C13,-303 110,-303 110,-303 116,-303 122,-309 122,-315 122,-315 122,-335 122,-335 122,-341 116,-347 110,-347 110,-347 13,-347 13,-347 7,-347 1,-341 1,-335 1,-335 1,-315 1,-315 1,-309 7,-303 13,-303"/>
 </g>
@@ -66,7 +66,7 @@
 <title>_composite_1_state_1</title>
 <polygon fill="transparent" stroke="transparent" stroke-width="2" points="155,-154 32,-154 32,-108 155,-108 155,-154"/>
 <text text-anchor="start" x="74.3236" y="-137.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">state_1</text>
-<text text-anchor="start" x="38.4994" y="-117.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">entry ^out.in_state_1</text>
+<text text-anchor="start" x="38.164" y="-117.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">enter ^out.in_state_1</text>
 <polygon fill="#000000" stroke="#000000" points="32.5,-131 32.5,-131 155.5,-131 155.5,-131 32.5,-131"/>
 <path fill="none" stroke="#000000" stroke-width="2" d="M45,-109C45,-109 142,-109 142,-109 148,-109 154,-115 154,-121 154,-121 154,-141 154,-141 154,-147 148,-153 142,-153 142,-153 45,-153 45,-153 39,-153 33,-147 33,-141 33,-141 33,-121 33,-121 33,-115 39,-109 45,-109"/>
 </g>
@@ -82,7 +82,7 @@
 <title>_composite_1_state_2</title>
 <polygon fill="transparent" stroke="transparent" stroke-width="2" points="155,-62 32,-62 32,-16 155,-16 155,-62"/>
 <text text-anchor="start" x="74.3236" y="-45.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">state_2</text>
-<text text-anchor="start" x="38.4994" y="-25.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">entry ^out.in_state_2</text>
+<text text-anchor="start" x="38.164" y="-25.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">enter ^out.in_state_2</text>
 <polygon fill="#000000" stroke="#000000" points="32.5,-39 32.5,-39 155.5,-39 155.5,-39 32.5,-39"/>
 <path fill="none" stroke="#000000" stroke-width="2" d="M45,-17C45,-17 142,-17 142,-17 148,-17 154,-23 154,-29 154,-29 154,-49 154,-49 154,-55 148,-61 142,-61 142,-61 45,-61 45,-61 39,-61 33,-55 33,-49 33,-49 33,-29 33,-29 33,-23 39,-17 45,-17"/>
 </g>

+ 106 - 0
test/test_files/features/history/test_history_default.svg

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by graphviz version 2.40.1 (20161225.0304)
+ -->
+<!-- Title: state transitions Pages: 1 -->
+<svg width="210pt" height="467pt"
+ viewBox="0.00 0.00 210.00 467.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 463)">
+<title>state transitions</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-463 206,-463 206,4 -4,4"/>
+<g id="clust1" class="cluster">
+<title>cluster__composite</title>
+<path fill="none" stroke="#000000" stroke-width="2" d="M20,-8C20,-8 182,-8 182,-8 188,-8 194,-14 194,-20 194,-20 194,-344 194,-344 194,-350 188,-356 182,-356 182,-356 20,-356 20,-356 14,-356 8,-350 8,-344 8,-344 8,-20 8,-20 8,-14 14,-8 20,-8"/>
+<text text-anchor="start" x="73.6622" y="-337.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">composite</text>
+</g>
+<g id="clust2" class="cluster">
+<title>cluster__composite_b</title>
+<path fill="none" stroke="#000000" stroke-width="2" d="M28,-16C28,-16 156,-16 156,-16 162,-16 168,-22 168,-28 168,-28 168,-224 168,-224 168,-230 162,-236 156,-236 156,-236 28,-236 28,-236 22,-236 16,-230 16,-224 16,-224 16,-28 16,-28 16,-22 22,-16 28,-16"/>
+<text text-anchor="start" x="88.6646" y="-217.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">b</text>
+</g>
+<!-- __initial -->
+<g id="node1" class="node">
+<title>__initial</title>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="34" cy="-453.5" rx="5.5" ry="5.5"/>
+</g>
+<!-- _outer -->
+<g id="node2" class="node">
+<title>_outer</title>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="62,-420 6,-420 6,-384 62,-384 62,-420"/>
+<text text-anchor="start" x="20.329" y="-398.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">outer</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M18.3333,-385C18.3333,-385 49.6667,-385 49.6667,-385 55.3333,-385 61,-390.6667 61,-396.3333 61,-396.3333 61,-407.6667 61,-407.6667 61,-413.3333 55.3333,-419 49.6667,-419 49.6667,-419 18.3333,-419 18.3333,-419 12.6667,-419 7,-413.3333 7,-407.6667 7,-407.6667 7,-396.3333 7,-396.3333 7,-390.6667 12.6667,-385 18.3333,-385"/>
+</g>
+<!-- __initial&#45;&gt;_outer -->
+<g id="edge1" class="edge">
+<title>__initial&#45;&gt;_outer</title>
+<path fill="none" stroke="#000000" d="M34,-447.9886C34,-443.6293 34,-437.1793 34,-430.4801"/>
+<polygon fill="#000000" stroke="#000000" points="37.5001,-430.0122 34,-420.0122 30.5001,-430.0122 37.5001,-430.0122"/>
+<text text-anchor="middle" x="35.3895" y="-431" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+</g>
+<!-- _composite_history -->
+<g id="node6" class="node">
+<title>_composite_history</title>
+<ellipse fill="transparent" stroke="#000000" stroke-width="2" cx="34" cy="-300" rx="18" ry="18"/>
+<text text-anchor="middle" x="34" y="-296.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">H</text>
+</g>
+<!-- _outer&#45;&gt;_composite_history -->
+<g id="edge4" class="edge">
+<title>_outer&#45;&gt;_composite_history</title>
+<path fill="none" stroke="#000000" d="M34,-383.7644C34,-368.317 34,-345.9149 34,-328.164"/>
+<polygon fill="#000000" stroke="#000000" points="37.5001,-328.0776 34,-318.0777 30.5001,-328.0777 37.5001,-328.0776"/>
+<text text-anchor="middle" x="35.3895" y="-367" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+</g>
+<!-- _composite -->
+<!-- _composite_initial -->
+<g id="node4" class="node">
+<title>_composite_initial</title>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="158" cy="-300" rx="5.5" ry="5.5"/>
+</g>
+<!-- _composite_b -->
+<!-- _composite_initial&#45;&gt;_composite_b -->
+<g id="edge2" class="edge">
+<title>_composite_initial&#45;&gt;_composite_b</title>
+<path fill="none" stroke="#000000" d="M158.0911,-294.3042C158.2368,-285.2002 158.5386,-266.3388 158.86,-246.2472"/>
+<polygon fill="#000000" stroke="#000000" points="162.3635,-246.0543 159.024,-235.9995 155.3644,-245.9422 162.3635,-246.0543"/>
+<text text-anchor="middle" x="159.3895" y="-256" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+</g>
+<!-- _composite_a -->
+<g id="node5" class="node">
+<title>_composite_a</title>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="130,-318 74,-318 74,-282 130,-282 130,-318"/>
+<text text-anchor="start" x="98.6646" y="-296.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">a</text>
+<path fill="none" stroke="#000000" stroke-width="2" d="M86.3333,-283C86.3333,-283 117.6667,-283 117.6667,-283 123.3333,-283 129,-288.6667 129,-294.3333 129,-294.3333 129,-305.6667 129,-305.6667 129,-311.3333 123.3333,-317 117.6667,-317 117.6667,-317 86.3333,-317 86.3333,-317 80.6667,-317 75,-311.3333 75,-305.6667 75,-305.6667 75,-294.3333 75,-294.3333 75,-288.6667 80.6667,-283 86.3333,-283"/>
+</g>
+<!-- _composite_b_initial -->
+<g id="node8" class="node">
+<title>_composite_b_initial</title>
+<ellipse fill="#000000" stroke="#000000" stroke-width="2" cx="132" cy="-175" rx="5.5" ry="5.5"/>
+</g>
+<!-- _composite_b_s2 -->
+<g id="node9" class="node">
+<title>_composite_b_s2</title>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="160,-70 80,-70 80,-24 160,-24 160,-70"/>
+<text text-anchor="start" x="113.6646" y="-53.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">s2</text>
+<text text-anchor="start" x="85.5072" y="-33.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">enter ^out.s2</text>
+<polygon fill="#000000" stroke="#000000" points="80,-47 80,-47 160,-47 160,-47 80,-47"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M93,-25C93,-25 147,-25 147,-25 153,-25 159,-31 159,-37 159,-37 159,-57 159,-57 159,-63 153,-69 147,-69 147,-69 93,-69 93,-69 87,-69 81,-63 81,-57 81,-57 81,-37 81,-37 81,-31 87,-25 93,-25"/>
+</g>
+<!-- _composite_b_initial&#45;&gt;_composite_b_s2 -->
+<g id="edge3" class="edge">
+<title>_composite_b_initial&#45;&gt;_composite_b_s2</title>
+<path fill="none" stroke="#000000" d="M130.6684,-169.5354C128.9008,-161.7901 126,-147.1522 126,-134.5 126,-134.5 126,-134.5 126,-87.5 126,-85.1011 125.8957,-82.6307 125.7146,-80.1495"/>
+<polygon fill="#000000" stroke="#000000" points="129.1758,-79.6033 124.6084,-70.0436 122.2174,-80.3651 129.1758,-79.6033"/>
+<text text-anchor="middle" x="127.3895" y="-108" font-family="Helvetica,sans-Serif" font-size="10.00" fill="#000000"> </text>
+</g>
+<!-- _composite_b_s1 -->
+<g id="node10" class="node">
+<title>_composite_b_s1</title>
+<polygon fill="transparent" stroke="transparent" stroke-width="2" points="104,-198 24,-198 24,-152 104,-152 104,-198"/>
+<text text-anchor="start" x="57.6646" y="-181.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">s1</text>
+<text text-anchor="start" x="29.5072" y="-161.2" font-family="Helvetica,sans-Serif" font-size="12.00" fill="#000000">enter ^out.s1</text>
+<polygon fill="#000000" stroke="#000000" points="24,-175 24,-175 104,-175 104,-175 24,-175"/>
+<path fill="none" stroke="#000000" stroke-width="2" d="M37,-153C37,-153 91,-153 91,-153 97,-153 103,-159 103,-165 103,-165 103,-185 103,-185 103,-191 97,-197 91,-197 91,-197 37,-197 37,-197 31,-197 25,-191 25,-185 25,-185 25,-165 25,-165 25,-159 31,-153 37,-153"/>
+</g>
+</g>
+</svg>

+ 45 - 0
test/test_files/features/history/test_history_default.xml

@@ -0,0 +1,45 @@
+<test>
+  <!-- Entering a history state whose parent hasn't been exited before:
+       should enter the parent's default state -->
+  <statechart>
+    <inport name="in">
+      <event name="start"/>
+    </inport>
+    <outport name="out">
+      <event name="s1"/>
+      <event name="s2"/>
+    </outport>
+
+    <root initial="outer">
+      <state id="outer">
+        <transition target="/composite/history"/>
+      </state>
+      <state id="composite" initial="b">
+        <state id="a"/>
+        <state id="b" initial="s2">
+          <state id="s1">
+            <onentry>
+              <raise event="s1"/>
+            </onentry>
+          </state>
+          <state id="s2">
+            <onentry>
+              <raise event="s2"/>
+            </onentry>
+          </state>
+        </state>
+        <history id="history" type="shallow"/>
+      </state>
+    </root>
+  </statechart>
+
+  <input>
+    <event port="in" name="start" time="0 d"/>
+  </input>
+
+  <output>
+    <big_step>
+      <event port="out" name="s2"/>
+    </big_step>
+  </output>
+</test>