瀏覽代碼

fixed creating multiple instances + deletion still needs to be fixed + started on FixTimer to ensure that it works in DEVS

sampieters 1 年之前
父節點
當前提交
08df85d052

+ 166 - 113
examples/BouncingBalls/PyDEVS/best_target.py

@@ -224,43 +224,39 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
+            elif input[2].name == "create_instance":
                 new_instance = MainAppInstance(self)
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].parameters[0]]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
                 pass
-            elif input[3].name == "associate_instance":
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_associated":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -283,7 +279,7 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -587,43 +583,40 @@ class Field(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
+            elif input[2].name == "create_instance":
                 new_instance = FieldInstance(self)
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].instance]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
-                pass
-            elif input[3].name == "associate_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_associated":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -646,7 +639,7 @@ class Field(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -782,43 +775,90 @@ class Button(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
-                new_instance = ButtonInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
+            elif input[2].name == "create_instance":
+                new_instance = ButtonInstance(self, input[2].parameters[2], input[2].parameters[3], input[2].parameters[4])
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, parameters=[f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].instance]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
-                pass
-            elif input[3].name == "associate_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
+                instances = self.instances
+                for i in instances:
+                    try:
+                        for assoc_name in i.associations:
+                            if assoc_name != 'parent':
+                                traversal_list = self.processAssociationReference(assoc_name)
+                                instances = self.getInstances(i["instance"], traversal_list)
+                                if len(instances) > 0:
+                                    raise RuntimeException("Error removing instance from association %s, still %i children left connected with association %s" % (association_name, len(instances), assoc_name))
+                                del i["instance"].controller.input_ports[i["instance"].narrow_cast_port]
+                                association.removeInstance(i["instance"])
+                                self.instances.discard(i["instance"])
+                                self.eventless.discard(i["instance"])
+                    except AssociationException as exception:
+                        raise RuntimeException("Error removing instance from association '" + association_name + "': " + str(exception))
+                    i.user_defined_destructor()
+                    i.stop()
+                
+                ev = Event("instance_deleted", None, [input[0]])
+                self.to_send.append((input[1], input[0], ev))
+            #source.addEvent(Event("instance_deleted", parameters = [parameters[1]]))
+
+
+
+
+
+
+
+
+
+
+                #instance = self.instances[input[2].instance]
+                #try:
+                #    for assoc_name in instance.associations:
+                #        if assoc_name != 'parent':
+                #            traversal_list = self.processAssociationReference(assoc_name)
+                #            instances = self.getInstances(i["instance"], traversal_list)
+                #            if len(instances) > 0:
+                #                raise RuntimeException("Error removing instance from association %s, still %i children left connected with association %s" % (assoc_name, len(instances), assoc_name))
+                    #del i["instance"].controller.input_ports[i["instance"].narrow_cast_port]
+                    #association.removeInstance(instance)
+                #    self.instances.remove(instance)
+                #    self.eventless.discard(instance)
+                #except AssociationException as exception:
+                #    raise RuntimeException("Error removing instance from association '" + assoc_name + "': " + str(exception))
+                #instance.user_defined_destructor()
+                #instance.stop()
+
+                #ev = Event("instance_deleted", None, [input[0]])
+                #self.to_send.append((input[1], input[0], ev))
+
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_associated":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -841,7 +881,7 @@ class Button(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -1104,43 +1144,56 @@ class Ball(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
-                new_instance = BallInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
+            elif input[2].name == "create_instance":
+                new_instance = BallInstance(self, input[2].parameters[2], input[2].parameters[3], input[2].parameters[4])
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"], len(self.instances)-1)
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].instance]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
+                instance = self.instances[input[2].instance]
+                try:
+                    for assoc_name in instance.associations:
+                        if assoc_name != 'parent':
+                            traversal_list = self.processAssociationReference(assoc_name)
+                            instances = self.getInstances(i["instance"], traversal_list)
+                            if len(instances) > 0:
+                                raise RuntimeException("Error removing instance from association %s, still %i children left connected with association %s" % (assoc_name, len(instances), assoc_name))
+                    #del i["instance"].controller.input_ports[i["instance"].narrow_cast_port]
+                    #association.removeInstance(instance)
+                    self.instances.remove(instance)
+                    self.eventless.discard(instance)
+                except AssociationException as exception:
+                    raise RuntimeException("Error removing instance from association '" + assoc_name + "': " + str(exception))
+                instance.user_defined_destructor()
+                instance.stop()
+                ev = Event("instance_deleted", None, parameters = [input[0]])
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "associate_instance":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
-                pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[3].instance]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_associated":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -1163,7 +1216,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -1184,7 +1237,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
 
 class ObjectManagerState:
     def __init__(self):
-        self.to_send = [(None, "MainApp", 0, Event("start_instance", None, [0]))]
+        self.to_send = [(None, "MainApp", Event("start_instance", None, [0], 0))]
 
 class ObjectManager(AtomicDEVS):
     def __init__(self, name):
@@ -1209,11 +1262,11 @@ class ObjectManager(AtomicDEVS):
     
     def outputFnc(self):
         out_dict = {}
-        for (source, target, id, message) in self.State.to_send:
+        for (source, target, message) in self.State.to_send:
             if self.output[target] in out_dict:
-                out_dict[self.output[target]].append((source, target, id, message))
+                out_dict[self.output[target]].append((source, target, message))
             else:
-                out_dict[self.output[target]] = [(source, target, id, message)]
+                out_dict[self.output[target]] = [(source, target, message)]
         return out_dict
     
     def timeAdvance(self):

+ 1 - 1
examples/BouncingBalls/PyDEVS/runner.py

@@ -1,5 +1,5 @@
 import tkinter as tk
-import target as target
+import examples.BouncingBalls.PyDEVS.target as target
 from sccd.runtime.libs.ui_v2 import UI
 from sccd.runtime.DEVS_loop import DEVSSimulator
 

+ 95 - 128
examples/BouncingBalls/PyDEVS/target.py

@@ -224,43 +224,39 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
+            elif input[2].name == "create_instance":
                 new_instance = MainAppInstance(self)
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].instance]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
                 pass
-            elif input[3].name == "associate_instance":
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[3].instance]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_associated":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -283,7 +279,7 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -587,43 +583,39 @@ class Field(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
+            elif input[2].name == "create_instance":
                 new_instance = FieldInstance(self)
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].instance]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
                 pass
-            elif input[3].name == "associate_instance":
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[3].instance]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_associated":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -646,7 +638,7 @@ class Field(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -782,60 +774,39 @@ class Button(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
-                new_instance = ButtonInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
+            elif input[2].name == "create_instance":
+                new_instance = ButtonInstance(self, input[2].parameters[2], input[2].parameters[3], input[2].parameters[4])
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].instance]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
-                instance = self.instances[input[3].instance]
-                try:
-                    for assoc_name in instance.associations:
-                        if assoc_name != 'parent':
-                            traversal_list = self.processAssociationReference(assoc_name)
-                            instances = self.getInstances(i["instance"], traversal_list)
-                            if len(instances) > 0:
-                                raise RuntimeException("Error removing instance from association %s, still %i children left connected with association %s" % (assoc_name, len(instances), assoc_name))
-                    #del i["instance"].controller.input_ports[i["instance"].narrow_cast_port]
-                    #association.removeInstance(instance)
-                    self.instances.remove(instance)
-                    self.eventless.discard(instance)
-                except AssociationException as exception:
-                    raise RuntimeException("Error removing instance from association '" + assoc_name + "': " + str(exception))
-                instance.user_defined_destructor()
-                instance.stop()
-                ev = Event("instance_deleted", None, parameters = [input[0]])
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "associate_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[3].instance]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_associated":
+                pass
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -858,7 +829,7 @@ class Button(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -1121,43 +1092,39 @@ class Ball(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            elif input[3].name == "create_instance":
-                new_instance = BallInstance(self, input[3].parameters[1], input[3].parameters[2], input[3].parameters[3])
+            elif input[2].name == "create_instance":
+                new_instance = BallInstance(self, input[2].parameters[2], input[2].parameters[3], input[2].parameters[4])
                 self.instances.append(new_instance)
                 p = new_instance.associations.get("parent")
                 if p:
-                    p.addInstance("fields[0]")
-                ev = Event("instance_created", None, [f"{input[3].parameters[0]}[{len(self.instances)-1}]"])
-                self.to_send.append((input[1], input[0], input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = self.instances[input[3].instance]
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[3].instance)
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
                 pass
-            elif input[3].name == "associate_instance":
+            elif input[2].name == "associate_instance":
                 pass
-            elif input[3].name == "disassociate_instance":
+            elif input[2].name == "disassociate_instance":
                 pass
-            elif input[3].name == "instance_created":
-                association = self.processAssociationReference(input[3].parameters[0])[0]
-                instance = self.instances[input[2]]
-                p = instance.associations.get(association[0])
-                if p:
-                    p.addInstance(input[3].parameters[0])
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_started":
-                instance = self.instances[input[3].instance]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
                 pass
-            elif input[3].name == "instance_associated":
+            elif input[2].name == "instance_associated":
                 pass
-            elif input[3].name == "instance_disassociated":
+            elif input[2].name == "instance_disassociated":
                 pass
             else:
-                ev = input[3]
+                ev = input[2]
                 self.addInput(ev)
         return self.instances
     
@@ -1180,7 +1147,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[3].port == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -1201,7 +1168,7 @@ class Ball(AtomicDEVS, ObjectManagerBase):
 
 class ObjectManagerState:
     def __init__(self):
-        self.to_send = [(None, "MainApp", 0, Event("start_instance", None, [0], 0))]
+        self.to_send = [(None, "MainApp", Event("start_instance", None, [0], 0))]
 
 class ObjectManager(AtomicDEVS):
     def __init__(self, name):
@@ -1226,11 +1193,11 @@ class ObjectManager(AtomicDEVS):
     
     def outputFnc(self):
         out_dict = {}
-        for (source, target, id, message) in self.State.to_send:
+        for (source, target, message) in self.State.to_send:
             if self.output[target] in out_dict:
-                out_dict[self.output[target]].append((source, target, id, message))
+                out_dict[self.output[target]].append((source, target, message))
             else:
-                out_dict[self.output[target]] = [(source, target, id, message)]
+                out_dict[self.output[target]] = [(source, target, message)]
         return out_dict
     
     def timeAdvance(self):

+ 24 - 0
examples/FixedTimer/PyDEVS/runner.py

@@ -0,0 +1,24 @@
+from pypdevs.simulator import Simulator
+import target as target
+
+from tkinter import *
+from sccd.runtime.libs.ui import ui
+
+
+
+model = target.Controller(name="controller")
+#refs = {"ui": model.ui, "field_ui": model.atomic1.field_ui}
+ui.window = Tk()
+ui.window.withdraw()
+
+sim = Simulator(model)
+sim.setRealTime(True)
+sim.setRealTimeInputFile(None)
+#sim.setRealTimePorts(refs)
+sim.setVerbose(None)
+sim.setRealTimePlatformTk(ui.window)
+
+ui.simulator = sim
+
+sim.simulate()
+ui.window.mainloop()

+ 275 - 0
examples/FixedTimer/PyDEVS/target.py

@@ -0,0 +1,275 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration) and Sam Pieters (DEVS)
+
+Model author: Simon Van Mierlo
+Model name:   Timer (Eventloop Version)
+
+"""
+
+from sccd.runtime.DEVS_statecharts_core import *
+from pypdevs.DEVS import *
+from pypdevs.infinity import *
+from pypdevs.simulator import *
+from sccd.runtime.libs.ui import ui
+from time import time
+
+CANVAS_WIDTH = 500
+CANVAS_HEIGHT = 250
+FONT_SIZE = 50
+
+# package "Timer (Eventloop Version)"
+
+class MainAppInstance(RuntimeClassBase):
+    def __init__(self, atomdevs):
+        RuntimeClassBase.__init__(self, atomdevs)
+        self.associations = {}
+        
+        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
+        MainAppInstance.user_defined_constructor(self)
+    
+    def user_defined_constructor(self):
+        self.canvas = ui.append_canvas(ui.window,CANVAS_WIDTH,CANVAS_HEIGHT,{'background':'#222222'})
+        self.clock_text = self.canvas.element.create_text(
+            CANVAS_WIDTH / 2,
+            CANVAS_HEIGHT / 2,
+            text='0.0', 
+            anchor='center',
+            font=("TkDefaultFont", FONT_SIZE)
+            )
+        self.actual_clock_text = self.canvas.element.create_text(
+            CANVAS_WIDTH / 2, 
+            (CANVAS_HEIGHT / 2) + FONT_SIZE, 
+            text='0.0', 
+            anchor='center',
+            font=("TkDefaultFont", FONT_SIZE)
+        )
+        interrupt_button = ui.append_button(ui.window, 'INTERRUPT');
+        continue_button = ui.append_button(ui.window, 'CONTINUE');
+        #ui.bind_event(interrupt_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'interrupt_clicked');
+        #ui.bind_event(continue_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'continue_clicked');
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # user defined method
+    def update_timers(self):
+        self.canvas.element.itemconfigure(self.clock_text, text=str('%.2f' % (self.getSimulatedTime() / 1000.0)))
+        self.canvas.element.itemconfigure(self.actual_clock_text, text='%.2f' % (time() / 1000.0))
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, "", self)
+        
+        # state /running
+        self.states["/running"] = State(1, "/running", self)
+        self.states["/running"].setEnter(self._running_enter)
+        self.states["/running"].setExit(self._running_exit)
+        
+        # state /interrupted
+        self.states["/interrupted"] = State(2, "/interrupted", self)
+        
+        # add children
+        self.states[""].addChild(self.states["/running"])
+        self.states[""].addChild(self.states["/interrupted"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/running"]
+        
+        # transition /running
+        _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
+        _running_0.setAction(self._running_0_exec)
+        _running_0.setTrigger(Event("_0after"))
+        self.states["/running"].addTransition(_running_0)
+        _running_1 = Transition(self, self.states["/running"], [self.states["/interrupted"]])
+        _running_1.setAction(self._running_1_exec)
+        _running_1.setTrigger(Event("interrupt_clicked", self.getInPortName("ui")))
+        self.states["/running"].addTransition(_running_1)
+        
+        # transition /interrupted
+        _interrupted_0 = Transition(self, self.states["/interrupted"], [self.states["/interrupted"]])
+        _interrupted_0.setAction(self._interrupted_0_exec)
+        _interrupted_0.setTrigger(Event("interrupt_clicked", self.getInPortName("ui")))
+        self.states["/interrupted"].addTransition(_interrupted_0)
+        _interrupted_1 = Transition(self, self.states["/interrupted"], [self.states["/running"]])
+        _interrupted_1.setAction(self._interrupted_1_exec)
+        _interrupted_1.setTrigger(Event("continue_clicked", self.getInPortName("ui")))
+        self.states["/interrupted"].addTransition(_interrupted_1)
+    
+    def _running_enter(self):
+        self.addTimer(0, 0.05)
+    
+    def _running_exit(self):
+        self.removeTimer(0)
+    
+    def _running_0_exec(self, parameters):
+        self.update_timers()
+    
+    def _running_1_exec(self, parameters):
+        self.update_timers()
+    
+    def _interrupted_0_exec(self, parameters):
+        self.update_timers()
+    
+    def _interrupted_1_exec(self, parameters):
+        self.update_timers()
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/running"].getEffectiveTargetStates()
+        RuntimeClassBase.initializeStatechart(self)
+
+class MainApp(AtomicDEVS, ObjectManagerBase):
+    def __init__(self, name):
+        AtomicDEVS.__init__(self, name)
+        ObjectManagerBase.__init__(self)
+        self.elapsed = 0
+        self.name = "MainApp"
+        self.obj_manager_out = self.addOutPort("obj_manager_out")
+        self.outputs = {}
+        self.obj_manager_in = self.addInPort("obj_manager_in")
+        self.input = self.addInPort("input")
+        self.instances.append(MainAppInstance(self))
+        self.next_time = INFINITY
+    
+    def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
+        self.next_time = 0
+        all_inputs = []
+        if self.obj_manager_in in inputs:
+            all_inputs.extend(inputs[self.obj_manager_in])
+        if self.input in inputs:
+            all_inputs.extend(inputs[self.input])
+        for input in all_inputs:
+            if isinstance(input, str):
+                tem = eval(input)
+                self.addInput(tem)
+            elif input[2].name == "create_instance":
+                new_instance = MainAppInstance(self)
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
+                instance.start()
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
+                pass
+            elif input[2].name == "associate_instance":
+                pass
+            elif input[2].name == "disassociate_instance":
+                pass
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
+                pass
+            elif input[2].name == "instance_associated":
+                pass
+            elif input[2].name == "instance_disassociated":
+                pass
+            else:
+                ev = input[2]
+                self.addInput(ev)
+        return self.instances
+    
+    def intTransition(self):
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
+        if not (earliest == INFINITY):
+            self.simulated_time = earliest
+        self.to_send = []
+        self.handleInput()
+        self.stepAll()
+        next_earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        if not (len(self.to_send) == 0):
+            self.next_time = 0
+        elif next_earliest == INFINITY:
+            self.next_time = INFINITY
+        else:
+            self.next_time = next_earliest - earliest
+        return self.instances
+    
+    def outputFnc(self):
+        to_dict = {}
+        for sending in self.to_send:
+            if sending[2].port == None:
+                if self.obj_manager_out in to_dict:
+                    to_dict[self.obj_manager_out].append(sending)
+                else:
+                    to_dict[self.obj_manager_out] = [sending]
+            else:
+                the_port = None
+                for port in self.OPorts:
+                    if port.name == sending[0]:
+                        the_port = port
+                if the_port in to_dict:
+                    to_dict[the_port].append(sending)
+                else:
+                    to_dict[the_port] = [sending]
+        return to_dict
+    
+    def timeAdvance(self):
+        return self.next_time
+
+class ObjectManagerState:
+    def __init__(self):
+        self.to_send = [(None, "MainApp", Event("start_instance", None, [0], 0))]
+
+class ObjectManager(AtomicDEVS):
+    def __init__(self, name):
+        AtomicDEVS.__init__(self, name)
+        self.State = ObjectManagerState()
+        self.input = self.addInPort("input")
+        self.output = {}
+        self.output["MainApp"] = self.addOutPort()
+    
+    def extTransition(self, inputs):
+        all_inputs = inputs[self.input]
+        for input in all_inputs:
+            self.State.to_send.append(input)
+        return self.State
+    
+    def intTransition(self):
+        self.State.to_send = []
+        return self.State
+    
+    def outputFnc(self):
+        out_dict = {}
+        for (source, target, message) in self.State.to_send:
+            if self.output[target] in out_dict:
+                out_dict[self.output[target]].append((source, target, message))
+            else:
+                out_dict[self.output[target]] = [(source, target, message)]
+        return out_dict
+    
+    def timeAdvance(self):
+        if self.State.to_send:
+            return 0
+        return INFINITY
+
+class Controller(CoupledDEVS):
+    def __init__(self, name):
+        CoupledDEVS.__init__(self, name)
+        self.ui = self.addInPort("ui")
+        self.objectmanager = self.addSubModel(ObjectManager("ObjectManager"))
+        self.atomic0 = self.addSubModel(MainApp("MainApp"))
+        self.connectPorts(self.atomic0.obj_manager_out, self.objectmanager.input)
+        self.connectPorts(self.objectmanager.output["MainApp"], self.atomic0.obj_manager_in)

+ 12 - 0
examples/FixedTimer/Python/runner.py

@@ -0,0 +1,12 @@
+import tkinter as tk
+import target as target
+from sccd.runtime.libs.ui import ui
+from sccd.runtime.statecharts_core import Event
+from sccd.runtime.tkinter_eventloop import *
+
+if __name__ == '__main__':
+	ui.window = tk.Tk()
+
+	controller = target.Controller(TkEventLoop(ui.window))
+	controller.start()
+	ui.window.mainloop()

+ 148 - 0
examples/FixedTimer/Python/target.py

@@ -0,0 +1,148 @@
+"""
+Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
+
+Model author: Simon Van Mierlo
+Model name:   Timer (Eventloop Version)
+
+"""
+
+from sccd.runtime.statecharts_core import *
+from sccd.runtime.libs.ui import ui
+from time import time
+
+CANVAS_WIDTH = 500
+CANVAS_HEIGHT = 500
+FONT_SIZE = 50
+
+# package "Timer (Eventloop Version)"
+
+class MainApp(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
+        MainApp.user_defined_constructor(self)
+    
+    def user_defined_constructor(self):
+        self.canvas = ui.append_canvas(ui.window,500,500,{'background':'#222222'})
+        self.clock_text = self.canvas.element.create_text(
+            CANVAS_WIDTH / 2,
+            CANVAS_HEIGHT / 2,
+            text='0.0', 
+            anchor='center',
+            font=("TkDefaultFont", FONT_SIZE)
+            )
+        self.actual_clock_text = self.canvas.element.create_text(
+            CANVAS_WIDTH / 2, 
+            (CANVAS_HEIGHT / 2) + FONT_SIZE, 
+            text='0.0', 
+            anchor='center',
+            font=("TkDefaultFont", FONT_SIZE)
+        )
+        interrupt_button = ui.append_button(ui.window, 'INTERRUPT');
+        continue_button = ui.append_button(ui.window, 'CONTINUE');
+        ui.bind_event(interrupt_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'interrupt_clicked');
+        ui.bind_event(continue_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'continue_clicked');
+    
+    def user_defined_destructor(self):
+        pass
+    
+    
+    # user defined method
+    def update_timers(self):
+        self.canvas.element.itemconfigure(self.clock_text, text=str('%.2f' % (self.getSimulatedTime() / 1000.0)))
+        self.canvas.element.itemconfigure(self.actual_clock_text, text='%.2f' % (time() / 1000.0))
+    
+    
+    # builds Statechart structure
+    def build_statechart_structure(self):
+        
+        # state <root>
+        self.states[""] = State(0, "", self)
+        
+        # state /running
+        self.states["/running"] = State(1, "/running", self)
+        self.states["/running"].setEnter(self._running_enter)
+        self.states["/running"].setExit(self._running_exit)
+        
+        # state /interrupted
+        self.states["/interrupted"] = State(2, "/interrupted", self)
+        
+        # add children
+        self.states[""].addChild(self.states["/running"])
+        self.states[""].addChild(self.states["/interrupted"])
+        self.states[""].fixTree()
+        self.states[""].default_state = self.states["/running"]
+        
+        # transition /running
+        _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
+        _running_0.setAction(self._running_0_exec)
+        _running_0.setTrigger(Event("_0after"))
+        self.states["/running"].addTransition(_running_0)
+        _running_1 = Transition(self, self.states["/running"], [self.states["/interrupted"]])
+        _running_1.setAction(self._running_1_exec)
+        _running_1.setTrigger(Event("interrupt_clicked", self.getInPortName("ui")))
+        self.states["/running"].addTransition(_running_1)
+        
+        # transition /interrupted
+        _interrupted_0 = Transition(self, self.states["/interrupted"], [self.states["/interrupted"]])
+        _interrupted_0.setAction(self._interrupted_0_exec)
+        _interrupted_0.setTrigger(Event("interrupt_clicked", self.getInPortName("ui")))
+        self.states["/interrupted"].addTransition(_interrupted_0)
+        _interrupted_1 = Transition(self, self.states["/interrupted"], [self.states["/running"]])
+        _interrupted_1.setAction(self._interrupted_1_exec)
+        _interrupted_1.setTrigger(Event("continue_clicked", self.getInPortName("ui")))
+        self.states["/interrupted"].addTransition(_interrupted_1)
+    
+    def _running_enter(self):
+        self.addTimer(0, 0.05)
+    
+    def _running_exit(self):
+        self.removeTimer(0)
+    
+    def _running_0_exec(self, parameters):
+        self.update_timers()
+    
+    def _running_1_exec(self, parameters):
+        self.update_timers()
+    
+    def _interrupted_0_exec(self, parameters):
+        self.update_timers()
+    
+    def _interrupted_1_exec(self, parameters):
+        self.update_timers()
+    
+    def initializeStatechart(self):
+        # enter default state
+        self.default_targets = self.states["/running"].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 == "MainApp":
+            instance = MainApp(self.controller)
+            instance.associations = {}
+        else:
+            raise Exception("Cannot instantiate class " + class_name)
+        return instance
+
+class Controller(EventLoopControllerBase):
+    def __init__(self, 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("ui")
+        self.object_manager.createInstance("MainApp", [])

+ 73 - 0
examples/FixedTimer/sccd.xml

@@ -0,0 +1,73 @@
+<?xml version="1.0" ?>
+<diagram author="Simon Van Mierlo" name="Timer (Eventloop Version)">
+    <top>
+        from sccd.runtime.libs.ui import ui_v2 as ui 
+        from time import time
+
+        CANVAS_WIDTH = 500
+        CANVAS_HEIGHT = 250
+        FONT_SIZE = 50
+    </top>
+    
+    <inport name="ui" />
+
+    <class name="MainApp" default="true">
+        <method name="MainApp">
+            <body>
+                <![CDATA[
+                self.canvas = ui.append_canvas(ui.window,CANVAS_WIDTH,CANVAS_HEIGHT,{'background':'#222222'})
+                self.clock_text = self.canvas.element.create_text(
+                    CANVAS_WIDTH / 2,
+                    CANVAS_HEIGHT / 2,
+                    text='0.0', 
+                    anchor='center',
+                    font=("TkDefaultFont", FONT_SIZE)
+                    )
+                self.actual_clock_text = self.canvas.element.create_text(
+                    CANVAS_WIDTH / 2, 
+                    (CANVAS_HEIGHT / 2) + FONT_SIZE, 
+                    text='0.0', 
+                    anchor='center',
+                    font=("TkDefaultFont", FONT_SIZE)
+                )
+                interrupt_button = ui.append_button(ui.window, 'INTERRUPT');
+                continue_button = ui.append_button(ui.window, 'CONTINUE');
+                #ui.bind_event(interrupt_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'interrupt_clicked');
+                #ui.bind_event(continue_button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'continue_clicked');
+                ]]>
+            </body>        
+        </method>
+        <method name="update_timers">
+            <body>
+                self.canvas.element.itemconfigure(self.clock_text, text=str('%.2f' % (self.getSimulatedTime() / 1000.0)))
+                self.canvas.element.itemconfigure(self.actual_clock_text, text='%.2f' % (time() / 1000.0))
+            </body>
+        </method>
+        <scxml initial="running">
+            <state id="running">
+                <transition target="." after="0.05">
+                    <script>
+                        self.update_timers()
+                    </script>
+                </transition>
+                <transition target="../interrupted" event="interrupt_clicked" port="ui">
+                    <script>
+                        self.update_timers()
+                    </script>
+                </transition>
+            </state>
+            <state id="interrupted">
+                <transition target="." event="interrupt_clicked" port="ui">
+                    <script>
+                        self.update_timers()
+                    </script>
+                </transition>
+                <transition target="../running" event="continue_clicked" port="ui">
+                    <script>
+                        self.update_timers()
+                    </script>
+                </transition>
+            </state>
+        </scxml>
+    </class>
+</diagram>

+ 1 - 1
examples/Timer/PyDEVS/runner.py

@@ -2,7 +2,7 @@ from pypdevs.simulator import Simulator
 import target as target
 
 from tkinter import *
-from sccd.runtime.libs.DEVui import ui
+from sccd.runtime.libs.ui import ui
 
 
 

+ 55 - 48
examples/Timer/PyDEVS/target.py

@@ -11,7 +11,7 @@ from pypdevs.DEVS import *
 from pypdevs.infinity import *
 from pypdevs.simulator import *
 from sccd.runtime.libs.ui import ui
-from sccd.runtime.accurate_time import AccurateTime
+from time import time
 
 # package "Timer (Eventloop Version)"
 
@@ -33,7 +33,7 @@ class MainAppInstance(RuntimeClassBase):
         MainAppInstance.user_defined_constructor(self)
     
     def user_defined_constructor(self):
-        self.canvas = ui.append_canvas(ui.window,100,100,{'background':'#eee'})
+        self.canvas = ui.append_canvas(ui.window,100,100,{'background':'#222222'})
         self.clock_text = self.canvas.element.create_text(25,25,{'text':'0.0'})
         self.actual_clock_text = self.canvas.element.create_text(25,50,{'text':'0.0'})
         interrupt_button = ui.append_button(ui.window, 'INTERRUPT');
@@ -47,8 +47,8 @@ class MainAppInstance(RuntimeClassBase):
     
     # user defined method
     def update_timers(self):
-        self.canvas.element.itemconfigure(self.clock_text, text=str('%.2f' % (self.getSimulatedTime())))
-        #self.canvas.element.itemconfigure(self.actual_clock_text, text='%.2f' % (time() / 1000.0))
+        self.canvas.element.itemconfigure(self.clock_text, text=str('%.2f' % (self.getSimulatedTime() / 1000.0)))
+        self.canvas.element.itemconfigure(self.actual_clock_text, text='%.2f' % (time() / 1000.0))
     
     
     # builds Statechart structure
@@ -119,14 +119,16 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
         AtomicDEVS.__init__(self, name)
         ObjectManagerBase.__init__(self)
         self.elapsed = 0
+        self.name = "MainApp"
         self.obj_manager_out = self.addOutPort("obj_manager_out")
         self.outputs = {}
         self.obj_manager_in = self.addInPort("obj_manager_in")
         self.input = self.addInPort("input")
-        self.instances.add(MainAppInstance(self))
-        self.next_time = 0
+        self.instances.append(MainAppInstance(self))
+        self.next_time = INFINITY
     
     def extTransition(self, inputs):
+        self.simulated_time = (self.simulated_time + self.elapsed)
         self.next_time = 0
         all_inputs = []
         if self.obj_manager_in in inputs:
@@ -137,60 +139,62 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
             if isinstance(input, str):
                 tem = eval(input)
                 self.addInput(tem)
-            if input[3].name == "create_instance":
-                self.instances.add(MainAppInstance(self))
-                ev = Event("instance_created", None, parameters=[f"{input[0]}[{len(self.instances)-1}]"])
-                self.to_send.append(("MainApp", TODO, input[2], ev))
-            elif input[3].name == "start_instance":
-                instance = list(self.instances)[input[2]]
+            elif input[2].name == "create_instance":
+                new_instance = MainAppInstance(self)
+                self.instances.append(new_instance)
+                p = new_instance.associations.get("parent")
+                if p:
+                    p.addInstance(input[2].instance)
+                ev = Event("instance_created", None, [f"{input[2].parameters[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[1], input[0], ev))
+            elif input[2].name == "start_instance":
+                instance = self.instances[input[2].instance]
                 instance.start()
-                ev = Event("instance_started", None, parameters=[])
-                self.to_send.append((input[0], input[1], input[2], ev))
-            elif input[3].name == "delete_instance":
-                ev = Event("instance_deleted", None, parameters=[TODO])
-                self.to_send.append((TODO, TODO, TODO, ev))
-            elif input[3].name == "associate_instance":
-                ev = Event("instance_associated", None, parameters=[TODO])
-                self.to_send.append((TODO, TODO, TODO, ev))
-            elif input[3].name == "disassociate_instance":
-                ev = Event("instance_disassociated", None, parameters=[TODO])
-                self.to_send.append((TODO, TODO, TODO, ev))
-            elif input[3].name == "instance_created":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-                instance.associations['fields'].instances[0] = input[3].parameters[0]
-            elif input[3].name == "instance_started":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_deleted":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_associated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "instance_disassociated":
-                instance = list(self.instances)[input[2]]
-                instance.addEvent(input[3])
-            elif input[3].name == "set_association_name":
-                ev = input[3]
-                self.addInput(ev, force_internal=True)
+                ev = Event("instance_started", None, [f"{input[0]}[{len(self.instances)-1}]"], input[2].instance)
+                self.to_send.append((input[0], input[1], ev))
+            elif input[2].name == "delete_instance":
+                pass
+            elif input[2].name == "associate_instance":
+                pass
+            elif input[2].name == "disassociate_instance":
+                pass
+            elif input[2].name == "instance_created":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_started":
+                instance = self.instances[input[2].instance]
+                instance.addEvent(input[2])
+            elif input[2].name == "instance_deleted":
+                pass
+            elif input[2].name == "instance_associated":
+                pass
+            elif input[2].name == "instance_disassociated":
+                pass
+            else:
+                ev = input[2]
+                self.addInput(ev)
         return self.instances
     
     def intTransition(self):
-        earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
+        earliest = min(self.getEarliestEventTime(), self.simulated_time + self.input_queue.getEarliestTime())
         if not (earliest == INFINITY):
             self.simulated_time = earliest
         self.to_send = []
         self.handleInput()
         self.stepAll()
         next_earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
-        self.next_time = next_earliest - earliest
+        if not (len(self.to_send) == 0):
+            self.next_time = 0
+        elif next_earliest == INFINITY:
+            self.next_time = INFINITY
+        else:
+            self.next_time = next_earliest - earliest
         return self.instances
     
     def outputFnc(self):
         to_dict = {}
         for sending in self.to_send:
-            if sending[0] == None:
+            if sending[2].port == None:
                 if self.obj_manager_out in to_dict:
                     to_dict[self.obj_manager_out].append(sending)
                 else:
@@ -211,7 +215,7 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
 
 class ObjectManagerState:
     def __init__(self):
-        self.to_send = [(None, "MainApp", 0, Event("start_instance", None, None))]
+        self.to_send = [(None, "MainApp", Event("start_instance", None, [0], 0))]
 
 class ObjectManager(AtomicDEVS):
     def __init__(self, name):
@@ -233,8 +237,11 @@ class ObjectManager(AtomicDEVS):
     
     def outputFnc(self):
         out_dict = {}
-        for (source, target, id, message) in self.State.to_send:
-            out_dict[self.output[target]] = [(source, target, id, message)]
+        for (source, target, message) in self.State.to_send:
+            if self.output[target] in out_dict:
+                out_dict[self.output[target]].append((source, target, message))
+            else:
+                out_dict[self.output[target]] = [(source, target, message)]
         return out_dict
     
     def timeAdvance(self):

+ 2 - 2
examples/Timer/Python/target.py

@@ -8,7 +8,7 @@ Model name:   Timer (Eventloop Version)
 
 from sccd.runtime.statecharts_core import *
 from sccd.runtime.libs.ui import ui
-from sccd.runtime.accurate_time import AccurateTime
+from time import time
 
 # package "Timer (Eventloop Version)"
 
@@ -30,7 +30,7 @@ class MainApp(RuntimeClassBase):
         MainApp.user_defined_constructor(self)
     
     def user_defined_constructor(self):
-        self.canvas = ui.append_canvas(ui.window,100,100,{'background':'#eee'})
+        self.canvas = ui.append_canvas(ui.window,100,100,{'background':'#222222'})
         self.clock_text = self.canvas.element.create_text(25,25,{'text':'0.0'})
         self.actual_clock_text = self.canvas.element.create_text(25,50,{'text':'0.0'})
         interrupt_button = ui.append_button(ui.window, 'INTERRUPT');

+ 2 - 2
examples/Timer/sccd.xml

@@ -2,7 +2,7 @@
 <diagram author="Simon Van Mierlo" name="Timer (Eventloop Version)">
     <top>
         from sccd.runtime.libs.ui import ui
-        from sccd.runtime.accurate_time import time
+        from time import time
     </top>
     
     <inport name="ui" />
@@ -11,7 +11,7 @@
         <method name="MainApp">
             <body>
                 <![CDATA[
-                self.canvas = ui.append_canvas(ui.window,100,100,{'background':'#eee'})
+                self.canvas = ui.append_canvas(ui.window,100,100,{'background':'#222222'})
                 self.clock_text = self.canvas.element.create_text(25,25,{'text':'0.0'})
                 self.actual_clock_text = self.canvas.element.create_text(25,50,{'text':'0.0'})
                 interrupt_button = ui.append_button(ui.window, 'INTERRUPT');

+ 27 - 33
sccd/compiler/DEVS_generator.py

@@ -60,7 +60,7 @@ class DEVSGenerator(Visitor):
         self.writer.beginConstructor()
         self.writer.beginMethodBody()
 
-        self.writer.addAssignment(GLC.SelfProperty("to_send"), f"[(None, \"{class_diagram.default_class.name}\", 0, Event(\"start_instance\", None, [0], 0))]")
+        self.writer.addAssignment(GLC.SelfProperty("to_send"), f"[(None, \"{class_diagram.default_class.name}\", Event(\"start_instance\", None, [0], 0))]")
 
         self.writer.endMethodBody()
         self.writer.endConstructor()
@@ -112,12 +112,12 @@ class DEVSGenerator(Visitor):
         self.writer.beginMethodBody()
         self.writer.addAssignment("out_dict", "{}")
 
-        self.writer.beginForLoopIterateArray(GLC.SelfProperty("State.to_send"), "(source, target, id, message)")
+        self.writer.beginForLoopIterateArray(GLC.SelfProperty("State.to_send"), "(source, target, message)")
         self.writer.beginIf(GLC.ArrayContains("out_dict", "self.output[target]"))
-        self.writer.add(GLC.FunctionCall("out_dict[self.output[target]].append", ["(source, target, id, message)"]))
+        self.writer.add(GLC.FunctionCall("out_dict[self.output[target]].append", ["(source, target, message)"]))
         self.writer.endIf()
         self.writer.beginElse()
-        self.writer.addAssignment(f"out_dict[self.output[target]]", "[(source, target, id, message)]")
+        self.writer.addAssignment(f"out_dict[self.output[target]]", "[(source, target, message)]")
         self.writer.endElse()
         self.writer.endForLoopIterateArray()
 
@@ -386,68 +386,62 @@ class DEVSGenerator(Visitor):
         self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addInput"), ["tem"]))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("create_instance")))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("create_instance")))
 
         parameters = [GLC.SelfExpression()]
         for i, _ in enumerate(constructor.parameters):
-            parameters.append(f"input[3].parameters[{i+1}]")
+            parameters.append(f"input[2].parameters[{i+2}]")
 
         self.writer.addAssignment("new_instance", GLC.FunctionCall(f"{class_node.name}Instance", parameters))
         self.writer.add(GLC.FunctionCall(GLC.SelfProperty("instances.append"), ["new_instance"]))
 
         self.writer.addAssignment("p", "new_instance.associations.get(\"parent\")")
         self.writer.beginIf("p")
-        self.writer.add(GLC.FunctionCall("p.addInstance", [GLC.String("fields[0]")]))
+        self.writer.add(GLC.FunctionCall("p.addInstance", ["input[2].instance"]))
         self.writer.endIf()
 
-
-        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_created\"", "None", "[f\"{input[3].parameters[0]}[{len(self.instances)-1}]\"]"]))
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(input[1], input[0], input[2], ev)"]))
+        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_created\"", "None", "[f\"{input[2].parameters[0]}[{len(self.instances)-1}]\"], input[2].instance"]))
+        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(input[1], input[0], ev)"]))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("start_instance")))
-        self.writer.addAssignment("instance", "self.instances[input[3].instance]")
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("start_instance")))
+        self.writer.addAssignment("instance", "self.instances[input[2].instance]")
         self.writer.add(GLC.FunctionCall("instance.start"))
 
-        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_started\"", "None", "[f\"{input[0]}[{len(self.instances)-1}]\"], input[3].instance"]))
-        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(input[0], input[1], input[2], ev)"]))
+        self.writer.addAssignment("ev", GLC.FunctionCall("Event", ["\"instance_started\"", "None", "[f\"{input[0]}[{len(self.instances)-1}]\"], input[2].instance"]))
+        self.writer.add(GLC.FunctionCall(GLC.SelfProperty("to_send.append"), ["(input[0], input[1], ev)"]))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("delete_instance")))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("delete_instance")))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("associate_instance")))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("associate_instance")))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("disassociate_instance")))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("disassociate_instance")))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_created")))
-        self.writer.addAssignment("association", "self.processAssociationReference(input[3].parameters[0])[0]")
-        self.writer.addAssignment("instance", "self.instances[input[2]]")
-        self.writer.addAssignment("p", "instance.associations.get(association[0])")
-        self.writer.beginIf("p")
-        self.writer.add(GLC.FunctionCall("p.addInstance", ["input[3].parameters[0]"]))
-        self.writer.endIf()
-        self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[3]"]))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("instance_created")))
+        self.writer.addAssignment("instance", "self.instances[input[2].instance]")
+        self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[2]"]))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_started")))
-        self.writer.addAssignment("instance", "self.instances[input[3].instance]")
-        self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[3]"]))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("instance_started")))
+        self.writer.addAssignment("instance", "self.instances[input[2].instance]")
+        self.writer.add(GLC.FunctionCall("instance.addEvent", ["input[2]"]))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_deleted")))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("instance_deleted")))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_associated")))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("instance_associated")))
         self.writer.endElseIf()
 
-        self.writer.beginElseIf(GLC.EqualsExpression("input[3].name", GLC.String("instance_disassociated")))
+        self.writer.beginElseIf(GLC.EqualsExpression("input[2].name", GLC.String("instance_disassociated")))
         self.writer.endElseIf()
 
         self.writer.beginElse()
-        self.writer.addAssignment("ev", "input[3]")
+        self.writer.addAssignment("ev", "input[2]")
         self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addInput"), ["ev"]))
         self.writer.endElse()
         
@@ -488,7 +482,7 @@ class DEVSGenerator(Visitor):
         self.writer.beginMethodBody()
         self.writer.addAssignment("to_dict", "{}")
         self.writer.beginForLoopIterateArray(GLC.SelfProperty("to_send"), "sending")
-        self.writer.beginIf(GLC.EqualsExpression("sending[3].port", "None"))
+        self.writer.beginIf(GLC.EqualsExpression("sending[2].port", "None"))
 
         self.writer.beginIf(GLC.ArrayContains("to_dict", "self.obj_manager_out"))
         self.writer.add(GLC.FunctionCall("to_dict[self.obj_manager_out].append", ["sending"]))

+ 74 - 48
sccd/runtime/DEVS_statecharts_core.py

@@ -56,7 +56,7 @@ class Association(object):
         if self.allowedToAdd():
             new_id = self.next_id
             self.next_id += 1
-            self.instances[new_id] = instance
+            self.instances[new_id] = new_id
             self.instances_to_ids[instance] = new_id
             self.size += 1
             return new_id
@@ -431,7 +431,8 @@ class RuntimeClassBase(object):
         self.configuration_bitmap = sum([2 ** s.state_id for s in states])
 
     def getSimulatedTime(self):
-        return self.controller.simulated_time
+        # TODO: added to be exactly the same as sccd
+        return self.controller.simulated_time * 1000
 
     def addTimer(self, index, timeout):
         #self.timers_to_add[index] = (self.controller.simulated_time + int(timeout * 1000), Event("_%iafter" % index))
@@ -820,7 +821,7 @@ class ObjectManagerBase(object):
             for i in self.getInstances(source, traversal_list):
                 #i["instance"].start()
                 # TODO: start instance over a link from mainapp to field
-                self.to_send.append((i['assoc_name'], i['to_class'], 0, Event("start_instance", None, [], i['instance'])))
+                self.to_send.append((i['assoc_name'], i['to_class'], Event("start_instance", None, [], i['instance'])))
 
 
 
@@ -836,6 +837,16 @@ class ObjectManagerBase(object):
             raise ParameterException ("The create event needs at least 2 parameters.")
 
         source = parameters[0]
+
+        # TODO: Added this otherwise the instance of the evet was always the last and you couldnt add a ball in another field, is this right? 
+        source_index = None
+        try:
+            source_index = self.processAssociationReference(source.association_name)
+            source_index = source_index[0][1]
+        except:
+            # TODO: I think the else is only for mainapp becuase it would not have an assocation name
+            source_index = 0
+
         association_name = parameters[1]
         
         traversal_list = self.processAssociationReference(association_name)
@@ -846,30 +857,16 @@ class ObjectManagerBase(object):
         if association.allowedToAdd():
             ''' allow subclasses to be instantiated '''
             class_name = association.to_class if len(parameters) == 2 else parameters[2]
-            #new_instance = self.createInstance(class_name, parameters[3:])
-
-            #id = None
-            #for index, i in enumerate(self.instances):
-            #    if i == source:
-            #        id = index
-            #        break
-
-            hulp = [association_name]
-            hulp.extend(parameters[3:])
-            self.to_send.append((self.name, class_name, 0, Event('create_instance', None, hulp)))
-
-            #if not new_instance:
-            #    raise ParameterException("Creating instance: no such class: " + class_name)
-
-            #try:
-            #    index = association.addInstance(new_instance)
-            #except AssociationException as exception:
-            #    raise RuntimeException("Error adding instance to association '" + association_name + "': " + str(exception))
-            #p = new_instance.associations.get("parent")
-            #if p:
-            #    p.addInstance(source)
-            #source.addEvent(Event("instance_created", None, [association_name+"["+str(index)+"]"]))
-            #return [source, association_name+"["+str(index)+"]"]
+
+            new_instance = association_name + f"[{len(self.instances)-1}]"
+
+            try:
+                index = association.addInstance(new_instance)
+            except AssociationException as exception:
+                raise RuntimeException("Error adding instance to association '" + association_name + "': " + str(exception))
+            
+            self.to_send.append((self.name, class_name, Event('create_instance', None, parameters[1:], source_index)))
+
         else:
             source.addEvent(Event("instance_creation_error", None, [association_name]))
             return []
@@ -888,28 +885,55 @@ class ObjectManagerBase(object):
             
             traversal_list = self.processAssociationReference(association_name)
             instances = self.getInstances(source, traversal_list)
-            # association = self.instances_map[source].getAssociation(traversal_list[0][0])
             association = source.associations[traversal_list[0][0]]
             
-            for i in instances:
-                self.to_send.append((i['assoc_name'], i['to_class'], 0, Event("delete_instance", None, None, i['instance'])))
-                #try:
-                    #for assoc_name in i["instance"].associations:
-                    #    if assoc_name != 'parent':
-                    #        traversal_list = self.processAssociationReference(assoc_name)
-                    #        instances = self.getInstances(i["instance"], traversal_list)
-                    #        if len(instances) > 0:
-                    #            raise RuntimeException("Error removing instance from association %s, still %i children left connected with association %s" % (association_name, len(instances), assoc_name))
-                    #del i["instance"].controller.input_ports[i["instance"].narrow_cast_port]
-                    #association.removeInstance(i["instance"])
-                    #self.instances.discard(i["instance"])
-                    #self.eventless.discard(i["instance"])
-                #except AssociationException as exception:
-                #    raise RuntimeException("Error removing instance from association '" + association_name + "': " + str(exception))
-                #i["instance"].user_defined_destructor()
-                #i["instance"].stop()
+            #for i in instances:
+            #    try:
+            #        for assoc_name in i["instance"].associations:
+            #            if assoc_name != 'parent':
+            #                traversal_list = self.processAssociationReference(assoc_name)
+            #                instances = self.getInstances(i["instance"], traversal_list)
+            #                if len(instances) > 0:
+            #                    raise RuntimeException("Error removing instance from association %s, still %i children left connected with association %s" % (association_name, len(instances), assoc_name))
+            #        del i["instance"].controller.input_ports[i["instance"].narrow_cast_port]
+            #        association.removeInstance(i["instance"])
+            #        self.instances.discard(i["instance"])
+            #        self.eventless.discard(i["instance"])
+            #    except AssociationException as exception:
+            #        raise RuntimeException("Error removing instance from association '" + association_name + "': " + str(exception))
+            #    i["instance"].user_defined_destructor()
+            #    i["instance"].stop()
                 
             #source.addEvent(Event("instance_deleted", parameters = [parameters[1]]))
+
+            index = self.processAssociationReference(source.association_name)
+            index = index[0][1]
+
+            self.to_send.append((source.association_name, association.to_class, Event("delete_instance", None, [parameters[1]], index)))
+        
+
+
+
+
+
+
+
+
+
+        #if len(parameters) < 2:
+        #    raise ParameterException ("The delete event needs at least 2 parameters.")
+        #else:
+        #    source = parameters[0]
+        #    association_name = parameters[1]
+            
+        #    traversal_list = self.processAssociationReference(association_name)
+        #    instances = self.getInstances(source, traversal_list)
+        #    association = source.associations[traversal_list[0][0]]
+            
+        #    for i in instances:
+        #        # TODO: source association name as index
+        #        self.to_send.append((source.association_name, i['to_class'], Event("delete_instance", None, None, i['instance'])))
+
                 
     def handleAssociateEvent(self, parameters):
         if len(parameters) != 3:
@@ -975,7 +999,7 @@ class ObjectManagerBase(object):
             for i in self.getInstances(source, traversal_list):
                 # TODO: port cannot be none but don't know yet how to do port 
                 ev = Event(cast_event.name, None, cast_event.parameters, i["instance"])
-                self.to_send.append((i["assoc_name"], i['to_class'], i["assoc_index"], ev))
+                self.to_send.append((i["assoc_name"], i['to_class'], ev))
 
                 #to_send_event = Event(cast_event.name, i["instance"].narrow_cast_port, cast_event.parameters)
                 #i["instance"].controller.addInput(to_send_event, force_internal=True)
@@ -1010,10 +1034,12 @@ class ObjectManagerBase(object):
                         pass
                 elif (index == -1):
                     for i in association.instances:
-                        parent = self.processAssociationReference(association.instances[i])[0]
+                        # TODO: this does not work anymore if only index
+                        #parent = self.processAssociationReference(association.instances[i])[0]
+                        parent = association.instances[i]
                         nexts.append({
                             "to_class": association.to_class,
-                            "instance": parent[1],
+                            "instance": parent,
                             "ref": current["instance"],
                             "assoc_name": name,
                             "assoc_index": index,

+ 1 - 2
sccd/runtime/statecharts_core.py

@@ -231,14 +231,13 @@ class ObjectManagerBase(object):
         instances = self.getInstances(source, traversal_list)
         
         association = source.associations[association_name]
-        # association = self.instances_map[source].getAssociation(association_name)
+
         if association.allowedToAdd():
             ''' allow subclasses to be instantiated '''
             class_name = association.to_class if len(parameters) == 2 else parameters[2]
             new_instance = self.createInstance(class_name, parameters[3:])
             if not new_instance:
                 raise ParameterException("Creating instance: no such class: " + class_name)
-            # index = association.addInstance(new_instance)
             try:
                 index = association.addInstance(new_instance)
             except AssociationException as exception: