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

Moved tests that are broken and wont be fixed in the short term to separate directory

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

+ 4 - 0
src/sccd/compiler/generic_generator.py

@@ -164,6 +164,10 @@ class GenericGenerator(Visitor):
             self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "big_step_maximality"), GLC.Property("StatechartSemantics", "TakeOne"))
         elif statechart.big_step_maximality == "take_many":
             self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "big_step_maximality"), GLC.Property("StatechartSemantics", "TakeMany"))
+        if statechart.combo_step_maximality == "take_one":
+            self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "combo_step_maximality"), GLC.Property("StatechartSemantics", "ComboTakeOne"))
+        elif statechart.combo_step_maximality == "take_many":
+            self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "combo_step_maximality"), GLC.Property("StatechartSemantics", "ComboTakeMany"))
         if statechart.internal_event_lifeline == "queue":
             self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "internal_event_lifeline"), GLC.Property("StatechartSemantics", "Queue"))
         elif statechart.internal_event_lifeline == "next_small_step":

+ 1 - 0
src/sccd/compiler/sccd_constructs.py

@@ -654,6 +654,7 @@ class StateChart(Visitable):
             return result
 
         self.big_step_maximality = getSemanticOption("big_step_maximality", ["take_one", "take_many"], "take_many")
+        self.combo_step_maximality = getSemanticOption("combo_step_maximality", ["take_one", "take_many"], "take_one")
         self.internal_event_lifeline = getSemanticOption("internal_event_lifeline", ["next_small_step", "next_combo_step", "queue"], "queue")
         self.input_event_lifeline = getSemanticOption("input_event_lifeline", ["first_small_step", "first_combo_step", "whole"], "first_combo_step")
         self.priority = getSemanticOption("priority", ["source_parent", "source_child"], "source_parent")

+ 8 - 0
src/sccd/compiler/schema/sccd.xsd

@@ -193,6 +193,14 @@
         </xsd:restriction>
       </xsd:simpleType>
     </xsd:attribute>
+    <xsd:attribute name="combo_step_maximality">
+      <xsd:simpleType>
+        <xsd:restriction base="xsd:string">
+          <xsd:enumeration value="take_one"/>
+          <xsd:enumeration value="take_many"/>
+        </xsd:restriction>
+      </xsd:simpleType>
+    </xsd:attribute>
     <xsd:attribute name="priority">
       <xsd:simpleType>
         <xsd:restriction base="xsd:string">

+ 8 - 7
src/sccd/runtime/controller.py

@@ -5,6 +5,7 @@ from sccd.runtime.event_queue import EventQueue, EventQueueDeque, Timestamp
 from sccd.runtime.event import *
 from sccd.runtime.object_manager import ObjectManager
 from sccd.runtime.infinity import INFINITY
+from sccd.runtime.debug import print_debug
 
 # The Controller class is a primitive that can be used to build backends of any kind:
 # Threads, integration with existing event loop, game loop, test framework, ...
@@ -73,12 +74,12 @@ class Controller:
                 had_unstable = True
                 for i in reversed(range(len(unstable))):
                     instance = unstable[i]
-                    output = instance.big_step(self.simulated_time, [])
+                    stable, output = instance.big_step(self.simulated_time, [])
                     process_big_step_output(output)
-                    if instance.is_stable():
+                    if stable:
                         del unstable[i]
             if had_unstable:
-                # print("all stabilized.")
+                print_debug("all instances stabilized.")
                 pass
 
         if now < self.simulated_time:
@@ -90,9 +91,9 @@ class Controller:
             # initialize the object manager, in turn initializing our default class
             # and add the generated events to the queue
             for i in self.object_manager.instances:
-                events = i.initialize(self.simulated_time)
+                stable, events = i.initialize(self.simulated_time)
                 process_big_step_output(events)
-                if not i.is_stable():
+                if not stable:
                     unstable.append(i)
 
         # Actual "event loop"
@@ -105,9 +106,9 @@ class Controller:
                 self.simulated_time = timestamp
             # run all instances for whom there are events
             for instance in entry.targets:
-                output = instance.big_step(timestamp, [entry.event])
+                stable, output = instance.big_step(timestamp, [entry.event])
                 process_big_step_output(output)
-                if not instance.is_stable():
+                if not stable:
                     unstable.append(instance)
 
         # continue to run instances until all are stable

+ 6 - 0
src/sccd/runtime/debug.py

@@ -0,0 +1,6 @@
+import os
+
+DEBUG = os.environ['SCCDDEBUG']
+def print_debug(msg):
+    if DEBUG:
+        print(msg)

+ 3 - 4
src/sccd/runtime/event.py

@@ -1,6 +1,6 @@
 import dataclasses
 from abc import ABC, abstractmethod
-from typing import List, Any
+from typing import List, Any, Tuple
 from sccd.runtime.event_queue import Timestamp
 
 @dataclasses.dataclass(frozen=True)
@@ -25,14 +25,13 @@ class OutputEvent:
 # Interface for all instances and also the Object Manager
 class Instance(ABC):
     @abstractmethod
-    def big_step(self, timestamp: Timestamp, input_events: List[Event]) -> List[OutputEvent]:
+    def initialize(self, timestamp: Timestamp) -> Tuple[bool, List[OutputEvent]]:
         pass
 
     @abstractmethod
-    def is_stable(self) -> bool:
+    def big_step(self, timestamp: Timestamp, input_events: List[Event]) -> Tuple[bool, List[OutputEvent]]:
         pass
 
-
 class OutputPortTarget(EventTarget):
     def __init__(self, outport: str):
         self.outport = outport

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

@@ -29,11 +29,11 @@ class ObjectManager(Instance):
         self.instances.append(i)
         return i
 
-    def initialize(self, now: Timestamp) -> List[OutputEvent]:
-        return []
+    def initialize(self, now: Timestamp) -> Tuple[bool, List[OutputEvent]]:
+        return True, []
 
     # Implementation of super class: Instance
-    def big_step(self, timestamp: Timestamp, input_events: List[Event]) -> List[OutputEvent]:
+    def big_step(self, timestamp: Timestamp, input_events: List[Event]) -> Tuple[bool, List[OutputEvent]]:
         output = []
         for e in input_events:
             try:
@@ -44,11 +44,7 @@ class ObjectManager(Instance):
                     output.extend(o)
             except KeyError:
                 pass
-        return output
-
-    # the object manager only makes a "transition" as a result of an event
-    def is_stable(self) -> bool:
-        return True
+        return True, output
 
     def _assoc_ref(self, input_string) -> List[Tuple[str,int]]:
         if len(input_string) == 0:

+ 16 - 23
src/sccd/runtime/statecharts_core.py

@@ -4,20 +4,15 @@ The classes and functions needed to run (compiled) SCCD models.
 
 import os
 import termcolor
-from typing import List
+from typing import List, Tuple
 from sccd.runtime.infinity import INFINITY
 from sccd.runtime.event_queue import Timestamp
 from sccd.runtime.event import Event, OutputEvent, Instance, InstancesTarget
+from sccd.runtime.debug import print_debug
 from collections import Counter
 
-DEBUG = os.environ['SCCDDEBUG']
 ELSE_GUARD = "ELSE_GUARD"
 
-def print_debug(msg):
-    if DEBUG:
-        print(msg)
-
-
 class RuntimeException(Exception):
     """
     Base class for runtime exceptions.
@@ -103,6 +98,9 @@ class StatechartSemantics:
     # Big Step Maximality
     TakeOne = 0
     TakeMany = 1
+    # Combo Step Maximality
+    ComboTakeOne = 0
+    ComboTakeMany = 1
     # Concurrency - not implemented yet
     Single = 0
     Many = 1
@@ -125,6 +123,7 @@ class StatechartSemantics:
     def __init__(self):
         # default semantics:
         self._big_step_maximality = self.TakeMany
+        self.combo_step_maximality = self.TakeOne
         self.internal_event_lifeline = self.Queue
         self.input_event_lifeline = self.FirstComboStep
         self.priority = self.SourceParent
@@ -346,11 +345,6 @@ class StatechartInstance(Instance):
         self.configuration_bitmap = 0
         self.eventless_states = 0 # number of states in current configuration that have at least one eventless outgoing transition.
 
-        # after creation, an instance is never stable, because it must enter its default configuration.
-        # entering the default configuration always makes up the first 'big step' of an instance.
-        # in each round, unstable instances are scheduled by the controller even if there are no events for them.
-        self.stable = False
-
         self.transition_mem = {}
         self.config_mem = {}
 
@@ -362,11 +356,8 @@ class StatechartInstance(Instance):
 
         self.ignore_events = Counter() # Mapping from event name to future times to ignore such event. Used for canceling timers.
 
-    # whether the statechart MAY still perform at least one transition, even in the absense of an event
-    def is_stable(self) -> bool:
-        return self.stable
-
-    def initialize(self, now: Timestamp) -> List[OutputEvent]:
+    # enter default states, generating a set of output events
+    def initialize(self, now: Timestamp) -> Tuple[bool, List[OutputEvent]]:
         states = self.model.root.getEffectiveTargetStates(self)
         self.configuration.extend(states)
         self.configuration_bitmap = sum([2**s.state_id for s in states])
@@ -374,11 +365,11 @@ class StatechartInstance(Instance):
             self.eventless_states += state.has_eventless_transitions
             if state.enter:
                 state.enter(self)
-        self.stable = not self.eventless_states
-        return self._big_step.output_events
+        stable = not self.eventless_states
+        return (stable, self._big_step.output_events)
 
-    # perform a big step. returns a set of output events
-    def big_step(self, now: Timestamp, input_events: List[Event]) -> List[OutputEvent]:
+    # perform a big step. generating a set of output events
+    def big_step(self, now: Timestamp, input_events: List[Event]) -> Tuple[bool, List[OutputEvent]]:
         filtered = []
         for e in input_events:
             if e.name in self.ignore_events:
@@ -400,8 +391,8 @@ class StatechartInstance(Instance):
             print_debug(termcolor.colored('completed big step', 'red'))
 
         # can the next big step still contain transitions, even if there are no input events?
-        self.stable = not self.eventless_states or (not filtered and not self._big_step.has_stepped)
-        return self._big_step.output_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):
         self._combo_step.next()
@@ -469,7 +460,9 @@ class StatechartInstance(Instance):
                 if s.state_id == state_id:
                     break
             else:
+                print_debug("not in state"+str(state_strings))
                 return False
+        print_debug("in state"+str(state_strings))
         return True
 
 

+ 11 - 8
test/semantics/original_semantics/history_deep.xml

@@ -6,9 +6,12 @@
     <description>
         Testing history deep.
     </description>
-    <outport name="test_output" />
+    <outport name="out" />
     <class name="Class1" default="true">
-        <scxml>
+        <scxml
+            big_step_maximality="take_many"
+            combo_step_maximality="take_many"
+            internal_event_lifeline="next_combo_step">
             <parallel id="parallel">
                 <state id="orthogonal" initial="wrapper">
                     <state id="wrapper" initial="state_1">
@@ -47,19 +50,19 @@
                     </state>
                     <state id="step1">
                         <transition cond="INSTATE('/parallel/orthogonal/wrapper/state_2/inner_4')" target="../step2">
-                            <raise port="test_output" event="check1" />
+                            <raise port="out" event="check1" />
                             <raise event="to_outer" />
                         </transition>
                     </state>
                     <state id="step2">
                         <transition cond="INSTATE('/parallel/orthogonal/outer')" target="../step3">
-                            <raise port="test_output" event="check2" />
+                            <raise port="out" event="check2" />
                             <raise event="to_history" />
                         </transition>
                     </state>
                     <state id="step3">
                         <transition cond="INSTATE('/parallel/orthogonal/wrapper/state_2/inner_4')" target="../end">
-                            <raise port="test_output" event="check3" />
+                            <raise port="out" event="check3" />
                         </transition>
                     </state>
                     <state id="end"/>
@@ -70,13 +73,13 @@
     <test>
        <expected>
            <slot>
-               <event name="check1" port="test_output"/>
+               <event name="check1" port="out"/>
            </slot>
            <slot>
-               <event name="check2" port="test_output"/>
+               <event name="check2" port="out"/>
            </slot>
            <slot>
-               <event name="check3" port="test_output"/>
+               <event name="check3" port="out"/>
            </slot>
         </expected>
     </test>

test/semantics/event_lifeline/40_event_consuming_whole_take_one.xml → test/wontfix/40_event_consuming_whole_take_one.xml


test/semantics/event_lifeline/41_event_consuming_whole_take_many.xml → test/wontfix/41_event_consuming_whole_take_many.xml


test/semantics/no_statechart/00_no_statechart_js.xml → test/wontfix/no_statechart/00_no_statechart_js.xml


test/semantics/no_statechart/00_no_statechart_py.xml → test/wontfix/no_statechart/00_no_statechart_py.xml


test/semantics/original_semantics/after_0.xml → test/wontfix/original_semantics/after_0.xml


test/semantics/original_semantics/associate_event.xml → test/wontfix/original_semantics/associate_event.xml


test/semantics/original_semantics/disassociate_event.xml → test/wontfix/original_semantics/disassociate_event.xml


test/semantics/original_semantics/event_consuming.xml → test/wontfix/original_semantics/event_consuming.xml


test/semantics/original_semantics/event_consuming_2.xml → test/wontfix/original_semantics/event_consuming_2.xml


test/semantics/original_semantics/guard.xml → test/wontfix/original_semantics/guard.xml


test/semantics/original_semantics/object_manager.xml → test/wontfix/original_semantics/object_manager.xml


test/semantics/timing/00_rapid_js.xml → test/wontfix/timing/00_rapid_js.xml


test/semantics/timing/00_rapid_py.xml → test/wontfix/timing/00_rapid_py.xml


test/semantics/timing/10_input_event_timeout_py.old → test/wontfix/timing/10_input_event_timeout_py.old