Sfoglia il codice sorgente

Made pypDEVS a platform instead of a language + added a README with example (first touches).

sampieters 1 anno fa
parent
commit
ebc34e9a68

+ 96 - 1
README.md

@@ -1,2 +1,97 @@
 # SCCD2DEVS
- Thesis project to convert the SCCD language to pyDEVS
+This project focuses on the conversion of SCCD XML files into a format compatible with pypDEVS, a Python implementation of the Parallel DEVS (pypDEVS) formalism. The SCCD XML format is commonly used for describing the configuration and behavior of complex systems, while pypDEVS provides a framework for modeling and simulating discrete-event systems.
+
+In this thesis project, we explore the process of transforming SCCD XML files into pypDEVS models, enabling seamless integration of SCCD-based system descriptions into the pDEVS simulation environment. By leveraging the capabilities of both SCCD and pypDEVS, we aim to facilitate the analysis and simulation of intricate systems, contributing to the advancement of modeling and simulation techniques in various domains.
+
+A small documentation for the project can be found here, providing insights into the conversion methodology, implementation details, and examples of utilizing the converted models within the pypDEVS framework. Through this work, we endeavor to bridge the gap between SCCD-based system specifications and the pypDEVS simulation paradigm, fostering greater flexibility and efficiency in system analysis and design processes.
+
+## Compiler
+To compile a conforming SCCD XML file, the provided Python compiler can be used. The compiler can compile conforming SCCD models to two languages: Python and Javascript. Four platforms are supported, TODO: fill in provided platforms.
+
+The compiler can be used from the command line as follows:
+```
+$python -m sccd.compiler.sccdc --help
+usage: python -m sccd.compiler.sccdc [-h] [-o OUTPUT] [-v VERBOSE]
+                                     [-p PLATFORM] [-l LANGUAGE]
+                                     input
+
+positional arguments:
+  input                 The path to the XML file to be compiled.
+
+optional arguments:
+  -h, --help            show this help message and exit
+  -o OUTPUT, --output OUTPUT
+                        The path to the generated code. Defaults to the same
+                        name as the input file but with matching extension.
+  -v VERBOSE, --verbose VERBOSE
+                        2 = all output; 1 = only warnings and errors; 0 = only
+                        errors; -1 = no output. Defaults to 2.
+  -p PLATFORM, --platform PLATFORM
+                        Let the compiled code run on top of threads, gameloop
+                        , eventloop or pypDEVS. The default is eventloop. PypDEVS is only supported for python
+  -l LANGUAGE, --language LANGUAGE
+                        Target language, either "javascript" or "python".
+                        Defaults to the latter.
+```
+
+## Runtime Platforms
+
+### PypDEVS
+The ```PypDEVS``` platform works only in the Python language. The platform works both with and without combination of a UI system that allows for scheduling events. Default implementations are provided for the Tkinter UI library on Python.
+
+## Examples
+All of the examples need two files: A ```runner.py``` and a ```target.py```. The target is generated by the compiler and the runner needs to be made seperatelly.
+
+### BouncingBalls
+To compile the ```BouncingBalls```example, run the following command
+
+```
+python3 sccds.py -o "./examples/BouncingBalls/PyDEVS/target.py" -p "pypDEVS" "./examples/BouncingBalls/sccd.xml"
+```
+
+This will generate a target for the runner which can be composed as follows:
+
+```
+from pypdevs.simulator import Simulator
+import target as target
+
+from tkinter import *
+from sccd.runtime.libs.ui_v2 import UI
+
+class OutputListener:
+	def __init__(self, ui):
+		self.ui = ui
+
+	def add(self, event):
+		if event.port == "ui":
+			method = getattr(self.ui, event.name)
+			method(*event.parameters)
+
+if __name__ == '__main__':
+	model = target.Controller(name="controller")
+	refs = {"ui": model.ui, "field_ui": model.atomic1.field_ui}
+
+	tkroot = Tk()
+	tkroot.withdraw()
+	sim = Simulator(model)
+	sim.setRealTime(True)
+	sim.setRealTimeInputFile(None)
+	sim.setRealTimePorts(refs)
+	sim.setVerbose(None)
+	sim.setRealTimePlatformTk(tkroot)
+
+
+	#controller = target.Controller(TkEventLoop(tkroot))
+	ui = UI(tkroot, "controller")
+	#controller.addMyOwnOutputListener(OutputListener(ui))
+	#controller.start()
+	sim.simulate()
+	tkroot.mainloop()
+```
+
+To finally run the sccd in pypDEVS, run the following command:
+```
+python3 runner.py
+```
+
+### Timer

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

@@ -269,7 +269,7 @@ class MainApp(AtomicDEVS, ObjectManagerBase):
         next_earliest = min(self.getEarliestEventTime(), self.input_queue.getEarliestTime())
         if not (len(self.to_send) == 0):
             self.next_time = 0
-        elif next_earliest == INFINITY:
+        if next_earliest == INFINITY:
             self.next_time = INFINITY
         else:
             self.next_time = next_earliest - earliest

+ 115 - 71
examples/BouncingBalls/Python/target.py

@@ -8,7 +8,7 @@ Tkinter frame with bouncing balls in it.
 """
 
 from sccd.runtime.statecharts_core import *
-from sccd.runtime.libs.ui import ui
+from sccd.runtime.libs import ui_v2 as ui
 from sccd.runtime.libs.utils import utils
 import random
 
@@ -150,7 +150,7 @@ class MainApp(RuntimeClassBase):
         self.removeTimer(0)
     
     def _running_root_0_exec(self, parameters):
-        ui.close_window(ui.window)
+        self.big_step.outputEvent(Event("destroy_all", self.getOutPortName("ui"), []))
     
     def _running_root_main_behaviour_initializing_0_exec(self, parameters):
         self.raiseInternalEvent(Event("create_field", None, []))
@@ -207,23 +207,27 @@ class Field(RuntimeClassBase):
         self.build_statechart_structure()
         
         # user defined attributes
-        self.canvas = None
-        self.field_window = None
+        self.window_id = None
+        self.canvas_id = None
         
         # call user defined constructor
         Field.user_defined_constructor(self)
     
     def user_defined_constructor(self):
-        self.field_window = ui.new_window(800,600,"BouncingBalls");
-        self.canvas = ui.append_canvas(self.field_window,800,550,{'background':'#eee'});
-        ui.bind_event(self.field_window, ui.EVENTS.WINDOW_CLOSE, self.controller, 'window_close', self.inports['field_ui']);
-        ui.bind_event(self.field_window, ui.EVENTS.KEY_PRESS, self.controller, 'key_press', self.inports['field_ui']);
-        ui.bind_event(self.canvas.element, ui.EVENTS.MOUSE_RIGHT_CLICK,    self.controller, 'right_click', self.inports['field_ui']);
-        ui.bind_event(self.canvas.element, ui.EVENTS.MOUSE_MOVE, self.controller, 'mouse_move', self.inports['field_ui']);
-        ui.bind_event(self.canvas.element, ui.EVENTS.MOUSE_RELEASE, self.controller, 'mouse_release', self.inports['field_ui']);
+        # All of these TkInter calls have been converted to in/out-events:
+        #self.field_window = ui.new_window(800,600,"BouncingBalls");
+        #self.canvas = ui.append_canvas(self.field_window,800,550,{'background':'#eee'});
+        #ui.bind_event(self.field_window, ui.EVENTS.WINDOW_CLOSE, self.controller, 'window_close', self.inports['field_ui']);
+        #ui.bind_event(self.field_window, ui.EVENTS.KEY_PRESS, self.controller, 'key_press', self.inports['field_ui']);
+        #ui.bind_event(self.canvas.element, ui.EVENTS.MOUSE_RIGHT_CLICK,    self.controller, 'right_click', self.inports['field_ui']);
+        #ui.bind_event(self.canvas.element, ui.EVENTS.MOUSE_MOVE, self.controller, 'mouse_move', self.inports['field_ui']);
+        #ui.bind_event(self.canvas.element, ui.EVENTS.MOUSE_RELEASE, self.controller, 'mouse_release', self.inports['field_ui']);
+        print("created field")
+        pass
     
     def user_defined_destructor(self):
-        ui.close_window(self.field_window);
+        # ui.close_window(self.field_window);
+        pass
     
     
     # builds Statechart structure
@@ -238,14 +242,17 @@ class Field(RuntimeClassBase):
         # state /root/waiting
         self.states["/root/waiting"] = State(2, "/root/waiting", self)
         
-        # state /root/initializing
-        self.states["/root/initializing"] = State(3, "/root/initializing", self)
+        # state /root/creating_window
+        self.states["/root/creating_window"] = State(3, "/root/creating_window", self)
+        self.states["/root/creating_window"].setEnter(self._root_creating_window_enter)
         
-        # state /root/creating
-        self.states["/root/creating"] = State(4, "/root/creating", self)
+        # state /root/creating_canvas
+        self.states["/root/creating_canvas"] = State(4, "/root/creating_canvas", self)
+        self.states["/root/creating_canvas"].setEnter(self._root_creating_canvas_enter)
         
-        # state /root/packing
-        self.states["/root/packing"] = State(5, "/root/packing", self)
+        # state /root/creating_button
+        self.states["/root/creating_button"] = State(5, "/root/creating_button", self)
+        self.states["/root/creating_button"].setEnter(self._root_creating_button_enter)
         
         # state /root/running
         self.states["/root/running"] = ParallelState(6, "/root/running", self)
@@ -256,8 +263,8 @@ class Field(RuntimeClassBase):
         # state /root/running/main_behaviour/running
         self.states["/root/running/main_behaviour/running"] = State(8, "/root/running/main_behaviour/running", self)
         
-        # state /root/running/main_behaviour/creating
-        self.states["/root/running/main_behaviour/creating"] = State(9, "/root/running/main_behaviour/creating", self)
+        # state /root/running/main_behaviour/creating_ball
+        self.states["/root/running/main_behaviour/creating_ball"] = State(9, "/root/running/main_behaviour/creating_ball", self)
         
         # state /root/running/deleting_behaviour
         self.states["/root/running/deleting_behaviour"] = State(10, "/root/running/deleting_behaviour", self)
@@ -286,9 +293,9 @@ class Field(RuntimeClassBase):
         # add children
         self.states[""].addChild(self.states["/root"])
         self.states["/root"].addChild(self.states["/root/waiting"])
-        self.states["/root"].addChild(self.states["/root/initializing"])
-        self.states["/root"].addChild(self.states["/root/creating"])
-        self.states["/root"].addChild(self.states["/root/packing"])
+        self.states["/root"].addChild(self.states["/root/creating_window"])
+        self.states["/root"].addChild(self.states["/root/creating_canvas"])
+        self.states["/root"].addChild(self.states["/root/creating_button"])
         self.states["/root"].addChild(self.states["/root/running"])
         self.states["/root"].addChild(self.states["/root/deleting"])
         self.states["/root"].addChild(self.states["/root/deleted"])
@@ -297,7 +304,7 @@ class Field(RuntimeClassBase):
         self.states["/root/running"].addChild(self.states["/root/running/child_behaviour"])
         self.states["/root/running"].addChild(self.states["/root/running/deleting_balls_behaviour"])
         self.states["/root/running/main_behaviour"].addChild(self.states["/root/running/main_behaviour/running"])
-        self.states["/root/running/main_behaviour"].addChild(self.states["/root/running/main_behaviour/creating"])
+        self.states["/root/running/main_behaviour"].addChild(self.states["/root/running/main_behaviour/creating_ball"])
         self.states["/root/running/deleting_behaviour"].addChild(self.states["/root/running/deleting_behaviour/running"])
         self.states["/root/running/child_behaviour"].addChild(self.states["/root/running/child_behaviour/listening"])
         self.states["/root/running/deleting_balls_behaviour"].addChild(self.states["/root/running/deleting_balls_behaviour/listening"])
@@ -310,39 +317,40 @@ class Field(RuntimeClassBase):
         self.states["/root/running/deleting_balls_behaviour"].default_state = self.states["/root/running/deleting_balls_behaviour/listening"]
         
         # transition /root/waiting
-        _root_waiting_0 = Transition(self, self.states["/root/waiting"], [self.states["/root/initializing"]])
+        _root_waiting_0 = Transition(self, self.states["/root/waiting"], [self.states["/root/creating_window"]])
         _root_waiting_0.setAction(self._root_waiting_0_exec)
         _root_waiting_0.setTrigger(Event("set_association_name", None))
         self.states["/root/waiting"].addTransition(_root_waiting_0)
         
-        # transition /root/initializing
-        _root_initializing_0 = Transition(self, self.states["/root/initializing"], [self.states["/root/creating"]])
-        _root_initializing_0.setAction(self._root_initializing_0_exec)
-        _root_initializing_0.setTrigger(None)
-        self.states["/root/initializing"].addTransition(_root_initializing_0)
+        # transition /root/creating_window
+        _root_creating_window_0 = Transition(self, self.states["/root/creating_window"], [self.states["/root/creating_canvas"]])
+        _root_creating_window_0.setAction(self._root_creating_window_0_exec)
+        _root_creating_window_0.setTrigger(Event("window_created", None))
+        self.states["/root/creating_window"].addTransition(_root_creating_window_0)
         
-        # transition /root/creating
-        _root_creating_0 = Transition(self, self.states["/root/creating"], [self.states["/root/packing"]])
-        _root_creating_0.setAction(self._root_creating_0_exec)
-        _root_creating_0.setTrigger(Event("instance_created", None))
-        self.states["/root/creating"].addTransition(_root_creating_0)
+        # transition /root/creating_canvas
+        _root_creating_canvas_0 = Transition(self, self.states["/root/creating_canvas"], [self.states["/root/creating_button"]])
+        _root_creating_canvas_0.setAction(self._root_creating_canvas_0_exec)
+        _root_creating_canvas_0.setTrigger(Event("canvas_created", None))
+        self.states["/root/creating_canvas"].addTransition(_root_creating_canvas_0)
         
-        # transition /root/packing
-        _root_packing_0 = Transition(self, self.states["/root/packing"], [self.states["/root/running"]])
-        _root_packing_0.setTrigger(Event("button_created", None))
-        self.states["/root/packing"].addTransition(_root_packing_0)
+        # transition /root/creating_button
+        _root_creating_button_0 = Transition(self, self.states["/root/creating_button"], [self.states["/root/running"]])
+        _root_creating_button_0.setAction(self._root_creating_button_0_exec)
+        _root_creating_button_0.setTrigger(Event("instance_created", None))
+        self.states["/root/creating_button"].addTransition(_root_creating_button_0)
         
         # transition /root/running/main_behaviour/running
-        _root_running_main_behaviour_running_0 = Transition(self, self.states["/root/running/main_behaviour/running"], [self.states["/root/running/main_behaviour/creating"]])
+        _root_running_main_behaviour_running_0 = Transition(self, self.states["/root/running/main_behaviour/running"], [self.states["/root/running/main_behaviour/creating_ball"]])
         _root_running_main_behaviour_running_0.setAction(self._root_running_main_behaviour_running_0_exec)
         _root_running_main_behaviour_running_0.setTrigger(Event("right_click", self.getInPortName("field_ui")))
         self.states["/root/running/main_behaviour/running"].addTransition(_root_running_main_behaviour_running_0)
         
-        # transition /root/running/main_behaviour/creating
-        _root_running_main_behaviour_creating_0 = Transition(self, self.states["/root/running/main_behaviour/creating"], [self.states["/root/running/main_behaviour/running"]])
-        _root_running_main_behaviour_creating_0.setAction(self._root_running_main_behaviour_creating_0_exec)
-        _root_running_main_behaviour_creating_0.setTrigger(Event("instance_created", None))
-        self.states["/root/running/main_behaviour/creating"].addTransition(_root_running_main_behaviour_creating_0)
+        # transition /root/running/main_behaviour/creating_ball
+        _root_running_main_behaviour_creating_ball_0 = Transition(self, self.states["/root/running/main_behaviour/creating_ball"], [self.states["/root/running/main_behaviour/running"]])
+        _root_running_main_behaviour_creating_ball_0.setAction(self._root_running_main_behaviour_creating_ball_0_exec)
+        _root_running_main_behaviour_creating_ball_0.setTrigger(Event("instance_created", None))
+        self.states["/root/running/main_behaviour/creating_ball"].addTransition(_root_running_main_behaviour_creating_ball_0)
         
         # transition /root/running/deleting_behaviour/running
         _root_running_deleting_behaviour_running_0 = Transition(self, self.states["/root/running/deleting_behaviour/running"], [self.states["/root/running/deleting_behaviour/running"]])
@@ -375,6 +383,15 @@ class Field(RuntimeClassBase):
         _root_running_0.setTrigger(Event("window_close", self.getInPortName("field_ui")))
         self.states["/root/running"].addTransition(_root_running_0)
     
+    def _root_creating_window_enter(self):
+        self.big_step.outputEvent(Event("create_window", self.getOutPortName("ui"), [800, 600, "BouncingBalls", self.inports['field_ui']]))
+    
+    def _root_creating_canvas_enter(self):
+        self.big_step.outputEvent(Event("create_canvas", self.getOutPortName("ui"), [self.window_id, 800, 550, {'background':'#eee'}, self.inports['field_ui']]))
+    
+    def _root_creating_button_enter(self):
+        self.big_step.outputEventOM(Event("create_instance", None, [self, "buttons", "Button", self.window_id, 'create_new_field', 'Spawn New Window']))
+    
     def _root_running_0_exec(self, parameters):
         self.big_step.outputEventOM(Event("delete_instance", None, [self, "buttons"]))
         self.big_step.outputEventOM(Event("delete_instance", None, [self, "balls"]))
@@ -383,10 +400,20 @@ class Field(RuntimeClassBase):
         association_name = parameters[0]
         self.association_name = association_name
     
-    def _root_initializing_0_exec(self, parameters):
-        self.big_step.outputEventOM(Event("create_instance", None, [self, "buttons", "Button", self.field_window, 'create_new_field', 'Spawn New Window']))
+    def _root_creating_window_0_exec(self, parameters):
+        window_id = parameters[0]
+        self.window_id = window_id
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.WINDOW_CLOSE, 'window_close', self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [window_id, ui.EVENTS.KEY_PRESS, 'key_press', self.inports['field_ui']]))
     
-    def _root_creating_0_exec(self, parameters):
+    def _root_creating_canvas_0_exec(self, parameters):
+        canvas_id = parameters[0]
+        self.canvas_id = canvas_id
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RIGHT_CLICK, 'right_click', self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_MOVE, 'mouse_move', self.inports['field_ui']]))
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [canvas_id, ui.EVENTS.MOUSE_RELEASE, 'mouse_release', self.inports['field_ui']]))
+    
+    def _root_creating_button_0_exec(self, parameters):
         association_name = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
     
@@ -396,7 +423,7 @@ class Field(RuntimeClassBase):
         button = parameters[2]
         self.big_step.outputEventOM(Event("create_instance", None, [self, "balls", "Ball", self.canvas, x, y]))
     
-    def _root_running_main_behaviour_creating_0_exec(self, parameters):
+    def _root_running_main_behaviour_creating_ball_0_exec(self, parameters):
         association_name = parameters[0]
         self.big_step.outputEventOM(Event("start_instance", None, [self, association_name]))
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, association_name, Event("set_association_name", None, [association_name])]))
@@ -419,6 +446,7 @@ class Field(RuntimeClassBase):
     
     def _root_deleting_0_exec(self, parameters):
         self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("delete_field", None, [self.association_name])]))
+        self.big_step.outputEvent(Event("destroy_window", self.getOutPortName("ui"), [self.window_id]))
     
     def initializeStatechart(self):
         # enter default state
@@ -426,7 +454,7 @@ class Field(RuntimeClassBase):
         RuntimeClassBase.initializeStatechart(self)
 
 class Button(RuntimeClassBase):
-    def __init__(self, controller, tkparent, event_name, button_text):
+    def __init__(self, controller, window_id, event_name, button_text):
         RuntimeClassBase.__init__(self, controller)
         
         self.inports["button_ui"] = controller.addInputPort("button_ui", self)
@@ -440,13 +468,21 @@ class Button(RuntimeClassBase):
         # build Statechart structure
         self.build_statechart_structure()
         
+        # user defined attributes
+        self.window_id = None
+        self.event_name = None
+        self.button_id = None
+        
         # call user defined constructor
-        Button.user_defined_constructor(self, tkparent, event_name, button_text)
+        Button.user_defined_constructor(self, window_id, event_name, button_text)
     
-    def user_defined_constructor(self, tkparent, event_name, button_text):
+    def user_defined_constructor(self, window_id, event_name, button_text):
+        self.window_id = window_id;
         self.event_name = event_name;
-        button = ui.append_button(tkparent, event_name);
-        ui.bind_event(button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'mouse_click', self.inports['button_ui']);
+        
+        # Translated to events:
+        #button = ui.append_button(tkparent, event_name);
+        #ui.bind_event(button.element, ui.EVENTS.MOUSE_CLICK, self.controller, 'mouse_click', self.inports['button_ui']);
     
     def user_defined_destructor(self):
         pass
@@ -458,23 +494,24 @@ class Button(RuntimeClassBase):
         # state <root>
         self.states[""] = State(0, "", self)
         
-        # state /initializing
-        self.states["/initializing"] = State(1, "/initializing", self)
+        # state /creating_button
+        self.states["/creating_button"] = State(1, "/creating_button", self)
+        self.states["/creating_button"].setEnter(self._creating_button_enter)
         
         # state /running
         self.states["/running"] = State(2, "/running", self)
         
         # add children
-        self.states[""].addChild(self.states["/initializing"])
+        self.states[""].addChild(self.states["/creating_button"])
         self.states[""].addChild(self.states["/running"])
         self.states[""].fixTree()
-        self.states[""].default_state = self.states["/initializing"]
+        self.states[""].default_state = self.states["/creating_button"]
         
-        # transition /initializing
-        _initializing_0 = Transition(self, self.states["/initializing"], [self.states["/running"]])
-        _initializing_0.setAction(self._initializing_0_exec)
-        _initializing_0.setTrigger(None)
-        self.states["/initializing"].addTransition(_initializing_0)
+        # transition /creating_button
+        _creating_button_0 = Transition(self, self.states["/creating_button"], [self.states["/running"]])
+        _creating_button_0.setAction(self._creating_button_0_exec)
+        _creating_button_0.setTrigger(Event("button_created", None))
+        self.states["/creating_button"].addTransition(_creating_button_0)
         
         # transition /running
         _running_0 = Transition(self, self.states["/running"], [self.states["/running"]])
@@ -483,8 +520,13 @@ class Button(RuntimeClassBase):
         _running_0.setGuard(self._running_0_guard)
         self.states["/running"].addTransition(_running_0)
     
-    def _initializing_0_exec(self, parameters):
-        self.big_step.outputEventOM(Event("narrow_cast", None, [self, 'parent', Event("button_created", None, [])]))
+    def _creating_button_enter(self):
+        self.big_step.outputEvent(Event("create_button", self.getOutPortName("ui"), [self.window_id, self.event_name, self.inports['button_ui']]))
+    
+    def _creating_button_0_exec(self, parameters):
+        button_id = parameters[0]
+        self.button_id = button_id
+        self.big_step.outputEvent(Event("bind_event", self.getOutPortName("ui"), [button_id, ui.EVENTS.MOUSE_CLICK, "mouse_click", self.inports['button_ui']]))
     
     def _running_0_exec(self, parameters):
         x = parameters[0]
@@ -500,7 +542,7 @@ class Button(RuntimeClassBase):
     
     def initializeStatechart(self):
         # enter default state
-        self.default_targets = self.states["/initializing"].getEffectiveTargetStates()
+        self.default_targets = self.states["/creating_button"].getEffectiveTargetStates()
         RuntimeClassBase.initializeStatechart(self)
 
 class Ball(RuntimeClassBase):
@@ -531,11 +573,12 @@ class Ball(RuntimeClassBase):
         self.mouse_pos = {};
         self.smooth = 0.4; # value between 0 and 1
         
-        circle = self.canvas.add_circle(x, y, self.r, {'fill':'#000'});
-        ui.bind_event(circle, ui.EVENTS.MOUSE_PRESS, self.controller, 'mouse_press', self.inports["ball_ui"]);
-        ui.bind_event(circle, ui.EVENTS.MOUSE_MOVE, self.controller, 'mouse_move', self.inports['ball_ui']);
-        ui.bind_event(circle, ui.EVENTS.MOUSE_RELEASE, self.controller, 'mouse_release', self.inports['ball_ui']);
-        self.element = circle;
+        # TODO:
+        #circle = self.canvas.add_circle(x, y, self.r, {'fill':'#000'});
+        #ui.bind_event(circle, ui.EVENTS.MOUSE_PRESS, self.controller, 'mouse_press', self.inports["ball_ui"]);
+        #ui.bind_event(circle, ui.EVENTS.MOUSE_MOVE, self.controller, 'mouse_move', self.inports['ball_ui']);
+        #ui.bind_event(circle, ui.EVENTS.MOUSE_RELEASE, self.controller, 'mouse_release', self.inports['ball_ui']);
+        #self.element = circle;
     
     def user_defined_destructor(self):
         self.canvas.remove_element(self.element);
@@ -730,4 +773,5 @@ class Controller(EventLoopControllerBase):
         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.addOutputPort("ui")
         self.object_manager.createInstance("MainApp", [])

+ 1 - 1
sccd/compiler/generic_generator.py

@@ -13,7 +13,7 @@ from sccd.compiler.sccd_constructs import FormalParameter
 from sccd.compiler.stateful_writer import StatefulWriter
 import sccd.compiler.generic_language_constructs as GLC
 
-Platforms = Enum("Threads","GameLoop","EventLoop") 
+Platforms = Enum("Threads","GameLoop","EventLoop", "PypDEVS") 
 
 class GenericGenerator(Visitor):
     

+ 4 - 3
sccd/compiler/sccdc.py

@@ -17,7 +17,6 @@ from sccd.compiler.javascript_writer import JavascriptWriter
 from sccd.compiler.python_writer import PythonWriter
 
 def generate(input_file, output_file, target_language, platform):
-	#TODO: Set DEVS to platform and not to language.
 	sccd = xmlToSccd(input_file)
 
 	if not target_language:
@@ -29,12 +28,12 @@ def generate(input_file, output_file, target_language, platform):
 		Logger.showError("Diagram specifies target language as \"" + sccd.language + "\", but language option of compiler has been set to \"" + target_language + "\". No output has been generated.")
 		return
 
-	if (target_language == "python" or target_language == "pypDEVS") and not output_file.endswith(".py") :
+	if target_language == "python" and not output_file.endswith(".py") :
 		output_file += ".py"
 	elif target_language == "javascript" and not output_file.endswith(".js") :
 		output_file += ".js"
 
-	if target_language == "pypDEVS":
+	if platform == 3:
 		generic = sccdToDEVS(sccd, platform)
 	else:
 		generic = sccdToGeneric(sccd, platform)
@@ -125,6 +124,8 @@ def main():
 			platform = Platforms.GameLoop
 		elif args['platform'] == "eventloop" :
 			platform = Platforms.EventLoop
+		elif args['platform'] == "pypdevs":
+			platform = Platforms.PypDEVS
 		else :
 			Logger.showError("Invalid platform.")
 			return