瀏覽代碼

fixed javascript backend

Simon Van Mierlo 9 年之前
父節點
當前提交
a10be18c2e

+ 422 - 0
examples/HTTP_client/client.py

@@ -0,0 +1,422 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Date:   Wed Aug 10 09:45:49 2016
+
+Model author: Yentl Van Tendeloo
+Model name:   HTTP client
+Model description:
+HTTP client in SCCD
+"""
+
+from sccd.runtime.statecharts_core import *
+import time
+import os
+import urllib
+import sys
+import json
+
+# package "HTTP client"
+
+class Prompt(RuntimeClassBase):
+    def __init__(self, controller):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        Prompt.user_defined_constructor(self)
+    
+    def user_defined_constructor(self):
+        self.counter = 0
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /init
+        self.states["/init"] = State(1, self)
+        self.states["/init"].setEnter(self._init_enter)
+        
+        # state /initializing
+        self.states["/initializing"] = State(2, self)
+        self.states["/initializing"].setEnter(self._initializing_enter)
+        self.states["/initializing"].setExit(self._initializing_exit)
+        
+        # state /send_request
+        self.states["/send_request"] = State(3, self)
+        self.states["/send_request"].setEnter(self._send_request_enter)
+        self.states["/send_request"].setExit(self._send_request_exit)
+        
+        # state /wait_reply
+        self.states["/wait_reply"] = State(4, self)
+        self.states["/wait_reply"].setEnter(self._wait_reply_enter)
+        self.states["/wait_reply"].setExit(self._wait_reply_exit)
+        
+        # add children
+        self.states[""].addChild(self.states["/init"])
+        self.states[""].addChild(self.states["/initializing"])
+        self.states[""].addChild(self.states["/send_request"])
+        self.states[""].addChild(self.states["/wait_reply"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/init"]
+        
+        # transition /init
+        _init_0 = Transition(self, self.states["/init"], [self.states["/initializing"]])
+        _init_0.setAction(self._init_0_exec)
+        _init_0.setTrigger(Event("instance_created", None))
+        self.states["/init"].addTransition(_init_0)
+        
+        # transition /initializing
+        _initializing_0 = Transition(self, self.states["/initializing"], [self.states["/initializing"]])
+        _initializing_0.setTrigger(Event("_0after"))
+        self.states["/initializing"].addTransition(_initializing_0)
+        _initializing_1 = Transition(self, self.states["/initializing"], [self.states["/send_request"]])
+        _initializing_1.setTrigger(Event("http_client_ready", None))
+        self.states["/initializing"].addTransition(_initializing_1)
+        
+        # transition /send_request
+        _send_request_0 = Transition(self, self.states["/send_request"], [self.states["/wait_reply"]])
+        _send_request_0.setAction(self._send_request_0_exec)
+        _send_request_0.setTrigger(Event("_1after"))
+        self.states["/send_request"].addTransition(_send_request_0)
+        
+        # transition /wait_reply
+        _wait_reply_0 = Transition(self, self.states["/wait_reply"], [self.states["/wait_reply"]])
+        _wait_reply_0.setTrigger(Event("_2after"))
+        self.states["/wait_reply"].addTransition(_wait_reply_0)
+        _wait_reply_1 = Transition(self, self.states["/wait_reply"], [self.states["/send_request"]])
+        _wait_reply_1.setAction(self._wait_reply_1_exec)
+        _wait_reply_1.setTrigger(Event("HTTP_output", None))
+        self.states["/wait_reply"].addTransition(_wait_reply_1)
+    
+    def _init_enter(self):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, 'to_server', 'HTTPClient', '127.0.0.1', 8080]))
+    
+    def _initializing_enter(self):
+        self.addTimer(0, 1.0)
+    
+    def _initializing_exit(self):
+        self.removeTimer(0)
+    
+    def _send_request_enter(self):
+        self.addTimer(1, 1)
+    
+    def _send_request_exit(self):
+        self.removeTimer(1)
+    
+    def _wait_reply_enter(self):
+        self.addTimer(2, 1.0)
+    
+    def _wait_reply_exit(self):
+        self.removeTimer(2)
+    
+    def _init_0_exec(self, parameters):
+        instancename = parameters[0]
+        self.big_step.outputEventOM(Event("start_instance", None, [self, instancename]))
+    
+    def _send_request_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'to_server', Event("HTTP_input", None, [str(self.counter), 'parent'])]))
+        print("Sending request: %s" % self.counter)
+        self.counter += 1
+    
+    def _wait_reply_1_exec(self, parameters):
+        data = parameters[0]
+        print("Got response: %s" % data)
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/init"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class HTTPClient(RuntimeClassBase):
+    def __init__(self, controller, hostname, port):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        HTTPClient.user_defined_constructor(self, hostname, port)
+    
+    def user_defined_constructor(self, hostname, port):
+        self.socket = None
+        self.destination = (hostname, port)
+        self.received_data = ""
+        self.send_data = ""
+        self.queue = []
+        self.destinations = []
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /init
+        self.states["/init"] = State(1, self)
+        self.states["/init"].setEnter(self._init_enter)
+        
+        # state /connecting
+        self.states["/connecting"] = State(2, self)
+        self.states["/connecting"].setEnter(self._connecting_enter)
+        
+        # state /connected
+        self.states["/connected"] = ParallelState(3, self)
+        
+        # state /connected/listening
+        self.states["/connected/listening"] = State(4, self)
+        
+        # state /connected/listening/listen
+        self.states["/connected/listening/listen"] = State(5, self)
+        self.states["/connected/listening/listen"].setEnter(self._connected_listening_listen_enter)
+        
+        # state /connected/listening/close
+        self.states["/connected/listening/close"] = State(6, self)
+        
+        # state /connected/sending
+        self.states["/connected/sending"] = State(7, self)
+        
+        # state /connected/sending/waiting_for_data
+        self.states["/connected/sending/waiting_for_data"] = State(8, self)
+        
+        # state /connected/sending/transferring
+        self.states["/connected/sending/transferring"] = State(9, self)
+        
+        # state /connected/queueing
+        self.states["/connected/queueing"] = State(10, self)
+        
+        # state /connected/queueing/queueing
+        self.states["/connected/queueing/queueing"] = State(11, self)
+        self.states["/connected/queueing/queueing"].setEnter(self._connected_queueing_queueing_enter)
+        
+        # state /connected/parsing
+        self.states["/connected/parsing"] = State(12, self)
+        
+        # state /connected/parsing/wait_for_header
+        self.states["/connected/parsing/wait_for_header"] = State(13, self)
+        
+        # state /connected/parsing/wait_for_payload
+        self.states["/connected/parsing/wait_for_payload"] = State(14, self)
+        
+        # add children
+        self.states[""].addChild(self.states["/init"])
+        self.states[""].addChild(self.states["/connecting"])
+        self.states[""].addChild(self.states["/connected"])
+        self.states["/connected"].addChild(self.states["/connected/listening"])
+        self.states["/connected"].addChild(self.states["/connected/sending"])
+        self.states["/connected"].addChild(self.states["/connected/queueing"])
+        self.states["/connected"].addChild(self.states["/connected/parsing"])
+        self.states["/connected/listening"].addChild(self.states["/connected/listening/listen"])
+        self.states["/connected/listening"].addChild(self.states["/connected/listening/close"])
+        self.states["/connected/sending"].addChild(self.states["/connected/sending/waiting_for_data"])
+        self.states["/connected/sending"].addChild(self.states["/connected/sending/transferring"])
+        self.states["/connected/queueing"].addChild(self.states["/connected/queueing/queueing"])
+        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_header"])
+        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_payload"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/init"]
+        self.states["/connected/listening"].default_state = self.states["/connected/listening/listen"]
+        self.states["/connected/sending"].default_state = self.states["/connected/sending/waiting_for_data"]
+        self.states["/connected/queueing"].default_state = self.states["/connected/queueing/queueing"]
+        self.states["/connected/parsing"].default_state = self.states["/connected/parsing/wait_for_header"]
+        
+        # transition /init
+        _init_0 = Transition(self, self.states["/init"], [self.states["/connecting"]])
+        _init_0.setAction(self._init_0_exec)
+        _init_0.setTrigger(Event("created_socket", "socket_in"))
+        self.states["/init"].addTransition(_init_0)
+        
+        # transition /connecting
+        _connecting_0 = Transition(self, self.states["/connecting"], [self.states["/connected"]])
+        _connecting_0.setAction(self._connecting_0_exec)
+        _connecting_0.setTrigger(Event("connected_socket", "socket_in"))
+        _connecting_0.setGuard(self._connecting_0_guard)
+        self.states["/connecting"].addTransition(_connecting_0)
+        
+        # transition /connected/listening/listen
+        _connected_listening_listen_0 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/listen"]])
+        _connected_listening_listen_0.setAction(self._connected_listening_listen_0_exec)
+        _connected_listening_listen_0.setTrigger(Event("received_socket", "socket_in"))
+        _connected_listening_listen_0.setGuard(self._connected_listening_listen_0_guard)
+        self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_0)
+        _connected_listening_listen_1 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/close"]])
+        _connected_listening_listen_1.setTrigger(Event("received_socket", "socket_in"))
+        _connected_listening_listen_1.setGuard(self._connected_listening_listen_1_guard)
+        self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_1)
+        
+        # transition /connected/sending/waiting_for_data
+        _connected_sending_waiting_for_data_0 = Transition(self, self.states["/connected/sending/waiting_for_data"], [self.states["/connected/sending/transferring"]])
+        _connected_sending_waiting_for_data_0.setAction(self._connected_sending_waiting_for_data_0_exec)
+        _connected_sending_waiting_for_data_0.setTrigger(None)
+        _connected_sending_waiting_for_data_0.setGuard(self._connected_sending_waiting_for_data_0_guard)
+        self.states["/connected/sending/waiting_for_data"].addTransition(_connected_sending_waiting_for_data_0)
+        
+        # transition /connected/sending/transferring
+        _connected_sending_transferring_0 = Transition(self, self.states["/connected/sending/transferring"], [self.states["/connected/sending/waiting_for_data"]])
+        _connected_sending_transferring_0.setAction(self._connected_sending_transferring_0_exec)
+        _connected_sending_transferring_0.setTrigger(Event("sent_socket", "socket_in"))
+        _connected_sending_transferring_0.setGuard(self._connected_sending_transferring_0_guard)
+        self.states["/connected/sending/transferring"].addTransition(_connected_sending_transferring_0)
+        
+        # transition /connected/queueing/queueing
+        _connected_queueing_queueing_0 = Transition(self, self.states["/connected/queueing/queueing"], [self.states["/connected/queueing/queueing"]])
+        _connected_queueing_queueing_0.setAction(self._connected_queueing_queueing_0_exec)
+        _connected_queueing_queueing_0.setTrigger(Event("HTTP_input", None))
+        self.states["/connected/queueing/queueing"].addTransition(_connected_queueing_queueing_0)
+        
+        # transition /connected/parsing/wait_for_header
+        _connected_parsing_wait_for_header_0 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/wait_for_payload"]])
+        _connected_parsing_wait_for_header_0.setAction(self._connected_parsing_wait_for_header_0_exec)
+        _connected_parsing_wait_for_header_0.setTrigger(None)
+        _connected_parsing_wait_for_header_0.setGuard(self._connected_parsing_wait_for_header_0_guard)
+        self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_0)
+        
+        # transition /connected/parsing/wait_for_payload
+        _connected_parsing_wait_for_payload_0 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]])
+        _connected_parsing_wait_for_payload_0.setAction(self._connected_parsing_wait_for_payload_0_exec)
+        _connected_parsing_wait_for_payload_0.setTrigger(None)
+        _connected_parsing_wait_for_payload_0.setGuard(self._connected_parsing_wait_for_payload_0_guard)
+        self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_0)
+    
+    def _init_enter(self):
+        self.big_step.outputEvent(Event("create_socket", "", []))
+    
+    def _connecting_enter(self):
+        self.big_step.outputEvent(Event("connect_socket", "", [self.socket, self.destination]))
+    
+    def _connected_listening_listen_enter(self):
+        self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket]))
+    
+    def _connected_queueing_queueing_enter(self):
+        pass
+    
+    def _init_0_exec(self, parameters):
+        socket = parameters[0]
+        self.socket = socket
+    
+    def _connecting_0_exec(self, parameters):
+        socket = parameters[0]
+        self.big_step.outputEventOM(Event("broad_cast", None, [Event("http_client_ready", None, [])]))
+    
+    def _connecting_0_guard(self, parameters):
+        socket = parameters[0]
+        return self.socket == socket
+    
+    def _connected_listening_listen_0_exec(self, parameters):
+        socket = parameters[0]
+        data = parameters[1]
+        self.received_data += data
+    
+    def _connected_listening_listen_0_guard(self, parameters):
+        socket = parameters[0]
+        data = parameters[1]
+        return (self.socket == socket) and (len(data) > 0)
+    
+    def _connected_listening_listen_1_guard(self, parameters):
+        socket = parameters[0]
+        data = parameters[1]
+        return (self.socket == socket) and (len(data) == 0)
+    
+    def _connected_sending_waiting_for_data_0_exec(self, parameters):
+        self.big_step.outputEvent(Event("send_socket", "socket_out", [self.socket, self.send_data]))
+    
+    def _connected_sending_waiting_for_data_0_guard(self, parameters):
+        return len(self.send_data) > 0
+    
+    def _connected_sending_transferring_0_exec(self, parameters):
+        socket = parameters[0]
+        sent_bytes = parameters[1]
+        self.send_data = self.send_data[sent_bytes:]
+    
+    def _connected_sending_transferring_0_guard(self, parameters):
+        socket = parameters[0]
+        sent_bytes = parameters[1]
+        return self.socket == socket
+    
+    def _connected_queueing_queueing_0_exec(self, parameters):
+        data = parameters[0]
+        destination = parameters[1]
+        self.send_data += "POST / HTTP/1.0\r\n"
+        self.send_data += "Content-Length: %i\r\n" % len(str(data))
+        self.send_data += "\r\n"
+        self.send_data += data
+        self.destinations.append(destination)
+    
+    def _connected_parsing_wait_for_header_0_exec(self, parameters):
+        header, self.received_data = self.received_data.split("\r\n\r\n", 1)
+        header = header.lower()
+        if "content-length" in header:
+            _, after = header.split("content-length:", 1)
+            after, _ = after.split("\r\n", 1)
+            after = after.strip()
+            self.length = int(after)
+        else:
+            self.length = float('inf')
+    
+    def _connected_parsing_wait_for_header_0_guard(self, parameters):
+        return '\r\n\r\n' in self.received_data
+    
+    def _connected_parsing_wait_for_payload_0_exec(self, parameters):
+        data = self.received_data[:self.length]
+        self.received_data = self.received_data[self.length:]
+        #params = dict([p.split('=') for p in data.split('&')])
+        #data = {k: urllib.unquote_plus(v) for k, v in params.iteritems()}
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, self.destinations.pop(0), Event("HTTP_output", None, [data])]))
+    
+    def _connected_parsing_wait_for_payload_0_guard(self, parameters):
+        return len(self.received_data) >= self.length
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/init"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ObjectManager(ObjectManagerBase):
+    def __init__(self, controller):
+        ObjectManagerBase.__init__(self, controller)
+    
+    def instantiate(self, class_name, construct_params):
+        if class_name == "Prompt":
+            instance = Prompt(self.controller)
+            instance.associations = {}
+            instance.associations["to_server"] = Association("HTTPClient", 1, 1)
+        elif class_name == "HTTPClient":
+            instance = HTTPClient(self.controller, construct_params[0], construct_params[1])
+            instance.associations = {}
+            instance.associations["parent"] = Association("Prompt", 1, 1)
+        else:
+            raise Exception("Cannot instantiate class " + class_name)
+        return instance
+
+class Controller(ThreadsControllerBase):
+    def __init__(self, keep_running = None, behind_schedule_callback = None):
+        if keep_running == None: keep_running = True
+        if behind_schedule_callback == None: behind_schedule_callback = None
+        ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback)
+        self.addInputPort("socket_in")
+        self.addOutputPort("socket_out")
+        self.object_manager.createInstance("Prompt", [])

+ 600 - 0
examples/HTTP_server/server.py

@@ -0,0 +1,600 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Date:   Wed Aug 10 09:45:50 2016
+
+Model author: Yentl Van Tendeloo
+Model name:   HTTP Server
+Model description:
+Example HTTP echo server.
+"""
+
+from sccd.runtime.statecharts_core import *
+import time
+import os
+import urllib
+import sys
+import json
+
+import sys
+
+# package "HTTP Server"
+
+class Echo(RuntimeClassBase):
+    def __init__(self, controller, params):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        Echo.user_defined_constructor(self, params)
+    
+    def user_defined_constructor(self, params):
+        self.source = None
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /init_server
+        self.states["/init_server"] = State(1, self)
+        self.states["/init_server"].setEnter(self._init_server_enter)
+        
+        # state /wait_for_requests
+        self.states["/wait_for_requests"] = State(2, self)
+        
+        # state /wait_for_requests/wait
+        self.states["/wait_for_requests/wait"] = State(3, self)
+        
+        # add children
+        self.states[""].addChild(self.states["/init_server"])
+        self.states[""].addChild(self.states["/wait_for_requests"])
+        self.states["/wait_for_requests"].addChild(self.states["/wait_for_requests/wait"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/init_server"]
+        self.states["/wait_for_requests"].default_state = self.states["/wait_for_requests/wait"]
+        
+        # transition /init_server
+        _init_server_0 = Transition(self, self.states["/init_server"], [self.states["/wait_for_requests"]])
+        _init_server_0.setAction(self._init_server_0_exec)
+        _init_server_0.setTrigger(Event("instance_created", None))
+        self.states["/init_server"].addTransition(_init_server_0)
+        
+        # transition /wait_for_requests/wait
+        _wait_for_requests_wait_0 = Transition(self, self.states["/wait_for_requests/wait"], [self.states["/wait_for_requests/wait"]])
+        _wait_for_requests_wait_0.setAction(self._wait_for_requests_wait_0_exec)
+        _wait_for_requests_wait_0.setTrigger(Event("HTTP_output", None))
+        self.states["/wait_for_requests/wait"].addTransition(_wait_for_requests_wait_0)
+    
+    def _init_server_enter(self):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, 'to_server', 'Server', '', 8080]))
+    
+    def _init_server_0_exec(self, parameters):
+        instancename = parameters[0]
+        self.big_step.outputEventOM(Event("start_instance", None, [self, instancename]))
+    
+    def _wait_for_requests_wait_0_exec(self, parameters):
+        source = parameters[0]
+        data = parameters[1]
+        print("Got input: " + str(data))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'to_server/%s' % source, Event("HTTP_input", None, [data])]))
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/init_server"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class Server(RuntimeClassBase):
+    def __init__(self, controller, address, port):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        Server.user_defined_constructor(self, address, port)
+    
+    def user_defined_constructor(self, address, port):
+        self.socket = None
+        self.address = address
+        self.port = port
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /main
+        self.states["/main"] = ParallelState(1, self)
+        
+        # state /main/forward
+        self.states["/main/forward"] = State(2, self)
+        
+        # state /main/forward/forward
+        self.states["/main/forward/forward"] = State(3, self)
+        
+        # state /main/server
+        self.states["/main/server"] = State(4, self)
+        
+        # state /main/server/init
+        self.states["/main/server/init"] = State(5, self)
+        self.states["/main/server/init"].setEnter(self._main_server_init_enter)
+        
+        # state /main/server/binding
+        self.states["/main/server/binding"] = State(6, self)
+        self.states["/main/server/binding"].setEnter(self._main_server_binding_enter)
+        
+        # state /main/server/listening
+        self.states["/main/server/listening"] = State(7, self)
+        self.states["/main/server/listening"].setEnter(self._main_server_listening_enter)
+        
+        # state /main/server/accepting
+        self.states["/main/server/accepting"] = State(8, self)
+        self.states["/main/server/accepting"].setEnter(self._main_server_accepting_enter)
+        self.states["/main/server/accepting"].setExit(self._main_server_accepting_exit)
+        
+        # state /main/close_socket
+        self.states["/main/close_socket"] = State(9, self)
+        
+        # state /main/close_socket/close
+        self.states["/main/close_socket/close"] = State(10, self)
+        
+        # add children
+        self.states[""].addChild(self.states["/main"])
+        self.states["/main"].addChild(self.states["/main/forward"])
+        self.states["/main"].addChild(self.states["/main/server"])
+        self.states["/main"].addChild(self.states["/main/close_socket"])
+        self.states["/main/forward"].addChild(self.states["/main/forward/forward"])
+        self.states["/main/server"].addChild(self.states["/main/server/init"])
+        self.states["/main/server"].addChild(self.states["/main/server/binding"])
+        self.states["/main/server"].addChild(self.states["/main/server/listening"])
+        self.states["/main/server"].addChild(self.states["/main/server/accepting"])
+        self.states["/main/close_socket"].addChild(self.states["/main/close_socket/close"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/main"]
+        self.states["/main/forward"].default_state = self.states["/main/forward/forward"]
+        self.states["/main/server"].default_state = self.states["/main/server/init"]
+        self.states["/main/close_socket"].default_state = self.states["/main/close_socket/close"]
+        
+        # transition /main/forward/forward
+        _main_forward_forward_0 = Transition(self, self.states["/main/forward/forward"], [self.states["/main/forward/forward"]])
+        _main_forward_forward_0.setAction(self._main_forward_forward_0_exec)
+        _main_forward_forward_0.setTrigger(Event("HTTP_output", None))
+        self.states["/main/forward/forward"].addTransition(_main_forward_forward_0)
+        
+        # transition /main/server/init
+        _main_server_init_0 = Transition(self, self.states["/main/server/init"], [self.states["/main/server/binding"]])
+        _main_server_init_0.setAction(self._main_server_init_0_exec)
+        _main_server_init_0.setTrigger(Event("created_socket", "socket_in"))
+        self.states["/main/server/init"].addTransition(_main_server_init_0)
+        
+        # transition /main/server/binding
+        _main_server_binding_0 = Transition(self, self.states["/main/server/binding"], [self.states["/main/server/listening"]])
+        _main_server_binding_0.setTrigger(Event("bound_socket", "socket_in"))
+        _main_server_binding_0.setGuard(self._main_server_binding_0_guard)
+        self.states["/main/server/binding"].addTransition(_main_server_binding_0)
+        
+        # transition /main/server/listening
+        _main_server_listening_0 = Transition(self, self.states["/main/server/listening"], [self.states["/main/server/accepting"]])
+        _main_server_listening_0.setAction(self._main_server_listening_0_exec)
+        _main_server_listening_0.setTrigger(Event("listened_socket", "socket_in"))
+        _main_server_listening_0.setGuard(self._main_server_listening_0_guard)
+        self.states["/main/server/listening"].addTransition(_main_server_listening_0)
+        
+        # transition /main/server/accepting
+        _main_server_accepting_0 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]])
+        _main_server_accepting_0.setAction(self._main_server_accepting_0_exec)
+        _main_server_accepting_0.setTrigger(Event("accepted_socket", "socket_in"))
+        self.states["/main/server/accepting"].addTransition(_main_server_accepting_0)
+        _main_server_accepting_1 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]])
+        _main_server_accepting_1.setAction(self._main_server_accepting_1_exec)
+        _main_server_accepting_1.setTrigger(Event("instance_created", None))
+        self.states["/main/server/accepting"].addTransition(_main_server_accepting_1)
+        _main_server_accepting_2 = Transition(self, self.states["/main/server/accepting"], [self.states["/main/server/accepting"]])
+        _main_server_accepting_2.setTrigger(Event("_0after"))
+        self.states["/main/server/accepting"].addTransition(_main_server_accepting_2)
+        
+        # transition /main/close_socket/close
+        _main_close_socket_close_0 = Transition(self, self.states["/main/close_socket/close"], [self.states["/main/close_socket/close"]])
+        _main_close_socket_close_0.setAction(self._main_close_socket_close_0_exec)
+        _main_close_socket_close_0.setTrigger(Event("close_socket", None))
+        self.states["/main/close_socket/close"].addTransition(_main_close_socket_close_0)
+    
+    def _main_server_init_enter(self):
+        self.big_step.outputEvent(Event("create_socket", "socket_out", []))
+    
+    def _main_server_binding_enter(self):
+        self.big_step.outputEvent(Event("bind_socket", "socket_out", [self.socket, (self.address, self.port)]))
+    
+    def _main_server_listening_enter(self):
+        self.big_step.outputEvent(Event("listen_socket", "socket_out", [self.socket]))
+    
+    def _main_server_accepting_enter(self):
+        self.addTimer(0, 1.0)
+    
+    def _main_server_accepting_exit(self):
+        self.removeTimer(0)
+    
+    def _main_forward_forward_0_exec(self, parameters):
+        association_name = parameters[0]
+        data = parameters[1]
+        print("Forward")
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("HTTP_output", None, [association_name, data])]))
+    
+    def _main_server_init_0_exec(self, parameters):
+        socket = parameters[0]
+        self.socket = socket
+    
+    def _main_server_binding_0_guard(self, parameters):
+        socket = parameters[0]
+        return self.socket == socket
+    
+    def _main_server_listening_0_exec(self, parameters):
+        socket = parameters[0]
+        self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket]))
+    
+    def _main_server_listening_0_guard(self, parameters):
+        socket = parameters[0]
+        return self.socket == socket
+    
+    def _main_server_accepting_0_exec(self, parameters):
+        socket = parameters[0]
+        connected_socket = parameters[1]
+        self.big_step.outputEventOM(Event("create_instance", None, [self, 'sockets', 'Socket', connected_socket]))
+        self.big_step.outputEvent(Event("accept_socket", "socket_out", [self.socket]))
+    
+    def _main_server_accepting_1_exec(self, parameters):
+        instancename = parameters[0]
+        self.big_step.outputEventOM(Event("start_instance", None, [self, instancename]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, instancename, Event("set_association_name", None, [instancename])]))
+    
+    def _main_close_socket_close_0_exec(self, parameters):
+        association_name = parameters[0]
+        self.big_step.outputEventOM(Event("delete_instance", None, [self, association_name]))
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/main"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class Socket(RuntimeClassBase):
+    def __init__(self, controller, my_socket):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # call user defined constructor
+        Socket.user_defined_constructor(self, my_socket)
+    
+    def user_defined_constructor(self, my_socket):
+        self.socket = my_socket
+        self.received_data = ""
+        self.send_data = ""
+        self.closed = False
+        self.association_name = None
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /init
+        self.states["/init"] = State(1, self)
+        
+        # state /connected
+        self.states["/connected"] = ParallelState(2, self)
+        
+        # state /connected/listening
+        self.states["/connected/listening"] = State(3, self)
+        
+        # state /connected/listening/listen
+        self.states["/connected/listening/listen"] = State(4, self)
+        self.states["/connected/listening/listen"].setEnter(self._connected_listening_listen_enter)
+        
+        # state /connected/listening/closed
+        self.states["/connected/listening/closed"] = State(5, self)
+        self.states["/connected/listening/closed"].setEnter(self._connected_listening_closed_enter)
+        
+        # state /connected/sending
+        self.states["/connected/sending"] = State(6, self)
+        
+        # state /connected/sending/waiting_for_data
+        self.states["/connected/sending/waiting_for_data"] = State(7, self)
+        
+        # state /connected/sending/transferring
+        self.states["/connected/sending/transferring"] = State(8, self)
+        
+        # state /connected/queueing
+        self.states["/connected/queueing"] = State(9, self)
+        
+        # state /connected/queueing/queueing
+        self.states["/connected/queueing/queueing"] = State(10, self)
+        
+        # state /connected/parsing
+        self.states["/connected/parsing"] = State(11, self)
+        
+        # state /connected/parsing/wait_for_header
+        self.states["/connected/parsing/wait_for_header"] = State(12, self)
+        
+        # state /connected/parsing/closing
+        self.states["/connected/parsing/closing"] = State(13, self)
+        self.states["/connected/parsing/closing"].setEnter(self._connected_parsing_closing_enter)
+        self.states["/connected/parsing/closing"].setExit(self._connected_parsing_closing_exit)
+        
+        # state /connected/parsing/wait_for_payload
+        self.states["/connected/parsing/wait_for_payload"] = State(14, self)
+        
+        # state /close
+        self.states["/close"] = State(15, self)
+        self.states["/close"].setEnter(self._close_enter)
+        
+        # add children
+        self.states[""].addChild(self.states["/init"])
+        self.states[""].addChild(self.states["/connected"])
+        self.states[""].addChild(self.states["/close"])
+        self.states["/connected"].addChild(self.states["/connected/listening"])
+        self.states["/connected"].addChild(self.states["/connected/sending"])
+        self.states["/connected"].addChild(self.states["/connected/queueing"])
+        self.states["/connected"].addChild(self.states["/connected/parsing"])
+        self.states["/connected/listening"].addChild(self.states["/connected/listening/listen"])
+        self.states["/connected/listening"].addChild(self.states["/connected/listening/closed"])
+        self.states["/connected/sending"].addChild(self.states["/connected/sending/waiting_for_data"])
+        self.states["/connected/sending"].addChild(self.states["/connected/sending/transferring"])
+        self.states["/connected/queueing"].addChild(self.states["/connected/queueing/queueing"])
+        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_header"])
+        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/closing"])
+        self.states["/connected/parsing"].addChild(self.states["/connected/parsing/wait_for_payload"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/init"]
+        self.states["/connected/listening"].default_state = self.states["/connected/listening/listen"]
+        self.states["/connected/sending"].default_state = self.states["/connected/sending/waiting_for_data"]
+        self.states["/connected/queueing"].default_state = self.states["/connected/queueing/queueing"]
+        self.states["/connected/parsing"].default_state = self.states["/connected/parsing/wait_for_header"]
+        
+        # transition /init
+        _init_0 = Transition(self, self.states["/init"], [self.states["/connected"]])
+        _init_0.setAction(self._init_0_exec)
+        _init_0.setTrigger(Event("set_association_name", None))
+        self.states["/init"].addTransition(_init_0)
+        
+        # transition /connected/listening/listen
+        _connected_listening_listen_0 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/listen"]])
+        _connected_listening_listen_0.setAction(self._connected_listening_listen_0_exec)
+        _connected_listening_listen_0.setTrigger(Event("received_socket", "socket_in"))
+        _connected_listening_listen_0.setGuard(self._connected_listening_listen_0_guard)
+        self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_0)
+        _connected_listening_listen_1 = Transition(self, self.states["/connected/listening/listen"], [self.states["/connected/listening/closed"]])
+        _connected_listening_listen_1.setAction(self._connected_listening_listen_1_exec)
+        _connected_listening_listen_1.setTrigger(Event("received_socket", "socket_in"))
+        _connected_listening_listen_1.setGuard(self._connected_listening_listen_1_guard)
+        self.states["/connected/listening/listen"].addTransition(_connected_listening_listen_1)
+        
+        # transition /connected/sending/waiting_for_data
+        _connected_sending_waiting_for_data_0 = Transition(self, self.states["/connected/sending/waiting_for_data"], [self.states["/connected/sending/transferring"]])
+        _connected_sending_waiting_for_data_0.setAction(self._connected_sending_waiting_for_data_0_exec)
+        _connected_sending_waiting_for_data_0.setTrigger(None)
+        _connected_sending_waiting_for_data_0.setGuard(self._connected_sending_waiting_for_data_0_guard)
+        self.states["/connected/sending/waiting_for_data"].addTransition(_connected_sending_waiting_for_data_0)
+        
+        # transition /connected/sending/transferring
+        _connected_sending_transferring_0 = Transition(self, self.states["/connected/sending/transferring"], [self.states["/connected/sending/waiting_for_data"]])
+        _connected_sending_transferring_0.setAction(self._connected_sending_transferring_0_exec)
+        _connected_sending_transferring_0.setTrigger(Event("sent_socket", "socket_in"))
+        _connected_sending_transferring_0.setGuard(self._connected_sending_transferring_0_guard)
+        self.states["/connected/sending/transferring"].addTransition(_connected_sending_transferring_0)
+        
+        # transition /connected/queueing/queueing
+        _connected_queueing_queueing_0 = Transition(self, self.states["/connected/queueing/queueing"], [self.states["/connected/queueing/queueing"]])
+        _connected_queueing_queueing_0.setAction(self._connected_queueing_queueing_0_exec)
+        _connected_queueing_queueing_0.setTrigger(Event("HTTP_input", None))
+        self.states["/connected/queueing/queueing"].addTransition(_connected_queueing_queueing_0)
+        
+        # transition /connected/parsing/wait_for_header
+        _connected_parsing_wait_for_header_0 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/wait_for_payload"]])
+        _connected_parsing_wait_for_header_0.setAction(self._connected_parsing_wait_for_header_0_exec)
+        _connected_parsing_wait_for_header_0.setTrigger(None)
+        _connected_parsing_wait_for_header_0.setGuard(self._connected_parsing_wait_for_header_0_guard)
+        self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_0)
+        _connected_parsing_wait_for_header_1 = Transition(self, self.states["/connected/parsing/wait_for_header"], [self.states["/connected/parsing/closing"]])
+        _connected_parsing_wait_for_header_1.setTrigger(None)
+        _connected_parsing_wait_for_header_1.setGuard(self._connected_parsing_wait_for_header_1_guard)
+        self.states["/connected/parsing/wait_for_header"].addTransition(_connected_parsing_wait_for_header_1)
+        
+        # transition /connected/parsing/closing
+        _connected_parsing_closing_0 = Transition(self, self.states["/connected/parsing/closing"], [self.states["/connected/parsing/closing"]])
+        _connected_parsing_closing_0.setAction(self._connected_parsing_closing_0_exec)
+        _connected_parsing_closing_0.setTrigger(Event("_0after"))
+        self.states["/connected/parsing/closing"].addTransition(_connected_parsing_closing_0)
+        
+        # transition /connected/parsing/wait_for_payload
+        _connected_parsing_wait_for_payload_0 = Transition(self, self.states["/connected/parsing/wait_for_payload"], [self.states["/connected/parsing/wait_for_header"]])
+        _connected_parsing_wait_for_payload_0.setAction(self._connected_parsing_wait_for_payload_0_exec)
+        _connected_parsing_wait_for_payload_0.setTrigger(None)
+        _connected_parsing_wait_for_payload_0.setGuard(self._connected_parsing_wait_for_payload_0_guard)
+        self.states["/connected/parsing/wait_for_payload"].addTransition(_connected_parsing_wait_for_payload_0)
+        
+        # transition /connected
+        _connected_0 = Transition(self, self.states["/connected"], [self.states["/close"]])
+        _connected_0.setTrigger(Event("close", None))
+        self.states["/connected"].addTransition(_connected_0)
+    
+    def _connected_listening_listen_enter(self):
+        self.big_step.outputEvent(Event("recv_socket", "socket_out", [self.socket]))
+    
+    def _connected_listening_closed_enter(self):
+        self.closed = True
+    
+    def _connected_parsing_closing_enter(self):
+        self.addTimer(0, 0.0)
+    
+    def _connected_parsing_closing_exit(self):
+        self.removeTimer(0)
+    
+    def _close_enter(self):
+        self.big_step.outputEvent(Event("close_socket", "socket_out", [self.socket]))
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("close_socket", None, [self.association_name])]))
+    
+    def _init_0_exec(self, parameters):
+        association_name = parameters[0]
+        self.association_name = association_name
+    
+    def _connected_listening_listen_0_exec(self, parameters):
+        socket = parameters[0]
+        data = parameters[1]
+        self.received_data += data
+        self.raiseInternalEvent(Event("received_data", None, []))
+    
+    def _connected_listening_listen_0_guard(self, parameters):
+        socket = parameters[0]
+        data = parameters[1]
+        return (self.socket == socket) and (len(data) > 0)
+    
+    def _connected_listening_listen_1_exec(self, parameters):
+        socket = parameters[0]
+        data = parameters[1]
+        self.raiseInternalEvent(Event("received_data", None, []))
+    
+    def _connected_listening_listen_1_guard(self, parameters):
+        socket = parameters[0]
+        data = parameters[1]
+        return (self.socket == socket) and (len(data) == 0)
+    
+    def _connected_sending_waiting_for_data_0_exec(self, parameters):
+        self.big_step.outputEvent(Event("send_socket", "socket_out", [self.socket, self.send_data]))
+    
+    def _connected_sending_waiting_for_data_0_guard(self, parameters):
+        return len(self.send_data) > 0
+    
+    def _connected_sending_transferring_0_exec(self, parameters):
+        socket = parameters[0]
+        sent_bytes = parameters[1]
+        self.send_data = self.send_data[sent_bytes:]
+    
+    def _connected_sending_transferring_0_guard(self, parameters):
+        socket = parameters[0]
+        sent_bytes = parameters[1]
+        return self.socket == socket
+    
+    def _connected_queueing_queueing_0_exec(self, parameters):
+        data = parameters[0]
+        #post_data = "&".join(["%s=%s" % (urllib.quote(k), urllib.quote(v)) for k, v in data.iteritems()])
+        #post_data = "&".join(["%s=%s" % (k, v) for k, v in data.iteritems()])
+        post_data = data
+        self.send_data += "HTTP/1.0 200 OK\r\n"
+        self.send_data += "Content-Length: %s\r\n" % len(post_data)
+        self.send_data += "Content-Type: %s; charset=UTF-8\r\n" % "text/plain"
+        self.send_data += "\r\n"
+        self.send_data += str(post_data)
+    
+    def _connected_parsing_wait_for_header_0_exec(self, parameters):
+        header, self.received_data = self.received_data.split("\r\n\r\n", 1)
+        header = header.lower()
+        if "content-length" in header:
+            _, after = header.split("content-length:", 1)
+            after = after.split("\r\n", 1)[0]
+            after = after.strip()
+            self.length = int(after)
+        else:
+            self.length = float('inf')
+    
+    def _connected_parsing_wait_for_header_0_guard(self, parameters):
+        return '\r\n\r\n' in self.received_data and self.received_data.startswith('POST')
+    
+    def _connected_parsing_wait_for_header_1_guard(self, parameters):
+        return self.closed and len(self.received_data) == 0
+    
+    def _connected_parsing_closing_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("close", None, []))
+    
+    def _connected_parsing_wait_for_payload_0_exec(self, parameters):
+        if self.length == float('inf'):
+            data = self.received_data
+            self.received_data = ""
+        else:
+            data = self.received_data[:self.length]
+            self.received_data = self.received_data[self.length:]
+        
+        print("Got data: " + str(data))
+        
+        # We support POST data only, so everything is in the data
+        #try:
+        #    params = dict([p.split('=') for p in data.split('&')])
+        #    data = {k: urllib.unquote_plus(v) for k, v in params.iteritems()}
+        #except:
+        #    data = {}
+        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("HTTP_output", None, [self.association_name, data])]))
+    
+    def _connected_parsing_wait_for_payload_0_guard(self, parameters):
+        return len(self.received_data) >= self.length or self.closed
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/init"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ObjectManager(ObjectManagerBase):
+    def __init__(self, controller):
+        ObjectManagerBase.__init__(self, controller)
+    
+    def instantiate(self, class_name, construct_params):
+        if class_name == "Echo":
+            instance = Echo(self.controller, construct_params[0])
+            instance.associations = {}
+            instance.associations["to_server"] = Association("Server", 1, 1)
+        elif class_name == "Server":
+            instance = Server(self.controller, construct_params[0], construct_params[1])
+            instance.associations = {}
+            instance.associations["sockets"] = Association("Socket", 0, -1)
+            instance.associations["parent"] = Association("Echo", 1, 1)
+        elif class_name == "Socket":
+            instance = Socket(self.controller, construct_params[0])
+            instance.associations = {}
+            instance.associations["parent"] = Association("Server", 1, 1)
+        else:
+            raise Exception("Cannot instantiate class " + class_name)
+        return instance
+
+class Controller(ThreadsControllerBase):
+    def __init__(self, params, keep_running = None, behind_schedule_callback = None):
+        if keep_running == None: keep_running = True
+        if behind_schedule_callback == None: behind_schedule_callback = None
+        ThreadsControllerBase.__init__(self, ObjectManager(self), keep_running, behind_schedule_callback)
+        self.addInputPort("socket_in")
+        self.addOutputPort("socket_out")
+        self.object_manager.createInstance("Echo", [params])

File diff suppressed because it is too large
+ 1701 - 0
examples/tanks/ai_controller.py


+ 506 - 0
examples/tanks/player_controller.py

@@ -0,0 +1,506 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Date:   Wed Aug 10 09:45:50 2016
+
+Model author: Glenn De Jonghe
+Model name:   Player Tank
+Model description:
+Handling the player tank.
+"""
+
+from sccd.runtime.statecharts_core import *
+
+# package "Player Tank"
+
+class Main(RuntimeClassBase):
+    def __init__(self, controller, tank):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # user defined attributes
+        self.tank = None
+        
+        # call user defined constructor
+        Main.user_defined_constructor(self, tank)
+    
+    def user_defined_constructor(self, tank):
+        self.tank = tank
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /state_1
+        self.states["/state_1"] = State(1, self)
+        
+        # state /state_2
+        self.states["/state_2"] = State(2, self)
+        
+        # state /state_3
+        self.states["/state_3"] = State(3, self)
+        
+        # state /state_4
+        self.states["/state_4"] = State(4, self)
+        
+        # state /end
+        self.states["/end"] = State(5, self)
+        
+        # add children
+        self.states[""].addChild(self.states["/state_1"])
+        self.states[""].addChild(self.states["/state_2"])
+        self.states[""].addChild(self.states["/state_3"])
+        self.states[""].addChild(self.states["/state_4"])
+        self.states[""].addChild(self.states["/end"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/state_1"]
+        
+        # transition /state_1
+        _state_1_0 = Transition(self, self.states["/state_1"], [self.states["/state_2"]])
+        _state_1_0.setAction(self._state_1_0_exec)
+        _state_1_0.setTrigger(None)
+        self.states["/state_1"].addTransition(_state_1_0)
+        
+        # transition /state_2
+        _state_2_0 = Transition(self, self.states["/state_2"], [self.states["/state_3"]])
+        _state_2_0.setTrigger(Event("instance_created", None))
+        self.states["/state_2"].addTransition(_state_2_0)
+        
+        # transition /state_3
+        _state_3_0 = Transition(self, self.states["/state_3"], [self.states["/state_4"]])
+        _state_3_0.setAction(self._state_3_0_exec)
+        _state_3_0.setTrigger(None)
+        self.states["/state_3"].addTransition(_state_3_0)
+        
+        # transition /state_4
+        _state_4_0 = Transition(self, self.states["/state_4"], [self.states["/end"]])
+        _state_4_0.setAction(self._state_4_0_exec)
+        _state_4_0.setTrigger(Event("instance_created", None))
+        self.states["/state_4"].addTransition(_state_4_0)
+    
+    def _state_1_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, 'cannon', 'Cannon', self.tank]))
+    
+    def _state_3_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, 'body', 'Body', self.tank]))
+    
+    def _state_4_0_exec(self, parameters):
+        self.big_step.outputEventOM(Event("start_instance", None, [self, 'cannon']))
+        self.big_step.outputEventOM(Event("start_instance", None, [self, 'body']))
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/state_1"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class Cannon(RuntimeClassBase):
+    def __init__(self, controller, tank):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # user defined attributes
+        self.tank = None
+        self.reload_time = None
+        
+        # call user defined constructor
+        Cannon.user_defined_constructor(self, tank)
+    
+    def user_defined_constructor(self, tank):
+        self.tank = tank
+        self.reload_time = tank.getReloadTime()
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /container
+        self.states["/container"] = ParallelState(1, self)
+        
+        # state /container/rotating
+        self.states["/container/rotating"] = State(2, self)
+        
+        # state /container/rotating/none
+        self.states["/container/rotating/none"] = State(3, self)
+        
+        # state /container/rotating/left
+        self.states["/container/rotating/left"] = State(4, self)
+        
+        # state /container/rotating/both
+        self.states["/container/rotating/both"] = State(5, self)
+        
+        # state /container/rotating/right
+        self.states["/container/rotating/right"] = State(6, self)
+        
+        # state /container/shoot
+        self.states["/container/shoot"] = State(7, self)
+        
+        # state /container/shoot/hold
+        self.states["/container/shoot/hold"] = State(8, self)
+        
+        # state /container/shoot/shoot
+        self.states["/container/shoot/shoot"] = State(9, self)
+        
+        # state /container/ammo
+        self.states["/container/ammo"] = State(10, self)
+        
+        # state /container/ammo/loaded
+        self.states["/container/ammo/loaded"] = State(11, self)
+        
+        # state /container/ammo/unloaded
+        self.states["/container/ammo/unloaded"] = State(12, self)
+        self.states["/container/ammo/unloaded"].setEnter(self._container_ammo_unloaded_enter)
+        self.states["/container/ammo/unloaded"].setExit(self._container_ammo_unloaded_exit)
+        
+        # add children
+        self.states[""].addChild(self.states["/container"])
+        self.states["/container"].addChild(self.states["/container/rotating"])
+        self.states["/container"].addChild(self.states["/container/shoot"])
+        self.states["/container"].addChild(self.states["/container/ammo"])
+        self.states["/container/rotating"].addChild(self.states["/container/rotating/none"])
+        self.states["/container/rotating"].addChild(self.states["/container/rotating/left"])
+        self.states["/container/rotating"].addChild(self.states["/container/rotating/both"])
+        self.states["/container/rotating"].addChild(self.states["/container/rotating/right"])
+        self.states["/container/shoot"].addChild(self.states["/container/shoot/hold"])
+        self.states["/container/shoot"].addChild(self.states["/container/shoot/shoot"])
+        self.states["/container/ammo"].addChild(self.states["/container/ammo/loaded"])
+        self.states["/container/ammo"].addChild(self.states["/container/ammo/unloaded"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/container"]
+        self.states["/container/rotating"].default_state = self.states["/container/rotating/none"]
+        self.states["/container/shoot"].default_state = self.states["/container/shoot/hold"]
+        self.states["/container/ammo"].default_state = self.states["/container/ammo/loaded"]
+        
+        # transition /container/rotating/none
+        _container_rotating_none_0 = Transition(self, self.states["/container/rotating/none"], [self.states["/container/rotating/left"]])
+        _container_rotating_none_0.setTrigger(Event("cannon-left-pressed", "input"))
+        self.states["/container/rotating/none"].addTransition(_container_rotating_none_0)
+        _container_rotating_none_1 = Transition(self, self.states["/container/rotating/none"], [self.states["/container/rotating/right"]])
+        _container_rotating_none_1.setTrigger(Event("cannon-right-pressed", "input"))
+        self.states["/container/rotating/none"].addTransition(_container_rotating_none_1)
+        
+        # transition /container/rotating/left
+        _container_rotating_left_0 = Transition(self, self.states["/container/rotating/left"], [self.states["/container/rotating/none"]])
+        _container_rotating_left_0.setTrigger(Event("cannon-left-released", "input"))
+        self.states["/container/rotating/left"].addTransition(_container_rotating_left_0)
+        _container_rotating_left_1 = Transition(self, self.states["/container/rotating/left"], [self.states["/container/rotating/both"]])
+        _container_rotating_left_1.setTrigger(Event("cannon-right-pressed", "input"))
+        self.states["/container/rotating/left"].addTransition(_container_rotating_left_1)
+        _container_rotating_left_2 = Transition(self, self.states["/container/rotating/left"], [self.states["/container/rotating/left"]])
+        _container_rotating_left_2.setAction(self._container_rotating_left_2_exec)
+        _container_rotating_left_2.setTrigger(Event("update", "engine"))
+        self.states["/container/rotating/left"].addTransition(_container_rotating_left_2)
+        
+        # transition /container/rotating/both
+        _container_rotating_both_0 = Transition(self, self.states["/container/rotating/both"], [self.states["/container/rotating/right"]])
+        _container_rotating_both_0.setTrigger(Event("cannon-left-released", "input"))
+        self.states["/container/rotating/both"].addTransition(_container_rotating_both_0)
+        _container_rotating_both_1 = Transition(self, self.states["/container/rotating/both"], [self.states["/container/rotating/left"]])
+        _container_rotating_both_1.setTrigger(Event("cannon-right-released", "input"))
+        self.states["/container/rotating/both"].addTransition(_container_rotating_both_1)
+        
+        # transition /container/rotating/right
+        _container_rotating_right_0 = Transition(self, self.states["/container/rotating/right"], [self.states["/container/rotating/both"]])
+        _container_rotating_right_0.setTrigger(Event("cannon-left-pressed", "input"))
+        self.states["/container/rotating/right"].addTransition(_container_rotating_right_0)
+        _container_rotating_right_1 = Transition(self, self.states["/container/rotating/right"], [self.states["/container/rotating/none"]])
+        _container_rotating_right_1.setTrigger(Event("cannon-right-released", "input"))
+        self.states["/container/rotating/right"].addTransition(_container_rotating_right_1)
+        _container_rotating_right_2 = Transition(self, self.states["/container/rotating/right"], [self.states["/container/rotating/right"]])
+        _container_rotating_right_2.setAction(self._container_rotating_right_2_exec)
+        _container_rotating_right_2.setTrigger(Event("update", "engine"))
+        self.states["/container/rotating/right"].addTransition(_container_rotating_right_2)
+        
+        # transition /container/shoot/hold
+        _container_shoot_hold_0 = Transition(self, self.states["/container/shoot/hold"], [self.states["/container/shoot/shoot"]])
+        _container_shoot_hold_0.setAction(self._container_shoot_hold_0_exec)
+        _container_shoot_hold_0.setTrigger(Event("shoot-pressed", "input"))
+        self.states["/container/shoot/hold"].addTransition(_container_shoot_hold_0)
+        
+        # transition /container/shoot/shoot
+        _container_shoot_shoot_0 = Transition(self, self.states["/container/shoot/shoot"], [self.states["/container/shoot/hold"]])
+        _container_shoot_shoot_0.setTrigger(Event("shoot-released", "input"))
+        self.states["/container/shoot/shoot"].addTransition(_container_shoot_shoot_0)
+        _container_shoot_shoot_1 = Transition(self, self.states["/container/shoot/shoot"], [self.states["/container/shoot/shoot"]])
+        _container_shoot_shoot_1.setAction(self._container_shoot_shoot_1_exec)
+        _container_shoot_shoot_1.setTrigger(Event("loaded", None))
+        self.states["/container/shoot/shoot"].addTransition(_container_shoot_shoot_1)
+        
+        # transition /container/ammo/loaded
+        _container_ammo_loaded_0 = Transition(self, self.states["/container/ammo/loaded"], [self.states["/container/ammo/unloaded"]])
+        _container_ammo_loaded_0.setAction(self._container_ammo_loaded_0_exec)
+        _container_ammo_loaded_0.setTrigger(Event("shoot", None))
+        self.states["/container/ammo/loaded"].addTransition(_container_ammo_loaded_0)
+        
+        # transition /container/ammo/unloaded
+        _container_ammo_unloaded_0 = Transition(self, self.states["/container/ammo/unloaded"], [self.states["/container/ammo/loaded"]])
+        _container_ammo_unloaded_0.setAction(self._container_ammo_unloaded_0_exec)
+        _container_ammo_unloaded_0.setTrigger(Event("_0after"))
+        self.states["/container/ammo/unloaded"].addTransition(_container_ammo_unloaded_0)
+    
+    def _container_ammo_unloaded_enter(self):
+        self.addTimer(0, self.reload_time)
+    
+    def _container_ammo_unloaded_exit(self):
+        self.removeTimer(0)
+    
+    def _container_rotating_left_2_exec(self, parameters):
+        self.tank.turnCannonLeft()
+    
+    def _container_rotating_right_2_exec(self, parameters):
+        self.tank.turnCannonRight()
+    
+    def _container_shoot_hold_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("shoot", None, []))
+    
+    def _container_shoot_shoot_1_exec(self, parameters):
+        self.raiseInternalEvent(Event("shoot", None, []))
+    
+    def _container_ammo_loaded_0_exec(self, parameters):
+        self.tank.shoot()
+        self.big_step.outputEvent(Event("reloading", "gui", []))
+    
+    def _container_ammo_unloaded_0_exec(self, parameters):
+        self.raiseInternalEvent(Event("loaded", None, []))
+        self.big_step.outputEvent(Event("loaded", "gui", []))
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/container"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class Body(RuntimeClassBase):
+    def __init__(self, controller, tank):
+        RuntimeClassBase.__init__(self, controller)
+        
+        self.semantics.big_step_maximality = StatechartSemantics.TakeMany
+        self.semantics.internal_event_lifeline = StatechartSemantics.Queue
+        self.semantics.input_event_lifeline = StatechartSemantics.FirstComboStep
+        self.semantics.priority = StatechartSemantics.SourceParent
+        self.semantics.concurrency = StatechartSemantics.Single
+        
+        # build Statechart structure
+        self.build_statechart_structure()
+        
+        # user defined attributes
+        self.tank = None
+        
+        # call user defined constructor
+        Body.user_defined_constructor(self, tank)
+    
+    def user_defined_constructor(self, tank):
+        self.tank = tank
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, self)
+        
+        # state /container
+        self.states["/container"] = ParallelState(1, self)
+        
+        # state /container/horizontal
+        self.states["/container/horizontal"] = State(2, self)
+        
+        # state /container/horizontal/none
+        self.states["/container/horizontal/none"] = State(3, self)
+        
+        # state /container/horizontal/left
+        self.states["/container/horizontal/left"] = State(4, self)
+        
+        # state /container/horizontal/both
+        self.states["/container/horizontal/both"] = State(5, self)
+        
+        # state /container/horizontal/right
+        self.states["/container/horizontal/right"] = State(6, self)
+        
+        # state /container/vertical
+        self.states["/container/vertical"] = State(7, self)
+        
+        # state /container/vertical/none
+        self.states["/container/vertical/none"] = State(8, self)
+        
+        # state /container/vertical/down
+        self.states["/container/vertical/down"] = State(9, self)
+        
+        # state /container/vertical/both
+        self.states["/container/vertical/both"] = State(10, self)
+        
+        # state /container/vertical/up
+        self.states["/container/vertical/up"] = State(11, self)
+        
+        # add children
+        self.states[""].addChild(self.states["/container"])
+        self.states["/container"].addChild(self.states["/container/horizontal"])
+        self.states["/container"].addChild(self.states["/container/vertical"])
+        self.states["/container/horizontal"].addChild(self.states["/container/horizontal/none"])
+        self.states["/container/horizontal"].addChild(self.states["/container/horizontal/left"])
+        self.states["/container/horizontal"].addChild(self.states["/container/horizontal/both"])
+        self.states["/container/horizontal"].addChild(self.states["/container/horizontal/right"])
+        self.states["/container/vertical"].addChild(self.states["/container/vertical/none"])
+        self.states["/container/vertical"].addChild(self.states["/container/vertical/down"])
+        self.states["/container/vertical"].addChild(self.states["/container/vertical/both"])
+        self.states["/container/vertical"].addChild(self.states["/container/vertical/up"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/container"]
+        self.states["/container/horizontal"].default_state = self.states["/container/horizontal/none"]
+        self.states["/container/vertical"].default_state = self.states["/container/vertical/none"]
+        
+        # transition /container/horizontal/none
+        _container_horizontal_none_0 = Transition(self, self.states["/container/horizontal/none"], [self.states["/container/horizontal/left"]])
+        _container_horizontal_none_0.setTrigger(Event("left-pressed", "input"))
+        self.states["/container/horizontal/none"].addTransition(_container_horizontal_none_0)
+        _container_horizontal_none_1 = Transition(self, self.states["/container/horizontal/none"], [self.states["/container/horizontal/right"]])
+        _container_horizontal_none_1.setTrigger(Event("right-pressed", "input"))
+        self.states["/container/horizontal/none"].addTransition(_container_horizontal_none_1)
+        
+        # transition /container/horizontal/left
+        _container_horizontal_left_0 = Transition(self, self.states["/container/horizontal/left"], [self.states["/container/horizontal/none"]])
+        _container_horizontal_left_0.setTrigger(Event("left-released", "input"))
+        self.states["/container/horizontal/left"].addTransition(_container_horizontal_left_0)
+        _container_horizontal_left_1 = Transition(self, self.states["/container/horizontal/left"], [self.states["/container/horizontal/both"]])
+        _container_horizontal_left_1.setTrigger(Event("right-pressed", "input"))
+        self.states["/container/horizontal/left"].addTransition(_container_horizontal_left_1)
+        _container_horizontal_left_2 = Transition(self, self.states["/container/horizontal/left"], [self.states["/container/horizontal/left"]])
+        _container_horizontal_left_2.setAction(self._container_horizontal_left_2_exec)
+        _container_horizontal_left_2.setTrigger(Event("update", "engine"))
+        self.states["/container/horizontal/left"].addTransition(_container_horizontal_left_2)
+        
+        # transition /container/horizontal/both
+        _container_horizontal_both_0 = Transition(self, self.states["/container/horizontal/both"], [self.states["/container/horizontal/right"]])
+        _container_horizontal_both_0.setTrigger(Event("left-released", "input"))
+        self.states["/container/horizontal/both"].addTransition(_container_horizontal_both_0)
+        _container_horizontal_both_1 = Transition(self, self.states["/container/horizontal/both"], [self.states["/container/horizontal/left"]])
+        _container_horizontal_both_1.setTrigger(Event("right-released", "input"))
+        self.states["/container/horizontal/both"].addTransition(_container_horizontal_both_1)
+        
+        # transition /container/horizontal/right
+        _container_horizontal_right_0 = Transition(self, self.states["/container/horizontal/right"], [self.states["/container/horizontal/both"]])
+        _container_horizontal_right_0.setTrigger(Event("left-pressed", "input"))
+        self.states["/container/horizontal/right"].addTransition(_container_horizontal_right_0)
+        _container_horizontal_right_1 = Transition(self, self.states["/container/horizontal/right"], [self.states["/container/horizontal/none"]])
+        _container_horizontal_right_1.setTrigger(Event("right-released", "input"))
+        self.states["/container/horizontal/right"].addTransition(_container_horizontal_right_1)
+        _container_horizontal_right_2 = Transition(self, self.states["/container/horizontal/right"], [self.states["/container/horizontal/right"]])
+        _container_horizontal_right_2.setAction(self._container_horizontal_right_2_exec)
+        _container_horizontal_right_2.setTrigger(Event("update", "engine"))
+        self.states["/container/horizontal/right"].addTransition(_container_horizontal_right_2)
+        
+        # transition /container/vertical/none
+        _container_vertical_none_0 = Transition(self, self.states["/container/vertical/none"], [self.states["/container/vertical/down"]])
+        _container_vertical_none_0.setTrigger(Event("down-pressed", "input"))
+        self.states["/container/vertical/none"].addTransition(_container_vertical_none_0)
+        _container_vertical_none_1 = Transition(self, self.states["/container/vertical/none"], [self.states["/container/vertical/up"]])
+        _container_vertical_none_1.setTrigger(Event("up-pressed", "input"))
+        self.states["/container/vertical/none"].addTransition(_container_vertical_none_1)
+        
+        # transition /container/vertical/down
+        _container_vertical_down_0 = Transition(self, self.states["/container/vertical/down"], [self.states["/container/vertical/none"]])
+        _container_vertical_down_0.setTrigger(Event("down-released", "input"))
+        self.states["/container/vertical/down"].addTransition(_container_vertical_down_0)
+        _container_vertical_down_1 = Transition(self, self.states["/container/vertical/down"], [self.states["/container/vertical/both"]])
+        _container_vertical_down_1.setTrigger(Event("up-pressed", "input"))
+        self.states["/container/vertical/down"].addTransition(_container_vertical_down_1)
+        _container_vertical_down_2 = Transition(self, self.states["/container/vertical/down"], [self.states["/container/vertical/down"]])
+        _container_vertical_down_2.setAction(self._container_vertical_down_2_exec)
+        _container_vertical_down_2.setTrigger(Event("update", "engine"))
+        self.states["/container/vertical/down"].addTransition(_container_vertical_down_2)
+        
+        # transition /container/vertical/both
+        _container_vertical_both_0 = Transition(self, self.states["/container/vertical/both"], [self.states["/container/vertical/up"]])
+        _container_vertical_both_0.setTrigger(Event("down-released", "input"))
+        self.states["/container/vertical/both"].addTransition(_container_vertical_both_0)
+        _container_vertical_both_1 = Transition(self, self.states["/container/vertical/both"], [self.states["/container/vertical/down"]])
+        _container_vertical_both_1.setTrigger(Event("up-released", "input"))
+        self.states["/container/vertical/both"].addTransition(_container_vertical_both_1)
+        
+        # transition /container/vertical/up
+        _container_vertical_up_0 = Transition(self, self.states["/container/vertical/up"], [self.states["/container/vertical/both"]])
+        _container_vertical_up_0.setTrigger(Event("down-pressed", "input"))
+        self.states["/container/vertical/up"].addTransition(_container_vertical_up_0)
+        _container_vertical_up_1 = Transition(self, self.states["/container/vertical/up"], [self.states["/container/vertical/none"]])
+        _container_vertical_up_1.setTrigger(Event("up-released", "input"))
+        self.states["/container/vertical/up"].addTransition(_container_vertical_up_1)
+        _container_vertical_up_2 = Transition(self, self.states["/container/vertical/up"], [self.states["/container/vertical/up"]])
+        _container_vertical_up_2.setAction(self._container_vertical_up_2_exec)
+        _container_vertical_up_2.setTrigger(Event("update", "engine"))
+        self.states["/container/vertical/up"].addTransition(_container_vertical_up_2)
+    
+    def _container_horizontal_left_2_exec(self, parameters):
+        self.tank.turnLeft()
+    
+    def _container_horizontal_right_2_exec(self, parameters):
+        self.tank.turnRight()
+    
+    def _container_vertical_down_2_exec(self, parameters):
+        self.tank.moveDown()
+    
+    def _container_vertical_up_2_exec(self, parameters):
+        self.tank.moveUp()
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/container"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class ObjectManager(ObjectManagerBase):
+    def __init__(self, controller):
+        ObjectManagerBase.__init__(self, controller)
+    
+    def instantiate(self, class_name, construct_params):
+        if class_name == "Main":
+            instance = Main(self.controller, construct_params[0])
+            instance.associations = {}
+            instance.associations["cannon"] = Association("Cannon", 1, 1)
+            instance.associations["body"] = Association("Body", 1, 1)
+        elif class_name == "Cannon":
+            instance = Cannon(self.controller, construct_params[0])
+            instance.associations = {}
+        elif class_name == "Body":
+            instance = Body(self.controller, construct_params[0])
+            instance.associations = {}
+        else:
+            raise Exception("Cannot instantiate class " + class_name)
+        return instance
+
+class Controller(EventLoopControllerBase):
+    def __init__(self, tank, event_loop_callbacks, finished_callback = None, behind_schedule_callback = None):
+        if finished_callback == None: finished_callback = None
+        if behind_schedule_callback == None: behind_schedule_callback = None
+        EventLoopControllerBase.__init__(self, ObjectManager(self), event_loop_callbacks, finished_callback, behind_schedule_callback)
+        self.addInputPort("engine")
+        self.addInputPort("input")
+        self.addOutputPort("gui")
+        self.object_manager.createInstance("Main", [tank])

+ 18 - 8
src/javascript_sccd_runtime/statecharts_core.js

@@ -139,6 +139,7 @@ function ObjectManagerBase(controller) {
 	this.controller = controller;
 	this.events = new EventQueue();
 	this.instances = new Array();
+	this.regex = /^([a-zA-Z_]\w*)(?:\[(\d+)\])?$/;
 }
 
 ObjectManagerBase.prototype.addEvent = function(the_event, time_offset) {
@@ -175,7 +176,7 @@ ObjectManagerBase.prototype.stepAll = function() {
 };
 
 ObjectManagerBase.prototype.step = function() {
-	while (this.events.getEarliestTime() <= time()) {
+	while (this.events.getEarliestTime() <= this.controller.simulated_time) {
 		this.handleEvent(this.events.pop());
 	}
 };
@@ -207,13 +208,12 @@ ObjectManagerBase.prototype.processAssociationReference = function(input_string)
 	if (input_string.length == 0) {
 		throw new AssociationReferenceException("Empty association reference.");
 	}
-	var regex = /^([a-zA-Z_]\w*)(?:\[(\d+)\])?$/;
 	var path_string = input_string.split('/');
 	var result = new Array();
 	if (input_string !== "") {
 		for (var p in path_string) {
 			if (!path_string.hasOwnProperty(p)) continue;
-			var m = regex.exec(path_string[p]);
+			var m = this.regex.exec(path_string[p]);
 			if (m) {
 				var name = m[1];
 				var index = m[2];
@@ -602,10 +602,11 @@ EventLoop.prototype.clear = function() {
 };
 
 // EventLoopControllerBase
-function EventLoopControllerBase(object_manager, event_loop, finished_callback) {
+function EventLoopControllerBase(object_manager, event_loop, finished_callback, behind_schedule_callback) {
 	ControllerBase.call(this, object_manager);
 	this.event_loop = event_loop;
 	this.finished_callback = finished_callback;
+    this.behind_schedule_callback = behind_schedule_callback;
 	this.last_print_time = 0;
 }
 
@@ -636,8 +637,8 @@ EventLoopControllerBase.prototype.run = function() {
 		// simulate
 		this.handleInput();
 		this.object_manager.stepAll();
-		// set next timeout
-		earliest_event_time = ControllerBase.prototype.getEarliestEventTime.call(this);
+		// schedule next timeout
+		var earliest_event_time = ControllerBase.prototype.getEarliestEventTime.call(this);
 		if (earliest_event_time == Infinity) {
             if (this.finished_callback != undefined) this.finished_callback(); // TODO: This is not necessarily correct (keep_running necessary?)
             return;
@@ -832,7 +833,7 @@ Transition.prototype.isEnabled = function(events) {
     } else {
         for (var i in events) {
             the_event = events[i];
-            if ((this.trigger === null || (this.trigger.name == the_event.name && (!this.trigger.port || this.trigger.port == the_event.port))) && (this.guard === null || this.guard(the_event.parameters))) {
+            if ((this.trigger.name == the_event.name && (!this.trigger.port || this.trigger.port == the_event.port)) && (this.guard === null || this.guard(the_event.parameters))) {
                 this.enabled_event = the_event;
                 return true;
             }
@@ -996,6 +997,10 @@ RuntimeClassBase.prototype.start = function() {
 	this.processBigStepOutput();
 };
 
+RuntimeClassBase.prototype.sccd_yield = function() {
+    return Math.max(0, (time() - this.controller.simulated_time) / 1000.0);
+}
+
 RuntimeClassBase.prototype.getSimulatedTime = function() {
     return this.controller.simulated_time;
 }
@@ -1206,7 +1211,12 @@ RuntimeClassBase.prototype.raiseInternalEvent = function(the_event) {
 };
 
 RuntimeClassBase.prototype.initializeStatechart = function() {
-	// pure virtual
+	this.updateConfiguration(this.default_targets);
+    for (let state of this.default_targets) {
+        if (state.enter != null) {
+            state.enter();
+        }
+    }
 };
 
 // BigStepState

+ 2 - 1
src/python_sccd/python_sccd_runtime/statecharts_core.py

@@ -3,7 +3,6 @@ import re
 import threading
 import traceback
 import math
-import cPickle
 from heapq import heappush, heappop
 from infinity import INFINITY
 from Queue import Queue, Empty 
@@ -887,6 +886,8 @@ class RuntimeClassBase(object):
         # self.earliest_event_time keeps track of the earliest time this instance will execute a transition
         if not is_stable:
             self.earliest_event_time = 0
+        elif not self.active:
+            self.earliest_event_time = INFINITY
         else:
             self.earliest_event_time = self.events.getEarliestTime()
         heappush(self.controller.object_manager.instance_times, (self.earliest_event_time, self))