Browse Source

Added some missing files for MoSIS: the digital watch example and the
railway framework

Yentl Van Tendeloo 8 years ago
parent
commit
5469eb4130
86 changed files with 138385 additions and 0 deletions
  1. 641 0
      exported_to_sccdxml/DigitalWatchGUI.py
  2. 67 0
      exported_to_sccdxml/classes/translator.xml
  3. 15 0
      exported_to_sccdxml/digitalwatch.xml
  4. 6 0
      exported_to_sccdxml/imgs/convert.sh
  5. BIN
      exported_to_sccdxml/imgs/green.gif
  6. BIN
      exported_to_sccdxml/imgs/green.png
  7. BIN
      exported_to_sccdxml/imgs/lights.png
  8. 99 0
      exported_to_sccdxml/imgs/lights.svg
  9. BIN
      exported_to_sccdxml/imgs/rail.gif
  10. BIN
      exported_to_sccdxml/imgs/rail.png
  11. 210 0
      exported_to_sccdxml/imgs/rail.svg
  12. BIN
      exported_to_sccdxml/imgs/red.gif
  13. BIN
      exported_to_sccdxml/imgs/red.png
  14. BIN
      exported_to_sccdxml/imgs/station.gif
  15. BIN
      exported_to_sccdxml/imgs/station.png
  16. BIN
      exported_to_sccdxml/imgs/train.gif
  17. BIN
      exported_to_sccdxml/imgs/train.png
  18. 61 0
      exported_to_sccdxml/imgs/train.svg
  19. BIN
      exported_to_sccdxml/imgs/yellow.gif
  20. BIN
      exported_to_sccdxml/imgs/yellow.png
  21. BIN
      exported_to_sccdxml/noteSmall.gif
  22. 17 0
      exported_to_sccdxml/python_runtime/.project
  23. 5 0
      exported_to_sccdxml/python_runtime/.pydevproject
  24. 0 0
      exported_to_sccdxml/python_runtime/__init__.py
  25. 9 0
      exported_to_sccdxml/python_runtime/accurate_time.py
  26. 58 0
      exported_to_sccdxml/python_runtime/event_queue.py
  27. 3 0
      exported_to_sccdxml/python_runtime/infinity.py
  28. 1 0
      exported_to_sccdxml/python_runtime/libs/__init__.py
  29. 59 0
      exported_to_sccdxml/python_runtime/libs/drawing.py
  30. 107 0
      exported_to_sccdxml/python_runtime/libs/ui.py
  31. 19 0
      exported_to_sccdxml/python_runtime/libs/utils.py
  32. 22 0
      exported_to_sccdxml/python_runtime/nextafter.py
  33. 947 0
      exported_to_sccdxml/python_runtime/statecharts_core.py
  34. 21 0
      exported_to_sccdxml/python_runtime/tkinter_eventloop.py
  35. 17 0
      exported_to_sccdxml/python_sccd_compiler/.project
  36. 5 0
      exported_to_sccdxml/python_sccd_compiler/.pydevproject
  37. 14 0
      exported_to_sccdxml/python_sccd_compiler/compiler_exceptions.py
  38. 911 0
      exported_to_sccdxml/python_sccd_compiler/generic_generator.py
  39. 990 0
      exported_to_sccdxml/python_sccd_compiler/generic_language_constructs.py
  40. 285 0
      exported_to_sccdxml/python_sccd_compiler/javascript_writer.py
  41. 170 0
      exported_to_sccdxml/python_sccd_compiler/lexer.py
  42. 701 0
      exported_to_sccdxml/python_sccd_compiler/old_generators/csharp_generator.py
  43. 741 0
      exported_to_sccdxml/python_sccd_compiler/old_generators/javascript_generator.py
  44. 644 0
      exported_to_sccdxml/python_sccd_compiler/old_generators/python_generator.py
  45. 77 0
      exported_to_sccdxml/python_sccd_compiler/path_calculator.py
  46. 353 0
      exported_to_sccdxml/python_sccd_compiler/python_writer.py
  47. 1131 0
      exported_to_sccdxml/python_sccd_compiler/sccd_constructs.py
  48. 129 0
      exported_to_sccdxml/python_sccd_compiler/sccdc.py
  49. 156 0
      exported_to_sccdxml/python_sccd_compiler/state_linker.py
  50. 222 0
      exported_to_sccdxml/python_sccd_compiler/stateful_writer.py
  51. 52 0
      exported_to_sccdxml/python_sccd_compiler/super_class_linker.py
  52. 118 0
      exported_to_sccdxml/python_sccd_compiler/utils.py
  53. 30 0
      exported_to_sccdxml/python_sccd_compiler/visitor.py
  54. 23 0
      exported_to_sccdxml/run_digital_watch.py
  55. 191 0
      exported_to_sccdxml/run_train.py
  56. 16 0
      exported_to_sccdxml/train.xml
  57. BIN
      exported_to_sccdxml/watch.gif
  58. BIN
      exported_to_sccdxml/watch.jpg
  59. 2992 0
      users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.defaultIcons.metamodel
  60. 28320 0
      users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.defaultIcons.model
  61. 797 0
      users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.metamodel
  62. 7488 0
      users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.model
  63. BIN
      users/(default)/Formalisms/ClassicDEVS/icons/arrow_up.png
  64. BIN
      users/(default)/Formalisms/ClassicDEVS/icons/clock.png
  65. 4361 0
      users/(default)/Formalisms/TrainDoor/.autosave.TrainDoor.defaultIcons.model
  66. 1747 0
      users/(default)/Formalisms/TrainDoor/.autosave.TrainDoor.model
  67. 8222 0
      users/(default)/Formalisms/TrainDoor/.autosave.instance.model
  68. 501 0
      users/(default)/Formalisms/TrainDoor/TrainDoor.defaultIcons.metamodel
  69. 4361 0
      users/(default)/Formalisms/TrainDoor/TrainDoor.defaultIcons.model
  70. 863 0
      users/(default)/Formalisms/TrainDoor/TrainDoor.defaultIcons.pattern.metamodel
  71. 176 0
      users/(default)/Formalisms/TrainDoor/TrainDoor.metamodel
  72. 1747 0
      users/(default)/Formalisms/TrainDoor/TrainDoor.model
  73. 263 0
      users/(default)/Formalisms/TrainDoor/TrainDoor.pattern.metamodel
  74. 191 0
      users/(default)/Formalisms/TrainDoor/closed.svg
  75. 2337 0
      users/(default)/Formalisms/TrainDoor/instance.model
  76. 185 0
      users/(default)/Formalisms/TrainDoor/open.svg
  77. 1459 0
      users/(default)/Formalisms/TrainDoor/rules/.autosave.R_closed_to_state.model
  78. 5671 0
      users/(default)/Formalisms/TrainDoor/rules/.autosave.R_init.model
  79. 2298 0
      users/(default)/Formalisms/TrainDoor/rules/.autosave.R_open_to_state.model
  80. 4187 0
      users/(default)/Formalisms/TrainDoor/rules/.autosave.R_transitions.model
  81. 18200 0
      users/(default)/Formalisms/TrainDoor/rules/.autosave.T_to_SCCD.model
  82. 2298 0
      users/(default)/Formalisms/TrainDoor/rules/R_closed_to_state.model
  83. 5671 0
      users/(default)/Formalisms/TrainDoor/rules/R_init.model
  84. 2298 0
      users/(default)/Formalisms/TrainDoor/rules/R_open_to_state.model
  85. 4209 0
      users/(default)/Formalisms/TrainDoor/rules/R_transitions.model
  86. 18200 0
      users/(default)/Formalisms/TrainDoor/rules/T_to_SCCD.model

+ 641 - 0
exported_to_sccdxml/DigitalWatchGUI.py

@@ -0,0 +1,641 @@
+#
+# DigitalWatchGUI.py
+#
+# class DigitalWatchGUI provides a simple Tkinter GUI for a Digital Watch
+# to add: battery dies ... DONE OCT 2008 by Reehan Shaikh reehan.shaikh@cs.mcgill.ca
+
+# Updated for the SCCDXML compiler and AToMPM formalism by Yentl Van Tendeloo
+
+from Tkinter import *
+import tkFont
+from time import *
+from Tkinter import PhotoImage
+import python_runtime.statecharts_core as statecharts_core
+
+CANVAS_W = 222
+CANVAS_H = 236
+
+OVAL_X0=2
+OVAL_Y0=1
+OVAL_X1=CANVAS_W-OVAL_X0 
+OVAL_Y1=CANVAS_H-OVAL_Y0 
+
+RECT_X0=51
+RECT_Y0=95
+RECT_X1=CANVAS_W-RECT_X0+1
+RECT_Y1=CANVAS_H-RECT_Y0+10 
+
+FONT_TIME=("terminal", 14)
+FONT_DATE=("terminal", 8)
+FONT_NOTE=("symbol", 10)
+
+class DigitalWatchGUI:
+  
+  def __init__(self, parent):
+    self.controller = DigitalWatchGUI_Controller()
+    self.staticGUI  = DigitalWatchGUI_Static(parent, self.controller)
+    self.dynamicGUI = DigitalWatchGUI_Dynamic(self.controller)
+           
+class DigitalWatchGUI_Controller:
+
+  def __init__(self):
+    self.statechart = None
+    self.GUI  = None
+    self.battery = True
+        
+  def bindDynamic(self, statechart):
+    self.statechart = statechart
+  
+  def bindStatic(self, GUI):
+    self.GUI = GUI
+              
+  #Interface for the GUI                                 
+  def window_close(self):
+    import sys
+    sys.exit(0)
+    self.statechart.event('GUI Quit')
+
+  def topRightPressed(self):
+    self.statechart.event('topRightPressed')
+
+  def topRightReleased(self):
+    self.statechart.event('topRightReleased')
+  
+  def topLeftPressed(self):
+    self.statechart.event('topLeftPressed')
+  
+  def topLeftReleased(self):
+    self.statechart.event('topLeftReleased')
+    
+  def bottomRightPressed(self):
+    self.statechart.event('bottomRightPressed')
+
+  def bottomRightReleased(self):
+    self.statechart.event('bottomRightReleased')
+  
+  def bottomLeftPressed(self):
+    self.statechart.event('bottomLeftPressed')
+  
+  def bottomLeftReleased(self):
+    self.statechart.event('bottomLeftReleased')
+
+  def alarm(self):
+    self.statechart.event('alarmStart')
+    
+  #Interface for the statechart
+   
+  #synchronize the state with the display:
+
+  def batteryHalf(self):
+    self.battery = False
+    self.GUI.battery = False
+    self.refreshDateDisplay()
+ 
+  def batteryFull(self):
+    self.battery = True
+    self.GUI.battery = True
+    self.refreshDateDisplay()
+ 
+  def refreshTimeDisplay(self):
+    self.GUI.drawTime()
+            
+  def refreshChronoDisplay(self):
+    self.GUI.drawChrono()
+  
+  def refreshDateDisplay(self):    
+    self.GUI.drawDate()
+    
+  def refreshAlarmDisplay(self):
+    self.GUI.drawAlarm()    
+
+   
+  #Modify the state:
+  
+  def increaseTimeByOne(self):
+    self.GUI.increaseTimeByOne()    
+   
+  def resetChrono(self):
+    self.GUI.resetChrono()
+    
+  def increaseChronoByOne(self):
+    self.GUI.increaseChronoByOne()
+    
+  #Select current display:
+  def startSelection(self):
+    self.GUI.startSelection()
+    
+  def selectNext(self):
+    self.GUI.selectNext()    
+       
+  #Modify the state corresponing to the selection  
+  def increaseSelection(self):
+    self.GUI.increaseSelection()
+        
+  def stopSelection(self):
+    self.GUI.stopSelection()
+                    
+         
+  #Light / Alarm:
+  
+  def setIndiglo(self):
+    self.GUI.setIndiglo()
+    
+  def unsetIndiglo(self):
+    self.GUI.unsetIndiglo()
+    
+  def setAlarm(self):
+    self.GUI.setAlarm()
+
+  # Query 
+  def getTime(self):
+    return self.GUI.getTime()
+
+  def getAlarm(self):
+    return self.GUI.getAlarm()
+     
+  #Check if time = alarm set time
+  def checkTime(self):
+    if self.GUI.getTime()[0] == self.GUI.getAlarm()[0] and self.GUI.getTime()[1] == self.GUI.getAlarm()[1] and self.GUI.getTime()[2] == self.GUI.getAlarm()[2]:
+      self.alarm()
+      return True
+    else:
+      return False
+    
+class DigitalWatchGUI_Dynamic:
+  
+  def __init__(self, controller):
+    self.controller = controller
+    self.controller.bindDynamic(self)
+
+  def setStatechart(self, controller):
+    print("STATECHART set")
+    self.controller_SCCD = controller
+    
+  def event(self, evt, param=[]):
+    self.controller_SCCD.addInput(statecharts_core.Event(evt, "tkinter_input", param), 0.0)
+
+#======================================================================#
+# GUI Static class
+
+class DigitalWatchGUI_Static(Frame):
+
+  def __init__(self, parent, controller):
+    Frame.__init__(self, parent)
+
+    self.parent = parent
+    self.controller = controller
+    self.controller.bindStatic(self)
+    self.battery = True
+    
+    tmpDate = list(localtime()[0:3]) 
+    self.curDate=[tmpDate[1],tmpDate[2],int(str(tmpDate[0])[3:]) ] 
+    self.dateTag=None
+    
+    self.curTime=list(localtime()[3:6])
+    self.timeTag=None
+    
+    self.curAlarm=[12,0,0]
+    self.alarmTag=None
+    
+    self.curChrono=[0,0,0]
+    self.chronoTag=None
+    
+    self.noteImage=PhotoImage(file="./noteSmall.gif")    
+    self.watchImage=PhotoImage(file="./watch.gif")
+    
+    self.alarmNoteTag = None
+    
+    self.curSelectionInfo = None
+    self.curSelection     = ["hours", "minutes", "seconds",
+                             "months", "days", "years"]
+    self.curSelectionIndex = 0 
+    
+    self.lastPressed = ""
+        
+    self.createWidgets()
+    
+    #self.b_playpause.focus_force()
+    parent.protocol("WM_DELETE_WINDOW", self.controller.window_close)
+    
+    self.drawTime()
+    self.drawDate()
+          
+  def getTime(self):
+    return self.curTime
+
+  def getAlarm(self):
+    return self.curAlarm 
+    
+  def createWidgets(self):
+
+    self.pack()
+    self.displayCanvas = Canvas(master=self,
+                           takefocus=1,
+                           width=CANVAS_W, height=CANVAS_H,
+                           background="black")
+  
+    self.displayCanvas.pack(fill=BOTH, expand=1)
+    self.displayCanvas.focus_set()
+    
+    self.watch = self.displayCanvas.create_image(0,0,image=self.watchImage,anchor="nw")
+    
+        
+    self.display = self.displayCanvas.create_rectangle(RECT_X0,
+                                                       RECT_Y0,
+                                                       RECT_X1,
+                                                       RECT_Y1,
+                                                       fill="#DCDCDC")
+                                                       
+    self.topRightButton = self.displayCanvas.create_rectangle(CANVAS_W-13,
+                                                              60,
+                                                              CANVAS_W-3,
+                                                              70,
+                                                              fill='')
+
+    self.topLeftButton = self.displayCanvas.create_rectangle(3,
+                                                             62,
+                                                             13,
+                                                             72,
+                                                             fill='')
+                                                              
+    self.bottomRightButton = self.displayCanvas.create_rectangle(CANVAS_W-10,
+                                                           162,
+                                                           CANVAS_W,
+                                                           172,
+                                                           fill='')
+                                                           
+    self.bottomLeftButton = self.displayCanvas.create_rectangle(3,
+                                                                161,
+                                                                13,
+                                                                171,
+                                                                fill='')
+                                                                                                                                  
+    self.displayCanvas.bind("<ButtonPress-1>", self.mouse1Click)
+    self.displayCanvas.bind("<ButtonRelease-1>", self.mouse1Release)                                                              
+                                                                                               
+  def mouse1Click(self, event):
+    X = self.displayCanvas.canvasx(event.x)
+    Y = self.displayCanvas.canvasy(event.y)
+    
+    objTag = self.displayCanvas.find_closest(X,Y,halo=5)
+        
+    if self.topRightButton in objTag:
+      self.controller.topRightPressed()
+      self.lastPressed = "topRight"
+    elif self.topLeftButton in objTag:
+      self.controller.topLeftPressed()
+      self.lastPressed = "topLeft"
+    elif self.bottomLeftButton in objTag:
+      self.controller.bottomLeftPressed()
+      self.lastPressed = "bottomLeft"
+    elif self.bottomRightButton in objTag:
+      self.controller.bottomRightPressed()
+      self.lastPressed = "bottomRight"
+    else:
+      self.lastPressed = ""
+  
+  def mouse1Release(self, event):
+    if self.lastPressed == "topRight":
+      self.controller.topRightReleased()
+    elif self.lastPressed == "topLeft":
+      self.controller.topLeftReleased()
+    elif self.lastPressed == "bottomLeft":
+      self.controller.bottomLeftReleased()
+    elif self.lastPressed == "bottomRight":
+      self.controller.bottomRightReleased()
+    self.lastPressed=""
+        
+  def __intToString(self, i):
+    if i<10:
+      return "0"+str(i)
+    else:
+      return str(i)
+      
+  def __getTimeAsString(self):
+    hours   = self.__intToString(self.curTime[0])
+    minutes = self.__intToString(self.curTime[1])
+    seconds = self.__intToString(self.curTime[2])        
+                  
+    return hours+":"+minutes+":"+seconds
+    
+  def __getAlarmAsString(self):  
+    hours   = self.__intToString(self.curAlarm[0])
+    minutes = self.__intToString(self.curAlarm[1])
+    seconds = self.__intToString(self.curAlarm[2])        
+                  
+    return hours+":"+minutes+":"+seconds  
+  
+    
+  def __getChronoAsString(self):
+    minutes   = self.__intToString(self.curChrono[0])
+    seconds   = self.__intToString(self.curChrono[1])
+    centisecs = self.__intToString(self.curChrono[2])
+
+    return minutes+":"+seconds+":"+centisecs 
+    
+  def __getDateAsString(self):   
+    month = self.__intToString(self.curDate[0])
+    day   = self.__intToString(self.curDate[1])
+    year  = self.__intToString(self.curDate[2])
+    
+    return month+"/"+day+"/"+year
+    
+  def increaseHoursByOne(self):
+    if self.timeTag != None:
+      self.curTime[0]=(self.curTime[0]+1)%24
+    else:
+      self.curAlarm[0]=(self.curAlarm[0]+1)%24
+    
+  def increaseMinutesByOne(self):
+    if self.timeTag != None:
+      self.curTime[1]=(self.curTime[1]+1)%60
+    else:
+      self.curAlarm[1]=(self.curAlarm[1]+1)%60
+  
+  def increaseSecondsByOne(self):
+    if self.timeTag != None:
+      self.curTime[2]=(self.curTime[2]+1)%60
+    else:
+      self.curAlarm[2]=(self.curAlarm[2]+1)%60
+    
+  def increaseMonthsByOne(self):
+    self.curDate[0]=(self.curDate[0]+1)%13
+    if self.curDate[0]==0:
+      self.curDate[0]=1
+    
+  def increaseDaysByOne(self):
+    numDays = self.getNumDays()
+    self.curDate[1]=(self.curDate[1]+1)%(numDays+1)
+    if self.curDate[1]==0:
+      self.curDate[1]=1
+    
+  def increaseYearsByOne(self):
+    self.curDate[2]=(self.curDate[2]+1)%100
+    if self.curDate[2]==0:
+      self.curDate[2]=1
+    
+  def getNumDays(self):
+    month = self.curDate[0]
+    year  = self.curDate[2]
+    numDays=0
+    if month==2: #february
+      if year%4==0: #leap year
+        numDays=29
+      else:
+        numDays=28
+    else:
+      if (month%2==1 and month<=7) or (month%2==0 and month>=8):
+        numDays=31
+      else:
+        numDays=30
+    return numDays
+    
+  def stopSelection(self):
+    if self.curSelectionInfo != None:
+      self.parent.after_cancel(self.curSelectionInfo[0])
+      self.parent.after_cancel(self.curSelectionInfo[1])
+      self.parent.after_cancel(self.curSelectionInfo[2])      
+      self.curSelectionInfo=None 
+      
+    if self.timeTag != None:
+      self.drawTime()
+      self.drawDate()
+    else:
+      self.drawAlarm()
+  
+  
+  def increaseSelection(self):
+  
+    self.stopSelection()
+    selection = self.curSelection[self.curSelectionIndex]
+
+    if selection == "hours":
+      self.increaseHoursByOne()     
+    elif selection == "minutes":
+      self.increaseMinutesByOne()
+    elif selection == "seconds":
+      self.increaseSecondsByOne()
+    elif selection == "months":
+      self.increaseMonthsByOne()
+    elif selection == "days":
+      self.increaseDaysByOne()
+    elif selection == "years":
+      self.increaseYearsByOne()
+      
+    if self.timeTag != None:
+      self.drawTime()
+      self.drawDate()      
+    else:
+      self.drawAlarm()
+      
+    self.animateSelection()
+  
+  def selectNext(self):
+    self.stopSelection()
+    if self.timeTag != None:
+      numDigits=len(self.curSelection)
+      self.drawTime()
+      self.drawDate()
+    else:
+      numDigits=3
+      self.drawAlarm()
+    self.curSelectionIndex=(self.curSelectionIndex+1)%numDigits
+    self.animateSelection()
+    
+  def startSelection(self):
+    self.curSelectionIndex=0
+    self.animateSelection()
+          
+  def animateSelection(self):
+ 
+    timeFunc=None
+    if self.timeTag != None:
+      timeFunc=self.drawTime
+    else:
+      timeFunc=self.drawAlarm
+ 
+    curSelection  = self.curSelection[self.curSelectionIndex]
+    deleteEvent   = None
+    creationEvent = None
+
+    if curSelection in ["hours", "minutes", "seconds"]:
+      toDrawTime    = ["hours", "minutes", "seconds"]
+      toDrawTime.remove(curSelection)  
+      deleteEvent   = self.parent.after(500, timeFunc, toDrawTime)      
+      creationEvent = self.parent.after(1000, timeFunc)
+    else:
+      toDrawDate    = ["years", "months", "days"]
+      toDrawDate.remove(curSelection)
+      deleteEvent   = self.parent.after(500, self.drawDate, toDrawDate)      
+      creationEvent = self.parent.after(1000, self.drawDate)
+
+    animationEvent  = self.parent.after(1000,self.animateSelection)
+
+    self.curSelectionInfo = [deleteEvent,
+                             creationEvent,
+                             animationEvent]    
+    
+    
+        
+  def increaseTimeByOne(self):
+    self.curTime[2]=self.curTime[2]+1
+    self.curTime[1]=(self.curTime[1]+self.curTime[2]/60)
+    self.curTime[0]=(self.curTime[0]+self.curTime[1]/60)
+    
+    self.curTime[2]=self.curTime[2]%60
+    self.curTime[1]=self.curTime[1]%60
+    self.curTime[0]=self.curTime[0]%24
+    
+    if self.curTime[0]==0 and\
+       self.curTime[1]==0 and\
+       self.curTime[2]==0:
+      self.increaseDateByOne()
+                            
+  def increaseDateByOne(self):  
+    month = self.curDate[0]
+    day   = self.curDate[1]
+    year  = self.curDate[2]
+    
+    numMonths = 12
+    numDays   = self.getNumDays()
+                   
+    self.curDate[1]=self.curDate[1]+1
+    self.curDate[0]=(self.curDate[0]+self.curDate[1]/(numDays+1))
+    self.curDate[2]=(self.curDate[2]+self.curDate[0]/(numMonths+1))
+    
+    self.curDate[1]=self.curDate[1]%(numDays+1)
+    self.curDate[0]=self.curDate[0]%(numMonths+1)
+    
+  def increaseChronoByOne(self):
+    self.curChrono[2]=self.curChrono[2]+1
+    self.curChrono[1]=(self.curChrono[1]+self.curChrono[2]/100)
+    self.curChrono[0]=(self.curChrono[0]+self.curChrono[1]/100)
+    
+    self.curChrono[2]=self.curChrono[2]%100
+    self.curChrono[1]=self.curChrono[1]%100
+    self.curChrono[0]=self.curChrono[0]%100 
+    
+    
+  def clearDisplay(self):
+    if self.alarmTag != None:
+      self.displayCanvas.delete(self.alarmTag)
+      self.alarmTag = None
+    if self.timeTag != None:
+      self.displayCanvas.delete(self.timeTag)
+      self.timeTag = None
+    if self.chronoTag != None:
+      self.displayCanvas.delete(self.chronoTag)
+      self.chronoTag = None 
+      
+  def clearDate(self):
+    if self.dateTag != None:
+      self.displayCanvas.delete(self.dateTag)
+      self.dateTag = None
+ 
+  def drawTime(self, toDraw=["hours","minutes","seconds"]): 
+    timeToDraw = self.__getTimeAsString()
+
+    if "hours" not in toDraw:
+      timeToDraw="  "+timeToDraw[2:]
+    if "minutes" not in toDraw:
+      timeToDraw=timeToDraw[0:3]+"  "+timeToDraw[5:]
+    if "seconds" not in toDraw:
+      timeToDraw=timeToDraw[0:6]+"  "
+      
+    if not self.battery:
+      timeToDraw = "88:88:88"
+
+    self.clearDisplay()     
+      
+    self.timeTag =self.displayCanvas.create_text((RECT_X0+RECT_X1)/2,
+                                                 (RECT_Y0+RECT_Y1)/2+5,
+                                                  font = FONT_TIME,
+                                                  justify = "center",
+                                                  text    = timeToDraw)
+                                                  
+  def hideTime(self):
+    if self.timeTag != None:
+      self.displayCanvas.delete(self.timeTag)
+      self.timeTag=None
+                                                                 
+  def drawChrono(self):
+    chronoToDraw  = self.__getChronoAsString()
+
+    self.clearDisplay()
+      
+    if not self.battery:
+      chronoToDraw = "88:88:88"
+      
+    self.chronoTag =self.displayCanvas.create_text((RECT_X0+RECT_X1)/2,
+                                                   (RECT_Y0+RECT_Y1)/2+5,
+                                                  font = FONT_TIME,
+                                                  justify = "center",
+                                                  text    = chronoToDraw)                                                  
+                                                                                                                  
+  def hideChrono(self):
+    if self.chronoTag != None:
+      self.displayCanvas.delete(self.chronoTag)
+      self.chronoTag=None
+      
+  def resetChrono(self):
+    self.curChrono=[0,0,0]
+                                           
+  def drawDate(self, toDraw=["years","months","days"]):
+    dateToDraw = self.__getDateAsString()
+    
+    if "months" not in toDraw:
+      dateToDraw="  "+dateToDraw[2:]      
+    if "days" not in toDraw:
+      dateToDraw=dateToDraw[0:3]+"  "+dateToDraw[5:]           
+    if "years" not in toDraw:
+      dateToDraw=dateToDraw[0:6]+"  "
+
+    if not self.battery:
+      dateToDraw = "88/88/88"
+
+    self.clearDate()
+ 
+    self.dateTag=self.displayCanvas.create_text(RECT_X1-33,
+                                                RECT_Y0+7,
+                                                font = FONT_DATE,
+                                                justify = "center",
+                                                text    = dateToDraw)
+                                   
+  def drawAlarm(self, toDraw=["hours","minutes","seconds"]):    
+    alarmToDraw = self.__getAlarmAsString()
+        
+    if "hours" not in toDraw:
+      alarmToDraw="  "+alarmToDraw[2:]
+    if "minutes" not in toDraw:
+      alarmToDraw=alarmToDraw[0:3]+"  "+alarmToDraw[5:]
+    if "seconds" not in toDraw:
+      alarmToDraw=alarmToDraw[0:6]+"  "
+
+    if not self.battery:
+      alarmToDraw = "88:88:88"
+
+    self.clearDisplay()
+    
+    self.alarmTag =self.displayCanvas.create_text((RECT_X0+RECT_X1)/2,
+                                                  (RECT_Y0+RECT_Y1)/2+5,
+                                                   font = FONT_TIME,
+                                                   justify = "center",
+                                                   text    = alarmToDraw)
+                                                  
+  def hideAlarm(self):
+    if self.alarmTag != None:
+      self.displayCanvas.delete(self.alarmTag)
+      self.alarmTag=None                                   
+
+  def setAlarm(self):
+    if self.alarmNoteTag != None:
+      self.displayCanvas.delete(self.alarmNoteTag)
+      self.alarmNoteTag=None
+    else:
+      self.alarmNoteTag = self.displayCanvas.create_image(RECT_X0+5,RECT_Y0+3,image=self.noteImage,anchor="nw")     
+                                           
+  def setIndiglo(self):
+    self.displayCanvas.itemconfigure(self.display, fill='#96DCFA')
+
+  def unsetIndiglo(self):
+    self.displayCanvas.itemconfigure(self.display, fill="#DCDCDC")      

+ 67 - 0
exported_to_sccdxml/classes/translator.xml

@@ -0,0 +1,67 @@
+    <class name="Translator" default="true">
+        <relationships>
+            <association name="model" class="Train" />
+        </relationships>
+		<constructor>
+			<parameter name="root"/>
+			<body>
+				self.root = root
+			</body>
+		</constructor>
+        <scxml initial="init">
+			<state id="init">
+				<onentry>
+					<raise scope="cd" event="create_instance">
+						<parameter expr="'model'"/>
+						<parameter expr="'Train'"/>
+						<parameter expr="self.root"/>
+					</raise>
+				</onentry>
+				<transition event="instance_created" target="../broadcast_input">
+					<parameter name="instancename"/>
+					<raise scope="cd" event="start_instance">
+						<parameter expr="instancename"/>
+					</raise>
+				</transition>
+			</state>
+			
+            <state id="broadcast_input">
+                <transition port="tkinter_input" event="accel" target=".">
+                    <parameter name="acceleration"/>
+                    <raise scope="broad" event="accel">
+                        <parameter expr="acceleration"/>
+                    </raise>
+                </transition>
+                <transition port="tkinter_input" event="open" target=".">
+                    <raise scope="broad" event="open"/>
+                </transition>
+                <transition port="tkinter_input" event="close" target=".">
+                    <raise scope="broad" event="close"/>
+                </transition>
+                <transition port="tkinter_input" event="pause" target=".">
+                    <raise scope="broad" event="pause"/>
+                </transition>
+                <transition port="tkinter_input" event="continue" target=".">
+                    <raise scope="broad" event="continue"/>
+                </transition>
+                <transition port="tkinter_input" event="awake" target=".">
+                    <raise scope="broad" event="awake"/>
+                </transition>
+                <transition port="tkinter_input" event="red_light" target=".">
+                    <raise scope="broad" event="red_light"/>
+                </transition>
+                <transition port="tkinter_input" event="yellow_light" target=".">
+                    <raise scope="broad" event="yellow_light"/>
+                </transition>
+                <transition port="tkinter_input" event="green_light" target=".">
+                    <raise scope="broad" event="green_light"/>
+                </transition>
+                <transition port="tkinter_input" event="enter" target=".">
+                    <raise scope="broad" event="enter"/>
+                </transition>
+                <transition port="tkinter_input" event="leave" target=".">
+                    <raise scope="broad" event="leave"/>
+                </transition>
+            </state>
+        </scxml>
+    </class>

+ 15 - 0
exported_to_sccdxml/digitalwatch.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<diagram author="Yentl Van Tendeloo" name="Digital Watch">
+    <description>
+        Digital watch in SCCD
+    </description>
+    <top>
+        import Tkinter as tk
+        import json
+        import httplib
+    </top>
+
+    <inport name="tkinter_input"/>
+
+    <class src="classes/model.xml" default="true"/>
+</diagram>

+ 6 - 0
exported_to_sccdxml/imgs/convert.sh

@@ -0,0 +1,6 @@
+convert train.png -resize x30 train.gif
+convert rail.png -resize x40 rail.gif
+convert red.png -resize 20x red.gif
+convert yellow.png -resize 20x yellow.gif
+convert green.png -resize 20x green.gif
+convert station.png -resize 200x station.gif

BIN
exported_to_sccdxml/imgs/green.gif


BIN
exported_to_sccdxml/imgs/green.png


BIN
exported_to_sccdxml/imgs/lights.png


+ 99 - 0
exported_to_sccdxml/imgs/lights.svg

@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="72.680222"
+   height="126.21831"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="lights.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="7.9195959"
+     inkscape:cx="27.991111"
+     inkscape:cy="66.389805"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="2558"
+     inkscape:window-height="1422"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-87.40358,-139.71474)">
+    <path
+       sodipodi:type="arc"
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path2985"
+       sodipodi:cx="123.74369"
+       sodipodi:cy="202.8239"
+       sodipodi:rx="33.840111"
+       sodipodi:ry="60.609154"
+       d="m 157.5838,202.8239 c 0,33.47351 -15.15073,60.60915 -33.84011,60.60915 -18.68938,0 -33.84011,-27.13564 -33.84011,-60.60915 0,-33.47351 15.15073,-60.60916 33.84011,-60.60916 18.68938,0 33.84011,27.13565 33.84011,60.60916 z" />
+    <path
+       sodipodi:type="arc"
+       style="color:#000000;fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path3755"
+       sodipodi:cx="264.65997"
+       sodipodi:cy="171.50917"
+       sodipodi:rx="16.162441"
+       sodipodi:ry="16.162441"
+       d="m 280.82241,171.50917 c 0,8.92627 -7.23617,16.16244 -16.16244,16.16244 -8.92627,0 -16.16244,-7.23617 -16.16244,-16.16244 0,-8.92627 7.23617,-16.16244 16.16244,-16.16244 8.92627,0 16.16244,7.23617 16.16244,16.16244 z"
+       transform="translate(-140.91628,-6.0609153)" />
+    <path
+       transform="translate(-140.91628,68.690366)"
+       sodipodi:type="arc"
+       style="color:#000000;fill:#00ff00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path3755-2"
+       sodipodi:cx="264.65997"
+       sodipodi:cy="171.50917"
+       sodipodi:rx="16.162441"
+       sodipodi:ry="16.162441"
+       d="m 280.82241,171.50917 c 0,8.92627 -7.23617,16.16244 -16.16244,16.16244 -8.92627,0 -16.16244,-7.23617 -16.16244,-16.16244 0,-8.92627 7.23617,-16.16244 16.16244,-16.16244 8.92627,0 16.16244,7.23617 16.16244,16.16244 z" />
+    <path
+       transform="translate(-140.91628,31.31466)"
+       sodipodi:type="arc"
+       style="color:#000000;fill:#ffff00;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path3755-9"
+       sodipodi:cx="264.65997"
+       sodipodi:cy="171.50917"
+       sodipodi:rx="16.162441"
+       sodipodi:ry="16.162441"
+       d="m 280.82241,171.50917 c 0,8.92627 -7.23617,16.16244 -16.16244,16.16244 -8.92627,0 -16.16244,-7.23617 -16.16244,-16.16244 0,-8.92627 7.23617,-16.16244 16.16244,-16.16244 8.92627,0 16.16244,7.23617 16.16244,16.16244 z" />
+  </g>
+</svg>

BIN
exported_to_sccdxml/imgs/rail.gif


BIN
exported_to_sccdxml/imgs/rail.png


+ 210 - 0
exported_to_sccdxml/imgs/rail.svg

@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="303.85715"
+   height="63.326157"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   inkscape:export-filename="/home/yentl/UA/teaching/MoSIS/2015-2016/Statecharts/solution/imgs/rail.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90"
+   sodipodi:docname="rail.svg">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.6"
+     inkscape:cx="135.56736"
+     inkscape:cy="20.958559"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="2558"
+     inkscape:window-height="1422"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(207.90026,-35.432276)">
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -357.14286,18.714287 302.857146,0"
+       id="path3775"
+       inkscape:connector-curvature="0"
+       transform="translate(149.7426,25.026392)" />
+    <path
+       style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -207.40026,89.097821 302.85715,0"
+       id="path3775-6"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -351.02801,13.405884 0,57.326157"
+       id="path3814"
+       inkscape:connector-curvature="0"
+       transform="translate(149.7426,25.026392)" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -190.17374,38.432276 0,57.326157"
+       id="path3814-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -179.06206,38.432276 0,57.326157"
+       id="path3814-8"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -167.95039,38.432276 0,57.326157"
+       id="path3814-7"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -156.83869,38.432276 0,57.326157"
+       id="path3814-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -145.72704,38.432276 0,57.326157"
+       id="path3814-29"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -134.61535,38.432276 0,57.326157"
+       id="path3814-293"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -123.50368,38.432276 0,57.326157"
+       id="path3814-85"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -112.39199,38.432276 0,57.326157"
+       id="path3814-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -101.28031,38.432276 0,57.326157"
+       id="path3814-58"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -90.16864,38.432276 0,57.326157"
+       id="path3814-12"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -79.056955,38.432276 0,57.326157"
+       id="path3814-0"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -67.945277,38.432276 0,57.326157"
+       id="path3814-3"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -56.833598,38.432276 0,57.326157"
+       id="path3814-24"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -45.721926,38.432276 0,57.326157"
+       id="path3814-31"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -34.610249,38.432276 0,57.326157"
+       id="path3814-9"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -23.498561,38.432276 0,57.326157"
+       id="path3814-82"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -12.386893,38.432276 0,57.326157"
+       id="path3814-72"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m -1.275207,38.432276 0,57.326157"
+       id="path3814-09"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 9.8364729,38.432276 0,57.326157"
+       id="path3814-96"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 20.948149,38.432276 0,57.326157"
+       id="path3814-39"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 32.059824,38.432276 0,57.326157"
+       id="path3814-584"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 43.171505,38.432276 0,57.326157"
+       id="path3814-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 54.283177,38.432276 0,57.326157"
+       id="path3814-23"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 65.394863,38.432276 0,57.326157"
+       id="path3814-83"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 76.506538,38.432276 0,57.326157"
+       id="path3814-098"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:none;stroke:#864612;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       d="m 87.618218,38.432276 0,57.326157"
+       id="path3814-91"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>

BIN
exported_to_sccdxml/imgs/red.gif


BIN
exported_to_sccdxml/imgs/red.png


BIN
exported_to_sccdxml/imgs/station.gif


BIN
exported_to_sccdxml/imgs/station.png


BIN
exported_to_sccdxml/imgs/train.gif


BIN
exported_to_sccdxml/imgs/train.png


File diff suppressed because it is too large
+ 61 - 0
exported_to_sccdxml/imgs/train.svg


BIN
exported_to_sccdxml/imgs/yellow.gif


BIN
exported_to_sccdxml/imgs/yellow.png


BIN
exported_to_sccdxml/noteSmall.gif


+ 17 - 0
exported_to_sccdxml/python_runtime/.project

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>python_runtime</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>

+ 5 - 0
exported_to_sccdxml/python_runtime/.pydevproject

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
+</pydev_project>

+ 0 - 0
exported_to_sccdxml/python_runtime/__init__.py


+ 9 - 0
exported_to_sccdxml/python_runtime/accurate_time.py

@@ -0,0 +1,9 @@
+import time as t
+import os
+
+if os.name == 'posix':
+	def time():
+		return t.time()
+elif os.name == 'nt':
+	def time():
+		return t.clock()

+ 58 - 0
exported_to_sccdxml/python_runtime/event_queue.py

@@ -0,0 +1,58 @@
+from infinity import INFINITY
+
+class EventQueue(object):
+    class EventQueueEntry(object):        
+        def __init__(self, event_list, time_offset) :
+            self.event_list = event_list
+            self.time_offset = time_offset
+        
+        def decreaseTime(self, offset) :
+            self.time_offset -= offset;   
+        
+        def getEvents(self) :
+            return self.event_list
+        
+        def getTime (self) :
+            return self.time_offset
+
+    def __init__(self):
+        self.event_list = []
+
+    def add(self, event_list, time_offset) :
+        entry = EventQueue.EventQueueEntry(event_list, time_offset);
+        #We maintain a sorted stable list
+        insert_index = 0;
+        index = len(self.event_list)-1
+        while (index >= 0) :
+            if (self.event_list[index].getTime() <= time_offset) :
+                insert_index = index + 1;
+                break;
+            index -= 1
+        self.event_list.insert(insert_index, entry)
+    
+    def decreaseTime(self, offset) :
+        for event in self.event_list :
+            event.decreaseTime(offset)
+    
+    def isEmpty(self) :
+        return len(self.event_list) == 0
+    
+    def getEarliestTime(self) :
+        """Returns the earliest time. INFINITY if no events are present."""
+        if self.isEmpty() :
+            return INFINITY
+        else :
+            return self.event_list[0].getTime()
+    
+    def popDueEvents(self) :
+        result = []
+        if (self.isEmpty() or self.event_list[0].getTime() > 0.0) :
+            #There are no events, or the earliest event isn't due, so we can already return an emtpy result
+            return result
+
+        index = 0;
+        while (index < len(self.event_list) and self.event_list[index].getTime() <= 0.0) :
+            result.append(self.event_list[index].getEvents()) #Add all events that are due (offset less than 0) to the result
+            index += 1
+        self.event_list = self.event_list[len(result):]
+        return result;

+ 3 - 0
exported_to_sccdxml/python_runtime/infinity.py

@@ -0,0 +1,3 @@
+# Instantiate singleton:        
+INFINITY = float('inf')
+

+ 1 - 0
exported_to_sccdxml/python_runtime/libs/__init__.py

@@ -0,0 +1 @@
+

+ 59 - 0
exported_to_sccdxml/python_runtime/libs/drawing.py

@@ -0,0 +1,59 @@
+"""
+ *REALLY* Small framework for creating/manipulating/deleting Tkinter Canvas elements.
+ 
+ NOTE: keep this synced with svg.js
+ 
+ Author: Raphael Mannadiar
+ Date: 2014/08/21
+"""
+
+from utils import utils
+
+
+class drawing:
+    class canvas_wrapper:
+        def __init__(self, element):
+            self.element = element
+            self.width = int(element.cget("width"))
+            self.height = int(element.cget("height"))
+
+        def add_circle(self, x, y, r, style):
+            new_element_id = self.element.create_oval(x-r, y-r, x+r, y+r, **style)
+            return drawing.ui_element_wrapper(self, new_element_id, x, y)
+
+        def add_rectangle(self, x, y, w, h, style):
+            new_element_id = self.element.create_rectangle(x-w/2.0, y-h/2.0, x+w/2.0, y+h/2.0, **style)
+            return drawing.ui_element_wrapper(self, new_element_id, x, y)
+
+        def remove_element(self, element):
+            self.element.delete(element.element_id)
+
+
+    class ui_element_wrapper:
+        def __init__(self, canvas_wrapper, element_id, x, y):
+            self.canvas_wrapper = canvas_wrapper
+            self.element_id = element_id
+            self.a = 0
+            self.x = x
+            self.y = y
+
+        def set_position(self, x, y):
+            self.move(x-self.x, y-self.y)
+
+        def get_position(self):
+            return utils._bunch(x=self.x, y=self.y)
+
+        def move(self, dx, dy):
+            self.x += dx
+            self.y += dy
+            self.canvas_wrapper.element.move(self.element_id, dx, dy)
+
+        def set_rotation(self, a):
+            raise Exception("Not implemented yet")
+
+        def rotate(self, a):
+            raise Exception("Not implemented yet")
+
+        def set_color(self, color):
+            self.canvas_wrapper.element.itemconfig(self.element_id, fill=color)
+

+ 107 - 0
exported_to_sccdxml/python_runtime/libs/ui.py

@@ -0,0 +1,107 @@
+"""
+ *REALLY* Small framework for creating/manipulating/deleting gui elements in Tkinter.
+ 
+ NOTE: keep this synced with ui.js
+ 
+ Author: Raphael Mannadiar
+ Date: 2014/08/21
+"""
+
+import Tkinter as tk
+from python_runtime.statecharts_core import Event
+from drawing import drawing
+from utils import utils
+
+
+class ui:
+	window = None
+	__nextWindowId = 0
+
+	EVENTS = utils._bunch(
+		KEY_PRESS = 			'<Key>',
+		MOUSE_CLICK = 			'<Button>',
+		MOUSE_MOVE = 			'<Motion>',
+		MOUSE_PRESS =			'<ButtonPress>',
+		MOUSE_RELEASE =		'<ButtonRelease>',
+		MOUSE_RIGHT_CLICK =	'<Button-3>',
+		WINDOW_CLOSE = 		'WM_DELETE_WINDOW');
+
+	MOUSE_BUTTONS = utils._bunch(
+		LEFT		= 1,
+		MIDDLE	= 2,
+		RIGHT		= 3);
+
+	KEYCODES	= utils._bunch(
+		DELETE	= 119);
+
+	@staticmethod
+	def append_button(_window,text):
+		button = tk.Button(_window, text=text)
+		button.pack()
+		return ui.wrap_element(button)
+
+
+	@staticmethod
+	def append_canvas(_window,width,height,style):
+		canvas = tk.Canvas(_window,width=width,height=height)
+		canvas.config(**style)
+		canvas.pack()
+		return drawing.canvas_wrapper(canvas)
+
+
+	@staticmethod
+	def bind_event(source,event,controller,raise_name,port="ui",time_offset=0.0):
+
+		def __handle_event(ev=None):
+			if event == ui.EVENTS.KEY_PRESS :
+				controller.addInput(Event(raise_name, port, [ev.keycode,source]),time_offset)
+
+			elif event == ui.EVENTS.MOUSE_CLICK or \
+				  event == ui.EVENTS.MOUSE_MOVE or \
+				  event == ui.EVENTS.MOUSE_PRESS or \
+				  event == ui.EVENTS.MOUSE_RELEASE or \
+		  		  event == ui.EVENTS.MOUSE_RIGHT_CLICK :
+				controller.addInput(Event(raise_name, port, [ev.x, ev.y, ev.num]),time_offset)
+
+			elif event == ui.EVENTS.WINDOW_CLOSE :
+				controller.addInput(Event(raise_name, port, [source]),time_offset)
+
+			else :
+				raise Exception('Unsupported event');
+	
+		if event == ui.EVENTS.WINDOW_CLOSE :
+			source.protocol(event, __handle_event)
+
+		elif issubclass(drawing.ui_element_wrapper,source.__class__) :
+			source.canvas_wrapper.element.tag_bind(source.element_id, event, __handle_event)
+
+		else :
+			source.bind(event, __handle_event)
+
+
+	@staticmethod
+	def close_window(_window):
+		_window.destroy()
+
+
+	@staticmethod
+	def log(value):
+		print(value)
+
+
+	@staticmethod
+	def new_window(width,height):
+		_window = tk.Toplevel(ui.window)
+		_window.geometry(str(width)+"x"+str(height)+"+300+300")
+		return _window
+
+
+	@staticmethod
+	def println(value,target):
+		raise Exception('Not implemented yet');
+
+
+	@staticmethod
+	def wrap_element(element):
+		return utils._bunch(element=element)
+

+ 19 - 0
exported_to_sccdxml/python_runtime/libs/utils.py

@@ -0,0 +1,19 @@
+import random
+
+class utils:
+
+	@staticmethod
+	def random():
+		return random.random()
+
+
+	"""
+		provide "." access to dictionaries
+
+		example: d = {'a':1}
+			before: d['a'] => 1, d.a => error
+			after:  d['a'] = d.a
+	"""
+	class _bunch:
+  		def __init__(self, **kwds):
+ 			self.__dict__.update(kwds)

+ 22 - 0
exported_to_sccdxml/python_runtime/nextafter.py

@@ -0,0 +1,22 @@
+import imp
+
+try:
+	# if module 'numpy' exists, use it
+	found = imp.find_module('numpy')
+	nextafter = imp.load_module('numpy', *found).nextafter
+
+except ImportError:
+	import math
+	# this ad-hoc implementation won't always give the exact same result as the C implementation used by numpy, but it's good enough for our purposes
+	def nextafter(x, y):
+		m,e = math.frexp(x)
+		exp = e - 53
+		if exp < -1022 or m == 0.0:
+			exp = -1022
+		epsilon = math.ldexp(1.0, exp)
+		if y > x:
+			return x + epsilon
+		elif y < x:
+			return x - epsilon
+		else:
+			return x

+ 947 - 0
exported_to_sccdxml/python_runtime/statecharts_core.py

@@ -0,0 +1,947 @@
+import abc
+import re
+from accurate_time import time
+import threading
+import traceback
+import math
+from nextafter import nextafter
+from infinity import INFINITY
+from event_queue import EventQueue
+from Queue import Queue, Empty
+
+class RuntimeException(Exception):
+	def __init__(self, message):
+		self.message = message
+	def __str__(self):
+		return repr(self.message)
+
+class AssociationException(RuntimeException):
+	pass
+
+class AssociationReferenceException(RuntimeException):
+	pass
+
+class ParameterException(RuntimeException):
+	pass
+
+class InputException(RuntimeException):
+	pass
+
+class Association(object):
+	#wrapper object for one association relation
+	def __init__(self, to_class, min_card, max_card):
+		self.to_class = to_class
+		self.min_card = min_card
+		self.max_card = max_card
+		self.instances = {}  # maps index (as string) to instance
+		self.instances_to_ids = {}
+		self.size = 0
+		self.next_id = 0
+		
+
+	def allowedToAdd(self):
+		return self.max_card == -1 or self.size < self.max_card
+		
+	def allowedToRemove(self):
+		return self.min_card == -1 or self.size > self.min_card
+		
+	def addInstance(self, instance):
+		if self.allowedToAdd() :
+			new_id = self.next_id
+			self.next_id += 1
+			self.instances[new_id] = instance
+			self.instances_to_ids[instance] = new_id
+			self.size += 1
+			return new_id
+		else :
+			raise AssociationException("Not allowed to add the instance to the association.")
+		
+	def removeInstance(self, instance):
+		if self.allowedToRemove() :
+			del self.instances[self.instances_to_ids[instance]]
+			del self.instances_to_ids[instance]
+			self.size -= 1
+		else :
+			raise AssociationException("Not allowed to remove the instance from the association.")
+		
+	def getInstance(self, index):
+		try :
+			return self.instances[index]
+		except IndexError :
+			raise AssociationException("Invalid index for fetching instance(s) from association.")
+
+"""class InstanceWrapper(object):
+	#wrapper object for an instance and its relevant information needed in the object manager
+	def __init__(self, instance, associations):
+		self.instance = instance
+		self.associations = {}
+		for association in associations :
+			self.associations[association.getName()] = association  
+		
+	def getAssociation(self, name):
+		try :
+			return self.associations[name]
+		except KeyError :
+			raise AssociationReferenceException("Unknown association %s." % name)
+	
+	def getInstance(self):
+		return self.instance"""
+
+class ObjectManagerBase(object):
+	__metaclass__  = abc.ABCMeta
+	
+	def __init__(self, controller):
+		self.controller = controller
+		self.events = EventQueue()
+		self.instances = [] #a dictionary that maps RuntimeClassBase to InstanceWrapper
+		
+	def addEvent(self, event, time_offset = 0.0):
+		self.events.add(event, time_offset)
+		
+	# Broadcast an event to all instances
+	def broadcast(self, new_event):
+		for i in self.instances:
+			i.addEvent(new_event)
+		
+	def getWaitTime(self):  
+		#first get waiting time of the object manager's events
+		smallest_time = self.events.getEarliestTime()
+		#check all the instances
+		for instance in self.instances:
+			smallest_time = min(smallest_time, instance.getEarliestEventTime())
+		return smallest_time
+	
+	def stepAll(self, delta):
+		self.step(delta)
+		for i in self.instances:
+			i.step(delta)
+
+	def step(self, delta):
+		self.events.decreaseTime(delta)
+		for event in self.events.popDueEvents() :
+			self.handleEvent(event)
+			   
+	def start(self):
+		for i in self.instances:
+			i.start()		   
+			   
+	def handleEvent(self, e):   
+		if e.getName() == "narrow_cast" :
+			self.handleNarrowCastEvent(e.getParameters())
+			
+		elif e.getName() == "broad_cast" :
+			self.handleBroadCastEvent(e.getParameters())
+			
+		elif e.getName() == "create_instance" :
+			self.handleCreateEvent(e.getParameters())
+			
+		elif e.getName() == "associate_instance" :
+			self.handleAssociateEvent(e.getParameters())
+			
+		elif e.getName() == "start_instance" :
+			self.handleStartInstanceEvent(e.getParameters())
+			
+		elif e.getName() == "delete_instance" :
+			self.handleDeleteInstanceEvent(e.getParameters())
+			
+	def processAssociationReference(self, input_string):
+		if len(input_string) == 0 :
+			raise AssociationReferenceException("Empty association reference.")
+		regex_pattern = re.compile("^([a-zA-Z_]\w*)(?:\[(\d+)\])?$")
+		path_string =  input_string.split("/")
+		result = []
+		for piece in path_string :
+			match = regex_pattern.match(piece)
+			if match :
+				name = match.group(1)
+				index = match.group(2)
+				if index is None :
+					index = -1
+				result.append((name,int(index)))
+			else :
+				raise AssociationReferenceException("Invalid entry in association reference. Input string: " + input_string)
+		return result
+	
+	def handleStartInstanceEvent(self, parameters):
+		if len(parameters) != 2 :
+			raise ParameterException ("The start instance event needs 2 parameters.")  
+		else :
+			source = parameters[0]
+			traversal_list = self.processAssociationReference(parameters[1])
+			for i in self.getInstances(source, traversal_list) :
+				i["instance"].start()
+			source.addEvent(Event("instance_started", parameters = [parameters[1]]))
+		
+	def handleBroadCastEvent(self, parameters):
+		if len(parameters) != 1 :
+			raise ParameterException ("The broadcast event needs 1 parameter.")
+		self.broadcast(parameters[0])
+
+	def handleCreateEvent(self, parameters):
+		if len(parameters) < 2 :
+			raise ParameterException ("The create event needs at least 2 parameters.")
+
+		source = parameters[0]
+		association_name = parameters[1]
+		
+		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:
+				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)+"]"]))
+		else :
+			source.addEvent(Event("instance_creation_error", None, [association_name]))
+
+	def handleDeleteInstanceEvent(self, parameters):
+		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 = self.instances_map[source].getAssociation(traversal_list[0][0])
+			association = source.associations[traversal_list[0][0]]
+			for i in instances:
+				try:
+					association.removeInstance(i["instance"])
+				except AssociationException as exception:
+					raise RuntimeException("Error removing instance from association '" + association_name + "': " + str(exception))
+				i["instance"].stop()
+				#if hasattr(i.instance, 'user_defined_destructor'):
+				i["instance"].user_defined_destructor()
+			source.addEvent(Event("instance_deleted", parameters = [parameters[1]]))
+				
+	def handleAssociateEvent(self, parameters):
+		if len(parameters) != 3 :
+			raise ParameterException ("The associate_instance event needs 3 parameters.")
+		else :
+			source = parameters[0]
+			to_copy_list = self.getInstances(source,self.processAssociationReference(parameters[1]))
+			if len(to_copy_list) != 1 :
+				raise AssociationReferenceException ("Invalid source association reference.")
+			wrapped_to_copy_instance = to_copy_list[0]["instance"]
+			dest_list = self.processAssociationReference(parameters[2])
+			if len(dest_list) == 0 :
+				raise AssociationReferenceException ("Invalid destination association reference.")
+			last = dest_list.pop()
+			if last[1] != -1 :
+				raise AssociationReferenceException ("Last association name in association reference should not be accompanied by an index.")
+				
+			for i in self.getInstances(source, dest_list) :
+				i["instance"].associations[last[0]].addInstance(wrapped_to_copy_instance)
+		
+	def handleNarrowCastEvent(self, parameters):
+		if len(parameters) != 3 :
+			raise ParameterException ("The associate_instance event needs 3 parameters.")
+		source = parameters[0]
+		traversal_list = self.processAssociationReference(parameters[1])
+		cast_event = parameters[2]
+		for i in self.getInstances(source, traversal_list) :
+			i["instance"].addEvent(cast_event)
+		
+	def getInstances(self, source, traversal_list):
+		currents = [{
+			"instance" : source,
+			"ref" : None,
+			"assoc_name" : None,
+			"assoc_index" : None
+		}]
+		#currents = [source]
+		for (name, index) in traversal_list :
+			nexts = []
+			for current in currents :
+				association = current["instance"].associations[name]
+				if (index >= 0 ) :
+					nexts.append({
+						"instance" : association.instances[index],
+						"ref" : current["instance"],
+						"assoc_name" : name,
+						"assoc_index" : index
+					})
+				elif (index == -1) :
+					for i in association.instances:
+						nexts.append({
+							"instance" : association.instances[i],
+							"ref" : current["instance"],
+							"assoc_name" : name,
+							"assoc_index" : index
+						})
+					#nexts.extend( association.instances.values() )
+				else :
+					raise AssociationReferenceException("Incorrect index in association reference.")
+			currents = nexts
+		return currents
+			
+	@abc.abstractmethod
+	def instantiate(self, class_name, construct_params):
+		pass
+		
+	def createInstance(self, to_class, construct_params = []):
+		instance = self.instantiate(to_class, construct_params)
+		self.instances.append(instance)
+		return instance
+	
+class Event(object):
+	def __init__(self, event_name, port = "", parameters = []):
+		self.name = event_name
+		self.parameters = parameters
+		self.port = port
+
+	def getName(self):
+		return self.name
+
+	def getPort(self):
+		return self.port
+
+	def getParameters(self):
+		return self.parameters
+	
+	def __repr__(self):
+		representation = "(event name : " + str(self.name) + "; port : " + str(self.port)
+		if self.parameters :
+			representation += "; parameters : " + str(self.parameters)
+		representation += ")"
+		return representation
+	
+class OutputListener(object):
+	def __init__(self, port_names):
+		self.port_names = port_names
+		self.queue = Queue()
+
+	def add(self, event):
+		if len(self.port_names) == 0 or event.getPort() in self.port_names :
+			self.queue.put_nowait(event)
+			
+	""" Tries for timeout seconds to fetch an event, returns None if failed.
+		0 as timeout means no waiting (blocking), returns None if queue is empty.
+		-1 as timeout means blocking until an event can be fetched. """
+	def fetch(self, timeout = 0):
+		if timeout < 0:
+			timeout = INFINITY
+		while timeout >= 0:
+			try:
+				# wait in chunks of 100ms because we
+				# can't receive (keyboard)interrupts while waiting
+				return self.queue.get(True, 0.1 if timeout > 0.1 else timeout)
+			except Empty:
+				timeout -= 0.1
+		return None
+
+class InputPortEntry(object):
+	def __init__(self, virtual_name, instance):
+		self.virtual_name = virtual_name
+		self.instance = instance
+		
+class ControllerBase(object):
+
+	def __init__(self, object_manager):
+		self.object_manager = object_manager
+
+		self.private_port_counter = 0
+
+		# Keep track of input ports
+		self.input_ports = {}
+		self.input_queue = EventQueue()
+
+		# Keep track of output ports
+		self.output_ports = []
+		self.output_listeners = []
+
+		# Let statechart run one last time before stopping
+		self.done = False
+			
+	def addInputPort(self, virtual_name, instance = None):
+		if instance == None :
+			port_name = virtual_name
+		else:
+			port_name = "private_" + str(self.private_port_counter) + "_" + virtual_name
+			self.private_port_counter += 1
+		self.input_ports[port_name] = InputPortEntry(virtual_name, instance)
+		return port_name
+		
+	def addOutputPort(self, port_name):
+		self.output_ports.append(port_name)
+
+	def broadcast(self, new_event):
+		self.object_manager.broadcast(new_event)
+		
+	def start(self):
+		self.object_manager.start()
+	
+	def stop(self):
+		pass
+
+	def addInput(self, input_event_list, time_offset = 0.0):
+		if not isinstance(input_event_list, list):
+			input_event_list = [input_event_list]
+
+		for e in input_event_list:
+			if e.getName() == ""  :
+				raise InputException("Input event can't have an empty name.")
+		
+			if e.getPort() not in self.input_ports :
+				raise InputException("Input port mismatch, no such port: " + e.getPort() + ".")		
+
+		self.input_queue.add(input_event_list, time_offset)
+
+	def getWaitTime(self):
+		return min(self.object_manager.getWaitTime(), self.input_queue.getEarliestTime())
+
+	def handleInput(self, delta):
+		self.input_queue.decreaseTime(delta)
+		for events in self.input_queue.popDueEvents():
+			for e in events:
+				input_port = self.input_ports[e.getPort()]
+				e.port = input_port.virtual_name
+				target_instance = input_port.instance
+				if target_instance == None:
+					self.broadcast(e)
+				else:
+					target_instance.addEvent(e)
+
+	def outputEvent(self, event):
+		for listener in self.output_listeners :
+			listener.add(event)
+
+	def addOutputListener(self, ports):
+		listener = OutputListener(ports)
+		self.output_listeners.append(listener)
+		return listener
+
+	def addMyOwnOutputListener(self, listener):
+		self.output_listeners.append(listener)
+
+	# deprecated, to add multiple events, use addInput instead
+	def addEventList(self, event_list):
+		for (event, time_offset) in event_list :
+			self.addInput(event, time_offset)
+			
+	def getObjectManager(self):
+		return self.object_manager
+		
+class GameLoopControllerBase(ControllerBase):
+	def __init__(self, object_manager):
+		ControllerBase.__init__(self, object_manager)
+		
+	def update(self, delta):
+		self.handleInput(delta)
+		self.object_manager.stepAll(delta)
+
+class EventLoop:
+	# parameters:
+	#  schedule - a callback scheduling another callback in the event loop
+	#      this callback should take 2 parameters: (callback, timeout) and return an ID
+	#  clear - a callback that clears a scheduled callback
+	#      this callback should take an ID that was returned by 'schedule'
+	def __init__(self, schedule, clear):
+		self.schedule_callback = schedule
+		self.clear_callback = clear
+		self.scheduled_id = None
+		self.last_time = None
+		self.next_wakeup = None
+		self.last_print = 0.0
+
+	def getScheduledTimeout(self):
+		if self.last_time and self.next_wakeup:
+			return self.next_wakeup - self.last_time
+		else:
+			return INFINITY
+
+	# schedule relative to last_time
+	#
+	# argument 'wait_time' is the amount of virtual (simulated) time to wait
+	#
+	# NOTE: if the next wakeup (in simulated time) is in the past, the timeout is '0',
+	# but because scheduling '0' timeouts hurts performance, we don't schedule anything
+	# and return False instead
+	def schedule(self, f, wait_time):
+		if self.scheduled_id:
+			# if the following error occurs, it is probably due to a flaw in the logic of EventLoopControllerBase
+			raise RuntimeException("EventLoop class intended to maintain at most 1 scheduled callback.")
+
+		if wait_time == INFINITY:
+			self.last_time = None
+			self.next_wakeup = None
+			is_scheduled = True
+		else:
+			now = time()
+			if not self.last_time:
+				self.last_time = now
+			self.next_wakeup = self.last_time + wait_time
+			# self.last_time is a very large value, and wait_time can be very small, so 
+			if self.next_wakeup - self.last_time < wait_time:
+				# due to floating point imprecision, it is possible for a nonzero wait-time to advance simulated time not enough to pop the next event, potentially even causing the model to hang, so we always take the ceil of the exact result of the addition self.last_time + wait_time.
+				self.next_wakeup = nextafter(self.next_wakeup, INFINITY)
+			remaining = max(self.next_wakeup - now, 0.0)
+			is_scheduled, self.scheduled_id = self.schedule_callback(f, remaining)
+		return is_scheduled
+
+	def clear(self):
+		if self.scheduled_id:
+			self.clear_callback(self.scheduled_id)
+			self.scheduled_id = None
+
+	def nextDelta(self):
+		now = time()
+		if self.next_wakeup:
+			simulated_now = self.next_wakeup
+		else:
+			simulated_now = now
+		if now - self.last_print > 1.0:
+			behind_schedule = now - simulated_now
+			if behind_schedule > 0.1:
+				print "Warning: running %.f ms behind schedule" % (behind_schedule*1000.0)
+				self.last_print = now
+		if self.last_time:
+			delta = simulated_now - self.last_time
+		else:
+			delta = 0.0
+		self.last_time = simulated_now
+		self.next_wakeup = None
+		return delta
+
+	# returns elapsed time since delta
+	def elapsed(self):
+		if self.last_time:
+			return time() - self.last_time
+		else:
+			return 0.0
+
+class EventLoopControllerBase(ControllerBase):
+	def __init__(self, object_manager, event_loop, finished_callback = None):
+		ControllerBase.__init__(self, object_manager)
+		self.event_loop = event_loop
+		self.finished_callback = finished_callback
+
+	def addInput(self, input_event, time_offset = 0.0):
+		elapsed = self.event_loop.elapsed()
+		controller_timeout = time_offset + elapsed
+		ControllerBase.addInput(self, input_event, controller_timeout)
+		if controller_timeout < self.event_loop.getScheduledTimeout():
+			# added event's timeout is sooner than existing timeout -> re-schedule
+			self.event_loop.clear()
+			if not self.event_loop.schedule(self.run, controller_timeout):
+				self.run()
+
+	def start(self):
+		ControllerBase.start(self)
+		self.run()
+
+	def stop(self):
+		self.event_loop.clear()
+		ControllerBase.stop(self)
+
+	def run(self):
+		while True:
+			# clear existing timeout
+			self.event_loop.clear()
+			# calculate last time since simulation
+			delta = self.event_loop.nextDelta()
+			# simulate
+			self.handleInput(delta)
+			self.object_manager.stepAll(delta)
+			# schedule next timeout
+			wait_time = self.getWaitTime()
+			scheduled = self.event_loop.schedule(self.run, wait_time)
+			if wait_time == INFINITY:
+				if self.finished_callback:
+					self.finished_callback()
+			if scheduled:
+				break
+		
+class ThreadsControllerBase(ControllerBase):
+	def __init__(self, object_manager, keep_running):
+		ControllerBase.__init__(self, object_manager)
+		self.keep_running = keep_running
+		self.input_condition = threading.Condition()
+		self.stop_thread = False
+		self.thread = threading.Thread(target=self.run)
+		
+	def handleInput(self, delta):
+		self.input_condition.acquire()
+		ControllerBase.handleInput(self, delta)
+		self.input_condition.release()
+		
+	def start(self):
+		self.thread.start()
+		
+	def stop(self):
+		self.input_condition.acquire()
+		self.stop_thread = True
+		self.input_condition.notifyAll()
+		self.input_condition.release()
+
+	def getWaitTime(self):
+		"""Compute time untill earliest next event"""
+		self.input_condition.acquire()
+		wait_time = ControllerBase.getWaitTime(self)
+		self.input_condition.release()
+
+		if wait_time == INFINITY :
+			if self.done :
+				self.done = False
+			else :
+				self.done = True
+				return 0.0
+		return wait_time
+
+	def handleWaiting(self):
+		self.input_condition.acquire()
+		wait_time = self.getWaitTime()
+		if(wait_time <= 0.0):
+			return
+		
+		if wait_time == INFINITY :
+			if self.keep_running :
+				self.input_condition.wait() #Wait for a signals
+			else :
+				self.stop_thread = True
+		
+		elif wait_time != 0.0 :
+			reduced_wait_time = wait_time - (time() - self.last_recorded_time)
+			if reduced_wait_time > 0.0 :
+				self.input_condition.wait(reduced_wait_time)	
+		self.input_condition.release()
+
+	def run(self):
+		self.last_recorded_time  = time()
+		super(ThreadsControllerBase, self).start()
+		last_iteration_time = 0.0
+		
+		while True:
+			self.input_condition.acquire()
+			self.handleInput(last_iteration_time)
+			self.input_condition.release()
+			#Compute the new state based on internal events
+			self.object_manager.stepAll(last_iteration_time)
+			
+			self.handleWaiting()
+			
+			self.input_condition.acquire()
+			if self.stop_thread : 
+				break
+			self.input_condition.release()
+			
+			previous_recorded_time = self.last_recorded_time
+			self.last_recorded_time = time()
+			last_iteration_time = self.last_recorded_time - previous_recorded_time
+		
+	def join(self):
+		self.thread.join()
+
+	def addInput(self, input_event, time_offset = 0.0):
+		self.input_condition.acquire()
+		super(ThreadsControllerBase, self).addInput(input_event, time_offset)
+		self.input_condition.notifyAll()
+		self.input_condition.release()
+
+	def addEventList(self, event_list):
+		self.input_condition.acquire()
+		super(ThreadsControllerBase, self).addEventList(event_list)
+		self.input_condition.release()
+
+class StatechartSemantics:
+	# Big Step Maximality
+	TakeOne = 0
+	TakeMany = 1
+	# Concurrency - not implemented yet
+	Single = 0
+	Many = 1
+	# Preemption - not implemented yet
+	NonPreemptive = 0
+	Preemptive = 1
+	# Internal Event Lifeline
+	Queue = 0
+	NextSmallStep = 1
+	NextComboStep = 2
+	# Input Event Lifeline
+	Whole = 0
+	FirstSmallStep = 1
+	FirstComboStep = 2
+	# Priority
+	SourceParent = 0
+	SourceChild = 1
+	# TODO: add Memory Protocol options
+	
+	def __init__(self):
+		# default semantics:
+		self.big_step_maximality = self.TakeMany
+		self.concurrency = self.Single
+		self.internal_event_lifeline = self.Queue
+		self.input_event_lifeline = self.FirstComboStep
+		self.priority = self.SourceParent
+
+class RuntimeClassBase(object):
+	__metaclass__  = abc.ABCMeta
+	
+	def __init__(self, controller):
+		self.active = False
+		self.is_stable = True
+		self.events = EventQueue()
+
+		self.controller = controller
+
+		self.timers = None
+		self.inports = {}
+
+		self.semantics = StatechartSemantics()
+
+	def start(self):
+		self.current_state = {}
+		self.history_state = {}
+		self.timers = {}
+
+		self.big_step = BigStepState()
+		self.combo_step = ComboStepState()
+		self.small_step = SmallStepState()
+
+		self.active = True
+		self.is_stable = False
+
+		self.initializeStatechart()
+		self.processBigStepOutput()
+	
+	def stop(self):
+		self.active = False
+		
+	def addEvent(self, event_list, time_offset = 0.0):
+		if not isinstance(event_list, list):
+			event_list = [event_list]
+		self.events.add(event_list, time_offset)
+		
+	def getEarliestEventTime(self) :
+		if not self.active:
+			return INFINITY
+		if not self.is_stable:
+			return 0.0
+		if self.timers:
+			return min(self.events.getEarliestTime(), min(self.timers.itervalues()))
+		return self.events.getEarliestTime()
+
+	def processBigStepOutput(self):
+		for e in self.big_step.getOutputEvents():
+			self.controller.outputEvent(e)
+		for e in self.big_step.getOutputEventsOM():
+			self.controller.object_manager.addEvent(e)
+
+	def step(self, delta):
+		if not self.active :
+			return
+		
+		# decrease event queue time
+		self.events.decreaseTime(delta)
+
+		# decrease timers time
+		next_timers = {}
+		for (key,value) in self.timers.iteritems() :
+			time = value - delta
+			if time <= 0.0 :
+				self.addEvent( Event("_" + str(key) + "after"), time)
+			else :
+				next_timers[key] = time
+		self.timers = next_timers
+
+		# execute big step(s)
+		due = self.events.popDueEvents()
+		if not due and not self.is_stable:
+			due = [[]]
+		for input_events in due:
+			# perform 1 big step per slot in 'due'
+			self.is_stable = not self.bigStep(input_events)
+			self.processBigStepOutput()
+
+	def inState(self, nodes):
+		for c in self.current_state.itervalues():
+			new_nodes = []
+			for n in nodes:
+				if not (n in c):
+					new_nodes.append(n)
+			nodes = new_nodes
+			if len(nodes) == 0:
+				return True
+		return False
+
+	def bigStep(self, input_events):
+		#print "new big step"
+		self.big_step.next(input_events)
+		self.small_step.reset()
+		self.combo_step.reset()
+		while self.comboStep():
+			self.big_step.setStepped()
+			if self.semantics.big_step_maximality == StatechartSemantics.TakeOne:
+				break # Take One -> only one combo step allowed
+		return self.big_step.hasStepped()
+
+	def comboStep(self):
+		#print "new combo step"
+		self.combo_step.next()
+		while self.smallStep():
+			self.combo_step.setStepped()
+		return self.combo_step.hasStepped()
+
+	def smallStep(self):
+		if self.small_step.hasStepped():
+			self.small_step.next()
+		self.generateCandidates()
+		if self.small_step.hasCandidates():
+			#print "new small step, have " + str(len(self.small_step.getCandidates())) + " candidates"
+			if self.semantics.concurrency == StatechartSemantics.Single:
+				transition, parameters = self.small_step.getCandidates()[0] # execute first of candidates
+				transition(parameters)
+			elif self.semantics.concurrency == StatechartSemantics.Many:
+				pass # TODO: implement
+			self.small_step.setStepped()
+		return self.small_step.hasStepped()
+
+	def getEnabledEvents(self):
+		result = self.small_step.getCurrentEvents() + self.combo_step.getCurrentEvents()
+		if self.semantics.input_event_lifeline == StatechartSemantics.Whole or (
+			not self.big_step.hasStepped() and
+				(self.semantics.input_event_lifeline == StatechartSemantics.FirstComboStep or (
+				not self.combo_step.hasStepped() and
+					self.semantics.input_event_lifeline == StatechartSemantics.FirstSmallStep))):
+			result += self.big_step.getInputEvents()
+		return result
+
+	def raiseInternalEvent(self, event):
+		if self.semantics.internal_event_lifeline == StatechartSemantics.NextSmallStep:
+			self.small_step.addNextEvent(event)
+		elif self.semantics.internal_event_lifeline == StatechartSemantics.NextComboStep:
+			self.combo_step.addNextEvent(event)
+		elif self.semantics.internal_event_lifeline == StatechartSemantics.Queue:
+			self.events.add([event], 0.0)
+
+	@abc.abstractmethod
+	def initializeStatechart(self):
+		pass
+
+	@abc.abstractmethod
+	def generateCandidates(self):
+		pass
+
+
+class BigStepState(object):
+	def __init__(self):
+		self.input_events = [] # input events received from environment before beginning of big step (e.g. from object manager, from input port)
+		self.output_events_port = [] # output events to be sent to output port after big step ends.
+		self.output_events_om = [] # output events to be sent to object manager after big step ends.
+		self.has_stepped = True
+
+	def next(self, input_events):
+		self.input_events = input_events
+		self.output_events_port = []
+		self.output_events_om = []
+		self.has_stepped = False
+
+	def getInputEvents(self):
+		return self.input_events
+
+	def getOutputEvents(self):
+		return self.output_events_port
+
+	def getOutputEventsOM(self):
+		return self.output_events_om
+
+	def outputEvent(self, event):
+		self.output_events_port.append(event)
+
+	def outputEventOM(self, event):
+		self.output_events_om.append(event)
+
+	def setStepped(self):
+		self.has_stepped = True
+
+	def hasStepped(self):
+		return self.has_stepped
+
+
+class ComboStepState(object):
+	def __init__(self):
+		self.current_events = [] # set of enabled events during combo step
+		self.next_events = [] # internal events that were raised during combo step
+		self.changed = [] # set of all or-states that were the arena of a triggered transition during big step.
+		self.has_stepped = True
+
+	def reset(self):
+		self.current_events = []
+		self.next_events = []
+
+	def next(self):
+		self.current_events = self.next_events
+		self.next_events = []
+		self.changed = []
+		self.has_stepped = False
+
+	def addNextEvent(self, event):
+		self.next_events.append(event)
+
+	def getCurrentEvents(self):
+		return self.current_events
+
+	def setArenaChanged(self, arena):
+		self.changed.append(arena)
+
+	def isArenaChanged(self, arena):
+		return (arena in self.changed)
+
+	def isStable(self):
+		return (len(self.changed) == 0)
+
+	def setStepped(self):
+		self.has_stepped = True
+
+	def hasStepped(self):
+		return self.has_stepped
+
+
+class SmallStepState(object):
+	def __init__(self):
+		self.current_events = [] # set of enabled events during small step
+		self.next_events = [] # events to become 'current' in the next small step
+		self.candidates = [] # document-ordered(!) list of transitions that can potentially be executed concurrently, or preempt each other, depending on concurrency semantics. If no concurrency is used and there are multiple candidates, the first one is chosen. Source states of candidates are *always* orthogonal to each other.
+		self.has_stepped = True
+
+	def reset(self):
+		self.current_events = []
+		self.next_events = []
+
+	def next(self):
+		self.current_events = self.next_events # raised events from previous small step
+		self.next_events = []
+		self.candidates = []
+		self.has_stepped = False
+
+	def addNextEvent(self, event):
+		self.next_events.append(event)
+
+	def getCurrentEvents(self):
+		return self.current_events
+
+	def addCandidate(self, t, p):
+		self.candidates.append((t, p))
+
+	def getCandidates(self):
+		return self.candidates
+
+	def hasCandidates(self):
+		return len(self.candidates) > 0
+
+	def setStepped(self):
+		self.has_stepped = True
+
+	def hasStepped(self):
+		return self.has_stepped
+

+ 21 - 0
exported_to_sccdxml/python_runtime/tkinter_eventloop.py

@@ -0,0 +1,21 @@
+from statecharts_core import EventLoop
+import math
+
+class TkEventLoop(EventLoop):
+	def __init__(self, tk):
+	
+		tk.sccd_force_update = False
+
+		# bind scheduler callback
+		def schedule(callback, timeout):
+			if timeout == 0:
+			# tk considers updating the window an 'idle' task, only to be done if no events are scheduled for a while. But this has the downside of the interface becoming completely unresponsive while the model is performing steps with no gaps in between. Thus we insert an 'update_idletasks()' to obtain "javascript event loop"-like behavior.
+				if tk.sccd_force_update:
+					tk.update_idletasks()
+					tk.sccd_force_update = False
+				else:
+					return (False, None) # don't schedule 0-timeout, it's more performant to just keep running
+			return (True, tk.after(int(math.ceil(timeout*1000.0)), callback))
+
+		EventLoop.__init__(self, schedule, tk.after_cancel)
+

+ 17 - 0
exported_to_sccdxml/python_sccd_compiler/.project

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>python_sccd_compiler</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>

+ 5 - 0
exported_to_sccdxml/python_sccd_compiler/.pydevproject

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+</pydev_project>

+ 14 - 0
exported_to_sccdxml/python_sccd_compiler/compiler_exceptions.py

@@ -0,0 +1,14 @@
+class CompilerException(Exception):
+	def __init__(self, message):
+		self.message = message
+	def __str__(self):
+		return repr(self.message)
+	
+class TransitionException(CompilerException):
+	pass
+
+class UnprocessedException(CompilerException):
+	pass
+
+class CodeBlockException(CompilerException):
+	pass

+ 911 - 0
exported_to_sccdxml/python_sccd_compiler/generic_generator.py

@@ -0,0 +1,911 @@
+# Generic Generator by Joeri Exelmans
+#
+# Visits SCCD-domain constructs (see sccd_constructs.py) and converts them
+# to a generic language AST (see generic_language_constructs.py), that can
+# then be visited by a target language writer.
+
+import traceback
+
+import time
+from utils import Enum, Logger
+
+from visitor import Visitor
+from sccd_constructs import FormalParameter
+from stateful_writer import StatefulWriter
+import generic_language_constructs as GLC
+
+Platforms = Enum("Threads","GameLoop","EventLoop") 
+
+class GenericGenerator(Visitor):
+	
+	def __init__(self, platform):
+		self.platform = platform
+		self.writer = StatefulWriter()
+
+	def generic_visit(self, node):
+		Logger.showWarning("GenericGenerator has no visit method for node of type '" + str(type(node)) + "'.")
+
+	def get(self):
+		return self.writer.get()
+
+	def visit_ClassDiagram(self, class_diagram):
+		header = ("Generated by Statechart compiler by Glenn De Jonghe and Joeri Exelmans\n"
+		          "\n"
+		          "Date:   " + time.asctime() + "\n")
+		if class_diagram.name or class_diagram.author or class_diagram.description:
+			header += "\n"
+		if class_diagram.author:
+			header += "Model author: " + class_diagram.author + "\n"
+		if class_diagram.name:
+			header += "Model name:   " + class_diagram.name + "\n"
+		if class_diagram.description.strip():
+			header += "Model description:\n"
+			header += class_diagram.description.strip()
+
+		self.writer.addMultiLineComment(header)
+		self.writer.addVSpace()
+		self.writer.addInclude(([GLC.RuntimeModuleIdentifier(), "statecharts_core"]))
+		if class_diagram.top.strip():
+			self.writer.addRawCode(class_diagram.top)
+		self.writer.addVSpace()
+
+		self.writer.beginPackage(class_diagram.name)
+		
+		#visit children
+		for c in class_diagram.classes :
+			c.accept(self)
+		 
+		self.writer.beginClass("ObjectManager", ["ObjectManagerBase"])
+
+		self.writer.beginConstructor()
+		self.writer.addFormalParameter("controller")
+		self.writer.beginMethodBody()
+		self.writer.beginSuperClassConstructorCall("ObjectManagerBase")
+		self.writer.addActualParameter("controller")
+		self.writer.endSuperClassConstructorCall()
+		self.writer.endMethodBody()
+		self.writer.endConstructor()
+
+		self.writer.beginMethod("instantiate")
+		self.writer.addFormalParameter("class_name")
+		self.writer.addFormalParameter("construct_params")
+		self.writer.beginMethodBody()
+		for index,c in enumerate(class_diagram.classes):
+			self.writer.beginElseIf(GLC.EqualsExpression("class_name", GLC.String(c.name)))
+			if c.isAbstract():
+				# cannot instantiate abstract class
+				self.writer.add(GLC.ThrowExceptionStatement(GLC.String("Cannot instantiate abstract class \"" + c.name + "\" with unimplemented methods \"" + "\", \"".join(c.abstract_method_names) + "\".")))
+			else:
+				new_expr = GLC.NewExpression(c.name, [GLC.SelfProperty("controller")])
+				param_count = 0
+				for p in c.constructors[0].parameters:
+					new_expr.getActualParameters().add(GLC.ArrayIndexedExpression("construct_params", str(param_count)))
+					param_count += 1
+				self.writer.addAssignment(
+					GLC.LocalVariableDeclaration("instance"),
+					new_expr)
+				self.writer.addAssignment(
+					GLC.Property("instance", "associations"),
+					GLC.MapExpression())
+				for a in c.associations:
+					a.accept(self)
+			self.writer.endElseIf()
+		self.writer.add(GLC.ReturnStatement("instance"))
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+		self.writer.endClass() # ObjectManager
+
+		if self.platform == Platforms.Threads:
+			controller_sub_class = "ThreadsControllerBase"
+		if self.platform == Platforms.EventLoop :
+			controller_sub_class = "EventLoopControllerBase"
+		elif self.platform == Platforms.GameLoop :
+			controller_sub_class = "GameLoopControllerBase"
+
+		self.writer.beginClass("Controller", [controller_sub_class])
+		self.writer.beginConstructor()
+		for p in class_diagram.default_class.constructors[0].parameters:
+			p.accept(self)
+		if self.platform == Platforms.EventLoop:
+			self.writer.addFormalParameter("event_loop_callbacks")
+			self.writer.addFormalParameter("finished_callback", GLC.NoneExpression())
+		elif self.platform == Platforms.Threads:
+			self.writer.addFormalParameter("keep_running", GLC.TrueExpression())
+		self.writer.beginMethodBody()
+		self.writer.beginSuperClassConstructorCall(controller_sub_class)
+		self.writer.addActualParameter(GLC.NewExpression("ObjectManager", [GLC.SelfExpression()]))
+		if self.platform == Platforms.EventLoop:
+			self.writer.addActualParameter("event_loop_callbacks")
+			self.writer.addActualParameter("finished_callback")
+		elif self.platform == Platforms.Threads:
+			self.writer.addActualParameter("keep_running")
+		self.writer.endSuperClassConstructorCall()
+		for i in class_diagram.inports:
+			self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addInputPort"), [GLC.String(i)]))
+		for o in class_diagram.outports:
+			self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addOutputPort"), [GLC.String(o)]))
+		actual_parameters = [p.getIdent() for p in class_diagram.default_class.constructors[0].parameters]
+		self.writer.add(GLC.FunctionCall(GLC.Property(GLC.SelfProperty("object_manager"), "createInstance"), [GLC.String(class_diagram.default_class.name), GLC.ArrayExpression(actual_parameters)]))
+		self.writer.endMethodBody()
+		self.writer.endConstructor()
+		self.writer.endClass() # Controller
+
+		# Visit test node if there is one
+		if class_diagram.test:
+			class_diagram.test.accept(self)
+
+		self.writer.endPackage()
+
+	def visit_DiagramTest(self, test):
+		# helper class
+		self.writer.beginClass("InputEvent")
+		self.writer.beginConstructor()
+		self.writer.addFormalParameter("name")
+		self.writer.addFormalParameter("port")
+		self.writer.addFormalParameter("parameters")
+		self.writer.addFormalParameter("time_offset")
+		self.writer.beginMethodBody()
+		self.writer.addAssignment(GLC.SelfProperty("name"), "name")
+		self.writer.addAssignment(GLC.SelfProperty("port"), "port")
+		self.writer.addAssignment(GLC.SelfProperty("parameters"), "parameters")
+		self.writer.addAssignment(GLC.SelfProperty("time_offset"), "time_offset")
+		self.writer.endMethodBody()
+		self.writer.endConstructor()
+		self.writer.endClass()
+		self.writer.beginClass("Test")
+		if test.input:
+			test.input.accept(self)
+		else:
+			self.writer.addStaticAttribute("input_events", GLC.ArrayExpression())
+		if test.expected:
+			test.expected.accept(self)
+		else:
+			self.writer.addStaticAttribute("expected_events", GLC.ArrayExpression())
+		self.writer.endClass()
+
+	def visit_DiagramTestInput(self, test_input):
+		# write array of input events
+		self.writer.startRecordingExpression()
+		self.writer.beginArray()
+		for e in test_input.input_events:
+			e.accept(self)
+		self.writer.endArray()
+		array_expr = self.writer.stopRecordingExpression()
+		self.writer.addStaticAttribute("input_events", array_expr)
+
+	def visit_DiagramTestInputEvent(self, event):
+		self.writer.add(GLC.NewExpression("InputEvent", [GLC.String(event.name), GLC.String(event.port), GLC.ArrayExpression(event.parameters), event.time]))
+
+	def visit_DiagramTestExpected(self, test_expected):
+		# write array of slots containing expected events
+		self.writer.startRecordingExpression()
+		self.writer.beginArray()
+		for s in test_expected.slots:
+			s.accept(self)
+		self.writer.endArray()
+		array_expr = self.writer.stopRecordingExpression()
+		self.writer.addStaticAttribute("expected_events", array_expr)
+
+	def visit_DiagramTestExpectedSlot(self, slot):
+		# write slot
+		self.writer.beginArray()
+		for e in slot.expected_events:
+			e.accept(self)
+		self.writer.endArray()
+
+	def visit_DiagramTestEvent(self, event):
+		self.writer.add(GLC.NewExpression("Event", [GLC.String(event.name), GLC.String(event.port), GLC.ArrayExpression(event.parameters)]))
+
+	def visit_Class(self, class_node):
+		"""
+		Generate code for Class construct
+		"""
+
+		super_classes = []
+		if not class_node.super_class_objs:
+			# if none of the class' super classes is defined in the diagram,
+			# we have to inherit RuntimeClassBase
+			if class_node.statechart:
+				# only inherit RuntimeClassBase if class has a statechart
+				super_classes.append("RuntimeClassBase")
+		if class_node.super_classes:
+			for super_class in class_node.super_classes:
+				super_classes.append(super_class)
+
+		self.writer.beginClass(class_node.name, super_classes)
+
+		#visit constructor
+		for i in class_node.constructors :
+			i.accept(self)
+
+		self.writer.beginMethod("user_defined_constructor")
+		for p in class_node.constructors[0].getParams():
+			p.accept(self)
+		self.writer.beginMethodBody()
+		for super_class in class_node.super_classes:
+			# begin call
+			if super_class in class_node.super_class_objs:
+				self.writer.beginSuperClassMethodCall(super_class, "user_defined_constructor")
+			else:
+				self.writer.beginSuperClassConstructorCall(super_class)
+			# write actual parameters
+			if super_class in class_node.constructors[0].super_class_parameters:
+				for p in class_node.constructors[0].super_class_parameters[super_class]:
+					self.writer.addActualParameter(p)
+			# end call
+			if super_class in class_node.super_class_objs:
+				self.writer.endSuperClassMethodCall()
+			else:
+				self.writer.endSuperClassConstructorCall()
+		self.writer.addRawCode(class_node.constructors[0].body)
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+
+
+		#visit children
+		for i in class_node.destructors :
+			i.accept(self)
+		for i in class_node.methods :
+			i.accept(self)
+
+		if class_node.statechart:
+			self.writer.beginMethod("initializeStatechart")
+			self.writer.beginMethodBody()
+
+			for c in class_node.statechart.composites :
+				self.writer.addAssignment(GLC.MapIndexedExpression(GLC.SelfProperty("current_state"), GLC.SelfProperty(c.full_name)), GLC.ArrayExpression())
+
+			if class_node.statechart.histories:
+				self.writer.addVSpace()
+				for node in class_node.statechart.combined_history_parents:
+					self.writer.addAssignment(GLC.MapIndexedExpression(GLC.SelfProperty("history_state"), GLC.SelfProperty(node.full_name)), GLC.ArrayExpression())
+
+			self.writer.addVSpace()
+			self.writer.addComment("Enter default state")	
+			for default_node in class_node.statechart.root.defaults:
+				if default_node.is_composite:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_"+default_node.full_name)))
+				elif default_node.is_basic:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+default_node.full_name)))
+			self.writer.endMethodBody()
+			self.writer.endMethod()
+
+			class_node.statechart.accept(self)
+
+		self.writer.endClass()
+
+
+	def visit_FormalParameter(self, formal_parameter):
+		self.writer.addFormalParameter(formal_parameter.getIdent(), formal_parameter.getDefault())
+		
+	def visit_Constructor(self, constructor):
+		self.writer.beginConstructor()
+		if constructor.parent_class.statechart:
+			self.writer.addFormalParameter("controller")
+		for p in constructor.getParams():
+			self.writer.addFormalParameter(p.getIdent(), p.getDefault())
+		self.writer.beginMethodBody() # constructor body
+
+		if constructor.parent_class.statechart:
+			self.writer.beginSuperClassConstructorCall("RuntimeClassBase")
+			self.writer.addActualParameter("controller")
+			self.writer.endSuperClassConstructorCall()
+
+			self.writer.addVSpace()
+
+			if constructor.parent_class.statechart.big_step_maximality == "take_one":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "big_step_maximality"), GLC.Property("StatechartSemantics", "TakeOne"))
+			elif constructor.parent_class.statechart.big_step_maximality == "take_many":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "big_step_maximality"), GLC.Property("StatechartSemantics", "TakeMany"))
+
+			if constructor.parent_class.statechart.internal_event_lifeline == "queue":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "internal_event_lifeline"), GLC.Property("StatechartSemantics", "Queue"))
+			elif constructor.parent_class.statechart.internal_event_lifeline == "next_small_step":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "internal_event_lifeline"), GLC.Property("StatechartSemantics", "NextSmallStep"))
+			elif constructor.parent_class.statechart.internal_event_lifeline == "next_combo_step":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "internal_event_lifeline"), GLC.Property("StatechartSemantics", "NextComboStep"))
+
+			if constructor.parent_class.statechart.input_event_lifeline == "first_small_step":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "input_event_lifeline"), GLC.Property("StatechartSemantics", "FirstSmallStep"))
+			elif constructor.parent_class.statechart.input_event_lifeline == "first_combo_step":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "input_event_lifeline"), GLC.Property("StatechartSemantics", "FirstComboStep"))
+			elif constructor.parent_class.statechart.input_event_lifeline == "whole":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "input_event_lifeline"), GLC.Property("StatechartSemantics", "Whole"))
+
+			if constructor.parent_class.statechart.priority == "source_parent":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "priority"), GLC.Property("StatechartSemantics", "SourceParent"))
+			elif constructor.parent_class.statechart.priority == "source_child":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "priority"), GLC.Property("StatechartSemantics", "SourceChild"))
+
+
+			if constructor.parent_class.statechart.concurrency == "single":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "concurrency"), GLC.Property("StatechartSemantics", "Single"))
+			elif constructor.parent_class.statechart.concurrency == "many":
+				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "concurrency"), GLC.Property("StatechartSemantics", "Many"))
+
+		for p in constructor.parent_class.inports:
+			self.writer.addAssignment(
+				GLC.MapIndexedExpression(GLC.SelfProperty("inports"), GLC.String(p)),
+				GLC.FunctionCall(GLC.Property("controller", "addInputPort"), [GLC.String(p), GLC.SelfExpression()]))
+
+		if constructor.parent_class.attributes:
+			self.writer.addVSpace()
+			self.writer.addComment("User defined attributes")
+			for attribute in constructor.parent_class.attributes:
+				if attribute.init_value is None :
+					self.writer.addAssignment(GLC.SelfProperty(attribute.name), GLC.NoneExpression())
+				else :
+					self.writer.addAssignment(GLC.SelfProperty(attribute.name), attribute.init_value)
+
+		self.writer.addVSpace()
+		self.writer.addComment("Call user defined constructor")
+		self.writer.beginSuperClassMethodCall(constructor.parent_class.name, "user_defined_constructor")
+		for p in constructor.getParams():
+			# we can't do p.accept(self) here because 'p' is a FormalParameter
+			# and we want to write it as an actual parameter
+			self.writer.addActualParameter(p.getIdent())
+		self.writer.endSuperClassMethodCall()
+		self.writer.endMethodBody()
+		self.writer.endConstructor()
+
+	def visit_Destructor(self, destructor):
+		self.writer.beginMethod("user_defined_destructor")
+		self.writer.beginMethodBody()
+		if destructor.body.strip():
+			self.writer.addRawCode(destructor.body)
+		if destructor.parent_class.super_classes:
+			self.writer.addComment("Call super class destructors")
+			for super_class in destructor.parent_class.super_classes:
+				# begin call
+				if super_class in destructor.parent_class.super_class_objs:
+					self.writer.beginSuperClassMethodCall(super_class, "user_defined_destructor")
+					self.writer.endSuperClassMethodCall()
+				else:
+					self.writer.beginSuperClassDestructorCall(super_class)
+					self.writer.endSuperClassDestructorCall()
+					pass
+
+				#self.writer.beginSuperClassMethodCall(super_class, "user_defined_destructor")
+				#self.writer.endSuperClassMethodCall()
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+		
+	def visit_Method(self, method):
+		self.writer.addVSpace()
+		self.writer.beginMethod(method.name, "User defined method")
+		for p in method.parameters:
+			p.accept(self)
+		self.writer.beginMethodBody()
+		self.writer.addRawCode(method.body)
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+		
+	def visit_Association(self, association):
+		self.writer.addAssignment(
+			GLC.MapIndexedExpression(
+				GLC.Property("instance", "associations"),
+				GLC.String(association.name)),
+			GLC.NewExpression("Association", [GLC.String(association.to_class), str(association.min), str(association.max)]))
+
+	#helper method
+	def writeTransitionsRecursively(self, current_node):
+		valid_children = []
+		for child in current_node.children :
+			if child.is_composite or child.is_basic :
+				valid_children.append(child)
+
+		has_candidates_children = (len(valid_children) > 0)
+		has_candidates_current = (len(current_node.transitions) > 0)
+
+		if has_candidates_children:
+			self.writer.beginMethod("generateCandidatesChildren_" + current_node.full_name)
+			self.writer.beginMethodBody()
+			if current_node.is_parallel_state:
+				self.writer.addAssignment(
+					GLC.LocalVariableDeclaration("branch_done"),
+					GLC.FalseExpression())
+				for child in valid_children :
+					self.writer.addAssignment(
+						"branch_done",
+						GLC.OrExpression(
+							GLC.FunctionCall(GLC.SelfProperty("generateCandidates_" + child.full_name)),
+							"branch_done"))
+				self.writer.add(GLC.ReturnStatement("branch_done"))
+			elif current_node.is_composite:
+				for i, child in enumerate(valid_children) :
+					self.writer.beginElseIf(GLC.EqualsExpression(
+						GLC.ArrayIndexedExpression(
+							GLC.MapIndexedExpression(
+								GLC.SelfProperty("current_state"),
+								GLC.SelfProperty(current_node.full_name)),
+							"0"),
+						GLC.SelfProperty(child.full_name)))
+					self.writer.add(GLC.ReturnStatement(GLC.FunctionCall(GLC.SelfProperty("generateCandidates_"+child.full_name))))
+					self.writer.endElseIf()
+				self.writer.add(GLC.ReturnStatement(GLC.FalseExpression()))
+			self.writer.endMethodBody()
+			self.writer.endMethod()
+
+		if has_candidates_current:
+			self.writer.beginMethod("generateCandidatesCurrent_" + current_node.full_name)
+			self.writer.beginMethodBody()
+			self.writeFromTransitions(current_node)
+			self.writer.add(GLC.ReturnStatement(GLC.FalseExpression()))
+			self.writer.endMethodBody()
+			self.writer.endMethod()
+
+		self.writer.beginMethod("generateCandidates_" + current_node.full_name)
+		self.writer.beginMethodBody()
+
+		if not has_candidates_children and not has_candidates_current:
+			self.writer.add(GLC.ReturnStatement(GLC.FalseExpression()))
+		else:
+			self.writer.beginIf(
+				GLC.NotExpression(GLC.FunctionCall(
+					GLC.Property(GLC.SelfProperty("combo_step"), "isArenaChanged"),
+					[GLC.SelfProperty(current_node.full_name)])))
+
+			if has_candidates_children and has_candidates_current:
+				self.writer.addAssignment(
+					GLC.LocalVariableDeclaration("branch_done"),
+					GLC.FalseExpression())
+
+			if not has_candidates_children and has_candidates_current:
+				self.writer.add(GLC.ReturnStatement(GLC.FunctionCall(GLC.SelfProperty("generateCandidatesCurrent_" + current_node.full_name))))
+			elif not has_candidates_current and has_candidates_children:
+				self.writer.add(GLC.ReturnStatement(GLC.FunctionCall(GLC.SelfProperty("generateCandidatesChildren_" + current_node.full_name))))
+			else:
+				self.writer.beginElseIf(GLC.EqualsExpression(
+					GLC.Property(GLC.SelfProperty("semantics"), "priority"),
+					GLC.Property("StatechartSemantics", "SourceParent")))
+				if has_candidates_current:
+					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesCurrent_" + current_node.full_name)))
+				if has_candidates_children:
+					self.writer.beginIf(GLC.NotExpression("branch_done"))
+					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesChildren_" + current_node.full_name)))
+					self.writer.endIf()
+				self.writer.endElseIf()
+				self.writer.beginElseIf(GLC.EqualsExpression(
+					GLC.Property(GLC.SelfProperty("semantics"), "priority"),
+					GLC.Property("StatechartSemantics", "SourceChild")))
+				if has_candidates_children:
+					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesChildren_" + current_node.full_name)))
+				if has_candidates_current:
+					self.writer.beginIf(GLC.NotExpression("branch_done"))
+					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesCurrent_" + current_node.full_name)))
+					self.writer.endIf()
+				self.writer.endElseIf()
+
+			if has_candidates_children and has_candidates_current:
+				self.writer.add(GLC.ReturnStatement("branch_done"))
+			self.writer.endIf()
+			self.writer.beginElse()
+			self.writer.add(GLC.ReturnStatement(GLC.TrueExpression()))
+			self.writer.endElse()
+
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+
+		for index, transition in enumerate(current_node.transitions, start=1):
+			self.writeTransitionAction(transition, index)
+		
+		for child in valid_children :
+			self.writeTransitionsRecursively(child)
+				
+	#helper method
+	def writeFromTransitions(self, current_node): 
+		# get all transition out of this state
+		out_transitions = current_node.transitions
+		if len(out_transitions) == 0 :
+			return
+		
+		for index, transition in enumerate(out_transitions, start=1):
+			self.writeTransitionCondition(transition, index)
+		
+	def visit_FormalEventParameter(self, formal_event_parameter):
+		self.writer.add(formal_event_parameter.name)
+		
+	def writeFormalEventParameters(self, transition):
+		parameters = transition.getTrigger().getParameters()
+		if(len(parameters) > 0) :
+			for index, parameter in enumerate(parameters):
+				self.writer.startRecordingExpression()
+				parameter.accept(self)
+				parameter_expr = self.writer.stopRecordingExpression()
+				self.writer.addAssignment(
+					GLC.LocalVariableDeclaration(parameter_expr),
+					GLC.ArrayIndexedExpression("parameters", str(index)))
+		
+		
+	def writeTransitionAction(self, transition, index):
+		self.writer.beginMethod("transition_" + transition.parent_node.full_name + "_" + str(index))
+		self.writer.addFormalParameter("parameters")
+		self.writer.beginMethodBody()
+
+		# handle parameters to actually use them
+		self.writeFormalEventParameters(transition)
+		
+		exits = transition.getExitNodes()
+		
+		# write exit actions
+		if not exits[-1].is_basic:
+			self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+exits[-1].full_name)))
+		else:
+			for node in exits:
+				if node.is_basic:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+node.full_name)))
+					
+		# write trigger actions
+		transition.getAction().accept(self)
+
+		# add arena of transition to list of 'changed' states,
+		# this may prevent other transitions whose arenas overlap to be taken
+		self.writer.add(
+			GLC.FunctionCall(
+				GLC.Property(GLC.SelfProperty("combo_step"), "setArenaChanged"),
+				[GLC.SelfProperty(transition.arena.full_name)]))
+
+		# write enter actions
+		for (entering_node, is_ending_node) in transition.getEnterNodes() : 
+			if is_ending_node :
+				if entering_node.is_composite:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_" + entering_node.full_name)))
+				elif entering_node.is_history:
+					if (entering_node.is_history_deep) :
+						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistoryDeep_" + entering_node.parent.full_name)))
+					else :
+						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistoryShallow_" + entering_node.parent.full_name)))
+				else:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_" + entering_node.full_name)))
+			else :
+				if entering_node.is_composite:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_" + entering_node.full_name)))
+
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+						
+	def writeTransitionCondition(self, transition, index):
+		trigger = transition.getTrigger()
+
+		self.writer.addAssignment(
+			GLC.LocalVariableDeclaration("enabled_events"),
+			GLC.FunctionCall(GLC.SelfProperty("getEnabledEvents")))
+
+		if not trigger.isUC():
+			self.writer.beginForLoopIterateArray("enabled_events", "e")
+			condition = GLC.EqualsExpression(
+				GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "name"),
+					GLC.String(trigger.getEvent()))
+			if trigger.getPort() != "":
+				condition = GLC.AndExpression(
+					condition,
+					GLC.EqualsExpression(
+						GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "port"),
+						GLC.String(trigger.getPort())))
+			self.writer.beginIf(condition)
+		# evaluate guard
+		if transition.hasGuard() :
+			# handle parameters for guard evaluation
+			if not transition.getTrigger().isUC():
+				self.writer.addAssignment(GLC.LocalVariableDeclaration("parameters"), GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "parameters"))
+				self.writeFormalEventParameters(transition)
+			self.writer.startRecordingExpression()
+			transition.getGuard().accept(self) # --> visit_Expression
+			expr = self.writer.stopRecordingExpression()
+			self.writer.beginIf(expr)
+
+		if trigger.isUC():
+			params_expr = GLC.ArrayExpression()
+		else:
+			params_expr = GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "parameters")
+		self.writer.add(GLC.FunctionCall(GLC.Property(GLC.SelfProperty("small_step"), "addCandidate"), [GLC.SelfProperty("transition_" + transition.parent_node.full_name + "_" + str(index)), params_expr]))
+
+		self.writer.add(GLC.ReturnStatement(GLC.TrueExpression()))
+
+		if transition.hasGuard() :
+			self.writer.endIf()
+		if not trigger.isUC() :
+			self.writer.endIf()
+			self.writer.endForLoopIterateArray()
+	
+	def visit_EnterAction(self, enter_method):
+		parent_node = enter_method.parent_node
+		self.writer.beginMethod("enter_" + parent_node.full_name)
+		self.writer.beginMethodBody()
+
+		# take care of any AFTER events
+		for transition in parent_node.transitions :
+			trigger = transition.getTrigger()
+			if trigger.isAfter() :
+				self.writer.startRecordingExpression()
+				trigger.after.accept(self)
+				after = self.writer.stopRecordingExpression()
+				
+				self.writer.addAssignment(
+					GLC.MapIndexedExpression(GLC.SelfProperty("timers"), str(trigger.getAfterIndex())),
+					after)
+
+		if enter_method.action:
+			enter_method.action.accept(self)
+		self.writer.add(
+			GLC.ArrayPushBack(
+					GLC.MapIndexedExpression(
+						GLC.SelfProperty("current_state"),
+						GLC.SelfProperty(parent_node.parent.full_name)),
+					GLC.SelfProperty(parent_node.full_name)))
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+		
+	#helper method
+	def writeEnterDefault(self, entered_node):
+		self.writer.beginMethod("enterDefault_" + entered_node.full_name)
+		self.writer.beginMethodBody()
+		self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+entered_node.full_name)))
+		if entered_node.is_composite:
+			l = entered_node.defaults
+			for i in l:
+				if i.is_composite:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_" + i.full_name)))
+				elif i.is_basic:
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_" + i.full_name)))
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+		 
+	def visit_ExitAction(self, exit_method):
+		exited_node = exit_method.parent_node
+		self.writer.beginMethod("exit_" + exited_node.full_name)
+		self.writer.beginMethodBody()
+
+		#If the exited node is composite take care of potential history and the leaving of descendants
+		if exited_node.is_composite :
+			#handle history
+			if exited_node.save_state_on_exit :
+				self.writer.addAssignment(
+					GLC.MapIndexedExpression(
+						GLC.SelfProperty("history_state"),
+						GLC.SelfProperty(exited_node.full_name)),
+					GLC.MapIndexedExpression(
+						GLC.SelfProperty("current_state"),
+						GLC.SelfProperty(exited_node.full_name)))
+			
+			#Take care of leaving children
+			children = exited_node.children
+			if exited_node.is_parallel_state:
+				for child in children:
+					if not child.is_history :
+						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+child.full_name)))
+			else:
+				for child in children:
+					if not child.is_history :
+						self.writer.beginIf(GLC.ArrayContains(
+								GLC.MapIndexedExpression(
+									GLC.SelfProperty("current_state"),
+									GLC.SelfProperty(exited_node.full_name)),
+								GLC.SelfProperty(child.full_name)))
+						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+child.full_name)))
+						self.writer.endIf()
+		
+		# take care of any AFTER events
+		for transition in exited_node.transitions :
+			trigger = transition.getTrigger()
+			if trigger.isAfter() :
+				self.writer.add(GLC.MapRemoveElement(
+					GLC.SelfProperty("timers"),
+					str(trigger.getAfterIndex())))
+				
+		#Execute user-defined exit action if present
+		if exit_method.action:
+			exit_method.action.accept(self)
+			
+		#Adjust state
+		self.writer.addAssignment(
+			GLC.MapIndexedExpression(
+				GLC.SelfProperty("current_state"),
+				GLC.SelfProperty(exited_node.parent.full_name)),
+			GLC.ArrayExpression()) # SPECIAL CASE FOR ORTHOGONAL??
+		
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+		
+			
+	#helper method
+	def writeEnterHistory(self, entered_node, is_deep):
+		self.writer.beginMethod("enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + entered_node.full_name)
+		self.writer.beginMethodBody()
+
+		self.writer.beginIf(GLC.EqualsExpression(
+			GLC.ArrayLength(
+				GLC.MapIndexedExpression(
+					GLC.SelfProperty("history_state"),
+					GLC.SelfProperty(entered_node.full_name))),
+			"0"))
+		"""self.writer.beginIfBlock(GLC.EqualsExpression(
+			GLC.ArrayLength(
+				GLC.MapIndexedExpression(
+					GLC.SelfProperty("history_state"),
+					GLC.SelfProperty(entered_node.full_name))),
+			"0"))"""
+		defaults = entered_node.defaults
+
+		for node in defaults:
+			if node.is_basic :
+				self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+node.full_name)))
+			elif node.is_composite :
+				self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_"+node.full_name)))
+
+		self.writer.endIf()
+		self.writer.beginElse()
+		children = entered_node.children
+		if entered_node.is_parallel_state:
+			for child in children:
+				if not child.is_history :
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+child.full_name)))
+					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistory"+("Deep" if is_deep else "Shallow")+"_"+child.full_name)))
+		else:
+			for child in children:
+				if not child.is_history :
+					self.writer.beginIf(GLC.ArrayContains(
+						GLC.MapIndexedExpression(
+							GLC.SelfProperty("history_state"),
+							GLC.SelfProperty(entered_node.full_name)),
+						GLC.SelfProperty(child.full_name)))
+					if child.is_composite:
+						if is_deep :
+							self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+child.full_name)))
+							self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistoryDeep_"+child.full_name)))
+						else :
+							self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_"+child.full_name)))
+					else:
+						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+child.full_name)))
+					self.writer.endIf()
+		self.writer.endElse()
+
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+
+	def visit_StateChart(self, statechart):
+
+		# assign each node a unique ID
+		self.writer.addVSpace()
+		self.writer.addComment("Unique IDs for all statechart nodes")
+		for (i,node) in enumerate(statechart.composites + statechart.basics):
+			self.writer.addStaticAttribute(node.full_name, str(i))
+
+
+
+		self.writer.addVSpace()
+		self.writer.addComment("Statechart enter/exit action method(s)")
+		
+		#visit enter and exit action of children
+		for i in statechart.composites + statechart.basics:
+			if i is not statechart.root :
+				i.enter_action.accept(self)
+				i.exit_action.accept(self)
+
+		# write out statecharts methods for enter/exit state
+		if len(statechart.composites) > 1 :
+			self.writer.addVSpace()
+			self.writer.addComment("Statechart enter/exit default method(s)")
+			for i in statechart.composites :
+				if i is not statechart.root :
+					self.writeEnterDefault(i)
+
+		# write out statecharts methods for enter/exit history
+		if statechart.histories:
+			self.writer.addVSpace()
+			self.writer.addComment("Statechart enter/exit history method(s)")
+			for i in statechart.shallow_history_parents:
+				self.writeEnterHistory(i, False)
+			for i in statechart.deep_history_parents:
+				self.writeEnterHistory(i, True) 
+
+		self.writer.addVSpace()
+		self.writer.addComment("Statechart transitions")
+		self.writeTransitionsRecursively(statechart.root)			
+				
+		# write out transition function
+		self.writer.beginMethod("generateCandidates", "Generate transition candidates for current small step")
+		self.writer.beginMethodBody()
+		self.writer.add(GLC.FunctionCall(
+				GLC.SelfProperty("generateCandidates_"+statechart.root.full_name)))
+		self.writer.endMethodBody()
+		self.writer.endMethod()
+
+	def visit_SelfReference(self, self_reference):
+		self.writer.add(GLC.SelfExpression())
+
+	def visit_StateReference(self, state_ref):
+		self.writer.beginArray()
+		for node in state_ref.getNodes():
+			self.writer.add(GLC.SelfProperty(node.full_name))
+		self.writer.endArray()
+
+	def visit_InStateCall(self, in_state_call):
+		self.writer.beginFunctionCall(GLC.SelfProperty("inState"))
+		self.writer.startRecordingExpression()
+		in_state_call.target.accept(self)
+		expr = self.writer.stopRecordingExpression()
+		self.writer.addActualParameter(expr)
+		self.writer.endFunctionCall()
+
+	def visit_Expression(self, expression):
+		self.writer.startRecordingExpression()
+		self.writer.beginGlue()
+		for part in expression.expression_parts:
+			part.accept(self)
+		self.writer.endGlue()
+		expr = self.writer.stopRecordingExpression()
+		self.writer.add(expr)
+
+	def visit_ExpressionPartString(self, e):
+		self.writer.add(e.string)
+		
+	def visit_RaiseEvent(self, raise_event):
+		self.writer.startRecordingExpression()
+		self.writer.begin(GLC.NewExpression("Event"))
+
+		self.writer.addActualParameter(GLC.String(raise_event.getEventName()))
+		if raise_event.isOutput():
+			self.writer.addActualParameter(GLC.String(raise_event.getPort()))
+		else:
+			self.writer.addActualParameter(GLC.NoneExpression())
+
+		self.writer.end()
+		new_event_expr = self.writer.stopRecordingExpression()
+
+		self.writer.startRecordingExpression()
+		self.writer.beginArray()
+		if raise_event.isCD():
+			self.writer.add(GLC.SelfExpression())
+		for param in raise_event.getParameters() :
+			param.accept(self) # -> visit_Expression will cause expressions to be added to array
+		self.writer.endArray()
+		parameters_array_expr = self.writer.stopRecordingExpression()
+		new_event_expr.getActualParameters().add(parameters_array_expr)
+
+		if raise_event.isNarrow():
+			self.writer.add(GLC.FunctionCall(
+				GLC.Property(GLC.SelfProperty("big_step"), "outputEventOM"), [
+					GLC.NewExpression("Event", [
+						GLC.String("narrow_cast"),
+						GLC.NoneExpression(),
+						GLC.ArrayExpression([
+							GLC.SelfExpression(),
+							raise_event.getTarget(),
+							new_event_expr])])]))
+		elif raise_event.isLocal():
+			self.writer.add(GLC.FunctionCall(
+				GLC.SelfProperty("raiseInternalEvent"),
+				[new_event_expr]))
+		elif raise_event.isOutput():
+			self.writer.add(GLC.FunctionCall(
+				GLC.Property(GLC.SelfProperty("big_step"), "outputEvent"),
+				[new_event_expr]))
+		elif raise_event.isCD():
+			self.writer.add(GLC.FunctionCall(
+				GLC.Property(GLC.SelfProperty("big_step"), "outputEventOM"),
+				[new_event_expr]))
+		elif raise_event.isBroad():
+			self.writer.add(GLC.FunctionCall(
+				GLC.Property(GLC.SelfProperty("big_step"), "outputEventOM"),
+				[GLC.NewExpression("Event", [
+					GLC.String("broad_cast"),
+					GLC.NoneExpression(),
+					GLC.ArrayExpression([
+						new_event_expr])])]))
+			
+	def visit_Script(self, script):
+		self.writer.addRawCode(script.code)
+		
+	def visit_Log(self, log):
+		self.writer.add(GLC.LogStatement(log.message))
+		
+	def visit_Assign(self, assign):
+		self.writer.startRecordingExpression()
+		assign.lvalue.accept(self) # --> visit_Expression
+		lvalue = self.writer.stopRecordingExpression()
+		self.writer.startRecordingExpression()
+		assign.expression.accept(self) # --> visit_Expression
+		rvalue = self.writer.stopRecordingExpression()
+		self.writer.addAssignment(lvalue, rvalue)
+

+ 990 - 0
exported_to_sccdxml/python_sccd_compiler/generic_language_constructs.py

@@ -0,0 +1,990 @@
+import abc
+from visitor import Visitor, Visitable
+
+
+class GenericConstruct(Visitable):
+	__metaclass__ = abc.ABCMeta
+
+
+# base class for constructs that are a collection of other constructs
+class AbstractList:
+	__metaclass__ = abc.ABCMeta
+
+	@abc.abstractmethod
+	def add(self, generic_construct):
+		pass
+
+
+class BlockEntry(GenericConstruct):
+	__metaclass__ = abc.ABCMeta
+
+	@abc.abstractmethod
+	def isEmpty(self):
+		pass
+
+
+class DeclarationBase:
+	def __init__(self, identifier, description = None):
+		self.identifier = identifier
+		self.description = description # string describing declared artifact
+
+	def getIdentifier(self):
+		return self.identifier
+
+	def getDescription(self):
+		return self.description
+
+
+class Statement(BlockEntry):
+	pass
+
+
+class Package(Statement, AbstractList, DeclarationBase):
+	def __init__(self, identifier, description = None):
+		DeclarationBase.__init__(self, identifier, description)
+		self.declarations = []
+
+	def add(self, item):
+		self.declarations.append(MakeDeclaration(item))
+
+	def getDeclarations(self):
+		return self.declarations
+
+	def isEmpty(self):
+		return False
+
+
+class FormalParameters(GenericConstruct, AbstractList):
+	def __init__(self, parameter_list = None):
+		if parameter_list is None: parameter_list = []
+		self.parameter_list = parameter_list
+
+	def add(self, parameter):
+		self.parameter_list.append(parameter)
+
+	def getParameterList(self):
+		return self.parameter_list
+
+class AST(GenericConstruct, AbstractList):
+	def __init__(self):
+		self.entries = []
+
+	def add(self, entry):
+		self.entries.append(MakeBlockEntry(entry))
+
+	def getEntries(self):
+		return self.entries
+
+
+class Block(AST):
+	def __init__(self):
+		AST.__init__(self)
+
+	def isEmpty(self):
+		for e in self.getEntries():
+			if not e.isEmpty():
+				return False
+		return True
+
+
+class ForLoopBody(Block):
+	def __init__(self, for_loop):
+		Block.__init__(self)
+		self.for_loop = for_loop
+
+	def getForLoop(self):
+		return self.for_loop
+
+
+class MethodBody(Block):
+	def __init__(self, method):
+		Block.__init__(self)
+		self.method = method
+
+	def getMethod(self):
+		return self.method
+
+
+#class ConstructorBody(MethodBody):
+#	def __init__(self, method):
+#		MethodBody.__init__(self, method)
+
+#class DestructorBody(MethodBody):
+#	def __init__(self, method):
+#		MethodBody.__init__(self, method)
+
+
+class ClassMember(GenericConstruct, DeclarationBase):
+	def __init__(self, c, identifier, description = None):
+		DeclarationBase.__init__(self, identifier, description)
+		self.c = c # Class
+
+	def getClass(self):
+		return self.c
+
+
+class MethodBase(ClassMember):
+	def __init__(self, c, identifier, description = None):
+		ClassMember.__init__(self, c, identifier, description)
+		self.formal_parameters = FormalParameters()
+		self.body = MethodBody(self)
+
+	def getBody(self):
+		return self.body
+
+	def getFormalParameters(self):
+		return self.formal_parameters
+
+
+class Method(MethodBase):
+	def __init__(self, c, identifier, description = None):
+		MethodBase.__init__(self, c, identifier, description)
+
+
+class Constructor(MethodBase):
+	def __init__(self, c, description = None):
+		MethodBase.__init__(self, c, None, description)
+
+
+class Destructor(MethodBase):
+	def __init__(self, c, description = None):
+		MethodBase.__init__(self, c, None, description)
+
+
+class Class(GenericConstruct, AbstractList, DeclarationBase):
+	def __init__(self, identifier, super_class_identifier_list = None, description = None):
+		DeclarationBase.__init__(self, identifier, description)
+		self.super_class_identifier_list = super_class_identifier_list # string
+		self.constructor = Constructor(self)
+		self.destructor = Destructor(self)
+		self.members = []
+
+	def getSuperClassIdentifierList(self):
+		return self.super_class_identifier_list
+
+	def getConstructor(self):
+		return self.constructor
+
+	def getDestructor(self):
+		return self.destructor
+
+	def add(self, class_member):
+		self.members.append(class_member)
+
+	def getMembers(self):
+		return self.members
+
+
+class AttributeBase(ClassMember):
+	def __init__(self, c, identifier, init_value = None):
+		ClassMember.__init__(self, c, identifier)
+		self.init_value = MakeExpression(init_value)
+
+	def getInitValue(self):
+		return self.init_value
+
+
+class Attribute(AttributeBase):
+	def __init__(self, c, identifier, init_value = None):
+		AttributeBase.__init__(self, c, identifier, init_value)
+
+
+class StaticAttribute(AttributeBase):
+	def __init__(self, c, name, init_value = None):
+		AttributeBase.__init__(self, c, name, init_value)
+
+
+class FormalParameter(GenericConstruct, DeclarationBase):
+	def __init__(self, identifier, default_value = None, description = None):
+		DeclarationBase.__init__(self, identifier, description)
+		#self.identifier = identifier
+		self.default_value = MakeExpression(default_value)
+
+	def getDefaultValue(self):
+		return self.default_value
+
+
+class IncludeStatement(Statement):
+	def __init__(self, module_path, imported_symbols = None):
+		if imported_symbols is None: imported_symbols = []
+		self.module_path = MakeExpressionList(module_path) # list of modules
+		self.imported_symbols = imported_symbols
+
+	def getModulePath(self):
+		return self.module_path
+
+	def getImportedSymbols(self):
+		return self.imported_symbols
+
+	def isEmpty(self):
+		return False
+
+
+class ReturnStatement(Statement):
+	def __init__(self, expr):
+		self.expr = MakeExpression(expr)
+
+	def getExpression(self):
+		return self.expr
+
+	def isEmpty(self):
+		return False
+
+class BreakStatement(Statement):
+	def isEmpty(self):
+		return False	
+
+class ThrowExceptionStatement(Statement):
+	def __init__(self, expr):
+		self.expr = MakeExpression(expr)
+
+	def getExpression(self):
+		return self.expr
+
+	def isEmpty(self):
+		return False
+
+
+class VSpace(BlockEntry):
+	def isEmpty(self):
+		return True
+
+
+class CommentBase(BlockEntry):
+	def __init__(self, text):
+		self.text = text
+
+	def isEmpty(self):
+		return True
+
+	def getText(self):
+		return self.text
+
+
+class SingleLineComment(CommentBase):
+	def __init__(self, text):
+		CommentBase.__init__(self,text)
+
+
+class MultiLineComment(CommentBase):
+	def __init__(self, text):
+		CommentBase.__init__(self,text)
+
+
+class ConditionalStatementBase(Statement, AbstractList):
+	def __init__(self, body = None):
+		if body is None: body = Block()
+		self.body = body
+
+	def add(self, stmt):
+		self.body.add(stmt)
+
+	def getBody(self):
+		return self.body
+
+	def isEmpty(self):
+		return False
+
+
+class IfStatement(ConditionalStatementBase):
+	def __init__(self, condition):
+		ConditionalStatementBase.__init__(self)
+		self.condition = MakeExpression(condition)
+
+	def getCondition(self):
+		return self.condition
+
+
+class ElseStatement(ConditionalStatementBase):
+	def __init__(self):
+		ConditionalStatementBase.__init__(self)
+
+
+class ElseIfStatement(IfStatement):
+	def __init__(self, condition, is_first = False):
+		IfStatement.__init__(self, condition)
+		self.is_first = is_first
+
+	# in a series of ElseIfStatements, the first ElseIfStatement will be a normal if statement
+	def isFirst(self):
+		return self.is_first
+
+
+class ForLoopIterateBase(ConditionalStatementBase):
+	def __init__(self, collection_expr, iterator_identifier):
+		ConditionalStatementBase.__init__(self, ForLoopBody(self))
+		self.collection_expr = MakeExpression(collection_expr)
+		self.iterator_identifier = iterator_identifier
+
+	def getCollectionExpression(self):
+		return self.collection_expr
+
+	def getIteratorIdentifier(self):
+		return self.iterator_identifier
+
+
+class ForLoopIterateArray(ForLoopIterateBase):
+	def __init__(self, array_expr, iterator_identifier):
+		ForLoopIterateBase.__init__(self, array_expr, iterator_identifier)
+
+
+class ForLoopIterateMapValues(ForLoopIterateBase):
+	def __init__(self, map_expr, iterator_identifier):
+		ForLoopIterateBase.__init__(self, map_expr, iterator_identifier)
+
+
+class ExpressionStatement(Statement):
+	def __init__(self, expression):
+		self.expression = expression
+
+	def getExpression(self):
+		return self.expression
+
+	def isEmpty(self):
+		return False
+
+
+# block of raw code
+class RawCode(BlockEntry):
+	def __init__(self, text):
+		self.text = text
+
+	def getText(self):
+		return self.text
+
+	def isEmpty(self):
+		return (len(self.text.strip()) == 0)
+
+
+# log message to console
+class LogStatement(Statement):
+	def __init__(self, msg):
+		self.msg = msg
+
+	def getMessage(self):
+		return self.msg
+
+	def isEmpty(self):
+		return False
+
+
+class Expression(GenericConstruct):
+	__metaclass__ = abc.ABCMeta
+
+	@abc.abstractmethod
+	def isCompound(self):
+		pass
+
+class SimpleExpression(Expression):
+	def isCompound(self):
+		return False
+
+class CompoundExpression(Expression):
+	def isCompound(self):
+		return True
+
+class RuntimeModuleIdentifier(SimpleExpression):
+	pass
+
+# Not a real language construct, simply 'glues' expressions together.
+class Glue(SimpleExpression, AbstractList):
+	def __init__(self):
+		self.expression_list = []
+
+	def add(self, expr):
+		self.expression_list.append(MakeExpression(expr))
+
+	def getExpressionList(self):
+		return self.expression_list
+
+
+class ForLoopCurrentElement(SimpleExpression):
+	def __init__(self, collection_expr, iterator_identifier):
+		self.collection_expr = MakeExpression(collection_expr)
+		self.iterator_identifier = iterator_identifier
+
+	def getCollectionExpression(self):
+		return self.collection_expr
+
+	def getIteratorIdentifier(self):
+		return self.iterator_identifier
+
+
+class Literal(SimpleExpression):
+	def __init__(self, text):
+		self.text = text
+
+	def getText(self):
+		return self.text
+
+
+class String(Literal):
+	def __init__(self, text):
+		Literal.__init__(self, text)
+
+
+class Property(SimpleExpression):
+	def __init__(self, owner, prop):
+		self.owner = MakeExpression(owner)
+		self.prop = prop
+
+	def getOwnerExpression(self):
+		return self.owner
+
+	def getProperty(self):
+		return self.prop
+
+
+class MapIndexedExpression(SimpleExpression):
+	def __init__(self, map_expr, key_expr):
+		self.map_expr = MakeExpression(map_expr)
+		self.key_expr = MakeExpression(key_expr)
+
+	def getMapExpression(self):
+		return self.map_expr
+
+	def getKeyExpression(self):
+		return self.key_expr
+
+
+class ArrayIndexedExpression(SimpleExpression):
+	def __init__(self, array_expr, index_expr):
+		self.array_expr = MakeExpression(array_expr)
+		self.index_expr = MakeExpression(index_expr)
+
+	def getArrayExpression(self):
+		return self.array_expr
+
+	def getIndexExpression(self):
+		return self.index_expr
+
+
+class ActualParameters(GenericConstruct, AbstractList):
+	def __init__(self, parameter_list = None):
+		if parameter_list is None: parameter_list = []
+		self.parameter_list = MakeExpressionList(parameter_list)
+
+	def add(self, p):
+		self.parameter_list.append(MakeExpression(p))
+		pass
+
+	def getParameterList(self):
+		return self.parameter_list
+
+
+class FunctionCallBase(SimpleExpression):
+	def __init__(self, actual_parameters = None):
+		if actual_parameters is None: actual_parameters = ActualParameters()
+		self.actual_parameters = MakeActualParameters(actual_parameters)
+
+	def getActualParameters(self):
+		return self.actual_parameters
+	
+
+
+class FunctionCall(FunctionCallBase):
+	def __init__(self, function_expr, actual_parameters = None):
+		FunctionCallBase.__init__(self, actual_parameters)
+		self.function_expr = MakeExpression(function_expr)
+
+	def getFunctionExpression(self):
+		return self.function_expr
+
+
+class SuperClassCallBase(FunctionCallBase):
+	def __init__(self, super_class_identifier, actual_parameters = None):
+		FunctionCallBase.__init__(self, actual_parameters)
+		self.super_class_identifier = super_class_identifier
+
+	def getSuperClassIdentifier(self):
+		return self.super_class_identifier
+
+
+class SuperClassConstructorCall(SuperClassCallBase):
+	def __init__(self, super_class_identifier, actual_parameters = None):
+		SuperClassCallBase.__init__(self, super_class_identifier, actual_parameters)
+
+
+class SuperClassDestructorCall(SuperClassCallBase):
+	def __init__(self, super_class_identifier):
+		SuperClassCallBase.__init__(self, super_class_identifier)
+
+
+class SuperClassMethodCall(SuperClassCallBase):
+	def __init__(self, super_class_identifier, method_identifier, actual_parameters = None):
+		SuperClassCallBase.__init__(self, super_class_identifier, actual_parameters)
+		self.method_identifier = method_identifier
+
+	def getMethodIdentifier(self):
+		return self.method_identifier
+
+
+class NewExpression(FunctionCallBase):
+	def __init__(self, type_expr, actual_parameters = None):
+		FunctionCallBase.__init__(self, actual_parameters)
+		self.type_expr = MakeExpression(type_expr)
+
+	def getTypeExpression(self):
+		return self.type_expr
+
+
+class SelfExpression(SimpleExpression):
+	pass
+
+
+class SelfProperty(Property):
+	def __init__(self, prop):
+		Property.__init__(self, SelfExpression(), prop)
+
+
+class Operator(GenericConstruct):
+	pass
+
+
+class AndOperator(Operator):
+	pass
+
+class OrOperator(Operator):
+	pass
+
+class LessThanOperator(Operator):
+	pass
+
+class GreaterThanOperator(Operator):
+	pass
+
+class NotOperator(Operator):
+	pass
+
+class EqualsOperator(Operator):
+	pass
+
+class AssignmentOperator(Operator):
+	pass
+
+class ProductOperator(Operator):
+	pass
+
+
+class UnaryExpression(CompoundExpression):
+	def __init__(self, operator, expr):
+		self.operator = operator
+		self.expr = MakeExpression(expr)
+
+	def getExpression(self):
+		return self.expr
+
+	def getOperator(self):
+		return self.operator
+
+
+class BinaryExpression(CompoundExpression):
+	def __init__(self, lhs_expr, operator, rhs_expr):
+		self.lhs_expr = MakeExpression(lhs_expr)
+		self.operator = operator
+		self.rhs_expr = MakeExpression(rhs_expr)
+
+	def getLhsExpression(self):
+		return self.lhs_expr
+
+	def getRhsExpression(self):
+		return self.rhs_expr
+
+	def getOperator(self):
+		return self.operator
+
+
+class NotExpression(UnaryExpression):
+	def __init__(self, expr):
+		UnaryExpression.__init__(self, NotOperator(), expr)
+
+class AndExpression(BinaryExpression):
+	def __init__(self, lexpr = None, rexpr = None):
+		BinaryExpression.__init__(self, lexpr, AndOperator(), rexpr)
+
+class OrExpression(BinaryExpression):
+	def __init__(self, lexpr = None, rexpr = None):
+		BinaryExpression.__init__(self, lexpr, OrOperator(), rexpr)
+
+class LessThanExpression(BinaryExpression):
+	def __init__(self, lexpr = None, rexpr = None):
+		BinaryExpression.__init__(self, lexpr, LessThanOperator(), rexpr)
+
+class GreaterThanExpression(BinaryExpression):
+	def __init__(self, lexpr = None, rexpr = None):
+		BinaryExpression.__init__(self, lexpr, GreaterThanOperator(), rexpr)
+
+class EqualsExpression(BinaryExpression):
+	def __init__(self, lexpr = None, rexpr = None):
+		BinaryExpression.__init__(self, lexpr, EqualsOperator(), rexpr)
+
+class AssignmentExpression(BinaryExpression):
+	def __init__(self, lexpr = None, rexpr = None):
+		BinaryExpression.__init__(self, lexpr, AssignmentOperator(), rexpr)
+
+class ProductExpression(BinaryExpression):
+	def __init__(self, lexpr = None, rexpr = None):
+		BinaryExpression.__init__(self, lexpr, ProductOperator(), rexpr)
+
+
+class FalseExpression(SimpleExpression):
+	pass
+
+class TrueExpression(SimpleExpression):
+	pass
+
+
+class LocalVariableDeclaration(Expression, DeclarationBase):
+	def __init__(self, identifier, init_value = None, description = None):
+		DeclarationBase.__init__(self, identifier, description)
+		self.init_value = MakeExpression(init_value)
+
+	def getInitValue(self):
+		self.init_value
+
+	def isCompound(self):
+		return (self.init_value != None)
+
+
+class MapExpression(SimpleExpression):
+	def __init__(self, elements = None):
+		if elements is None: elements = {}
+		self.elements = MakeExpressionMap(elements)
+
+	def getElements(self):
+		return self.elements
+
+class MapRemoveElement(Statement):
+	def __init__(self, map_expr, key_expr):
+		self.map_expr = MakeExpression(map_expr)
+		self.key_expr = MakeExpression(key_expr)
+
+	def getMapExpression(self):
+		return self.map_expr
+
+	def getKeyExpression(self):
+		return self.key_expr
+
+	def isEmpty(self):
+		return False
+
+
+class ArrayExpression(SimpleExpression, AbstractList):
+	def __init__(self, elements = None):
+		if elements is None: elements = []
+		self.elements = MakeExpressionList(elements)
+
+	def add(self, element):
+		self.elements.append(MakeExpression(element))
+
+	def getElements(self):
+		return self.elements
+
+
+class ArrayLength(SimpleExpression):
+	def __init__(self, array_expr):
+		self.array_expr = MakeExpression(array_expr)
+
+	def getArrayExpression(self):
+		return self.array_expr
+
+
+class ArrayElementOperation(Expression):
+	def __init__(self, array_expr, elem_expr):
+		self.array_expr = MakeExpression(array_expr)
+		self.elem_expr = MakeExpression(elem_expr)
+
+	def getArrayExpression(self):
+		return self.array_expr
+
+	def getElementExpression(self):
+		return self.elem_expr
+
+class ArrayIndexOf(ArrayElementOperation, SimpleExpression):
+	def __init__(self, array_expr, elem_expr):
+		ArrayElementOperation.__init__(self, array_expr, elem_expr)
+
+class ArrayContains(ArrayElementOperation, CompoundExpression):
+	def __init__(self, array_expr, elem_expr):
+		ArrayElementOperation.__init__(self, array_expr, elem_expr)
+
+class ArrayPushBack(ArrayElementOperation, SimpleExpression):
+	def __init__(self, array_expr, elem_expr):
+		ArrayElementOperation.__init__(self, array_expr, elem_expr)
+
+
+class NoneExpression(SimpleExpression):
+	pass
+
+
+# helpers
+
+def MakeExpression(expr):
+	if isinstance(expr, Expression):
+		return expr
+	elif isinstance(expr, basestring):
+		return Literal(expr)
+	elif expr is None:
+		return None
+	else:
+		raise Exception("Can't turn argument of type '" + str(type(expr)) + "' into Expression.")
+
+def MakeExpressionList(l):
+	if not isinstance(l, list):
+		raise Exception("Expected argument of type 'list'.")
+	for i in range(len(l)):
+		l[i] = MakeExpression(l[i])
+	return l
+
+def MakeExpressionMap(m):
+	if not isinstance(m, dict):
+		raise Exception("Expected argument of type 'dict'.")
+	for key in m.keys():
+		m[key] = MakeExpression(m[key])
+	return m
+
+def MakeBlockEntry(stmt):
+	if isinstance(stmt, BlockEntry):
+		return stmt
+	elif isinstance(stmt, Expression):
+		return ExpressionStatement(stmt)
+	elif stmt is None:
+		return None
+	else:
+		raise Exception("Can't turn argument of type '" + str(type(stmt)) + "' into BlockEntry.")
+
+def MakeDeclaration(obj):
+	if isinstance(obj, DeclarationBase):
+		return obj
+	else:
+		raise Exception("Can't turn argument of type '" + str(type(stmt)) + "' into DeclarationBase.")
+
+def MakeActualParameters(obj):
+	if isinstance(obj, ActualParameters):
+		return obj
+	elif isinstance (obj, list):
+		return ActualParameters(obj)
+	else:
+		raise Exception("Can't turn argument of type '" + str(type(obj)) + "' into ActualParameters.")
+
+"""def MakeFormalParameter(parameter, default_value):
+	if isinstance(parameter, FormalParameter):
+		return parameter
+	elif default_value:
+		return FormalParameter(parameter, default_value)
+	else:
+		return FormalParameter(parameter)"""
+
+
+class GenericWriterBase(Visitor):
+	__metaclass__ = abc.ABCMeta
+
+	# overrides Visitor.generic_visit
+	def generic_visit(self, node):
+		raise Exception("Writer has no visit method for node of type '" + str(type(node)) + "'.")
+
+	#### HELPERS ####
+
+	def writeAll(self, l):
+		for item in l:
+			item.accept(self)
+
+	def writeTuple(self, obj):
+		self.out.extendWrite("(")
+		self.writeCommaSeparated(obj)
+		self.out.extendWrite(")")
+
+	@abc.abstractmethod
+	def writeComment(self, text):
+		pass
+
+	@abc.abstractmethod
+	def writeMultiLineComment(self, text):
+		pass
+
+	def writeCommaSeparated(self, l):
+		for i in range(len(l)):
+			if i != 0:
+				self.out.extendWrite(", ")
+			l[i].accept(self)
+
+	def writeDescription(self, decl):
+		description = decl.getDescription()
+		if description:
+			self.writeComment(description)
+
+	def writeCompoundExpr(self, expr):
+		if expr.isCompound():
+			self.out.extendWrite("(")
+		expr.accept(self)
+		if expr.isCompound():
+			self.out.extendWrite(")")
+
+	#### VISIT METHODS BASE IMPLEMENTATIONS ####
+
+	def visit_ArrayIndexedExpression(self, i):
+		a = i.getArrayExpression()
+		index = i.getIndexExpression()
+
+		a.accept(self)
+		self.out.extendWrite("[")
+		index.accept(self)
+		self.out.extendWrite("]")
+
+	def visit_ActualParameters(self, p):
+		self.writeTuple(p.getParameterList())
+
+	def visit_AssignmentOperator(self, assign):
+		self.out.extendWrite(" = ")
+
+	def visit_BinaryExpression(self, b):
+		lhs = b.getLhsExpression()
+		rhs = b.getRhsExpression()
+		op = b.getOperator()
+
+		self.writeCompoundExpr(lhs)
+		op.accept(self)
+		self.writeCompoundExpr(rhs)
+
+	def visit_FormalParameters(self, p):
+		self.writeTuple(p.getParameterList())
+
+	def visit_FunctionCall(self, f):
+		func = f.getFunctionExpression()
+		params = f.getActualParameters()
+
+		func.accept(self)
+		params.accept(self)
+
+	def visit_Glue(self, g):
+		self.writeAll(g.getExpressionList())
+
+	def visit_GreaterThanOperator(self, g):
+		self.out.extendWrite(" > ")
+
+	def visit_LessThanOperator(self, l):
+		self.out.extendWrite(" < ")
+
+	def visit_Literal(self, l):
+		self.out.extendWrite(l.getText())
+
+	def visit_MultiLineComment(self, c):
+		self.writeMultiLineComment(c.getText())
+
+	def visit_ProductOperator(self, p):
+		self.out.extendWrite(" * ")
+
+	def visit_Property(self, p):
+		owner = p.getOwnerExpression()
+		prop = p.getProperty()
+
+		owner.accept(self)
+		self.out.extendWrite("." + prop)
+
+	def visit_RawCode(self, c):
+		self.out.writeCodeCorrectIndent(c.getText())
+
+	def visit_SingleLineComment(self, comment):
+		self.writeComment(comment.getText())
+
+	def visit_String(self, string):
+		self.out.extendWrite("\"" + string.getText().replace("\"", "\\\"") + "\"")
+
+	def visit_UnaryExpression(self, u):
+		expr = u.getExpression()
+		op = u.getOperator()
+
+		op.accept(self)
+		self.writeCompoundExpr(expr)
+
+	def visit_VSpace(self, v):
+		self.out.write()
+
+
+class CLikeWriterBase(GenericWriterBase):
+
+	### HELPERS ###
+
+	def writeComment(self, text):
+		self.out.write("// " + text)
+
+	def writeMultiLineComment(self, text):
+		self.out.write("/* " + text + "*/")
+
+	### VISIT METHODS ###
+
+	def visit_AndOperator(self, a):
+		self.out.extendWrite(" && ")
+
+	def visit_Block(self, b):
+		self.out.extendWrite(" {")
+		self.out.indent()
+		self.writeAll(b.getEntries())
+		self.out.dedent()
+		self.out.write("}")
+
+	def visit_BreakStatement(self, b):
+		self.out.write("break;")
+
+	def visit_ElseStatement(self, else_stmt):
+		self.out.extendWrite(" else ")
+		else_stmt.getBody().accept(self)
+
+	def visit_ElseIfStatement(self, else_if):
+		condition = else_if.getCondition()
+		body = else_if.getBody()
+
+		if else_if.isFirst():
+			self.out.write("if (")
+		else:
+			self.out.extendWrite(" else if (")
+		condition.accept(self)
+		self.out.extendWrite(")")
+		body.accept(self)
+
+	def visit_EqualsOperator(self, e):
+		self.out.extendWrite(" == ")
+
+	def visit_ExpressionStatement(self, stmt):
+		self.out.write() # expressions never begin with a newline
+		stmt.getExpression().accept(self)
+		self.out.extendWrite(";")
+
+	def visit_FalseExpression(self, f):
+		self.out.extendWrite("false")
+
+	def visit_IfStatement(self, if_stmt):
+		condition = if_stmt.getCondition()
+		body = if_stmt.getBody()
+
+		self.out.write("if (")
+		condition.accept(self)
+		self.out.extendWrite(")")
+		body.accept(self)
+
+	def visit_NewExpression(self, new):
+		type_expr = new.getTypeExpression()
+		params = new.getActualParameters()
+
+		self.out.extendWrite("new ")
+		type_expr.accept(self)
+		params.accept(self)
+
+	def visit_NotOperator(self, n):
+		self.out.extendWrite("!")
+
+	def visit_OrOperator(self, o):
+		self.out.extendWrite(" || ")
+
+	def visit_ReturnStatement(self, r):
+		self.out.write("return ")
+		r.getExpression().accept(self)
+		self.out.extendWrite(";")
+
+	def visit_SelfExpression(self, s):
+		self.out.extendWrite("this")
+
+	def visit_TrueExpression(self, t):
+		self.out.extendWrite("true")
+
+

+ 285 - 0
exported_to_sccdxml/python_sccd_compiler/javascript_writer.py

@@ -0,0 +1,285 @@
+from visitor import Visitor
+from generic_language_constructs import *
+
+class JavascriptWriter(CLikeWriterBase):
+	def __init__(self, outputter):
+		self.out = outputter
+
+	### VISIT METHODS ###
+
+	def visit_ArrayContains(self, a):
+		array = a.getArrayExpression()
+		el = a.getElementExpression()
+
+		self.out.extendWrite("(")
+		array.accept(self)
+		self.out.extendWrite(".indexOf(")
+		el.accept(self)
+		self.out.extendWrite(") !== -1)")
+
+	def visit_ArrayExpression(self, a):
+		elements = a.getElements()
+		if len(elements) == 0:
+			self.out.extendWrite("new Array()")
+		else:
+			self.out.extendWrite("[")
+			self.writeCommaSeparated(elements)
+			self.out.extendWrite("]")
+
+	def visit_ArrayIndexOf(self, a):
+		array = a.getArrayExpression()
+		el = a.getElementExpression()
+
+		array.accept(self)
+		self.out.extendWrite(".indexOf(")
+		el.accept(self)
+		self.out.extendWrite(")")
+
+	def visit_ArrayLength(self, a):
+		a.getArrayExpression().accept(self)
+		self.out.extendWrite(".length")
+
+	def visit_ArrayPushBack(self, a):
+		array = a.getArrayExpression()
+		el = a.getElementExpression()
+
+		array.accept(self)
+		self.out.extendWrite(".push(")
+		el.accept(self)
+		self.out.extendWrite(")")
+
+	def visit_AST(self, ast):
+		self.writeAll(ast.getEntries())
+
+	def visit_Class(self, c):
+		class_name = c.getIdentifier()
+		constructor = c.getConstructor()
+		super_classes = c.getSuperClassIdentifierList()
+		description = c.getDescription()
+
+		self.out.write()
+		if description:
+			self.writeComment(description)
+		constructor.accept(self)
+		if super_classes:
+			self.out.write(class_name + ".prototype = new Object();")
+			self.out.write("(function() {")
+			self.out.indent()
+			for s in super_classes:
+				# workaround for multiple inheritance
+				self.out.write("var proto = new " + s + "();")
+				self.out.write("for (prop in proto) {")
+				self.out.indent()
+				self.out.write(class_name + ".prototype[prop] = proto[prop];")
+				self.out.dedent()
+				self.out.write("}")
+			self.out.dedent()
+			self.out.write("})();")
+		self.writeAll(c.getMembers())
+
+	def visit_Constructor(self, constructor):
+		class_name = constructor.getClass().getIdentifier()
+		parameters = constructor.getFormalParameters()
+		body = constructor.getBody()
+
+		self.out.write("var " + class_name + " = function")
+		parameters.accept(self)
+		body.accept(self)
+		self.out.extendWrite(";")
+
+	def visit_EqualsOperator(self, e):
+		self.out.extendWrite(" === ")
+
+	def visit_ForLoopBody(self, body):
+		for_loop = body.getForLoop()
+		collection_expr = for_loop.getCollectionExpression()
+		iterator_identifier = for_loop.getIteratorIdentifier()
+
+		self.out.extendWrite(" {")
+		self.out.indent()
+		self.out.write("if (!")
+		collection_expr.accept(self)
+		self.out.extendWrite(".hasOwnProperty(" + iterator_identifier + ")) continue;")
+		self.writeAll(body.getEntries())
+		self.out.dedent()
+		self.out.write("}")
+
+	def visit_ForLoopCurrentElement(self, el):
+		collection = el.getCollectionExpression()
+		iterator = el.getIteratorIdentifier()
+
+		collection.accept(self)
+		self.out.extendWrite("["+iterator+"]")
+
+	def visit_ForLoopIterateArray(self, loop):
+		collection = loop.getCollectionExpression()
+		iterator = loop.getIteratorIdentifier()
+		body = loop.getBody()
+
+		self.out.write("for (var " + iterator + " in ")
+		collection.accept(self)
+		self.out.extendWrite(")")
+		body.accept(self)
+
+	def visit_ForLoopIterateMapValues(self, loop):
+		collection = loop.getCollectionExpression()
+		iterator = loop.getIteratorIdentifier()
+		body = loop.getBody()
+
+		self.out.write("for (var " + iterator + " in ")
+		collection.accept(self)
+		self.out.extendWrite(")")
+		body.accept(self)
+
+	def visit_FormalParameter(self, parameter):
+		self.out.extendWrite(parameter.getIdentifier())
+
+	def visit_IncludeStatement(self, i):
+		pass # javascript doesn't have an include mechanism
+
+	def visit_LocalVariableDeclaration(self, decl):
+		identifier = decl.getIdentifier()
+		init_value = decl.getInitValue()
+
+		self.out.extendWrite("var " + identifier)
+		if init_value:
+			self.out.extendWrite(" = ")
+			init_value.accept(self)
+
+	def visit_LogStatement(self, l):
+		self.out.write("console.log(\"" + l.getMessage() + "\");")
+
+	def visit_MapExpression(self, m):
+		elements = m.getElements()
+		if len(elements) == 0:
+			self.out.extendWrite("new Object()")
+		else:
+			self.out.extendWrite("{")
+			keys = elements.keys()
+			for i in range(len(keys)):
+				if i != 0:
+					self.out.extendWrite(", ")			
+				self.out.extendWrite(keys[i] + " : ")
+				self.out.extendWrite(" : ")
+				elements[keys[i]].accept(self)
+			self.out.extendWrite("}")
+
+	def visit_MapIndexedExpression(self, i):
+		m = i.getMapExpression()
+		key = i.getKeyExpression()
+
+		m.accept(self)
+		self.out.extendWrite("[")
+		key.accept(self)
+		self.out.extendWrite("]")
+
+	def visit_MapRemoveElement(self, stmt):
+		map_expr = stmt.getMapExpression()
+		key_expr = stmt.getKeyExpression()
+
+		self.out.write("delete ") # this is a statement, not an expression
+		map_expr.accept(self)
+		self.out.extendWrite("[")
+		key_expr.accept(self)
+		self.out.extendWrite("];")		
+
+	def visit_Method(self, method):
+		class_name = method.getClass().getIdentifier()
+		method_name = method.getIdentifier()
+		description = method.getDescription()
+		body = method.getBody()
+		parameters = method.getFormalParameters()
+
+		self.out.write()
+		if description:
+			self.writeComment(description)
+		self.writeDescription(method)
+		self.out.write(class_name + ".prototype." + method_name + " = function")
+		parameters.accept(self)
+		body.accept(self)
+		self.out.extendWrite(";")
+
+	def visit_MethodBody(self, body):
+		method = body.getMethod()
+		formal_parameters = method.getFormalParameters()
+		formal_parameter_list = formal_parameters.getParameterList()
+
+		self.out.extendWrite(" {")
+		self.out.indent()
+		# check for undefined parameters and replace them with default values
+		for p in formal_parameter_list:
+			p_id = p.getIdentifier()
+			p_default = p.getDefaultValue()
+			if p_default:
+				self.out.write("if (" + p_id + " === undefined) " + p_id + " = ")
+				p_default.accept(self)
+				self.out.extendWrite(";")
+		self.writeAll(body.getEntries())
+		self.out.dedent()
+		self.out.write("}")
+
+	def visit_NoneExpression(self, n):
+		self.out.extendWrite("null")
+
+	def visit_Package(self, package):
+		name = package.getIdentifier()
+		description = package.getDescription()
+
+		self.writeComment("package \"" + name + "\"")
+		if description:
+			self.writeComment(description)
+		self.out.write("var " + name + " = {};")
+		self.out.write("(function() {")
+		for d in package.getDeclarations():
+			d_id = d.getIdentifier()
+			d.accept(self)
+			self.out.write()
+			self.out.write("// add symbol '" + d_id + "' to package '" + name + "'")
+			self.out.write(name + "." + d_id + " = " + d_id + ";")
+		self.out.write("})();")
+
+	def visit_RuntimeModuleIdentifier(self, r):
+		self.out.extendWrite("javascript_runtime")
+
+	def visit_StaticAttribute(self, attr):
+		name = attr.getIdentifier()
+		init_value = attr.getInitValue()
+		class_name = attr.getClass().getIdentifier()
+
+		if init_value:
+			self.out.write(class_name + ".prototype." + name + " = ")
+			init_value.accept(self)
+			self.out.extendWrite(";")
+		else:
+			self.out.write(class_name + ".prototype." + name + " = null;")
+
+	def visit_SuperClassConstructorCall(self, call):
+		super_class = call.getSuperClassIdentifier()
+		params = call.getActualParameters()
+		param_list = [Literal("this")] + params.getParameterList()
+		params = ActualParameters(param_list)
+
+		self.out.extendWrite(super_class)
+		self.out.extendWrite(".call")
+		params.accept(self)
+
+	def visit_SuperClassDestructorCall(self, call):
+		pass # Javascript doesn't have destructors
+
+	def visit_SuperClassMethodCall(self, call):
+		super_class = call.getSuperClassIdentifier()
+		method_name = call.getMethodIdentifier()
+		params = call.getActualParameters()
+		param_list = [Literal("this")] + params.getParameterList()
+		params = ActualParameters(param_list)
+
+		self.out.extendWrite(super_class)
+		self.out.extendWrite(".prototype." + method_name + ".call")
+		params.accept(self)
+
+	def visit_ThrowExceptionStatement(self, stmt):
+		self.out.write("throw new Error(")
+		stmt.getExpression().accept(self)
+		self.out.extendWrite(");")
+
+

+ 170 - 0
exported_to_sccdxml/python_sccd_compiler/lexer.py

@@ -0,0 +1,170 @@
+from utils import Enum
+
+TokenType = Enum("SLASH",
+				 "LBRACKET",
+				 "RBRACKET",
+				 "COMMA",
+				 "DOT",
+				 "NUMBER",
+				 "WORD",
+				 "QUOTED",
+				 "WHITESPACE",
+				 "BINARYOPERATOR",
+				 "UNARYOPERATOR",
+				 "UNKNOWN"
+				)
+
+class Token(object):
+	""" A simple Token structure. Token type, value and position.
+	"""
+	def __init__(self, token_type, val, pos):
+		self.type = token_type
+		self.val = val
+		self.pos = pos
+
+	def __str__(self):
+		return '%s(%s) at %s' % (TokenType.name_of(self.type), self.val, self.pos)
+
+
+class LexerError(Exception):
+	def __init__(self, pos):
+		self.pos = pos
+		
+class Lexer(object):
+	single_rules = {
+			'/': TokenType.SLASH,
+			'(': TokenType.LBRACKET,
+			')': TokenType.RBRACKET,
+			',': TokenType.COMMA,
+			'.': TokenType.DOT,
+			'+': TokenType.BINARYOPERATOR,
+			'-': TokenType.BINARYOPERATOR,
+			'<': TokenType.BINARYOPERATOR,
+			'>': TokenType.BINARYOPERATOR,
+			'==': TokenType.BINARYOPERATOR,
+			'<=': TokenType.BINARYOPERATOR,
+			'>=': TokenType.BINARYOPERATOR,
+			'=': TokenType.BINARYOPERATOR,
+			'+=': TokenType.BINARYOPERATOR,
+			'-=': TokenType.BINARYOPERATOR,
+			'&&': TokenType.BINARYOPERATOR,
+			'||': TokenType.BINARYOPERATOR,
+			'!': TokenType.UNARYOPERATOR}
+	
+	def __init__(self, skip_white_space = True, accept_unknown_tokens = False):
+		self.skip_white_space = skip_white_space
+		self.accept_unknown_tokens = accept_unknown_tokens
+
+	def input(self, buf):
+		""" Initialize the lexer with a buffer as input.
+		"""
+		self.buf = buf
+		self.pos = 0
+		self.buflen = len(buf)
+
+	def nextToken(self):
+		""" Return the next token (a Token object) found in the
+			input buffer. None is returned if the end of the
+			buffer was reached.
+			In case of a lexing error (the current chunk of the
+			buffer matches no rule), a LexerError is raised.
+		"""
+		if self.skip_white_space :
+			self.skipWhiteSpace() 
+		if self.pos >= self.buflen:
+			return None
+
+		#c part of next token
+		c = self.buf[self.pos]
+		
+		#check if it is an operator
+		result_type = self.single_rules.get(c,None)
+		if result_type is not None :
+			if self.pos < self.buflen-1:
+				c2 = c+self.buf[self.pos+1]
+				result_type2 = self.single_rules.get(c2, None)
+				if result_type2 is not None:
+					c = c2
+					result_type = result_type2
+					self.pos += 1
+			token = Token(result_type, c, self.pos)
+			self.pos += 1
+			return token
+		else : #not an operator
+			if (self.isAlpha(c)) :
+				return self.processIdentifier()
+			elif (self.isDigit(c)) :
+				return self.processNumber()
+			elif ( c == "'" or c == '"') :
+				return self.processQuote()
+			elif (self.isWhiteSpace(c)) :
+				return self.processWhiteSpace()
+
+		# if we're here, no rule matched
+		if self.accept_unknown_tokens :
+			token = Token(TokenType.UNKNOWN, c, self.pos)
+			self.pos += 1
+			return token
+		raise LexerError("Invalid character at position " + str(self.pos) + ".")
+
+	def tokens(self):
+		""" Returns an iterator to the tokens found in the buffer.
+		"""
+		while True:
+			tok = self.nextToken()
+			if tok is None: break
+			yield tok
+			
+	def skipWhiteSpace(self):
+		while (self.pos < self.buflen) : 
+			if self.isWhiteSpace(self.buf[self.pos]) :
+				self.pos += 1
+			else :
+				break	  
+			
+	def isAlpha(self, c):
+		return c.isalpha() or c == '_';
+	
+	def isAlphaNum(self, c):
+		return c.isalnum() or c == '_';
+	
+	def isDigit(self, c):
+		return c.isdigit()
+	
+	def isWhiteSpace(self, c):
+		return c == ' ' or c == '\t' or c == '\r' or c == '\n'
+	
+	def processNumber(self):
+		nextpos = self.pos + 1
+		while (nextpos < self.buflen) and (self.isDigit(self.buf[nextpos])) :
+			nextpos += 1;
+		token = Token(TokenType.NUMBER, self.buf[self.pos:nextpos], self.pos)
+		self.pos = nextpos
+		return token
+	
+	def processIdentifier(self):
+		nextpos = self.pos + 1
+		while (nextpos < self.buflen) and (self.isAlphaNum(self.buf[nextpos])) :
+			nextpos += 1;
+		token = Token(TokenType.WORD, self.buf[self.pos:nextpos], self.pos)
+		self.pos = nextpos
+		return token
+	
+	def processQuote(self):
+		# self.pos points at the opening quote. Find the ending quote.
+		end_index = self.buf.find(self.buf[self.pos], self.pos + 1)
+	
+		if (end_index == -1) :
+			raise LexerError("Missing matching quote for the quote at position " + str(self.pos) + ".")
+		token = Token(TokenType.QUOTED, self.buf[self.pos:end_index+1], self.pos)
+
+		self.pos = end_index + 1;
+		return token;
+	
+	def processWhiteSpace(self):
+		nextpos = self.pos + 1
+		while (nextpos < self.buflen) and (self.isWhiteSpace(self.buf[nextpos])) :
+			nextpos += 1;
+		token = Token(TokenType.WHITESPACE, self.buf[self.pos:nextpos], self.pos)
+		self.pos = nextpos
+		return token

+ 701 - 0
exported_to_sccdxml/python_sccd_compiler/old_generators/csharp_generator.py

@@ -0,0 +1,701 @@
+"""Generates C#"""
+
+import time
+from constructs import FormalParameter
+from code_generation import CodeGenerator, Platforms
+
+class CSharpGenerator(CodeGenerator):
+    
+    def __init__(self):
+        self.supported_platforms = [Platforms.Threads, Platforms.GameLoop]
+                
+    def visit_ClassDiagram(self, class_diagram):
+        self.fOut.write("/*")
+        self.fOut.indent()
+        self.fOut.write("Statecharts + Class Diagram compiler by Glenn De Jonghe")
+        self.fOut.write()
+        self.fOut.write("Date:   " + time.asctime())
+        if class_diagram.name or class_diagram.author or class_diagram.description:
+            self.fOut.write()
+        if class_diagram.author:
+            self.fOut.write("Model author: " + class_diagram.author)
+        if class_diagram.name:
+            self.fOut.write("Model name:   " + class_diagram.name)
+        if class_diagram.description.strip():
+            self.fOut.write("Model description:")
+            self.fOut.write()
+            self.fOut.indent()
+            self.fOut.write(class_diagram.description.strip())
+            self.fOut.dedent()
+        self.fOut.dedent()
+        self.fOut.write('*/')
+        self.fOut.write()
+        
+        #Namespace using declarations by the user
+        self.fOut.write('using System;')
+        self.fOut.write('using System.Collections.Generic;')
+        self.fOut.write('using sccdlib;')
+
+        #User imports
+        if class_diagram.top.strip():
+            self.writeCodeCorrectIndent(class_diagram.top)
+        self.fOut.write()
+        
+        #visit children
+        for c in class_diagram.classes :
+            c.accept(self)
+         
+        #writing out ObjectManager
+        self.fOut.write('public class ObjectManager : ObjectManagerBase')
+        self.fOut.write('{')
+        self.fOut.indent()
+        self.fOut.write('public ObjectManager(ControllerBase controller): base(controller)')
+        self.fOut.write("{")
+        self.fOut.write("}")
+        self.fOut.write()
+        
+        self.fOut.write('protected override InstanceWrapper instantiate(string class_name, object[] construct_params)')
+        self.fOut.write('{')
+        self.fOut.indent()
+        self.fOut.write("RuntimeClassBase instance = null;")
+        self.fOut.write("List<Association> associations = new List<Association>();")
+        for index, c in enumerate(class_diagram.classes) :
+            if index == 0 :
+                self.fOut.write()
+            else :
+                self.fOut.write('}else ')
+            self.fOut.extendWrite('if (class_name == "' + c.name + '" ){')
+            self.fOut.indent()
+            self.fOut.write('object[] new_parameters = new object[construct_params.Length + 1];')
+            self.fOut.write('new_parameters[0] = this.controller;')
+            self.fOut.write('Array.Copy(construct_params, 0, new_parameters, 1, construct_params.Length);')
+            self.fOut.write('instance = (RuntimeClassBase) Activator.CreateInstance(typeof(' + c.name + '), new_parameters);')
+            for a in c.associations :
+                a.accept(self)
+            self.fOut.dedent()
+            if index == len(class_diagram.classes)-1 :
+                self.fOut.write('}')
+            
+        self.fOut.write('if (instance != null) {')
+        self.fOut.indent()
+        self.fOut.write('return new InstanceWrapper(instance, associations);')
+        self.fOut.dedent()
+        self.fOut.write('}')
+        self.fOut.write('return null;')
+        self.fOut.dedent()
+        self.fOut.write('}')
+        self.fOut.dedent()
+        self.fOut.write('}')
+        
+        # write out controller
+        self.fOut.write()
+        if self.platform == Platforms.Threads :
+            controller_sub_class = "ThreadsControllerBase"
+        elif self.platform == Platforms.GameLoop :
+            controller_sub_class = "GameLoopControllerBase"
+        self.fOut.write("public class Controller : " + controller_sub_class)
+        self.fOut.write("{")
+        self.fOut.indent()
+    
+        # write out constructor(s)
+        if class_diagram.default_class.constructors :
+            for constructor in class_diagram.default_class.constructors :
+                self.writeControllerConstructor(class_diagram, constructor.parameters)
+        else :
+            self.writeControllerConstructor(class_diagram)
+        
+        self.fOut.write("public static void Main()")
+        self.fOut.write("{")
+        self.fOut.indent()
+        self.fOut.write("Controller controller = new Controller();")
+        self.fOut.write("controller.start();")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        
+        self.fOut.dedent()
+        self.fOut.write("}")
+        
+    #helper method
+    def writeControllerConstructor(self, class_diagram, parameters = []):
+        self.fOut.write('public Controller(')
+        self.writeFormalParameters(parameters + [FormalParameter("keep_running", "bool", "true")])
+        self.fOut.extendWrite(") : base(keep_running)")
+        self.fOut.write('{')
+        self.fOut.indent()
+        
+        for p in class_diagram.inports:
+            self.fOut.write('this.addInputPort("' + p + '");')
+        for p in class_diagram.outports:
+            self.fOut.write('this.addOutputPort("' + p + '");')
+        self.fOut.write('this.object_manager = new ObjectManager(this);')
+        actual_parameters = [p.getIdent() for p in parameters]
+        self.fOut.write('this.object_manager.createInstance("'+ class_diagram.default_class.name +'", new object[]{' +  ', '.join(actual_parameters)+ '});')
+        self.fOut.dedent()
+        self.fOut.write('}')
+
+    def visit_Class(self, class_node):
+        """
+        Generate code for Class construct
+        """
+        self.fOut.write()
+        self.fOut.write("public class " + class_node.name )
+        # Take care of inheritance
+        if len(class_node.super_classes) > 1 :
+            raise Exception("C# doesn't allow multiple inheritance.");
+        elif len(class_node.super_classes) == 1 :
+            self.fOut.extendWrite(" : " + class_node.super_classes[0])
+        else :
+            self.fOut.extendWrite(" : " + "RuntimeClassBase")
+        self.fOut.write("{")
+        self.fOut.indent()
+        self.fOut.write()
+        
+        if class_node.statechart is not None:
+            # assign each node a unique ID
+            self.fOut.write("/// <summary>")
+            self.fOut.write("/// Enum uniquely representing all statechart nodes.")
+            self.fOut.write("/// </summary>")
+            self.fOut.write("public enum Node {")
+            self.fOut.indent()
+            for node in class_node.statechart.composites + class_node.statechart.basics:
+                self.fOut.write(node.full_name + ",");
+            self.fOut.dedent();
+            self.fOut.write("};")
+            self.fOut.write()
+            self.fOut.write("Dictionary<Node,List<Node>> current_state = new Dictionary<Node,List<Node>>();");
+            if len(class_node.statechart.histories) > 0 :
+                self.fOut.write("Dictionary<Node,List<Node>> history_state = new Dictionary<Node,List<Node>>();");
+            self.fOut.write();
+            
+        #User defined attributes
+        if class_node.attributes:
+            self.fOut.write("//User defined attributes")
+            for attribute in class_node.attributes:
+                self.fOut.write(attribute.type + " " + attribute.name)
+                if attribute.init_value is not None :
+                    self.fOut.write(" = " + attribute.init_value);
+                self.fOut.extendWrite(";")     
+            self.fOut.write()
+
+        if class_node.statechart is not None:  
+            self.fOut.write("/// <summary>")
+            self.fOut.write("/// Constructor part that is common for all constructors.")
+            self.fOut.write("/// </summary>")
+            self.fOut.write("private void commonConstructor(ControllerBase controller = null)")
+            self.fOut.write("{")
+            self.fOut.indent() 
+            self.fOut.write("this.controller = controller;")
+            self.fOut.write("this.object_manager = controller.getObjectManager();")
+            if class_node.statechart.nr_of_after_transitions != 0:
+                self.fOut.write("this.timers = new Dictionary<int,double>();")
+
+            self.fOut.write()
+            self.fOut.write("//Initialize statechart :")
+            self.fOut.write()
+
+            if class_node.statechart.histories:
+                for node in class_node.statechart.combined_history_parents:
+                    self.fOut.write("this.history_state[Node." + node.full_name + "] = new List<Node>();")
+                self.fOut.write()
+
+            for node in class_node.statechart.composites :
+                self.fOut.write("this.current_state[Node." + node.full_name + "] = new List<Node>();")
+                
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+        self.fOut.write("public override void start()")
+        self.fOut.write("{")
+        
+        self.fOut.indent()
+        self.fOut.write("base.start();")
+        for default_node in class_node.statechart.root.defaults:
+            if default_node.is_composite:
+                self.fOut.write("this.enterDefault_" + default_node.full_name + "();")
+            elif default_node.is_basic:
+                self.fOut.write("this.enter_" + default_node.full_name + "();")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+        #visit children
+        for i in class_node.constructors :
+            i.accept(self)
+        for i in class_node.destructors :
+            i.accept(self)
+        for i in class_node.methods :
+            i.accept(self)
+        if class_node.statechart is not None:
+            class_node.statechart.accept(self)
+          
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+
+    def writeFormalParameters(self, parameters = []):
+        """Helper method that writes a correct comma separated list of formal parameters"""    
+        first = True       
+        for param in parameters :
+            if first :
+                first = False
+            else :
+                self.fOut.extendWrite(', ')
+            param.accept(self)
+        
+    def visit_FormalParameter(self, formal_parameter):
+        self.fOut.extendWrite(formal_parameter.getType() + " " + formal_parameter.getIdent())
+        if formal_parameter.hasDefault() :
+            self.fOut.extendWrite(" = " + formal_parameter.getDefault())
+                    
+    def visit_Constructor(self, constructor):
+
+        self.fOut.write(constructor.access + " " + constructor.parent_class.name + "(")
+        self.writeFormalParameters([FormalParameter("controller", "ControllerBase", None)] + constructor.getParams())
+        self.fOut.extendWrite(")")
+        self.fOut.write("{")
+        self.fOut.indent()
+        self.fOut.write("this.commonConstructor(controller);")
+        if constructor.body :
+            self.fOut.write()
+            self.fOut.write("//constructor body (user-defined)")
+            self.writeCodeCorrectIndent(constructor.body)
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+    def visit_Destructor(self, destructor):
+        self.fOut.write("~" + destructor.parent_class.name + "()")
+        self.fOut.write("{")
+        if destructor.body :
+            self.fOut.indent()
+            self.writeCodeCorrectIndent(destructor.body)
+            self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+    def visit_Method(self, method):
+        self.fOut.write(method.access + " " + method.return_type + " " + method.name + "(")
+        self.writeFormalParameters(method.getParams())
+        self.fOut.extendWrite(")")
+        self.fOut.write("{")
+        self.fOut.indent()
+        if method.body :
+            self.fOut.indent()
+            self.writeCodeCorrectIndent(method.body)
+            self.fOut.dedent()
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+    def visit_Association(self, association):
+        self.fOut.write('associations.Add(new Association("' + association.name + '", "' + association.to_class + '", ' + str(association.min) + ', ' + str(association.max) + '));')
+        
+    #helper method
+    def writeTransitionsRecursively(self, current_node):
+        self.fOut.write("private bool transition_" + current_node.full_name + "(Event e)")
+        self.fOut.write("{")
+        self.fOut.indent()
+        
+        valid_children = []
+        for child in current_node.children :
+            if child.is_composite or child.is_basic :
+                valid_children.append(child)  
+         
+        self.fOut.write("bool catched = false;")
+        do_dedent = False
+        if current_node.solves_conflict_outer :
+            self.writeFromTransitions(current_node)
+            if current_node.is_parallel_state or current_node.is_composite :
+                self.fOut.write("if (!catched){")
+                self.fOut.indent()
+                do_dedent = True
+            
+        if current_node.is_parallel_state:
+            for child in valid_children :     
+                self.fOut.write("catched = this.transition_" + child.full_name + "(e) || catched;")
+        elif current_node.is_composite:
+            self.fOut.write()
+            for i, child in enumerate(valid_children) :
+                if i > 0 :
+                    self.fOut.extendWrite(" else ")
+                self.fOut.extendWrite("if (this.current_state[Node." + current_node.full_name + "][0] == Node." + child.full_name + "){")
+                self.fOut.indent()
+                self.fOut.write("catched = this.transition_" + child.full_name + "(e);")
+                self.fOut.dedent()
+                self.fOut.write("}")
+                
+        if current_node.solves_conflict_outer :
+            if do_dedent :
+                self.fOut.dedent()
+                self.fOut.write("}")
+        elif len(current_node.transitions) > 0 :
+                self.fOut.write("if (!catched) {")
+                self.fOut.indent()
+                self.writeFromTransitions(current_node)
+                self.fOut.dedent()
+                self.fOut.write("}")
+            
+        self.fOut.write("return catched;")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write();
+        
+        for child in valid_children :
+            self.writeTransitionsRecursively(child)
+                
+    #helper method
+    def writeFromTransitions(self, current_node): 
+        # get all transition out of this state
+        out_transitions = current_node.transitions
+        if len(out_transitions) == 0 :
+            return
+        
+        self.fOut.write('List<int> enableds = new List<int>();')
+        for index, transition in enumerate(out_transitions):
+            self.writeTransitionCondition(transition, index)
+            
+        self.fOut.write("if (enableds.Count > 1){")
+        self.fOut.indent()
+        self.fOut.write('Console.WriteLine("Runtime warning : indeterminism detected in a transition from node ' +  current_node.full_name+ '. Only the first in document order enabled transition is executed.");')
+        self.fOut.dedent()
+        self.fOut.write('}')
+        self.fOut.write("if (enableds.Count > 0){")
+        self.fOut.indent()
+        self.fOut.write('int enabled = enableds[0];')
+        self.fOut.write()      
+              
+        for index, transition in enumerate(out_transitions):
+            self.writeTransitionAction(transition, index)
+        
+        self.fOut.write('catched = true;')   
+        self.fOut.dedent()
+        self.fOut.write('}')         
+        self.fOut.write()
+        
+    def visit_FormalEventParameter(self, formal_event_parameter):
+        self.fOut.extendWrite(formal_event_parameter.getType() + " " + formal_event_parameter.name)
+        
+    def writeFormalEventParameters(self, transition):
+        parameters = transition.getTrigger().getParameters()
+        if(len(parameters) > 0) :
+            self.fOut.write('object[] parameters = e.getParameters();')
+            for index, parameter in enumerate(parameters):
+                self.fOut.write()
+                parameter.accept(self)
+                self.fOut.extendWrite(' = (' + parameter.getType() + ')parameters[' + str(index) + '];')
+        
+    def writeTransitionAction(self, transition, index):
+        if index > 1 :
+            self.fOut.extendWrite(" else ")
+        else :
+            self.fOut.write()
+        self.fOut.extendWrite("if (enabled == " + str(index) + "){")
+        self.fOut.indent()
+
+        # handle parameters to actually use them             
+        self.writeFormalEventParameters(transition)
+        
+        exits = transition.getExitNodes()
+        
+        # write out exit actions
+        if not exits[-1].is_basic:
+            self.fOut.write("this.exit_" + exits[-1].full_name + "();")
+        else:
+            for node in exits:
+                if node.is_basic:
+                    self.fOut.write("this.exit_" + node.full_name + "();")
+                    
+        # write out trigger actions
+        transition.getAction().accept(self)
+        
+        for (entering_node, is_ending_node) in transition.getEnterNodes() : 
+            if is_ending_node :
+                if entering_node.is_composite:
+                    self.fOut.write("this.enterDefault_" + entering_node.full_name + "();")
+                elif entering_node.is_history:
+                    if (entering_node.is_history_deep) :
+                        self.fOut.write("this.enterHistoryDeep_" + entering_node.parent.full_name + "();")
+                    else :
+                        self.fOut.write("this.enterHistoryShallow_" + entering_node.parent.full_name + "();")
+                else:
+                    self.fOut.write("this.enter_" + entering_node.full_name + "();")
+            else :
+                if entering_node.is_composite:
+                    self.fOut.write("this.enter_" + entering_node.full_name + "();")
+
+        self.fOut.dedent()
+        self.fOut.write('}')
+                        
+    def writeTransitionCondition(self, transition, index):
+        trigger = transition.getTrigger()
+        if not trigger.isUC():  
+            self.fOut.write('if (e.getName() == "' + trigger.getEvent() + '" && e.getPort() == "' + trigger.getPort() + '"){')
+            self.fOut.indent()   
+        # evaluate guard
+        if transition.hasGuard() :   
+            # handle parameters for guard evaluation       
+            self.writeFormalEventParameters(transition)  
+
+            self.fOut.write('if (')
+            transition.getGuard().accept(self)
+            self.fOut.extendWrite('){')
+            self.fOut.indent()    
+            
+        self.fOut.write("enableds.Add(" + str(index) + ");")
+
+        if transition.hasGuard() :
+            self.fOut.dedent()
+            self.fOut.write('}')
+        if not trigger.isUC() :
+            self.fOut.dedent()
+            self.fOut.write('}')
+        self.fOut.write()
+    
+    def visit_EnterAction(self, enter_method):
+        parent_node = enter_method.parent_node
+        self.fOut.write("private void enter_" + parent_node.full_name + "()")
+        self.fOut.write("{")
+        self.fOut.indent()
+        
+        # take care of any AFTER events
+        for transition in parent_node.transitions :
+            trigger = transition.getTrigger()
+            if trigger.isAfter() :
+                self.fOut.write("this.timers[" + str(trigger.getAfterIndex()) + "] = ")
+                trigger.after.accept(self)
+                self.fOut.extendWrite(";")
+        if enter_method.action:
+            enter_method.action.accept(self)
+        self.fOut.write("this.current_state[Node." + parent_node.parent.full_name + "].Add(Node." + parent_node.full_name + ");")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+    #helper method
+    def writeEnterDefault(self, entered_node):
+        self.fOut.write("private void enterDefault_" + entered_node.full_name + "()")
+        self.fOut.write("{")
+        self.fOut.indent()
+        self.fOut.write("this.enter_" + entered_node.full_name + "();")
+        if entered_node.is_composite:
+            l = entered_node.defaults
+            for i in l:
+                if i.is_composite:
+                    self.fOut.write("this.enterDefault_" + i.full_name + "();")
+                elif i.is_basic:
+                    self.fOut.write("this.enter_" + i.full_name + "();")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+         
+    def visit_ExitAction(self, exit_method):
+        exited_node = exit_method.parent_node
+        self.fOut.write("private void exit_" + exited_node.full_name + "()")
+        self.fOut.write("{")
+        self.fOut.indent()
+        #If the exited node is composite take care of potential history and the leaving of descendants
+        if exited_node.is_composite :
+            #handle history
+            if exited_node.save_state_on_exit:
+                self.fOut.write("this.history_state[Node." + exited_node.full_name + "].AddRange(this.current_state[Node." + exited_node.full_name + "]);")
+            
+            #Take care of leaving children
+            children = exited_node.children
+            if exited_node.is_parallel_state:
+                for child in children:
+                    if not child.is_history :
+                        self.fOut.write("this.exit_" + child.full_name + "();")
+            else:
+                for child in children:
+                    if not child.is_history :
+                        self.fOut.write("if (this.current_state[Node." + exited_node.full_name + "].Contains(Node." + child.full_name +  ")){")
+                        self.fOut.indent()
+                        self.fOut.write("this.exit_" + child.full_name + "();")
+                        self.fOut.dedent()  
+                        self.fOut.write("}")
+        
+        
+        # take care of any AFTER events
+        for transition in exited_node.transitions :
+            trigger = transition.getTrigger()
+            if trigger.isAfter() :
+                self.fOut.write("this.timers.Remove(" + str(trigger.getAfterIndex()) + ");")
+                
+        #Execute user-defined exit action if present
+        if exit_method.action:
+            exit_method.action.accept(self)
+            
+        #Adjust state
+        self.fOut.write("this.current_state[Node." + exited_node.parent.full_name + "].Remove(Node." + exited_node.full_name + ");")
+
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+            
+    #helper method
+    def writeEnterHistory(self, entered_node, is_deep):
+        self.fOut.write("private void enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + entered_node.full_name + "()")
+        self.fOut.write("{")
+        self.fOut.indent()
+        self.fOut.write("if (this.history_state[Node." + entered_node.full_name + "].Count == 0){")
+        self.fOut.indent()
+        defaults = entered_node.defaults
+
+        for node in defaults:
+            if node.is_basic :
+                self.fOut.write("this.enter_" + node.full_name + "();")
+            elif node.is_composite :
+                self.fOut.write("this.enterDefault_" + node.full_name + "();")
+
+        self.fOut.dedent()
+        self.fOut.write("} else {")
+        self.fOut.indent()
+        children = entered_node.children
+        if entered_node.is_parallel_state:
+            for child in children:
+                if not child.is_history :
+                    self.fOut.write("this.enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + child.full_name + "();")
+        else:
+            for child in children:
+                if not child.is_history :
+                    self.fOut.write("if (this.history_state[Node." + entered_node.full_name + "].Contains(Node." + child.full_name + ")){")
+                    self.fOut.indent()
+                    if child.is_composite:
+                        if is_deep :
+                            self.fOut.write("this.enter_" + child.full_name + "();")
+                            self.fOut.write("this.enterHistoryDeep_" + child.full_name + "();")
+                        else :
+                            self.fOut.write("this.enterDefault_" + child.full_name + "();")
+                    else:
+                        self.fOut.write("this.enter_" + child.full_name + "();")
+                    self.fOut.dedent()
+                    self.fOut.write("}")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+
+    def visit_StateChart(self, statechart):
+        self.fOut.write("//Statechart enter/exit action method(s) :")
+        self.fOut.write()
+        
+        #visit enter and exit actions of children
+        for i in statechart.composites + statechart.basics:
+            if i is not statechart.root :
+                i.enter_action.accept(self)
+                i.exit_action.accept(self)
+
+        # write out statecharts methods for enter/exit state
+        if len(statechart.composites) > 1 :
+            self.fOut.write("//Statechart enter/exit default method(s) :")
+            self.fOut.write()
+            for i in statechart.composites :
+                if i is not statechart.root :
+                    self.writeEnterDefault(i)
+
+        # write out statecharts methods for enter/exit history
+        if statechart.histories:
+            self.fOut.write("//Statechart enter/exit history method(s) :")
+            self.fOut.write()
+            for i in statechart.shallow_history_parents:
+                self.writeEnterHistory(i, False)
+            for i in statechart.deep_history_parents:
+                self.writeEnterHistory(i, True)   
+                
+        self.fOut.write("//Statechart transitions :")
+        self.fOut.write()
+        self.writeTransitionsRecursively(statechart.root)            
+                
+        # write out transition function
+        self.fOut.write("protected override void transition (Event e = null)")
+        self.fOut.write("{")
+        self.fOut.indent()
+        self.fOut.write("if (e == null) {");
+        self.fOut.indent()
+        self.fOut.write("e = new Event();")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write("this.state_changed = this.transition_" + statechart.root.full_name + "(e);")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+
+        # write out inState function
+        self.fOut.write("public bool inState(List<Node> nodes)")
+        self.fOut.write("{")
+        self.fOut.indent()
+        self.fOut.write("foreach(List<Node> actives in current_state.Values){")
+        self.fOut.indent()
+        self.fOut.write("foreach(Node node in actives)")
+        self.fOut.indent()
+        self.fOut.write("nodes.Remove (node);")
+        self.fOut.dedent()
+        self.fOut.write("if (nodes.Count == 0){")
+        self.fOut.indent()
+        self.fOut.write("return true;")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write("return false;")
+        self.fOut.dedent()
+        self.fOut.write("}")
+        self.fOut.write()
+        
+    def visit_ExpressionPartString(self, bare_string):
+        self.fOut.extendWrite(bare_string.string)
+        
+    def visit_SelfReference(self, self_reference):
+        self.fOut.extendWrite("this")
+        
+    def visit_StateReference(self, state_ref):
+        self.fOut.extendWrite("new List<Node>() {")
+        self.fOut.extendWrite(", ".join(["Node." + node.full_name for node in state_ref.getNodes()]))
+        self.fOut.extendWrite("}")
+        
+    def visit_InStateCall(self, in_state_call):
+        self.fOut.extendWrite("this.inState(")
+        in_state_call.target.accept(self)
+        self.fOut.extendWrite(")")
+        
+    def visit_RaiseEvent(self, raise_event):
+        if raise_event.isNarrow() or raise_event.isBroad():
+            self.fOut.write('Event send_event = new Event("' + raise_event.getEventName() + '", "", new object[] {')
+        elif raise_event.isLocal():
+            self.fOut.write('this.addEvent( new Event("' + raise_event.getEventName() +'", "", new object[] {')
+        elif raise_event.isOutput():
+            self.fOut.write('this.controller.outputEvent(new Event("' + raise_event.getEventName() + '", "' + raise_event.getPort() + '", new object[] {')
+        elif raise_event.isCD():
+            self.fOut.write('this.object_manager.addEvent(new Event("' + raise_event.getEventName() + '", "", new object[] { this, ')
+        first_param = True
+        for param in raise_event.getParameters() :
+            if first_param :
+                first_param = False
+            else :
+                self.fOut.extendWrite(',')
+            param.accept(self)
+        if raise_event.isNarrow():
+            self.fOut.extendWrite('});')
+            self.fOut.write('this.object_manager.addEvent(new Event("narrow_cast", "", new object[] {this, "' + raise_event.getTarget() + '" ,send_event}));')
+        elif raise_event.isBroad():
+            self.fOut.extendWrite('});')
+            self.fOut.write('this.object_manager.addEvent(new Event("broad_cast", "", new object[] {send_event}));')
+        else :
+            self.fOut.extendWrite('}));')
+            
+    def visit_Script(self, script):
+        self.writeCodeCorrectIndent(script.code)
+        
+    def visit_Log(self, log):
+        self.fOut.write('Console.WriteLine("' + log.message + '");')
+        
+    def visit_Assign(self, assign):
+        self.fOut.write()
+        assign.lvalue.accept(self)
+        self.fOut.extendWrite(" = ")
+        assign.expression.accept(self)
+        self.fOut.extendWrite(";")
+        

+ 741 - 0
exported_to_sccdxml/python_sccd_compiler/old_generators/javascript_generator.py

@@ -0,0 +1,741 @@
+import time
+from constructs import FormalParameter
+from code_generation import CodeGenerator, Platforms
+
+class JavascriptGenerator(CodeGenerator):
+	
+	def __init__(self):
+		self.supported_platforms = [Platforms.Threads, Platforms.GameLoop]
+				
+	def visit_ClassDiagram(self, class_diagram):
+		# header
+		self.fOut.write("/**");
+		self.fOut.write(" * Statechart compiler by Glenn De Jonghe")
+		self.fOut.write(" * Javascript generator by Joeri Exelmans")
+		self.fOut.write(" * ")
+		self.fOut.write(" * Date:   " + time.asctime())
+		if class_diagram.name or class_diagram.author or class_diagram.description:
+			self.fOut.write(" * ")
+		if class_diagram.author:
+			self.fOut.write(" * Model author: " + class_diagram.author)
+		if class_diagram.name:
+			self.fOut.write(" * Model name:   " + class_diagram.name)
+		if class_diagram.description.strip():
+			self.fOut.write(" * Model description:")
+			self.fOut.indent()
+			self.fOut.write(class_diagram.description.strip())
+			self.fOut.dedent()
+		self.fOut.write(" */")
+		
+		self.fOut.write()
+
+		self.fOut.write("// put everything in an object (serves as \"namespace\")")
+		self.fOut.write(class_diagram.name + " = {};")
+		self.fOut.write()
+		self.fOut.write("// closure scope")
+		self.fOut.write("(function() {")
+		self.fOut.write()
+		
+		#visit children
+		for c in class_diagram.classes :
+			c.accept(self)
+			self.fOut.write("// put class in global diagram object")
+			self.fOut.write(class_diagram.name + '.' + c.name + ' = ' + c.name + ';')
+			self.fOut.write()
+		 
+		#writing out ObjectManager
+		self.fOut.write('var ObjectManager = function(controller) {')
+		self.fOut.indent()
+		self.fOut.write("ObjectManagerBase.call(this, controller);")
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+
+		self.fOut.write("ObjectManager.prototype = new ObjectManagerBase();")
+		self.fOut.write()
+		
+		self.fOut.write('ObjectManager.prototype.instantiate = function(class_name, construct_params) {')
+		self.fOut.indent()
+		for index, c in enumerate(class_diagram.classes) :
+			if index == 0 : 
+				self.fOut.write()
+			else :
+				self.fOut.extendWrite(' else ')
+			self.fOut.extendWrite('if (class_name === "' + c.name + '") {')
+			self.fOut.indent()
+			if c.statechart :
+				self.fOut.write('var instance = new ' + c.name + '(this.controller')
+				param_count = 0
+				for p in c.constructors[0].parameters:
+					self.fOut.extendWrite(', construct_params[' + str(param_count) + ']')
+					param_count += 1
+				self.fOut.extendWrite(');')
+			else :
+				self.fOut.write('var instance = new ' + c.name + '(')
+				param_count = 0
+				for p in c.constructors[0].parameters:
+					if (param_count != 0):
+						self.fOut.extendWrite(', ')
+					self.fOut.extendWrite('construct_params[' + str(param_count) + ']')
+					param_count += 1
+				self.fOut.extendWrite(');');
+			self.fOut.write('instance.associations = new Object();')
+			for a in c.associations :
+				a.accept(self)
+			self.fOut.dedent()
+			self.fOut.write('}')
+		self.fOut.write('return instance;')
+		self.fOut.dedent()
+		self.fOut.write("};")
+
+		self.fOut.write()
+		self.fOut.write("// put in global diagram object")
+		self.fOut.write(class_diagram.name + '.ObjectManager = ObjectManager;')
+
+		self.fOut.write()
+		if self.platform == Platforms.Threads :
+			controller_sub_class = "JsEventLoopControllerBase"
+		elif self.platform == Platforms.GameLoop :
+			controller_sub_class = "GameLoopControllerBase"
+
+		# write out __init__ method
+		if class_diagram.default_class.constructors :
+			self.writeControllerConstructor(class_diagram, controller_sub_class, class_diagram.default_class.constructors[0].parameters)
+		else :
+			self.writeControllerConstructor(class_diagram, controller_sub_class)
+
+		self.fOut.write("Controller.prototype = new " + controller_sub_class + "();")
+		self.fOut.write()
+		self.fOut.write("// put in global diagram object")
+		self.fOut.write(class_diagram.name + '.Controller = Controller;')
+		self.fOut.write()
+		self.fOut.write("})();")
+		self.fOut.write()
+
+	#helper method
+	def writeControllerConstructor(self, class_diagram, controller_sub_class, parameters = []):
+		self.writeConstructorSignature("Controller", parameters + [FormalParameter("keep_running", "", "true"), FormalParameter("finished_callback", "", None)])
+		self.fOut.indent()
+		self.fOut.write(controller_sub_class + ".call(this, new ObjectManager(this), keep_running, finished_callback);")
+		for i in class_diagram.inports:
+			self.fOut.write('this.addInputPort("' + i + '");')
+		for i in class_diagram.outports:
+			self.fOut.write('this.addOutputPort("' + i + '");')
+		actual_parameters = [p.getIdent() for p in parameters]
+		self.fOut.write('this.object_manager.createInstance("'+ class_diagram.default_class.name +'", [' +  ', '.join(actual_parameters)+ ']);')
+		self.fOut.dedent()
+		self.fOut.write('};')
+		self.fOut.write()
+
+	def visit_Class(self, class_node):
+		"""
+		Generate code for Class construct
+		"""
+
+		if class_node.super_classes:
+			super_classes = []
+			for super_class in class_node.super_classes:
+				super_classes.append(super_class)
+		else:
+			super_classes = ["RuntimeClassBase"]
+
+		#visit children
+		for i in class_node.constructors :
+			i.accept(self)
+
+		self.fOut.write()
+		self.fOut.write(class_node.name + ".prototype = new " + super_classes[0] + "();")
+		self.fOut.write()
+
+		if class_node.statechart is not None:
+			# assign each node a unique ID
+			self.fOut.write("// Unique IDs for all statechart nodes")
+			for (i,node) in enumerate(class_node.statechart.composites + class_node.statechart.basics):
+				self.fOut.write(class_node.name + ".prototype." + node.full_name + " = " + str(i) + ";")
+			self.fOut.write()
+
+		#visit children
+		for i in class_node.destructors :
+			i.accept(self)
+		for i in class_node.methods :
+			i.accept(self)
+		if class_node.statechart is not None:
+			class_node.statechart.accept(self)
+
+		self.writeMethodSignature(class_node.name, "user_defined_constructor", class_node.constructors[0].getParams())
+
+		self.fOut.indent()
+
+		for super_class in class_node.super_classes:
+			self.fOut.write(super_class + ".prototype.user_defined_constructor.call(this")
+			for p in class_node.constructors[0].super_class_parameters[super_class]:
+				self.fOut.extendWrite(", " + p)
+			self.fOut.extendWrite(");")
+
+
+		self.writeCodeCorrectIndent(class_node.constructors[0].body)
+		
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+		
+		self.writeMethodSignature(class_node.name, "start")
+		self.fOut.indent()
+		self.fOut.write(super_classes[0] + ".prototype.start.call(this);")
+		for default_node in class_node.statechart.root.defaults:
+			if default_node.is_composite:
+				self.fOut.write("this.enterDefault_" + default_node.full_name + "();")
+			elif default_node.is_basic:
+				self.fOut.write("this.enter_" + default_node.full_name + "();")
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+
+	#helper method
+	def writeConstructorSignature(self, prototype_name, parameters = []):
+		self.fOut.write("var " + prototype_name + " = function(")		   
+		for param in parameters :
+			if parameters.index(param) != 0:
+				self.fOut.extendWrite(', ')
+			param.accept(self)
+		self.fOut.extendWrite(") {")
+		self.fOut.indent()
+		for param in parameters :
+			if param.hasDefault() :
+				self.fOut.write("if (" + param.getIdent() + " === undefined) " +
+					param.getIdent() + " = " + param.getDefault() + ";")
+		self.fOut.dedent()
+
+	#helper method
+	def writeMethodSignature(self, prototype_name, method_name, parameters = []):
+		self.fOut.write(prototype_name + ".prototype." + method_name + " = function(")
+		for param in parameters :
+			if parameters.index(param) != 0 :
+				self.fOut.extendWrite(', ')
+			param.accept(self)
+		self.fOut.extendWrite(") {")
+		self.fOut.indent()
+		for param in parameters :
+			if param.hasDefault() :
+				self.fOut.write("if (!" + param.getIdent() + ") " +
+					param.getIdent() + " = " + param.getDefault() + ";")
+		self.fOut.dedent()
+		
+	#helper method
+	def writeMethod(self, prototype_name, name, parameters, return_type, body):
+		self.writeMethodSignature(prototype_name, name, parameters)
+		self.fOut.indent()
+		if body.strip():
+			self.writeCodeCorrectIndent(body)
+		self.fOut.write()
+		self.fOut.dedent()
+		self.fOut.write("};");
+		
+	def visit_FormalParameter(self, formal_parameter):
+		self.fOut.extendWrite(formal_parameter.getIdent())
+		
+	def visit_Constructor(self, constructor):
+		self.fOut.write("// Constructor")
+		parameters =  [FormalParameter("controller", "", None)] + constructor.getParams()
+		self.writeConstructorSignature(constructor.parent_class.name, parameters)
+		self.fOut.indent()
+
+		if constructor.parent_class.super_classes:
+			self.fOut.write(constructor.parent_class.super_classes[0] + ".call(this);")
+		else:
+			self.fOut.write("RuntimeClassBase.call(this);")
+
+		self.fOut.write()
+		self.fOut.write("if (controller) {")
+		self.fOut.indent()
+
+		#visit input, output ports
+		self.fOut.write("// User defined input ports")
+		self.fOut.write("this.inports = new Object();")
+		for p in constructor.parent_class.inports:
+			self.fOut.write("this.inports[\""+p+"\"] = controller.addInputPort(\""+p+"\", this);")
+
+		#for p in class_node.outports:
+
+		# write attributes
+		if constructor.parent_class.attributes:
+			self.fOut.write()
+			self.fOut.write("// User defined attributes")
+			for attribute in constructor.parent_class.attributes:
+				if attribute.init_value is None :
+					self.fOut.write("this." +  attribute.name + " = null;")
+				else :
+					self.fOut.write("this." +  attribute.name + " = " + attribute.init_value + ";")
+			self.fOut.write()
+
+		# if there is a statechart
+		if constructor.parent_class.statechart is not None:			
+			self.fOut.write("this.controller = controller;")
+			self.fOut.write("this.object_manager = controller.object_manager;")
+			self.fOut.write("this.current_state = new Object();")
+			self.fOut.write("this.history_state = new Object();")
+			if constructor.parent_class.statechart.nr_of_after_transitions:
+				self.fOut.write("this.timers = new Object();")
+			self.fOut.write()
+			self.fOut.write("// Initialize statechart")
+			
+			if constructor.parent_class.statechart.histories:
+				for node in constructor.parent_class.statechart.combined_history_parents:
+					self.fOut.write("this.history_state[" + constructor.parent_class.name + "." + node.full_name + "] = new Array();")
+				self.fOut.write()
+
+			for c in constructor.parent_class.statechart.composites :
+				self.fOut.write("this.current_state[this." + c.full_name + "] = new Array();")
+
+		self.fOut.write()
+		self.fOut.write("// Call user defined constructor")
+		self.fOut.write(constructor.parent_class.name + ".prototype.user_defined_constructor.call(this")
+		for p in constructor.getParams():
+			self.fOut.extendWrite(", ")
+			p.accept(self)
+		self.fOut.extendWrite(");")
+
+
+		self.fOut.dedent()
+		self.fOut.write("}")
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+
+	def visit_Destructor(self, destructor):
+		self.fOut.write("// User defined destructor")
+
+		self.writeMethodSignature(destructor.parent_class.name, "user_defined_destructor", [])
+		self.fOut.indent()
+		if destructor.body.strip():
+			self.writeCodeCorrectIndent(destructor.body)
+
+		if destructor.parent_class.super_classes:
+			self.fOut.write()
+			self.fOut.write("// Call super class destructors")
+			for super_class in destructor.parent_class.super_classes:
+				self.fOut.write(super_class + ".prototype.user_defined_destructor.call(this);")
+
+		self.fOut.dedent()
+		self.fOut.write("};");
+		self.fOut.write()
+		
+	def visit_Method(self, method):
+		self.fOut.write("// User defined method")
+		self.writeMethod(method.parent_class.name, method.name, method.parameters, method.return_type, method.body)
+		
+	def visit_Association(self, association):
+		self.fOut.write('instance.associations["' + association.name + '"] = new Association("' + association.to_class + '", ' + str(association.min) + ', ' + str(association.max) + ');')
+		
+	#helper method
+	def writeTransitionsRecursively(self, current_node):
+
+		self.writeMethodSignature(current_node.statechart.class_obj.name, "transition_" + current_node.full_name, [FormalParameter("event", "event")])
+		self.fOut.indent()
+		
+		valid_children = []
+		for child in current_node.children :
+			if child.is_composite or child.is_basic :
+				valid_children.append(child)  
+		 
+		self.fOut.write("var catched = false;")
+		do_dedent = False
+		if current_node.solves_conflict_outer :
+			self.writeFromTransitions(current_node)
+			if current_node.is_parallel_state or current_node.is_composite :
+				self.fOut.write("if (!catched) {")
+				self.fOut.indent()
+				do_dedent = True
+			
+		if current_node.is_parallel_state:
+			for child in valid_children :	 
+				self.fOut.write("catched = this.transition_" + child.full_name + "(event) || catched")
+		elif current_node.is_composite:
+			for i, child in enumerate(valid_children) :
+				if i > 0 :
+					self.fOut.write("else ")
+				else :
+					self.fOut.write()
+				self.fOut.extendWrite("if (this.current_state[this." + current_node.full_name + "][0] === this." + child.full_name + ") {")
+				self.fOut.indent()
+				self.fOut.write("catched = this.transition_" + child.full_name + "(event);")
+				self.fOut.dedent()
+				self.fOut.write("}")
+				
+		if current_node.solves_conflict_outer :
+			if do_dedent :
+				self.fOut.dedent()
+				self.fOut.write("}")
+		elif len(current_node.transitions) > 0 :
+				self.fOut.write("if (!catched) {")
+				self.fOut.indent()
+				self.writeFromTransitions(current_node)
+				self.fOut.dedent()
+				self.fOut.write("}");
+			
+		self.fOut.write("return catched;")
+		self.fOut.dedent()
+		self.fOut.write("};");
+		self.fOut.write();
+		
+		for child in valid_children :
+			self.writeTransitionsRecursively(child)
+				
+	#helper method
+	def writeFromTransitions(self, current_node): 
+		# get all transition out of this state
+		out_transitions = current_node.transitions
+		if len(out_transitions) == 0 :
+			return
+		
+		self.fOut.write('var enableds = new Array();')
+		for index, transition in enumerate(out_transitions, start=1):
+			self.writeTransitionCondition(transition, index)
+			
+		self.fOut.write("if (enableds.length > 1) {")
+		self.fOut.indent()
+		self.fOut.write('console.log("Runtime warning : indeterminism detected in a transition from node ' +  current_node.full_name+ '. Only the first in document order enabled transition is executed.")')
+		self.fOut.dedent()
+		self.fOut.write("}")
+		self.fOut.write()
+		self.fOut.write("if (enableds.length > 0) {")
+		self.fOut.indent()
+		self.fOut.write('var enabled = enableds[0];')	  
+			  
+		for index, transition in enumerate(out_transitions, start=1):
+			self.writeTransitionAction(transition, index)
+		
+		self.fOut.write('catched = true;')   
+		self.fOut.dedent()
+		self.fOut.write("}")
+		self.fOut.write()
+		
+	def visit_FormalEventParameter(self, formal_event_parameter):
+		self.fOut.extendWrite(formal_event_parameter.name)
+		
+	def writeFormalEventParameters(self, transition):
+		parameters = transition.getTrigger().getParameters()
+		if(len(parameters) > 0) :
+			self.fOut.write('var parameters = event.parameters;')
+			for index, parameter in enumerate(parameters):
+				self.fOut.write()
+				self.fOut.write("var ")
+				parameter.accept(self)
+				self.fOut.extendWrite(' = parameters[' + str(index) + '];')
+		
+		
+	def writeTransitionAction(self, transition, index):
+		if index > 1 :
+			self.fOut.write("else ")
+		else :
+			self.fOut.write()
+		self.fOut.extendWrite("if (enabled === " + str(index) + ") {")
+		self.fOut.indent()
+
+		# handle parameters to actually use them			 
+		self.writeFormalEventParameters(transition)
+		
+		exits = transition.getExitNodes()
+		
+		# write out exit actions
+		if not exits[-1].is_basic:
+			self.fOut.write("this.exit_" + exits[-1].full_name + "();")
+		else:
+			for node in exits:
+				if node.is_basic:
+					self.fOut.write("this.exit_" + node.full_name + "();")
+					
+		# write out trigger actions
+		transition.getAction().accept(self)
+		
+		for (entering_node, is_ending_node) in transition.getEnterNodes() : 
+			if is_ending_node :
+				if entering_node.is_composite:
+					self.fOut.write("this.enterDefault_" + entering_node.full_name + "();")
+				elif entering_node.is_history:
+					if (entering_node.is_history_deep) :
+						self.fOut.write("this.enterHistoryDeep_" + entering_node.parent.full_name + "();")
+					else :
+						self.fOut.write("this.enterHistoryShallow_" + entering_node.parent.full_name + "();")
+				else:
+					self.fOut.write("this.enter_" + entering_node.full_name + "();")
+			else :
+				if entering_node.is_composite:
+					self.fOut.write("this.enter_" + entering_node.full_name + "();")
+
+		self.fOut.dedent()
+		self.fOut.write("}")
+						
+	def writeTransitionCondition(self, transition, index):
+		trigger = transition.getTrigger()
+		if not trigger.isUC():  
+			self.fOut.write('if (event.name === "' + trigger.getEvent() + '"' + ((' && event.port === "' + trigger.getPort()+'"') if trigger.getPort() != "" else '') + ') {')
+			self.fOut.indent()   
+		# evaluate guard
+		if transition.hasGuard() :   
+			# handle parameters for guard evaluation	   
+			self.writeFormalEventParameters(transition)
+
+			self.fOut.write('if (')
+			transition.getGuard().accept(self)
+			self.fOut.extendWrite(') {')
+			self.fOut.indent()	
+			
+		self.fOut.write("enableds.push(" + str(index) + ");")
+
+		if transition.hasGuard() :
+			self.fOut.dedent()
+			self.fOut.write("}")
+		if not trigger.isUC() :
+			self.fOut.dedent()
+			self.fOut.write("}")
+		self.fOut.write()
+	
+	def visit_EnterAction(self, enter_method):
+		parent_node = enter_method.parent_node
+		self.writeMethodSignature(parent_node.statechart.class_obj.name, "enter_" + parent_node.full_name, [])
+		self.fOut.indent()
+		# take care of any AFTER events
+		for transition in parent_node.transitions :
+			trigger = transition.getTrigger()
+			if trigger.isAfter() :
+				self.fOut.write("this.timers[" + str(trigger.getAfterIndex()) + "] = ")
+				trigger.after.accept(self)
+				self.fOut.extendWrite(" * 1000.0; /* convert ms to s */")
+		if enter_method.action:
+			enter_method.action.accept(self)
+		self.fOut.write("this.current_state[this." + parent_node.parent.full_name + "].push(this." + parent_node.full_name + ");")
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+		
+	#helper method
+	def writeEnterDefault(self, entered_node):
+		self.writeMethodSignature(entered_node.statechart.class_obj.name, "enterDefault_" + entered_node.full_name, [])
+		self.fOut.indent()
+		self.fOut.write("this.enter_" + entered_node.full_name + "();")
+		if entered_node.is_composite:
+			l = entered_node.defaults
+			for i in l:
+				if i.is_composite:
+					self.fOut.write("this.enterDefault_" + i.full_name + "();")
+				elif i.is_basic:
+					self.fOut.write("this.enter_" + i.full_name + "();")
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+		 
+	def visit_ExitAction(self, exit_method):
+		exited_node = exit_method.parent_node
+		self.writeMethodSignature(exited_node.statechart.class_obj.name, "exit_" + exited_node.full_name, [])
+		self.fOut.indent()
+		
+		#If the exited node is composite take care of potential history and the leaving of descendants
+		if exited_node.is_composite :
+			#handle history
+			if exited_node.save_state_on_exit :
+				self.fOut.write("this.history_state[this." + exited_node.full_name + "] = this.current_state[this." + exited_node.full_name + "];")
+			
+			#Take care of leaving children
+			children = exited_node.children
+			if exited_node.is_parallel_state:
+				for child in children:
+					if not child.is_history :
+						self.fOut.write("this.exit_" + child.full_name + "();")
+			else:
+				for child in children:
+					if not child.is_history :
+						self.fOut.write("if (this.current_state[this." + exited_node.full_name + "].indexOf(this." + child.full_name +  ") !== -1) {")
+						self.fOut.indent()
+						self.fOut.write("this.exit_" + child.full_name + "();")
+						self.fOut.dedent()
+						self.fOut.write("}")
+		
+		
+		# take care of any AFTER events
+		for transition in exited_node.transitions :
+			trigger = transition.getTrigger()
+			if trigger.isAfter() :
+				self.fOut.write("delete this.timers[" + str(trigger.getAfterIndex()) + "];")
+				
+		#Execute user-defined exit action if present
+		if exit_method.action:
+			exit_method.action.accept(self)
+			
+		#Adjust state
+		self.fOut.write("this.current_state[this." + exited_node.parent.full_name + "] = new Array();") # SPECIAL CASE FOR ORTHOGONAL??
+		
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+		
+			
+	#helper method
+	def writeEnterHistory(self, entered_node, is_deep):
+		self.writeMethodSignature(entered_node.statechart.class_obj.name, "enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + entered_node.full_name, [])
+		self.fOut.indent()
+		self.fOut.write("if (this.history_state[this." + entered_node.full_name + "].length === 0) {")
+		self.fOut.indent()
+		defaults = entered_node.defaults
+
+		for node in defaults:
+			if node.is_basic :
+				self.fOut.write("this.enter_" + node.full_name + "();")
+			elif node.is_composite :
+				self.fOut.write("this.enterDefault_" + node.full_name + "();")
+
+		self.fOut.dedent()
+		self.fOut.write("} else {")
+		self.fOut.indent()
+		children = entered_node.children
+		if entered_node.is_parallel_state:
+			for child in children:
+				if not child.is_history :
+					self.fOut.write("this.enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + child.full_name + "();")
+		else:
+			for child in children:
+				if not child.is_history :
+					self.fOut.write("if (this.history_state[this." + entered_node.full_name + "].indexOf(this." + child.full_name + ") !== -1) {")
+					self.fOut.indent()
+					if child.is_composite:
+						if is_deep :
+							self.fOut.write("this.enter_" + child.full_name + "()")
+							self.fOut.write("this.enterHistoryDeep_" + child.full_name + "()")
+						else :
+							self.fOut.write("this.enterDefault_" + child.full_name + "()")
+					else:
+						self.fOut.write("this.enter_" + child.full_name + "()")
+					self.fOut.dedent()
+					self.fOut.write("}")
+		self.fOut.dedent()
+		self.fOut.write("}")
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+
+	def visit_StateChart(self, statechart):
+		self.fOut.write("// Statechart enter/exit action method(s) :")
+		self.fOut.write()
+		
+		#visit enter and exit action of children
+		for i in statechart.composites + statechart.basics:
+			if i is not statechart.root :
+				i.enter_action.accept(self)
+				i.exit_action.accept(self)
+
+		# write out statecharts methods for enter/exit state
+		if len(statechart.composites) > 1 :
+			self.fOut.write("// Statechart enter/exit default method(s) :")
+			self.fOut.write()
+			for i in statechart.composites :
+				if i is not statechart.root :
+					self.writeEnterDefault(i)
+
+		# write out statecharts methods for enter/exit history
+		if statechart.histories:
+			self.fOut.write("// Statechart enter/exit history method(s) :")
+			self.fOut.write()
+			for i in statechart.shallow_history_parents:
+				self.writeEnterHistory(i, False)
+			for i in statechart.deep_history_parents:
+				self.writeEnterHistory(i, True) 
+		   
+		   
+		self.fOut.write("// Statechart transitions :")	 
+		self.fOut.write()
+		self.writeTransitionsRecursively(statechart.root)			
+				
+		# write out transition function
+		self.fOut.write("// Execute transitions")
+		self.writeMethodSignature(statechart.class_obj.name, "transition", [FormalParameter("event", "Event", "new Event()")])
+		self.fOut.indent()
+		self.fOut.write("this.state_changed = this.transition_" + statechart.root.full_name + "(event);")
+		self.fOut.dedent()
+		self.fOut.write("};");
+		self.fOut.write()
+
+		# write out inState function
+		self.fOut.write("// inState method for statechart")
+		self.writeMethodSignature(statechart.class_obj.name, "inState", [FormalParameter("nodes", "Array")])
+		#self.fOut.write("def inState(self, nodes):")
+		self.fOut.indent()
+		self.fOut.write("for (var c in this.current_state) {")
+		self.fOut.indent()
+		self.fOut.write("if (!this.current_state.hasOwnProperty(c)) continue;")
+
+		self.fOut.write("var new_nodes = new Array();")
+		self.fOut.write("for (var n in nodes) {")
+		self.fOut.indent()
+		self.fOut.write("if (!nodes.hasOwnProperty(n)) continue;")
+		self.fOut.write("if (this.current_state[c].indexOf(nodes[n]) === -1) {")
+		self.fOut.indent()
+		self.fOut.write("new_nodes.push(nodes[n]);")
+		self.fOut.dedent()
+		self.fOut.write("}")
+		self.fOut.dedent()
+		self.fOut.write("}")
+		self.fOut.write("nodes = new_nodes;")
+		self.fOut.write("if (nodes.length === 0) {")
+		self.fOut.indent()
+		self.fOut.write("return true;")
+		self.fOut.dedent()
+
+		self.fOut.write("}")
+		self.fOut.dedent()
+		self.fOut.write("}")
+		self.fOut.write("return false;")
+		self.fOut.dedent()
+		self.fOut.write("};")
+		self.fOut.write()
+
+	def visit_ExpressionPartString(self, bare_string):
+		self.fOut.extendWrite(bare_string.string)
+		
+	def visit_SelfReference(self, self_reference):
+		self.fOut.extendWrite("this")
+		
+	def visit_StateReference(self, state_ref):
+		self.fOut.extendWrite("[" + ",".join(["this." + node.full_name for node in state_ref.getNodes()]) + "]")
+		
+	def visit_InStateCall(self, in_state_call):
+		self.fOut.extendWrite("this.inState(")
+		in_state_call.target.accept(self)
+		self.fOut.extendWrite(")")
+		
+	def visit_RaiseEvent(self, raise_event):
+		if raise_event.isNarrow() or raise_event.isBroad():
+			self.fOut.write('var send_event = new Event("' + raise_event.getEventName() + '", null, [')
+		elif raise_event.isLocal():
+			self.fOut.write('this.addEvent(new Event("' + raise_event.getEventName() + '", null, [')
+		elif raise_event.isOutput():
+			self.fOut.write('this.controller.outputEvent(new Event("' + raise_event.getEventName() + '", "' + raise_event.getPort() + '", [')
+		elif raise_event.isCD():
+			self.fOut.write('this.object_manager.addEvent(new Event("' + raise_event.getEventName() + '", null, [this, ')
+		first_param = True
+		for param in raise_event.getParameters() :
+			if first_param :
+				first_param = False
+			else :
+				self.fOut.extendWrite(',')
+			param.accept(self)
+		if raise_event.isNarrow():
+			self.fOut.extendWrite(']);')
+			self.fOut.write('this.object_manager.addEvent(new Event("narrow_cast", null, [this, ' + raise_event.getTarget() + ' , send_event]));')
+		elif raise_event.isBroad():
+			self.fOut.extendWrite(']);')
+			self.fOut.write('this.object_manager.addEvent(new Event("broad_cast", null, [send_event]));')
+		else :
+			self.fOut.extendWrite(']));')
+			
+	def visit_Script(self, script):
+		self.writeCodeCorrectIndent(script.code)
+		
+	def visit_Log(self, log):
+		self.fOut.write('console.log("' + log.message + '");')
+		
+	def visit_Assign(self, assign):
+		self.fOut.write()
+		assign.lvalue.accept(self)
+		self.fOut.extendWrite(" = ")
+		assign.expression.accept(self)
+	

+ 644 - 0
exported_to_sccdxml/python_sccd_compiler/old_generators/python_generator.py

@@ -0,0 +1,644 @@
+import time
+from constructs import FormalParameter
+from code_generation import CodeGenerator, Platforms
+
+class PythonGenerator(CodeGenerator):
+	
+	def __init__(self):
+		self.supported_platforms = [Platforms.Threads, Platforms.GameLoop]
+				
+	def visit_ClassDiagram(self, class_diagram):
+		self.fOut.write("# Statechart compiler by Glenn De Jonghe")
+		self.fOut.write("#")
+		self.fOut.write("# Date:   " + time.asctime())
+		if class_diagram.name or class_diagram.author or class_diagram.description:
+			self.fOut.write()
+		if class_diagram.author:
+			self.fOut.write("# Model author: " + class_diagram.author)
+		if class_diagram.name:
+			self.fOut.write("# Model name:   " + class_diagram.name)
+		if class_diagram.description.strip():
+			self.fOut.write("# Model description:")
+			self.fOut.write('"""')
+			self.fOut.indent()
+			self.fOut.write(class_diagram.description.strip())
+			self.fOut.dedent()
+			self.fOut.write('"""')
+		self.fOut.write()
+		
+		#Mandatory imports
+		self.fOut.write('from python_runtime.statecharts_core import ObjectManagerBase, Event, InstanceWrapper, RuntimeClassBase, Association')
+		#User imports
+		if class_diagram.top.strip():
+			self.writeCodeCorrectIndent(class_diagram.top)
+		self.fOut.write()
+		
+		#visit children
+		for c in class_diagram.classes :
+			c.accept(self)
+		 
+		#writing out ObjectManager
+		self.fOut.write('class ObjectManager (ObjectManagerBase):')
+		self.fOut.indent()
+		self.fOut.write('def __init__(self, controller):')
+		self.fOut.indent()
+		self.fOut.write("super(ObjectManager, self).__init__(controller)")
+		self.fOut.dedent()
+		self.fOut.write()
+		
+		self.fOut.write('def instantiate(self, class_name, construct_params):')
+		self.fOut.indent()
+		self.fOut.write("associations = []")
+		for index, c in enumerate(class_diagram.classes) :
+			if index == 0 : 
+				self.fOut.write()
+			else :
+				self.fOut.write('el')
+			self.fOut.extendWrite('if class_name == "' + c.name + '" :')
+			self.fOut.indent()
+			if c.statechart :
+				self.fOut.write('instance =  ' + c.name + '(self.controller, *construct_params)')
+			else :
+				self.fOut.write('instance =  ' + c.name + '(*construct_params)')
+			for a in c.associations :
+				a.accept(self)
+			self.fOut.dedent()
+		self.fOut.write('if instance:')
+		self.fOut.indent()
+		self.fOut.write('return InstanceWrapper(instance, associations)')
+		self.fOut.dedent()
+		self.fOut.write('else :')
+		self.fOut.indent()
+		self.fOut.write('return None')
+		self.fOut.dedent()
+		self.fOut.dedent()
+		self.fOut.dedent()
+		
+		self.fOut.write()
+		if self.platform == Platforms.Threads :
+			controller_sub_class = "ThreadsControllerBase"
+		elif self.platform == Platforms.GameLoop :
+			controller_sub_class = "GameLoopControllerBase"
+		self.fOut.write("from python_runtime.statecharts_core import " + controller_sub_class)
+
+		# write out controller
+		self.fOut.write("class Controller(" + controller_sub_class + "):")
+		self.fOut.indent()
+	
+		# write out __init__ method
+		if class_diagram.default_class.constructors :
+			for constructor in class_diagram.default_class.constructors :
+				self.writeControllerConstructor(class_diagram, constructor.parameters)
+		else :
+			self.writeControllerConstructor(class_diagram)
+
+		self.fOut.dedent()
+		self.fOut.write("def main():")
+		self.fOut.indent()
+		self.fOut.write("controller = Controller()")
+		self.fOut.write("controller.start()")
+		self.fOut.dedent()
+		self.fOut.write()
+	
+		self.fOut.write('if __name__ == "__main__":')
+		self.fOut.indent()
+		self.fOut.write("main()")
+		self.fOut.dedent()
+		self.fOut.write()
+		
+	#helper method
+	def writeControllerConstructor(self, class_diagram, parameters = []):
+		self.writeMethodSignature('__init__', parameters + [FormalParameter("keep_running", "", "True")])
+		self.fOut.indent()
+		self.fOut.write("super(Controller, self).__init__(ObjectManager(self), keep_running)")
+		for i in class_diagram.inports:
+			self.fOut.write('self.addInputPort("' + i + '")')
+		for i in class_diagram.outports:
+			self.fOut.write('self.addOutputPort("' + i + '")')
+		actual_parameters = [p.getIdent() for p in parameters]
+		self.fOut.write('self.object_manager.createInstance("'+ class_diagram.default_class.name +'", [' +  ', '.join(actual_parameters)+ '])')
+		self.fOut.write()
+		self.fOut.dedent()
+
+	def visit_Class(self, class_node):
+		"""
+		Generate code for Class construct
+		"""
+		self.fOut.write()
+		# take care of inheritance
+		if class_node.super_classes:
+			class_node.super_classes.append("RuntimeClassBase")
+			super_classes = []
+			for super_class in class_node.super_classes:
+				super_classes.append(super_class)
+			self.fOut.write("class " + class_node.name + "(" + ", ".join(super_classes) +  "):")
+		else:
+			self.fOut.write("class " + class_node.name + "(RuntimeClassBase):")
+
+		self.fOut.indent()
+		self.fOut.write()
+		
+		if class_node.statechart is not None:
+			# assign each node a unique ID
+			self.fOut.write("# Unique IDs for all statechart nodes")
+			for (i,node) in enumerate(class_node.statechart.composites + class_node.statechart.basics):
+				self.fOut.write(node.full_name + " = " + str(i))
+	
+			self.fOut.write()
+			self.writeMethodSignature("commonConstructor", [FormalParameter("controller", "", "None")])
+		else :
+			self.writeMethodSignature("commonConstructor")
+		self.fOut.indent()
+		self.fOut.write('"""Constructor part that is common for all constructors."""')
+		self.fOut.write("RuntimeClassBase.__init__(self)")
+
+		# write private input/output ports
+		self.fOut.write()
+		self.fOut.write("# User defined input ports")
+		self.fOut.write("self.inports = {}")
+		for p in class_node.inports:
+			self.fOut.write("self.inports[\""+p+"\"] = controller.addInputPort(\""+p+"\", self)")
+
+		# write attributes
+		if class_node.attributes:
+			self.fOut.write()
+			self.fOut.write("# User defined attributes")
+			for attribute in class_node.attributes:
+				if attribute.init_value is None :
+					self.fOut.write("self." +  attribute.name + " = None")
+				else :
+					self.fOut.write("self." +  attribute.name + " = " + attribute.init_value)	 
+			self.fOut.write()
+
+		# if there is a statechart
+		if class_node.statechart is not None:			
+			self.fOut.write("self.controller = controller")
+			self.fOut.write("self.object_manager = controller.getObjectManager()")
+			self.fOut.write("self.current_state = {}")
+			self.fOut.write("self.history_state = {}")
+			if class_node.statechart.nr_of_after_transitions:
+				self.fOut.write("self.timers = {}")
+			self.fOut.write()
+			self.fOut.write("#Initialize statechart :")
+			self.fOut.write()
+			
+			if class_node.statechart.histories:
+				for node in class_node.statechart.combined_history_parents:
+					self.fOut.write("self.history_state[" + class_node.name + "." + node.full_name + "] = []")
+				self.fOut.write()
+
+			for c in class_node.statechart.composites :
+				self.fOut.write("self.current_state[self." + c.full_name + "] = []")
+		
+		self.fOut.dedent()
+		self.fOut.write()
+		
+		self.writeMethodSignature("start")
+		self.fOut.indent()
+		self.fOut.write("super(" + class_node.name + ", self).start()")
+		if class_node.statechart:
+			for default_node in class_node.statechart.root.defaults:
+				if default_node.is_composite:
+					self.fOut.write("self.enterDefault_" + default_node.full_name + "()")
+				elif default_node.is_basic:
+					self.fOut.write("self.enter_" + default_node.full_name + "()")
+		self.fOut.dedent()
+		self.fOut.write()
+		
+		#visit children
+		for i in class_node.constructors :
+			i.accept(self)
+		for i in class_node.destructors :
+			i.accept(self)
+		for i in class_node.methods :
+			i.accept(self)
+		if class_node.statechart is not None:
+			class_node.statechart.accept(self)
+		  
+		# write out str method
+		self.fOut.dedent()
+
+	#helper method
+	def writeMethodSignature(self, name, parameters = []):
+		self.fOut.write("def " + name + "(self")		   
+		for param in parameters :
+			self.fOut.extendWrite(', ')
+			param.accept(self)
+		self.fOut.extendWrite("):")
+		
+	#helper method
+	def writeMethod(self, name, parameters, return_type, body):
+		self.writeMethodSignature(name, parameters)
+		self.fOut.indent()
+		if body.strip():
+			self.writeCodeCorrectIndent(body)
+		else:
+			self.fOut.write("return")
+		self.fOut.write()
+		self.fOut.dedent()
+		
+	def visit_FormalParameter(self, formal_parameter):
+		self.fOut.extendWrite(formal_parameter.getIdent())
+		if formal_parameter.hasDefault() :
+			self.fOut.extendWrite(" = " + formal_parameter.getDefault())
+		
+	def visit_Constructor(self, constructor):
+		self.fOut.write("#The actual constructor")
+		parameters =  [FormalParameter("controller", "", None)] + constructor.getParams()
+		self.writeMethodSignature("__init__", parameters)
+		self.fOut.indent()
+		if constructor.parent_class.statechart is not None :
+			self.fOut.write("self.commonConstructor(controller)")
+		else :
+			self.fOut.write("self.commonConstructor()")
+		if constructor.body :
+			self.fOut.write()
+			self.fOut.write("#constructor body (user-defined)")
+			self.writeCodeCorrectIndent(constructor.body)
+		self.fOut.dedent()
+		self.fOut.write()
+		
+	def visit_Destructor(self, destructor):
+		self.fOut.write("# User defined destructor")
+		self.writeMethod("__del__", [], "", destructor.body)
+		
+	def visit_Method(self, method):
+		self.fOut.write("# User defined method")
+		self.writeMethod(method.name, method.parameters, method.return_type, method.body)
+		
+	def visit_Association(self, association):
+		self.fOut.write('associations.append(Association("' + association.name + '", "' + association.to_class + '", ' + str(association.min) + ', ' + str(association.max) + '))')
+		
+	#helper method
+	def writeTransitionsRecursively(self, current_node):
+		self.fOut.write("def transition_" + current_node.full_name + "(self, event) :")
+		self.fOut.indent()
+		
+		valid_children = []
+		for child in current_node.children :
+			if child.is_composite or child.is_basic :
+				valid_children.append(child)  
+		 
+		self.fOut.write("catched = False")
+		do_dedent = False
+		if current_node.solves_conflict_outer :
+			self.writeFromTransitions(current_node)
+			if current_node.is_parallel_state or current_node.is_composite :
+				self.fOut.write("if not catched :")
+				self.fOut.indent()
+				do_dedent = True
+			
+		if current_node.is_parallel_state:
+			for child in valid_children :	 
+				self.fOut.write("catched = self.transition_" + child.full_name + "(event) or catched")
+		elif current_node.is_composite:
+			for i, child in enumerate(valid_children) :
+				if i > 0 :
+					self.fOut.write("el")
+				else :
+					self.fOut.write()
+				self.fOut.extendWrite("if self.current_state[self." + current_node.full_name + "][0] == self." + child.full_name + ":")
+				self.fOut.indent()
+				self.fOut.write("catched = self.transition_" + child.full_name + "(event)")
+				self.fOut.dedent()
+				
+		if current_node.solves_conflict_outer :
+			if do_dedent :
+				self.fOut.dedent()
+		elif len(current_node.transitions) > 0 :
+				self.fOut.write("if not catched :")
+				self.fOut.indent()
+				self.writeFromTransitions(current_node)
+				self.fOut.dedent()
+			
+		self.fOut.write("return catched")
+		self.fOut.dedent()
+		self.fOut.write();
+		
+		for child in valid_children :
+			self.writeTransitionsRecursively(child)
+				
+	#helper method
+	def writeFromTransitions(self, current_node): 
+		# get all transition out of this state
+		out_transitions = current_node.transitions
+		if len(out_transitions) == 0 :
+			return
+		
+		self.fOut.write('enableds = []')
+		for index, transition in enumerate(out_transitions, start=1):
+			self.writeTransitionCondition(transition, index)
+			
+		self.fOut.write("if len(enableds) > 1 :")
+		self.fOut.indent()
+		self.fOut.write('print "Runtime warning : indeterminism detected in a transition from node ' +  current_node.full_name+ '. Only the first in document order enabled transition is executed."')
+		self.fOut.dedent()
+		self.fOut.write()
+		self.fOut.write("if len(enableds) > 0 :")
+		self.fOut.indent()
+		self.fOut.write('enabled = enableds[0]')	  
+			  
+		for index, transition in enumerate(out_transitions, start=1):
+			self.writeTransitionAction(transition, index)
+		
+		self.fOut.write('catched = True')   
+		self.fOut.dedent()		 
+		self.fOut.write()
+		
+	def visit_FormalEventParameter(self, formal_event_parameter):
+		self.fOut.extendWrite(formal_event_parameter.name)
+		
+	def writeFormalEventParameters(self, transition):
+		parameters = transition.getTrigger().getParameters()
+		if(len(parameters) > 0) :
+			self.fOut.write('parameters = event.getParameters()')
+			for index, parameter in enumerate(parameters):
+				self.fOut.write()
+				parameter.accept(self)
+				self.fOut.extendWrite(' = parameters[' + str(index) + ']')
+		
+		
+	def writeTransitionAction(self, transition, index):
+		if index > 1 :
+			self.fOut.write("el")
+		else :
+			self.fOut.write()
+		self.fOut.extendWrite("if enabled == " + str(index) + " :")
+		self.fOut.indent()
+
+		# handle parameters to actually use them			 
+		self.writeFormalEventParameters(transition)
+		
+		exits = transition.getExitNodes()
+		
+		# write out exit actions
+		if not exits[-1].is_basic:
+			self.fOut.write("self.exit_" + exits[-1].full_name + "()")
+		else:
+			for node in exits:
+				if node.is_basic:
+					self.fOut.write("self.exit_" + node.full_name + "()")
+					
+		# write out trigger actions
+		transition.getAction().accept(self)
+		
+		for (entering_node, is_ending_node) in transition.getEnterNodes() : 
+			if is_ending_node :
+				if entering_node.is_composite:
+					self.fOut.write("self.enterDefault_" + entering_node.full_name + "()")
+				elif entering_node.is_history:
+					if (entering_node.is_history_deep) :
+						self.fOut.write("self.enterHistoryDeep_" + entering_node.parent.full_name + "()")
+					else :
+						self.fOut.write("self.enterHistoryShallow_" + entering_node.parent.full_name + "()")
+				else:
+					self.fOut.write("self.enter_" + entering_node.full_name + "()")
+			else :
+				if entering_node.is_composite:
+					self.fOut.write("self.enter_" + entering_node.full_name + "()")
+
+		self.fOut.dedent()
+						
+	def writeTransitionCondition(self, transition, index):
+		trigger = transition.getTrigger()
+		if not trigger.isUC():  
+			self.fOut.write('if event.name == "' + trigger.getEvent() + '" and event.getPort() == "' + trigger.getPort() + '" :')
+			self.fOut.indent()   
+		# evaluate guard
+		if transition.hasGuard() :   
+			# handle parameters for guard evaluation	   
+			self.writeFormalEventParameters(transition)
+
+			self.fOut.write('if ')
+			transition.getGuard().accept(self)
+			self.fOut.extendWrite(' :')
+			self.fOut.indent()	
+			
+		self.fOut.write("enableds.append(" + str(index) + ")")
+
+		if transition.hasGuard() :
+			self.fOut.dedent()
+		if not trigger.isUC() :
+			self.fOut.dedent()
+		self.fOut.write()
+	
+	def visit_EnterAction(self, enter_method):
+		parent_node = enter_method.parent_node
+		self.writeMethodSignature("enter_" + parent_node.full_name, [])
+		self.fOut.indent()
+		# take care of any AFTER events
+		for transition in parent_node.transitions :
+			trigger = transition.getTrigger()
+			if trigger.isAfter() :
+				self.fOut.write("self.timers[" + str(trigger.getAfterIndex()) + "] = ")
+				trigger.after.accept(self)
+		if enter_method.action:
+			enter_method.action.accept(self)
+		self.fOut.write("self.current_state[self." + parent_node.parent.full_name + "].append(self." + parent_node.full_name + ")")
+		self.fOut.dedent()
+		self.fOut.write()
+		
+	#helper method
+	def writeEnterDefault(self, entered_node):
+		self.writeMethodSignature("enterDefault_" + entered_node.full_name, [])
+		self.fOut.indent()
+		self.fOut.write("self.enter_" + entered_node.full_name + "()")
+		if entered_node.is_composite:
+			l = entered_node.defaults
+			for i in l:
+				if i.is_composite:
+					self.fOut.write("self.enterDefault_" + i.full_name + "()")
+				elif i.is_basic:
+					self.fOut.write("self.enter_" + i.full_name + "()")
+		self.fOut.dedent()
+		self.fOut.write()
+		 
+	def visit_ExitAction(self, exit_method):
+		exited_node = exit_method.parent_node
+		self.writeMethodSignature("exit_" + exited_node.full_name, [])
+		self.fOut.indent()
+		
+		#If the exited node is composite take care of potential history and the leaving of descendants
+		if exited_node.is_composite :
+			#handle history
+			if exited_node.save_state_on_exit :
+				self.fOut.write("self.history_state[self." + exited_node.full_name + "] = self.current_state[self." + exited_node.full_name + "]")
+			
+			#Take care of leaving children
+			children = exited_node.children
+			if exited_node.is_parallel_state:
+				for child in children:
+					if not child.is_history :
+						self.fOut.write("self.exit_" + child.full_name + "()")
+			else:
+				for child in children:
+					if not child.is_history :
+						self.fOut.write("if self." + child.full_name +  " in self.current_state[self." + exited_node.full_name + "] :")
+						self.fOut.indent()
+						self.fOut.write("self.exit_" + child.full_name + "()")
+						self.fOut.dedent()  
+		
+		
+		# take care of any AFTER events
+		for transition in exited_node.transitions :
+			trigger = transition.getTrigger()
+			if trigger.isAfter() :
+				self.fOut.write("self.timers.pop(" + str(trigger.getAfterIndex()) + ", None)")
+				
+		#Execute user-defined exit action if present
+		if exit_method.action:
+			exit_method.action.accept(self)
+			
+		#Adjust state
+		self.fOut.write("self.current_state[self." + exited_node.parent.full_name + "] = []") # SPECIAL CASE FOR ORTHOGONAL??
+		
+		self.fOut.dedent()
+		self.fOut.write()
+		
+			
+	#helper method
+	def writeEnterHistory(self, entered_node, is_deep):
+		self.writeMethodSignature("enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + entered_node.full_name, [])
+		self.fOut.indent()
+		self.fOut.write("if self.history_state[self." + entered_node.full_name + "] == []:")
+		self.fOut.indent()
+		defaults = entered_node.defaults
+
+		for node in defaults:
+			if node.is_basic :
+				self.fOut.write("self.enter_" + node.full_name + "()")
+			elif node.is_composite :
+				self.fOut.write("self.enterDefault_" + node.full_name + "()")
+
+		self.fOut.dedent()
+		self.fOut.write("else:")
+		self.fOut.indent()
+		children = entered_node.children
+		if entered_node.is_parallel_state:
+			for child in children:
+				if not child.is_history :
+					self.fOut.write("self.enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + child.full_name + "()")
+		else:
+			for child in children:
+				if not child.is_history :
+					self.fOut.write("if self." + child.full_name + " in self.history_state[self." + entered_node.full_name + "] :")
+					self.fOut.indent()
+					if child.is_composite:
+						if is_deep :
+							self.fOut.write("self.enter_" + child.full_name + "()")
+							self.fOut.write("self.enterHistoryDeep_" + child.full_name + "()")
+						else :
+							self.fOut.write("self.enterDefault_" + child.full_name + "()")
+					else:
+						self.fOut.write("self.enter_" + child.full_name + "()")
+					self.fOut.dedent()
+		self.fOut.dedent()
+		self.fOut.dedent()
+		self.fOut.write()
+
+	def visit_StateChart(self, statechart):
+		self.fOut.write("# Statechart enter/exit action method(s) :")
+		self.fOut.write()
+		
+		#visit enter and exit action of children
+		for i in statechart.composites + statechart.basics:
+			if i is not statechart.root :
+				i.enter_action.accept(self)
+				i.exit_action.accept(self)
+
+		# write out statecharts methods for enter/exit state
+		if len(statechart.composites) > 1 :
+			self.fOut.write("#Statechart enter/exit default method(s) :")
+			self.fOut.write()
+			for i in statechart.composites :
+				if i is not statechart.root :
+					self.writeEnterDefault(i)
+
+		# write out statecharts methods for enter/exit history
+		if statechart.histories:
+			self.fOut.write("#Statechart enter/exit history method(s) :")
+			self.fOut.write()
+			for i in statechart.shallow_history_parents:
+				self.writeEnterHistory(i, False)
+			for i in statechart.deep_history_parents:
+				self.writeEnterHistory(i, True) 
+		   
+		   
+		self.fOut.write("#Statechart transitions :")	 
+		self.fOut.write()
+		self.writeTransitionsRecursively(statechart.root)			
+				
+		# write out transition function
+		self.fOut.write("# Execute transitions")
+		self.fOut.write("def transition(self, event = Event(\"\")):")
+		self.fOut.indent()
+		self.fOut.write("self.state_changed = self.transition_" + statechart.root.full_name + "(event)")
+		self.fOut.dedent()
+
+		# write out inState function
+		self.fOut.write("# inState method for statechart")
+		self.fOut.write("def inState(self, nodes):")
+		self.fOut.indent()
+		self.fOut.write("for actives in self.current_state.itervalues():")
+		self.fOut.indent()
+		self.fOut.write("nodes = [node for node in nodes if node not in actives]")
+		self.fOut.write("if not nodes :")
+		self.fOut.indent()
+		self.fOut.write("return True")
+		self.fOut.dedent()
+		self.fOut.dedent()
+		self.fOut.write("return False")
+		self.fOut.dedent()
+		self.fOut.write()
+		
+	def visit_ExpressionPartString(self, bare_string):
+		self.fOut.extendWrite(bare_string.string)
+		
+	def visit_SelfReference(self, self_reference):
+		self.fOut.extendWrite("self")
+		
+	def visit_StateReference(self, state_ref):
+		self.fOut.extendWrite("[" + ",".join(["self." + node.full_name for node in state_ref.getNodes()]) + "]")
+		
+	def visit_InStateCall(self, in_state_call):
+		self.fOut.extendWrite("self.inState(")
+		in_state_call.target.accept(self)
+		self.fOut.extendWrite(")")
+		
+	def visit_RaiseEvent(self, raise_event):
+		if raise_event.isNarrow() or raise_event.isBroad():
+			self.fOut.write('send_event = Event("' + raise_event.getEventName() + '", parameters = [')
+		elif raise_event.isLocal():
+			self.fOut.write('self.addEvent(Event("' + raise_event.getEventName() +'", parameters = [')
+		elif raise_event.isOutput():
+			self.fOut.write('self.controller.outputEvent(Event("' + raise_event.getEventName() + '", port="' + raise_event.getPort() + '", parameters = [')
+		elif raise_event.isCD():
+			self.fOut.write('self.object_manager.addEvent(Event("' + raise_event.getEventName() + '", parameters = [self, ')
+		first_param = True
+		for param in raise_event.getParameters() :
+			if first_param :
+				first_param = False
+			else :
+				self.fOut.extendWrite(',')
+			param.accept(self)
+		if raise_event.isNarrow():
+			self.fOut.extendWrite('])')
+			self.fOut.write('self.object_manager.addEvent(Event("narrow_cast", parameters = [self, ' + raise_event.getTarget() + ' , send_event]))')
+		elif raise_event.isBroad():
+			self.fOut.extendWrite('])')
+			self.fOut.write('self.object_manager.addEvent(Event("broad_cast", parameters = [send_event]))')
+		else :
+			self.fOut.extendWrite(']))')
+			
+	def visit_Script(self, script):
+		self.writeCodeCorrectIndent(script.code)
+		
+	def visit_Log(self, log):
+		self.fOut.write('print "' + log.message + '"')
+		
+	def visit_Assign(self, assign):
+		self.fOut.write()
+		assign.lvalue.accept(self)
+		self.fOut.extendWrite(" = ")
+		assign.expression.accept(self)
+	

+ 77 - 0
exported_to_sccdxml/python_sccd_compiler/path_calculator.py

@@ -0,0 +1,77 @@
+from compiler_exceptions import *
+from visitor import Visitor
+
+class PathCalculator(Visitor):
+	""" Computes the states that must be exited and entered for a specific transition if the system is to make
+		that transition. 
+	"""
+	
+	def visit_ClassDiagram(self, class_diagram): 
+		for c in class_diagram.classes :
+			c.accept(self)
+
+	def visit_Class(self, c):
+		if c.statechart:
+			c.statechart.accept(self)
+		
+	def visit_StateChart(self, statechart):
+		for node in statechart.basics + statechart.composites:
+			node.accept(self)
+					 
+	def visit_StateChartNode(self, node):
+		for transition in node.transitions :
+			transition.accept(self)
+			
+	def visit_StateChartTransition(self, transition):
+		#Find the scope of the transition (lowest common proper ancestor)
+		#TODO: Could it be made more efficient if we calculated the LCA from the source node and just one of the target nodes?
+		LCA = self.calculateLCA(transition)
+		
+		#Calculate exit nodes
+		transition.exit_nodes = [transition.parent_node]
+		for node in transition.parent_node.getAncestors() :
+			if (node == LCA) :
+				break
+			transition.exit_nodes.append(node)
+	   
+		#Calculate enter nodes
+		transition.enter_nodes = []
+		
+		#we then add the branching paths to the other nodes
+		for target_node in transition.target.target_nodes :
+			to_append_list = [(target_node, True)]
+			for anc in target_node.getAncestors() :
+				if anc == LCA : #If we reach the LCA in the ancestor hierarchy we break
+					break;
+				to_add = True;  #boolean value to see if the current ancestor should be added to the result
+				for enter_node_entry in transition.enter_nodes :
+					if anc == enter_node_entry[0] :
+						to_add = False #If we reach an ancestor in the hierarchy that is already listed as enter node, we don't add and break
+						break
+				if to_add:
+					to_append_list.append((anc, False)) #Only the first from the ancestor list should get True
+				else :
+					break
+					
+			to_append_list.reverse() #the enter sequence should be in the reverse order of the ancestor hierarchy
+			transition.enter_nodes.extend(to_append_list)
+
+		# Calculate arena
+		current = LCA
+		while not current.is_composite:
+			current = current.parent
+		transition.arena = current
+
+	def calculateLCA(self, transition):
+		"""
+		Calculates the lowest common ancestor of a transition
+		""" 
+		for anc in transition.parent_node.getAncestors() :
+			all_descendants = True 
+			for node in transition.target.getNodes() :
+				if not node.isDescendantOf(anc) :
+					all_descendants = False
+					break
+			if all_descendants :
+				return anc
+		return None

+ 353 - 0
exported_to_sccdxml/python_sccd_compiler/python_writer.py

@@ -0,0 +1,353 @@
+from generic_language_constructs import *
+
+class PythonWriter(GenericWriterBase):
+	def __init__(self, outputter):
+		self.out = outputter
+
+
+	def writeComment(self, text):
+		self.out.write("# " + text)
+
+	def writeMultiLineComment(self, text):
+		self.out.write("\"\"\"\n" + text + "\n\"\"\"")
+
+	def visit_AndOperator(self, a):
+		self.out.extendWrite(" and ")
+
+	def visit_ArrayContains(self, a):
+		array = a.getArrayExpression()
+		el = a.getElementExpression()
+
+		el.accept(self)
+		self.out.extendWrite(" in ")
+		array.accept(self)
+
+	def visit_ArrayExpression(self, a):
+		self.out.extendWrite("[")
+		self.writeCommaSeparated(a.getElements())
+		self.out.extendWrite("]")
+
+	def visit_ArrayIndexOf(self, a):
+		array = a.getArrayExpression()
+		el = a.getElementExpression()
+
+		array.accept(self)
+		self.out.extendWrite(".index(")
+		el.accept(self)
+		self.out.extendWrite(")")
+
+	def visit_ArrayLength(self, a):
+		self.out.extendWrite("len(")
+		a.getArrayExpression().accept(self)
+		self.out.extendWrite(")")
+
+	def visit_ArrayPushBack(self, a):
+		array = a.getArrayExpression()
+		el = a.getElementExpression()
+
+		array.accept(self)
+		self.out.extendWrite(".append(")
+		el.accept(self)
+		self.out.extendWrite(")")
+
+	def visit_AST(self, ast):
+		self.writeAll(ast.getEntries())
+
+	def visit_Block(self, b):
+		self.out.indent()
+		self.writeAll(b.getEntries())
+		if b.isEmpty():
+			self.out.write("pass")
+		self.out.dedent()
+
+	def visit_BreakStatement(self, b):
+		self.out.write("break")
+
+	def visit_Class(self, c):
+		class_name = c.getIdentifier()
+		constructor = c.getConstructor()
+		super_classes = c.getSuperClassIdentifierList()
+		description = c.getDescription()
+
+		self.out.write()
+		if description:
+			self.writeComment(description)
+		self.out.write("class " + class_name)
+		if super_classes:
+			self.out.extendWrite("(" + ", ".join(super_classes) + ")")
+		self.out.extendWrite(":")
+		self.out.indent()
+		constructor.accept(self)
+		self.writeAll(c.getMembers())
+		self.out.dedent()
+
+	def visit_Constructor(self, constructor):
+		#class_name = constructor.getClass().getIdentifier()
+		parameters = constructor.getFormalParameters()
+		body = constructor.getBody()
+
+		self.out.write("def __init__")
+		parameters.accept(self)
+		self.out.extendWrite(":")
+		body.accept(self)
+
+	def visit_Destructor(self, destructor):
+		#class_name = destructor.getClass().getIdentifier()
+		parameters = destructor.getFormalParameters()
+		body = destructor.getBody()
+
+		self.out.write("def __del__")
+		parameters.accept(self)
+		self.out.extendWrite(":")
+		body.accept(self)
+
+	def visit_ElseStatement(self, else_stmt):
+		self.out.write("else:")
+		else_stmt.getBody().accept(self)
+
+	def visit_ElseIfStatement(self, else_if):
+		condition = else_if.getCondition()
+		body = else_if.getBody()
+
+		if else_if.isFirst():
+			self.out.write("if ")
+		else:
+			self.out.write("elif ")
+		condition.accept(self)
+		self.out.extendWrite(":")
+		body.accept(self)
+
+	def visit_EqualsOperator(self, e):
+		self.out.extendWrite(" == ")
+
+	def visit_ExpressionStatement(self, stmt):
+		self.out.write() # expressions don't begin with a newline
+		stmt.expression.accept(self)
+
+	def visit_FalseExpression(self, f):
+		self.out.extendWrite("False")
+
+	def visit_FormalParameter(self, parameter):
+		self.out.extendWrite(parameter.getIdentifier())
+		if parameter.getDefaultValue():
+			self.out.extendWrite(" = None") # correct default value will be assigned in function body
+
+	def visit_FormalParameters(self, p):
+		params = [Literal("self")] + p.getParameterList()
+		self.writeTuple(params)
+
+	def visit_ForLoopCurrentElement(self, el):
+		#collection = el.getCollectionExpression()
+		iterator = el.getIteratorIdentifier()
+
+		self.out.extendWrite(iterator)
+
+	def visit_ForLoopIterateArray(self, loop):
+		collection = loop.getCollectionExpression()
+		iterator = loop.getIteratorIdentifier()
+		body = loop.getBody()
+
+		self.out.write("for " + iterator + " in ")
+		collection.accept(self)
+		self.out.extendWrite(":")
+		body.accept(self)
+
+	def visit_ForLoopIterateMapValues(self, loop):
+		collection = loop.getCollectionExpression()
+		iterator = loop.getIteratorIdentifier()
+		body = loop.getBody()
+
+		self.out.write("for " + iterator + " in ")
+		collection.accept(self)
+		self.out.extendWrite(".itervalues():")
+		body.accept(self)
+
+	def visit_IfStatement(self, if_stmt):
+		condition = if_stmt.getCondition()
+		body = if_stmt.getBody()
+
+		self.out.write("if ")
+		condition.accept(self)
+		self.out.extendWrite(":")
+		body.accept(self)
+
+	def visit_IncludeStatement(self, i):
+		module_path = i.getModulePath()
+		imported_symbols = i.getImportedSymbols()
+
+		self.out.write("from ")
+		for j in range(len(module_path)):
+			if j != 0:
+				self.out.extendWrite(".")
+			module_path[j].accept(self)
+		self.out.extendWrite(" import ")
+		if imported_symbols:
+			self.writeCommaSeparated(imported_symbols)
+		else:
+			self.out.extendWrite("*")
+
+	def visit_LocalVariableDeclaration(self, decl):
+		identifier = decl.getIdentifier()
+		init_value = decl.getInitValue()
+
+		self.out.extendWrite(decl.getIdentifier())
+		if init_value:
+			self.out.extendWrite(" = ")
+			init_value.accept(self)
+
+	def visit_LogStatement(self, l):
+		self.out.write("print \"" + l.getMessage() + "\"")
+
+	def visit_MapExpression(self, m):
+		elements = m.getElements()
+		self.out.extendWrite("{")
+		keys = elements.keys()
+		for i in range(len(keys)):
+			if i != 0:
+				self.out.extendWrite(", ")			
+			self.out.extendWrite(keys[i] + " : ")
+			self.out.extendWrite(" : ")
+			elements[keys[i]].accept(self)
+		self.out.extendWrite("}")
+
+	def visit_MapIndexedExpression(self, i):
+		m = i.getMapExpression()
+		key = i.getKeyExpression()
+
+		m.accept(self)
+		self.out.extendWrite("[")
+		key.accept(self)
+		self.out.extendWrite("]")
+
+	def visit_MapRemoveElement(self, stmt):
+		map_expr = stmt.getMapExpression()
+		key_expr = stmt.getKeyExpression()
+
+		self.out.write() # this is a statement, not an expression
+		map_expr.accept(self)
+		self.out.extendWrite(".pop(")
+		key_expr.accept(self)
+		self.out.extendWrite(", None)")
+
+	def visit_Method(self, method):
+		class_name = method.getClass().getIdentifier()
+		method_name = method.getIdentifier()
+		description = method.getDescription()
+		body = method.getBody()
+		parameters = method.getFormalParameters()
+
+		self.out.write()
+		if description:
+			self.writeComment(description)
+		self.out.write("def " + method_name + "")
+		parameters.accept(self)
+		self.out.extendWrite(":")
+		body.accept(self)
+
+	def visit_MethodBody(self, body):
+		method = body.getMethod()
+		formal_parameters = method.getFormalParameters()
+		formal_parameter_list = formal_parameters.getParameterList()
+
+		self.out.indent()
+		# check for undefined parameters and replace them with default values
+		for p in formal_parameter_list:
+			p_id = p.getIdentifier()
+			p_default = p.getDefaultValue()
+			if p_default:
+				self.out.write("if " + p_id + " == None: " + p_id + " = ")
+				p_default.accept(self)
+		self.writeAll(body.getEntries())
+		if body.isEmpty():
+			self.out.write("pass")
+		self.out.dedent()
+
+	def visit_NewExpression(self, new):
+		type_expr = new.getTypeExpression()
+		params = new.getActualParameters()
+
+		type_expr.accept(self)
+		params.accept(self)
+
+	def visit_NoneExpression(self, n):
+		self.out.extendWrite("None")
+
+	def visit_NotOperator(self, n):
+		self.out.extendWrite("not ")
+
+	def visit_OrOperator(self, o):
+		self.out.extendWrite(" or ")
+
+	def visit_Package(self, package):
+		name = package.getIdentifier()
+		description = package.getDescription()
+
+		self.writeComment("package \"" + name + "\"")
+		if description:
+			self.writeComment(description)
+		self.writeAll(package.getDeclarations())
+
+	def visit_ReturnStatement(self, r):
+		self.out.write("return ")
+		r.getExpression().accept(self)
+
+	def visit_RuntimeModuleIdentifier(self, r):
+		self.out.extendWrite("python_runtime")
+
+	def visit_SelfExpression(self, s):
+		self.out.extendWrite("self")
+
+	def visit_StaticAttribute(self, attr):
+		name = attr.getIdentifier()
+		init_value = attr.getInitValue()
+		#class_name = attr.getClass().getIdentifier()
+
+		if init_value:
+			self.out.write(name + " = ")
+			init_value.accept(self)
+		else:
+			self.out.write(name + " = None")
+
+	def visit_SuperClassConstructorCall(self, call):
+		super_class = call.getSuperClassIdentifier()
+		params = call.getActualParameters()
+		param_list = [Literal("self")] + params.getParameterList()
+		params = ActualParameters(param_list)
+
+		self.out.extendWrite(super_class)
+		self.out.extendWrite(".__init__")
+		params.accept(self)
+
+	def visit_SuperClassDestructorCall(self, call):
+		super_class = call.getSuperClassIdentifier()
+		params = call.getActualParameters()
+		param_list = [Literal("self")] + params.getParameterList()
+		params = ActualParameters(param_list)
+
+		self.out.extendWrite("if hasattr(")
+		self.out.extendWrite(super_class)
+		self.out.extendWrite(", \"__del__\"):")
+		self.out.indent()
+		self.out.write(super_class)
+		self.out.extendWrite(".__del__")
+		params.accept(self)
+		self.out.dedent()
+
+	def visit_SuperClassMethodCall(self, call):
+		super_class = call.getSuperClassIdentifier()
+		method_name = call.getMethodIdentifier()
+		params = call.getActualParameters()
+		param_list = [Literal("self")] + params.getParameterList()
+		params = ActualParameters(param_list)
+
+		self.out.extendWrite(super_class + "." + method_name)
+		params.accept(self)
+
+	def visit_ThrowExceptionStatement(self, stmt):
+		self.out.write("raise Exception(")
+		stmt.getExpression().accept(self)
+		self.out.extendWrite(")")
+
+	def visit_TrueExpression(self, t):
+		self.out.extendWrite("True")
+

File diff suppressed because it is too large
+ 1131 - 0
exported_to_sccdxml/python_sccd_compiler/sccd_constructs.py


+ 129 - 0
exported_to_sccdxml/python_sccd_compiler/sccdc.py

@@ -0,0 +1,129 @@
+import argparse
+import os
+import sys
+from generic_generator import GenericGenerator, Platforms
+from utils import Enum, Logger, FileWriter
+from super_class_linker import SuperClassLinker
+from state_linker import StateLinker
+from path_calculator import PathCalculator
+from sccd_constructs import ClassDiagram
+from generic_language_constructs import GenericConstruct
+from compiler_exceptions import CompilerException
+
+from javascript_writer import JavascriptWriter
+from python_writer import PythonWriter
+
+def generate(input_file, output_file, target_language, platform):
+	sccd = xmlToSccd(input_file)
+
+	if not target_language:
+		if sccd.language:
+			target_language = sccd.language
+		else:
+			target_language = "python" # default
+	elif sccd.language and target_language != sccd.language:
+		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" and not output_file.endswith(".py") :
+		output_file += ".py"
+	elif target_language == "javascript" and not output_file.endswith(".js") :
+		output_file += ".js"
+
+	generic = sccdToGeneric(sccd, platform)
+	genericToTarget(generic, target_language, output_file)
+
+def xmlToSccd(xml_file):
+	cd = ClassDiagram(xml_file) # create AST
+	cd.accept(SuperClassLinker())
+	#SuperClassLinker().visit(cd) # visitor linking super classs references
+	StateLinker().visit(cd) # visitor fixing state references
+	PathCalculator().visit(cd) # visitor calculating paths
+	return cd
+	
+def sccdToGeneric(sccd, platform):
+	succesfull_generation = False
+	generator = GenericGenerator(platform)
+	sccd.accept(generator)
+	generic = generator.get()
+	Logger.showInfo("Classes <" + ", ".join(sccd.class_names) + "> have been converted to generic language constructs.")
+	return generic
+
+def genericToTarget(generic, target_language, output_file):
+	try:
+		f = FileWriter(output_file)
+		if target_language == "javascript":
+			writer = JavascriptWriter(f)
+		elif target_language == "python":
+			writer = PythonWriter(f)
+		else:
+			raise Exception("Language not supported")
+		generic.accept(writer)
+		Logger.showInfo("Generic language constructs have been converted to target language constructs and have been written to file '" + output_file + "'.")
+	finally:
+		f.close()
+		
+def main():
+	parser = argparse.ArgumentParser()
+	parser.add_argument('input', help='The path to the XML file to be compiled.')
+	parser.add_argument('-o', '--output', type=str, help='The path to the generated code. Defaults to the same name as the input file but with matching extension.')
+	parser.add_argument('-v', '--verbose', type=int, help='2 = all output; 1 = only warnings and errors; 0 = only errors; -1 = no output.  Defaults to 2.', default = 2)
+	parser.add_argument('-p', '--platform', type=str, help="Let the compiled code run on top of threads, gameloop or eventloop. The default is eventloop.")
+	parser.add_argument('-l', '--language', type=str, help='Target language, either "javascript" or "python". Defaults to the latter.')
+	
+	args = vars(parser.parse_args())
+	#Set verbose
+	if args['verbose'] is not None:
+		if args['verbose'] in [-1, 0,1,2] :
+			Logger.verbose = args['verbose']
+		else :
+			Logger.showError("Invalid verbose argument.")
+	else :
+		Logger.verbose = 2
+
+	#Set source file
+	source = args['input']
+	if not source.endswith(".xml") :
+		Logger.showError("Input file not valid.")
+		return
+	
+	#Set target language
+	if args['language'] :
+		target_language = args['language']
+	else :
+		target_language = ""
+
+	#Set output file
+	if args['output'] :
+		output = args['output']
+	else:
+		output = os.path.splitext(os.path.split(source)[1])[0]
+		
+	#Set platform	
+	if args['platform'] :
+		args['platform'] = args['platform'].lower()
+		if args['platform'] == "threads" :
+			platform = Platforms.Threads
+		elif args['platform'] == "gameloop" :
+			platform = Platforms.GameLoop
+		elif args['platform'] == "eventloop" :
+			platform = Platforms.EventLoop
+		else :
+			Logger.showError("Invalid platform.")
+			return		  
+	else :
+		platform = Platforms.EventLoop
+		
+	#Compile	
+	try :
+		generate(source, output, target_language, platform)
+	except CompilerException as exception :
+		Logger.showError(str(exception));
+		return 1
+
+	return 0
+
+if __name__ == "__main__":
+	sys.exit(main())
+
+

+ 156 - 0
exported_to_sccdxml/python_sccd_compiler/state_linker.py

@@ -0,0 +1,156 @@
+from visitor import Visitor
+from sccd_constructs import INSTATE_SEQ
+from compiler_exceptions import CompilerException
+from lexer import Lexer, Token, TokenType
+
+class StateReferenceException(CompilerException):
+	pass
+
+class StateLinker(Visitor):
+	
+	def __init__(self):
+		self.visiting_statechart = None
+		self.visiting_node = None
+		self.lexer = Lexer()
+	
+	def visit_ClassDiagram(self, class_diagram): 
+		for c in class_diagram.classes :
+			c.accept(self)
+
+	def visit_Class(self, c):
+		if c.statechart:
+			c.statechart.accept(self)
+		
+	def visit_StateChart(self, statechart):
+		self.visiting_statechart = statechart
+		for node in statechart.basics + statechart.composites:
+			node.accept(self)
+					 
+	def visit_StateChartNode(self, node):
+		self.visiting_node = node
+		node.enter_action.accept(self)
+		node.exit_action.accept(self)
+		for transition in node.transitions :
+			transition.accept(self)
+			
+	def visit_StateChartTransition(self, transition):
+		try :
+			transition.target.accept(self)
+		except StateReferenceException as exception :
+			raise StateReferenceException("Transition from <" + self.visiting_node.full_name + "> has invalid target. " + exception.message)
+		try :
+			transition.action.accept(self)
+		except StateReferenceException as exception :
+			raise StateReferenceException("Transition from <" + self.visiting_node.full_name + "> has invalid action. " + exception.message)
+		try :
+			if transition.guard :
+				transition.guard.accept(self)
+		except StateReferenceException as exception :
+			raise StateReferenceException("Transition from <" + self.visiting_node.full_name  + "> has invalid guard. " + exception.message)
+		
+	def visit_StateReference(self, state_reference):
+		state_reference.target_nodes = []
+		
+		current_node = None #Will be used to find the target state(s)
+		split_stack = [] #used for branching
+
+		self.lexer.input(state_reference.path_string)
+
+		for token in self.lexer.tokens() :
+			
+			if current_node == None : #current_node is not set yet or has been reset, the CHILD token can now have a special meaning
+				if token.type == TokenType.SLASH :
+					#Root detected
+					current_node = self.visiting_statechart.root
+					#Token consumed so continue
+					continue
+				else :
+					current_node = self.visiting_node
+					
+			if token.type == TokenType.DOT :
+				#Advance to next token
+				token = self.lexer.nextToken()
+				
+				if token is None or token.type == TokenType.SLASH :
+					#CURRENT operator "." detected
+					continue
+				elif token.type == TokenType.DOT :
+					#Advance to next token
+					token = self.lexer.nextToken()
+					if token is None or token.type == TokenType.SLASH :
+						#PARENT operator ".." detected
+						current_node = current_node.parent
+						if current_node is None :
+							raise StateReferenceException("Illegal use of PARENT \"..\" operator at position " + str(token.pos) + " in state reference. Root of statechart reached.")
+					
+					else :
+						raise StateReferenceException("Illegal use of PARENT \"..\" operator at position " + str(token.pos) + " in state reference.")
+	
+				else :
+					raise StateReferenceException("Illegal use of CURRENT \".\" operator at position " + str(token.pos) + " in state reference.")
+					
+			elif token.type == TokenType.SLASH :
+				continue
+			elif token.type == TokenType.WORD :
+				#try to advance to next child state
+				cname = token.val
+				found = False
+				for child in current_node.children :
+					if child.name == cname : 
+						found = True
+						current_node = child
+						break
+				if not found :
+					raise StateReferenceException("Refering to non exiting node at posisition " + str(token.pos) + " in state reference.")
+			elif token.type == TokenType.LBRACKET :
+				split_stack.append(current_node)
+			elif token.type == TokenType.RBRACKET :
+				if len(split_stack) > 0 :
+					split_stack.pop()
+				else :
+					raise StateReferenceException("Invalid token at position " + str(token.pos) + " in state reference.")
+			elif token.type == TokenType.COMMA :
+				state_reference.target_nodes.append(current_node)
+				if len(split_stack) > 0 :
+					current_node = split_stack[-1]
+				else :
+					current_node = None
+			
+			else :
+				raise StateReferenceException("Invalid token at position " + str(token.pos) + " in state reference.")
+		
+		if (len(split_stack) != 0) or (current_node is None) : #RB missing or extra COMMA
+			raise StateReferenceException("State reference ends unexpectedly.")
+		
+		#TODO better validation of the target! When is it a valid state configuration?
+		for node in state_reference.target_nodes :
+			if current_node == node :
+				raise StateReferenceException("A state reference can't reference the same node more than once.")
+			if node.isDescendantOrAncestorOf(current_node) :
+				raise StateReferenceException("A state reference can't reference a node and one of its descendants.");
+		
+		state_reference.target_nodes.append(current_node)
+			
+		if len(state_reference.target_nodes) == 0 :
+			raise StateReferenceException("Meaningless state reference.")
+
+	def visit_Expression(self, expression):
+		for part in expression.expression_parts :
+			part.accept(self)
+
+	def visit_EnterExitAction(self, action):
+		if action.action :
+			action.action.accept(self)
+			
+	def visit_Action(self, action):
+		for subaction in action.sub_actions :
+			subaction.accept(self)
+			
+	def visit_InStateCall(self, call):
+		try :
+			call.target.accept(self)
+		except StateReferenceException :
+			raise StateReferenceException("Invalid state reference for " + INSTATE_SEQ + " call.")
+		
+	def visit_Assign(self, assign):
+		assign.expression.accept(self)

+ 222 - 0
exported_to_sccdxml/python_sccd_compiler/stateful_writer.py

@@ -0,0 +1,222 @@
+# Used by generic_generator to create an AST of generic language constructs
+# while visiting an AST of SCCD constructs
+
+from generic_language_constructs import *
+
+class ExpressionWrapper(SimpleExpression, AbstractList):
+	def __init__(self, expr = None):
+		self.expr = expr
+
+	def add(self, expr):
+		if self.expr:
+			raise Exception("Expression can only be set once.")
+		self.expr = expr
+
+	def get(self):
+		return self.expr
+
+
+class StatefulWriter:
+
+	def __init__(self):
+		self.ast = AST()
+		self.last = None
+		self.stack = [self.ast]
+
+	def get(self):
+		return self.stack[-1]
+
+	def startRecordingExpression(self):
+		self.stack.append(ExpressionWrapper())
+
+	def stopRecordingExpression(self):
+		self.last = self.stack.pop()
+		if not isinstance(self.last, ExpressionWrapper):
+			raise Exception("Assymetry detected.")
+		return self.last.get()
+
+
+	def add(self, block_entry):
+		self.get().add(block_entry)
+
+	#### SHORTHANDS ####
+
+	def addActualParameter(self, expr):
+		self.get().getActualParameters().add(expr)
+
+	def addAssignment(self, lhs, rhs):
+		self.add(AssignmentExpression(lhs, rhs))
+
+	def addInclude(self, module_path, symbols = None):
+		self.add(IncludeStatement(module_path, symbols))
+
+	def addComment(self, comment):
+		self.add(SingleLineComment(comment))
+
+	def addFormalParameter(self, parameter, default_value = None):
+		self.get().getFormalParameters().add(FormalParameter(parameter, default_value))
+
+	def addMultiLineComment(self, comment):
+		self.add(MultiLineComment(comment))
+
+	def addRawCode(self, raw):
+		self.add(RawCode(raw))
+
+	def addStaticAttribute(self, identifier, init_value):
+		self.add(StaticAttribute(self.get(), identifier, init_value))
+
+	def addVSpace(self):
+		self.add(VSpace())
+
+
+	#### STATEFUL OPERATIONS ####
+
+	def begin(self, generic_construct):
+		self.add(generic_construct)
+		self.stack.append(generic_construct)
+
+	def beginArray(self):
+		self.begin(ArrayExpression())
+
+	def beginClass(self, class_name, super_class_names = None, comment = None):
+		self.begin(Class(class_name, super_class_names, comment))
+
+	def beginConstructor(self):
+		c = self.get().getConstructor()
+		self.stack.append(c)
+
+	def beginDestructor(self):
+		d = self.get().getDestructor()
+		self.stack.append(d)
+
+	def beginElse(self):
+		self.begin(ElseStatement())
+
+	def beginElseIf(self, condition):
+		self.begin(ElseIfStatement(condition, not isinstance(self.last, ElseIfStatement)))
+
+	def beginForLoopIterateArray(self, array_expr, iterator_identifier):
+		f = ForLoopIterateArray(array_expr, iterator_identifier)
+		self.get().add(f)
+		self.stack.append(f.getBody())
+
+	def beginForLoopIterateMapValues(self, map_expr, iterator_identifier):
+		f = ForLoopIterateMapValues(map_expr, iterator_identifier)
+		self.get().add(f)
+		self.stack.append(f.getBody())
+
+	def beginFunctionCall(self, function_expr):
+		f = FunctionCall(function_expr)
+		self.get().add(f)
+		self.stack.append(f)
+
+	def beginGlue(self):
+		g = Glue()
+		self.get().add(g)
+		self.stack.append(g)
+
+	def beginIf(self, condition):
+		self.begin(IfStatement(condition))
+
+
+	def beginMethod(self, name, comment = None):
+		m = Method(self.get(), name, comment)
+		self.get().add(m)
+		self.stack.append(m)
+
+	def beginMethodBody(self):
+		b = self.get().getBody()
+		self.stack.append(b)
+
+	def beginPackage(self, package_name):
+		p = Package(package_name)
+		self.get().add(p)
+		self.stack.append(p)
+
+	def beginSuperClassConstructorCall(self, super_class_identifier):
+		c = SuperClassConstructorCall(super_class_identifier)
+		self.get().add(c)
+		self.stack.append(c)
+
+	def beginSuperClassDestructorCall(self, super_class_identifier):
+		c = SuperClassDestructorCall(super_class_identifier)
+		self.get().add(c)
+		self.stack.append(c)
+
+	def beginSuperClassMethodCall(self, super_class_identifier, method_identifier):
+		c = SuperClassMethodCall(super_class_identifier, method_identifier)
+		self.get().add(c)
+		self.stack.append(c)
+
+
+	def end(self):
+		self.stack.pop()
+
+	def endArray(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, ArrayExpression)
+
+	def endClass(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, Class)
+
+	def endConstructor(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, Constructor)
+
+	def endDestructor(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, Destructor)
+
+	def endElse(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, ElseStatement)
+
+	def endElseIf(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, ElseIfStatement)
+
+	def endForLoopIterateArray(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, ForLoopBody)
+
+	def endForLoopIterateMapValues(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, ForLoopBody)
+
+	def endFunctionCall(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, FunctionCall)
+
+	def endGlue(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, Glue)
+
+	def endIf(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, IfStatement)
+
+	def endMethod(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, Method)
+
+	def endMethodBody(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, MethodBody)
+
+	def endPackage(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, Package)
+
+	def endSuperClassConstructorCall(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, SuperClassConstructorCall)
+
+	def endSuperClassDestructorCall(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, SuperClassDestructorCall)
+
+	def endSuperClassMethodCall(self):
+		self.last = self.stack.pop()
+		assert isinstance(self.last, SuperClassMethodCall)
+

+ 52 - 0
exported_to_sccdxml/python_sccd_compiler/super_class_linker.py

@@ -0,0 +1,52 @@
+from compiler_exceptions import *
+from utils import Logger
+from visitor import Visitor
+
+class SuperClassLinker(Visitor):
+	""" Computes the states that must be exited and entered for a specific transition if the system is to make
+		that transition. 
+	"""
+	
+	def visit_ClassDiagram(self, class_diagram): 
+		for c in class_diagram.classes :
+			c.accept(self)
+
+	def visit_Class(self, c):
+		# replace super class names by super class objects
+		for s in c.super_classes:
+			super_class = None
+			for clas in c.class_diagram.classes:
+				if clas.name == s:
+					super_class = clas
+			if super_class == None:
+				Logger.showWarning("Class <" + c.name + "> has undefined super class <" + s + ">.")
+			else:
+				c.super_class_objs[s] = super_class
+
+		# calculate list of abstract methods
+		c.abstract_method_names = getClassAbstractMethodNames(c)
+
+		# check if <super> tags exist for all inherited classes
+		for name,obj in c.super_class_objs.iteritems():
+			if obj:
+				if name not in c.constructors[0].super_class_parameters:
+					num_params = len(obj.constructors[0].parameters)
+					if num_params > 0:
+						raise CompilerException("Class <" + c.name + "> inherits <" + name + "> and <" + name + ">'s constructor has " + str(num_params) + " parameter(s), but there's no <super> entry for that class in <" + c.name + ">'s constructor.")
+
+def getClassAbstractMethodNames(c):
+	abstract_method_names = []
+	non_abstract_method_names = []
+	for m in c.methods:
+		if m.isAbstract():
+			abstract_method_names.append(m.name)
+		else:
+			non_abstract_method_names.append(m.name)
+	for s in c.super_classes:
+		if s in c.super_class_objs:
+			super_abstract_method_names = getClassAbstractMethodNames(c.super_class_objs[s])
+			for m_name in super_abstract_method_names:
+				if m_name not in non_abstract_method_names:
+					abstract_method_names.append(m_name)
+	return abstract_method_names
+

+ 118 - 0
exported_to_sccdxml/python_sccd_compiler/utils.py

@@ -0,0 +1,118 @@
+from compiler_exceptions import CodeBlockException
+from sys import stdout
+
+class Logger(object):
+	verbose = 0 #-1= no output
+				#0 = only errors
+				#1 = only warnings and errors
+				#2 = all output
+				
+	@staticmethod   
+	def showError(error):
+		if(Logger.verbose > -1) :
+			print "ERROR : " + error
+				
+	@staticmethod
+	def showWarning(warning):
+		if(Logger.verbose > 0) :
+			print "WARNING : " + warning
+			
+	@staticmethod	
+	def showInfo(info):
+		if(Logger.verbose > 1) :
+			print "INFO : " + info
+
+#######################
+
+class Enum():	
+	def __init__(self, *entries):
+		self._keys = entries
+		self._map = {}
+		for v,k in enumerate(self._keys) :
+			self._map[k] = v
+			
+	def __getattr__(self, name):
+		return self._map[name]
+			
+	def name_of(self, index):
+		return self._keys[index]
+
+#######################
+
+NOT_SET = 0
+SPACES_USED = 1
+TABS_USED = 2
+
+class FormattedWriter:
+
+	def __init__(self, out = stdout):
+		self.out = out
+		self.indentLevel = 0
+		self.indentSpace = "\t"
+		self.first_write = True
+
+	def write(self, text = ""):
+		if self.first_write :
+			self.first_write = False
+			if text == "":
+				self.out.write(self.indentLevel*self.indentSpace)
+			else:
+				self.out.write(self.indentLevel*self.indentSpace + text)  
+		else:
+			if text == "":
+				self.out.write("\n" + self.indentLevel*self.indentSpace)
+			else:
+				self.out.write("\n" + self.indentLevel*self.indentSpace + text)
+	
+	def extendWrite(self, text = ""):
+		self.out.write(text)
+				
+	def indent(self):
+		self.indentLevel+=1
+
+	def dedent(self):
+		self.indentLevel-=1
+
+	def writeCodeCorrectIndent(self, body):
+		lines = body.split('\n')
+		while( len(lines) > 0 and lines[-1].strip() == "") :
+			del(lines[-1])
+	
+		index = 0;
+		while( len(lines) > index and lines[index].strip() == "") :	   
+			index += 1
+			
+		if index >= len(lines) :
+			return
+		#first index where valid code is present
+		to_strip_index = len(lines[index].rstrip()) - len(lines[index].strip()) 
+		indent_type = NOT_SET;
+			
+		while index < len(lines):
+			strip_part = lines[index][:to_strip_index]
+			
+			if( ('\t' in strip_part and ' ' in strip_part) or
+				(indent_type == SPACES_USED and '\t' in strip_part) or
+				(indent_type == TABS_USED and ' ' in strip_part)
+			) :
+				raise CodeBlockException("Mixed tab and space indentation!")
+			
+			if indent_type == NOT_SET :
+				if ' ' in strip_part :
+					indent_type = SPACES_USED
+				elif '\t' in strip_part :
+					indent_type = TABS_USED
+					
+			self.write(lines[index][to_strip_index:])
+			index += 1
+
+
+class FileWriter(FormattedWriter):
+
+	def __init__(self, filename):
+		FormattedWriter.__init__(self, open(filename, 'w'))
+
+	def close(self):
+		self.out.close()
+
+#######################

+ 30 - 0
exported_to_sccdxml/python_sccd_compiler/visitor.py

@@ -0,0 +1,30 @@
+class Visitor(object):
+	def _visit(self, node, prepend, *args):
+		prepend = prepend + "_"
+		meth = None
+		for cls in node.__class__.__mro__:
+			meth_name = prepend + cls.__name__
+			meth = getattr(self, meth_name, None)
+			if meth:
+				break
+
+		if not meth:
+			meth = self.generic_visit
+		return meth(node, *args)
+	
+	def visit(self, node, *args):
+		self._visit(node, "visit", *args)
+	
+	def enter(self, node, *args):
+		self._visit(node, "enter", *args)
+		
+	def exit(self, node, *args):
+		self._visit(node, "exit", *args)
+
+	def generic_visit(self, node):
+		#print 'generic_visit '+node.__class__.__name__
+		pass
+		
+class Visitable(object):
+	def accept(self, visitor):
+		visitor.visit(self) 

+ 23 - 0
exported_to_sccdxml/run_digital_watch.py

@@ -0,0 +1,23 @@
+from Tkinter import *
+from DigitalWatchGUI import DigitalWatchGUI
+import digitalwatch
+from python_runtime.tkinter_eventloop import *
+
+def update(fixed_update_time, controller):
+	controller.update(fixed_update_time / 1000.0)
+	root.after(fixed_update_time, update, fixed_update_time, controller)
+
+root = Tk()
+root.withdraw()
+topLevel = Toplevel(root)
+topLevel.resizable(width=NO, height=NO)
+topLevel.title("DWatch")
+gui = DigitalWatchGUI(topLevel)
+
+try:
+	controller = digitalwatch.Controller(gui.controller, TkEventLoop(root))
+	controller.start()
+	gui.dynamicGUI.setStatechart(controller)
+	root.mainloop()
+finally:
+	controller.stop()

+ 191 - 0
exported_to_sccdxml/run_train.py

@@ -0,0 +1,191 @@
+from Tkinter import *
+import random
+import math
+
+import train
+from python_runtime.statecharts_core import Event
+from python_runtime.tkinter_eventloop import *
+
+width_railway = 20
+marked = {}
+kind_of_object = {}
+
+class SimulationGUI(Tk):
+    def __init__(self):
+        def update_scale(value):
+            if hasattr(self, "controller"):
+                self.controller.addInput(Event("accel", "tkinter_input", [float(value)]))
+
+        def press_continue():
+            self.controller.addInput(Event("continue", "tkinter_input", []))
+
+        def press_pause():
+            self.controller.addInput(Event("pause", "tkinter_input", []))
+
+        def press_open():
+            self.controller.addInput(Event("open", "tkinter_input", []))
+
+        def press_close():
+            self.controller.addInput(Event("close", "tkinter_input", []))
+
+        def press_awake():
+            self.controller.addInput(Event("awake", "tkinter_input", []))
+
+        Tk.__init__(self)
+        self.travelled_x = 0.0
+        self.travelled_x_int = 0
+        self.next_light = 0.0
+        self.frame = Frame(self)
+        self.frame.focus_set()
+        self.resizable(0, 0)
+        self.canvas = Canvas(self.frame, height=150, width=1000, bg="white")
+        self.img_train = PhotoImage(file="imgs/train.gif")
+        self.img_red = PhotoImage(file="imgs/red.gif")
+        self.img_yellow = PhotoImage(file="imgs/yellow.gif")
+        self.img_green = PhotoImage(file="imgs/green.gif")
+        self.img_station = PhotoImage(file="imgs/station.gif")
+        self.img_railway = PhotoImage(file="imgs/rail.gif")
+
+        self.label_error = Label(self.frame, text="")
+        self.slider_acceleration = Scale(self.frame, command=update_scale, orient=HORIZONTAL, resolution=0.01, from_=-1, to=1)
+        self.button_continue = Button(self.frame, text="continue", command=press_continue)
+        self.button_pause = Button(self.frame, text="pause", command=press_pause)
+        self.button_open = Button(self.frame, text="open", command=press_open)
+        self.button_close = Button(self.frame, text="close", command=press_close)
+        self.button_poll = Button(self.frame, text="poll", command=press_awake)
+
+        self.label_speed = Label(self.frame, text="")
+        self.label_doors = Label(self.frame, text="Doors are CLOSED")
+
+        self.items = []
+        self.rails = []
+        x = 0
+        while x <= 1000 + width_railway:
+            self.rails.append(self.canvas.create_image(x, 80, image=self.img_railway, anchor=NW))
+            x += width_railway
+
+        self.item_train = self.canvas.create_image(0, 75, image=self.img_train, anchor=NW)
+        self.label_speed.grid(row=0, column=0, columnspan=2)
+        self.label_doors.grid(row=1, column=0, columnspan=2)
+        self.canvas.grid(row=2, column=0, columnspan=2, sticky=W)
+        self.label_error.grid(row=3, column=0, columnspan=2)
+        self.slider_acceleration.grid(row=4, column=0, columnspan=2, sticky=W+E)
+        self.button_continue.grid(row=5, column=0, sticky=W+E)
+        self.button_pause.grid(row=5, column=1, sticky=W+E)
+        self.button_open.grid(row=6, column=0, sticky=W+E)
+        self.button_close.grid(row=6, column=1, sticky=W+E)
+        self.button_poll.grid(row=7, column=0, columnspan=2, sticky=W+E)
+        self.frame.grid()
+
+        self.remainder = 0.0
+        self.next_station = 1000
+        self.counter = 0
+        self.train = None
+        self.light_change_events = []
+        self.updateState()
+        self.after(20, self.throwEvents)
+        
+    def openDoors(self):
+        self.label_doors.config(text="Doors are OPEN")
+
+    def closeDoors(self):
+        self.label_doors.config(text="Doors are CLOSED")
+    
+    def trainIs(self, train):
+        self.train = train
+        
+    def throwEvents(self):
+        # Check if we passed anything
+        if hasattr(self, "controller"):
+            for item in self.items:
+                coords = self.canvas.coords(item)
+                if coords[0] < 30 and item not in marked:
+                    # Passed light or entered station
+                    t = kind_of_object[item]
+                    if t == "STATION":
+                        marked[item] = False
+                        self.controller.addInput(Event("enter", "tkinter_input", []))
+                    elif t == "RED":
+                        marked[item] = True
+                        self.controller.addInput(Event("red_light", "tkinter_input", []))
+                    elif t == "YELLOW":
+                        marked[item] = True
+                        self.controller.addInput(Event("yellow_light", "tkinter_input", []))
+                    elif t == "GREEN":
+                        marked[item] = True
+                        self.controller.addInput(Event("green_light", "tkinter_input", []))
+                elif coords[0] < -170 and not marked[item]:
+                    self.controller.addInput(Event("leave", "tkinter_input", []))
+                    marked[item] = True
+        self.after(20, self.throwEvents)
+        
+    def notify(self, msg, color):
+        self.label_error.config(text=msg, bg=color)
+        
+    def updateState(self):
+        def turn_green(item):
+            kind_of_object[item] = "GREEN"
+            self.canvas.itemconfigure(item, image=self.img_green)
+            
+        def turn_yellow(item):
+            self.canvas.itemconfigure(item, image=self.img_yellow)
+            kind_of_object[item] = "YELLOW"
+            self.light_change_events.append((self.counter + random.random() * 500 + 300, item, turn_green))
+        
+        if self.train is not None:
+            self.train.speed += self.train.acceleration / 2
+            self.label_speed.config(text="Speed: %.2f" % self.train.speed)
+            self.travelled_x += float(self.train.speed) / 20
+            delta_x = -int(self.travelled_x - self.travelled_x_int)
+            self.travelled_x_int = int(self.travelled_x)
+            # Move rails
+            for item in self.rails:
+                self.canvas.move(item, delta_x, 0)
+
+            # Move items and remove if necessary
+            for item in self.items:
+                self.canvas.move(item, delta_x, 0)
+                if self.canvas.coords(item) < -100:
+                    self.canvas.delete(item)
+                    self.items.remove(item)
+
+            # Update rails
+            while 1:
+                coords = self.canvas.coords(self.rails[0])
+                if coords[0] < -width_railway:
+                    self.canvas.delete(self.rails[0])
+                    self.rails.pop(0)
+                    self.rails.append(self.canvas.create_image(self.canvas.coords(self.rails[-1])[0]+width_railway, 80, image=self.img_railway, anchor=NW))
+                    self.canvas.tag_lower(self.rails[-1])
+                else:
+                    break
+
+            # Add in an element only if there is space
+            if self.next_station < self.travelled_x:
+                # Generate a station
+                self.items.append(self.canvas.create_image(1000, 120, image=self.img_station, anchor=NW))
+                kind_of_object[self.items[-1]] = "STATION"
+                self.next_station += random.random() * 3000 + 2000
+
+            if self.next_light < self.travelled_x:
+                self.next_light += 500
+                self.items.append(self.canvas.create_image(1000, 40, image=self.img_red, anchor=NW))
+                kind_of_object[self.items[-1]] = "RED"
+                self.light_change_events.append((self.counter + random.random() * 500, self.items[-1], turn_yellow))
+
+            self.counter += 1
+            for light_change in self.light_change_events:
+                if light_change[0] <= self.counter:
+                    light_change[2](light_change[1])
+                    self.light_change_events.remove(light_change)
+            
+root = SimulationGUI()
+if __name__ == "__main__":
+    random.seed(1)
+    controller = train.Controller(root, TkEventLoop(root))
+    root.controller = controller
+    controller.start()
+    try:
+        root.mainloop()
+    finally:
+        controller.stop()

+ 16 - 0
exported_to_sccdxml/train.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<diagram author="Yentl Van Tendeloo" name="Train Driving interface - Tkinter version">
+    <description>
+        Tkinter Train driving interface.
+    </description>
+    <top>
+       import json
+       import httplib
+    </top>
+
+    <inport name="tkinter_input"/>
+    <outport name="tkinter_output"/>
+
+    <class src="classes/model.xml"/>
+    <class src="classes/translator.xml" default="true"/>
+</diagram>

BIN
exported_to_sccdxml/watch.gif


BIN
exported_to_sccdxml/watch.jpg


File diff suppressed because it is too large
+ 2992 - 0
users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.defaultIcons.metamodel


File diff suppressed because it is too large
+ 28320 - 0
users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.defaultIcons.model


File diff suppressed because it is too large
+ 797 - 0
users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.metamodel


File diff suppressed because it is too large
+ 7488 - 0
users/(default)/Formalisms/ClassicDEVS/ClassicDEVS.model


BIN
users/(default)/Formalisms/ClassicDEVS/icons/arrow_up.png


BIN
users/(default)/Formalisms/ClassicDEVS/icons/clock.png


File diff suppressed because it is too large
+ 4361 - 0
users/(default)/Formalisms/TrainDoor/.autosave.TrainDoor.defaultIcons.model


File diff suppressed because it is too large
+ 1747 - 0
users/(default)/Formalisms/TrainDoor/.autosave.TrainDoor.model


File diff suppressed because it is too large
+ 8222 - 0
users/(default)/Formalisms/TrainDoor/.autosave.instance.model


+ 501 - 0
users/(default)/Formalisms/TrainDoor/TrainDoor.defaultIcons.metamodel

@@ -0,0 +1,501 @@
+{
+	"types": {
+		"OpenIcon": [
+			{
+				"name": "typename",
+				"type": "string",
+				"default": "OpenIcon"
+			},
+			{
+				"name": "position",
+				"type": "list<double>",
+				"default": [
+					382,
+					374
+				]
+			},
+			{
+				"name": "orientation",
+				"type": "double",
+				"default": 0
+			},
+			{
+				"name": "scale",
+				"type": "list<double>",
+				"default": [
+					1,
+					1
+				]
+			},
+			{
+				"name": "mapper",
+				"type": "code",
+				"default": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */"
+			},
+			{
+				"name": "parser",
+				"type": "code",
+				"default": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+			},
+			{
+				"name": "$contents",
+				"type": "map<string,*>",
+				"default": {
+					"nodes": {
+						"3": {
+							"src": {
+								"type": "string",
+								"value": "/Formalisms/TrainDoor/open.svg"
+							},
+							"width": {
+								"type": "double",
+								"value": 75
+							},
+							"height": {
+								"type": "double",
+								"value": 48
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Image",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									1,
+									2
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"11": {
+							"textContent": {
+								"type": "string",
+								"value": "T..."
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */\n({\"textContent\": getAttr(\"name\")})"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									9,
+									58
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						}
+					},
+					"edges": []
+				}
+			},
+			{
+				"name": "$asuri",
+				"type": "string",
+				"default": "-1"
+			}
+		],
+		"ClosedIcon": [
+			{
+				"name": "typename",
+				"type": "string",
+				"default": "ClosedIcon"
+			},
+			{
+				"name": "position",
+				"type": "list<double>",
+				"default": [
+					605,
+					356
+				]
+			},
+			{
+				"name": "orientation",
+				"type": "double",
+				"default": 0
+			},
+			{
+				"name": "scale",
+				"type": "list<double>",
+				"default": [
+					1,
+					1
+				]
+			},
+			{
+				"name": "mapper",
+				"type": "code",
+				"default": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */"
+			},
+			{
+				"name": "parser",
+				"type": "code",
+				"default": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+			},
+			{
+				"name": "$contents",
+				"type": "map<string,*>",
+				"default": {
+					"nodes": {
+						"5": {
+							"src": {
+								"type": "string",
+								"value": "/Formalisms/TrainDoor/closed.svg"
+							},
+							"width": {
+								"type": "double",
+								"value": 48
+							},
+							"height": {
+								"type": "double",
+								"value": 48
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Image",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									4,
+									10
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"9": {
+							"textContent": {
+								"type": "string",
+								"value": "T..."
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */\n({\"textContent\": getAttr(\"name\")})"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									12,
+									64
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						}
+					},
+					"edges": []
+				}
+			},
+			{
+				"name": "$asuri",
+				"type": "string",
+				"default": "-1"
+			}
+		],
+		"TransitionLink": [
+			{
+				"name": "link-style",
+				"type": "map<string,string>",
+				"default": {
+					"stroke": "#000000",
+					"stroke-dasharray": "",
+					"stroke-opacity": 1,
+					"stroke-width": 2
+				}
+			},
+			{
+				"name": "arrowHead",
+				"type": "ENUM(circle-black,circle-black-large,circle-white,circle-white-large,diamond-black,diamond-black-large,diamond-white,diamond-white-large,triangle-black,triangle-black-large,triangle-white,triangle-white-large,arrow-black,arrow-black-large,arrow-empty,arrow-empty-large,custom)",
+				"default": "custom"
+			},
+			{
+				"name": "arrowTail",
+				"type": "ENUM(circle-black,circle-black-large,circle-white,circle-white-large,diamond-black,diamond-black-large,diamond-white,diamond-white-large,triangle-black,triangle-black-large,triangle-white,triangle-white-large,arrow-black,arrow-black-large,arrow-empty,arrow-empty-large,custom)",
+				"default": "arrow-black"
+			},
+			{
+				"name": "typename",
+				"type": "string",
+				"default": "TransitionLink"
+			},
+			{
+				"name": "position",
+				"type": "list<double>",
+				"default": [
+					882,
+					366
+				]
+			},
+			{
+				"name": "orientation",
+				"type": "double",
+				"default": 0
+			},
+			{
+				"name": "scale",
+				"type": "list<double>",
+				"default": [
+					1,
+					1
+				]
+			},
+			{
+				"name": "mapper",
+				"type": "code",
+				"default": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */"
+			},
+			{
+				"name": "parser",
+				"type": "code",
+				"default": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+			},
+			{
+				"name": "$contents",
+				"type": "map<string,*>",
+				"default": {
+					"nodes": {
+						"7": {
+							"textContent": {
+								"type": "string",
+								"value": "<coded>"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,csattr:val,...} */\n({'textContent': getAttr(\"event\") + \" [\" + getAttr(\"condition\") + \"]\"})"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"$linkDecoratorInfo": {
+								"type": "map<string,double>",
+								"value": {
+									"xratio": 0.18404907975460122,
+									"yoffset": -26.5
+								}
+							}
+						},
+						"267": {
+							"segments": {
+								"type": "string",
+								"value": "m0,0 l10,4 l-10,4 l3,-4 z"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"fill": "#000000",
+									"opacity": 1,
+									"stroke-width": 1
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": ""
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* specify code that evaluates to an associative array of the form {...,attr:val,...} */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Path",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"$linkDecoratorInfo": {
+								"type": "map<string,double>",
+								"value": {
+									"xratio": 1,
+									"yoffset": -4
+								}
+							}
+						}
+					},
+					"edges": []
+				}
+			},
+			{
+				"name": "$asuri",
+				"type": "string",
+				"default": "-1"
+			},
+			{
+				"name": "$segments",
+				"type": "map<string,list<string>>",
+				"default": {}
+			}
+		]
+	},
+	"constraints": [],
+	"actions": [],
+	"cardinalities": {
+		"OpenIcon": [],
+		"ClosedIcon": [],
+		"TransitionLink": []
+	},
+	"legalConnections": {},
+	"connectorTypes": {},
+	"types2parentTypes": {
+		"OpenIcon": [],
+		"ClosedIcon": [],
+		"TransitionLink": []
+	}
+}

File diff suppressed because it is too large
+ 4361 - 0
users/(default)/Formalisms/TrainDoor/TrainDoor.defaultIcons.model


+ 863 - 0
users/(default)/Formalisms/TrainDoor/TrainDoor.defaultIcons.pattern.metamodel

@@ -0,0 +1,863 @@
+{
+	"types": {
+		"__pOpenIcon": [
+			{
+				"name": "typename",
+				"type": "string",
+				"default": "OpenIcon"
+			},
+			{
+				"name": "position",
+				"type": "list<double>",
+				"default": [
+					382,
+					374
+				]
+			},
+			{
+				"name": "orientation",
+				"type": "double",
+				"default": 0
+			},
+			{
+				"name": "scale",
+				"type": "list<double>",
+				"default": [
+					1,
+					1
+				]
+			},
+			{
+				"name": "mapper",
+				"type": "code",
+				"default": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+			},
+			{
+				"name": "parser",
+				"type": "code",
+				"default": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+			},
+			{
+				"name": "$contents",
+				"type": "map<string,*>",
+				"default": {
+					"nodes": {
+						"3": {
+							"src": {
+								"type": "string",
+								"value": "/Formalisms/TrainDoor/open.svg"
+							},
+							"width": {
+								"type": "double",
+								"value": 75
+							},
+							"height": {
+								"type": "double",
+								"value": 48
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Image",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									1,
+									2
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"11": {
+							"textContent": {
+								"type": "string",
+								"value": "T..."
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									9,
+									58
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"__pLabelText": {
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"textContent": {
+								"type": "string",
+								"value": "#"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#6000ff",
+									"fill": "#6000ff",
+									"font-size": "15px",
+									"opacity": "1"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "({'textContent':getAttr('__pLabel')})"
+							},
+							"parser": {
+								"type": "code",
+								"value": "({'__pLabel':getAttr('textContent')})"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text"
+						}
+					},
+					"edges": []
+				}
+			},
+			{
+				"name": "$asuri",
+				"type": "string",
+				"default": "-1"
+			}
+		],
+		"__pClosedIcon": [
+			{
+				"name": "typename",
+				"type": "string",
+				"default": "ClosedIcon"
+			},
+			{
+				"name": "position",
+				"type": "list<double>",
+				"default": [
+					605,
+					356
+				]
+			},
+			{
+				"name": "orientation",
+				"type": "double",
+				"default": 0
+			},
+			{
+				"name": "scale",
+				"type": "list<double>",
+				"default": [
+					1,
+					1
+				]
+			},
+			{
+				"name": "mapper",
+				"type": "code",
+				"default": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+			},
+			{
+				"name": "parser",
+				"type": "code",
+				"default": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+			},
+			{
+				"name": "$contents",
+				"type": "map<string,*>",
+				"default": {
+					"nodes": {
+						"5": {
+							"src": {
+								"type": "string",
+								"value": "/Formalisms/TrainDoor/closed.svg"
+							},
+							"width": {
+								"type": "double",
+								"value": 48
+							},
+							"height": {
+								"type": "double",
+								"value": 48
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Image",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									4,
+									10
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"9": {
+							"textContent": {
+								"type": "string",
+								"value": "T..."
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									12,
+									64
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"__pLabelText": {
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"textContent": {
+								"type": "string",
+								"value": "#"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#6000ff",
+									"fill": "#6000ff",
+									"font-size": "15px",
+									"opacity": "1"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "({'textContent':getAttr('__pLabel')})"
+							},
+							"parser": {
+								"type": "code",
+								"value": "({'__pLabel':getAttr('textContent')})"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text"
+						}
+					},
+					"edges": []
+				}
+			},
+			{
+				"name": "$asuri",
+				"type": "string",
+				"default": "-1"
+			}
+		],
+		"__pTransitionLink": [
+			{
+				"name": "link-style",
+				"type": "map<string,string>",
+				"default": {
+					"stroke": "#000000",
+					"stroke-dasharray": "",
+					"stroke-opacity": 1,
+					"stroke-width": 2
+				}
+			},
+			{
+				"name": "arrowHead",
+				"type": "ENUM(circle-black,circle-black-large,circle-white,circle-white-large,diamond-black,diamond-black-large,diamond-white,diamond-white-large,triangle-black,triangle-black-large,triangle-white,triangle-white-large,arrow-black,arrow-black-large,arrow-empty,arrow-empty-large,custom)",
+				"default": "custom"
+			},
+			{
+				"name": "arrowTail",
+				"type": "ENUM(circle-black,circle-black-large,circle-white,circle-white-large,diamond-black,diamond-black-large,diamond-white,diamond-white-large,triangle-black,triangle-black-large,triangle-white,triangle-white-large,arrow-black,arrow-black-large,arrow-empty,arrow-empty-large,custom)",
+				"default": "arrow-black"
+			},
+			{
+				"name": "typename",
+				"type": "string",
+				"default": "TransitionLink"
+			},
+			{
+				"name": "position",
+				"type": "list<double>",
+				"default": [
+					882,
+					366
+				]
+			},
+			{
+				"name": "orientation",
+				"type": "double",
+				"default": 0
+			},
+			{
+				"name": "scale",
+				"type": "list<double>",
+				"default": [
+					1,
+					1
+				]
+			},
+			{
+				"name": "mapper",
+				"type": "code",
+				"default": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+			},
+			{
+				"name": "parser",
+				"type": "code",
+				"default": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+			},
+			{
+				"name": "$contents",
+				"type": "map<string,*>",
+				"default": {
+					"nodes": {
+						"7": {
+							"textContent": {
+								"type": "string",
+								"value": "<coded>"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75,
+									"font-size": "20px",
+									"stroke-width": 1,
+									"arrow-start": "none",
+									"arrow-end": "none"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"$linkDecoratorInfo": {
+								"type": "map<string,double>",
+								"value": {
+									"xratio": 0.18404907975460122,
+									"yoffset": -26.5
+								}
+							}
+						},
+						"267": {
+							"segments": {
+								"type": "string",
+								"value": "m0,0 l10,4 l-10,4 l3,-4 z"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"fill": "#000000",
+									"opacity": 1,
+									"stroke-width": 1
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"parser": {
+								"type": "code",
+								"value": "/* mapping and parsing code is disabled by default because pattern attribute values are code */"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Path",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"$linkDecoratorInfo": {
+								"type": "map<string,double>",
+								"value": {
+									"xratio": 1,
+									"yoffset": -4
+								}
+							}
+						},
+						"__pLabelText": {
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"textContent": {
+								"type": "string",
+								"value": "#"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#6000ff",
+									"fill": "#6000ff",
+									"font-size": "15px",
+									"opacity": "1"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "({'textContent':getAttr('__pLabel')})"
+							},
+							"parser": {
+								"type": "code",
+								"value": "({'__pLabel':getAttr('textContent')})"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text"
+						}
+					},
+					"edges": []
+				}
+			},
+			{
+				"name": "$asuri",
+				"type": "string",
+				"default": "-1"
+			},
+			{
+				"name": "$segments",
+				"type": "map<string,list<string>>",
+				"default": {}
+			}
+		],
+		"__pStateIcon": [
+			{
+				"name": "typename",
+				"type": "string",
+				"default": "__pStateIcon"
+			},
+			{
+				"name": "position",
+				"type": "list<double>",
+				"default": [
+					0,
+					0
+				]
+			},
+			{
+				"name": "orientation",
+				"type": "double",
+				"default": 0
+			},
+			{
+				"name": "scale",
+				"type": "list<double>",
+				"default": [
+					1,
+					1
+				]
+			},
+			{
+				"name": "mapper",
+				"type": "code",
+				"default": ""
+			},
+			{
+				"name": "parser",
+				"type": "code",
+				"default": ""
+			},
+			{
+				"name": "$contents",
+				"type": "map<string,*>",
+				"default": {
+					"nodes": {
+						"text": {
+							"textContent": {
+								"type": "string",
+								"value": "__pStateIcon"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"stroke-dasharray": "",
+									"fill": "#000000",
+									"fill-opacity": "1",
+									"font-size": "13px"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": ""
+							},
+							"parser": {
+								"type": "code",
+								"value": ""
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									10,
+									76
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"rect": {
+							"width": {
+								"type": "double",
+								"value": 75
+							},
+							"height": {
+								"type": "double",
+								"value": 75
+							},
+							"cornerRadius": {
+								"type": "double",
+								"value": 15
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#000000",
+									"fill": "#ffffff",
+									"fill-opacity": 0.75
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": ""
+							},
+							"parser": {
+								"type": "code",
+								"value": ""
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Rectangle",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							}
+						},
+						"textBelowRect": {
+							"distance": {
+								"type": "double",
+								"value": 10
+							},
+							"alignment": {
+								"type": "ENUM(\"right\",\"left\",\"center\")",
+								"value": "center"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Below",
+							"position": {
+								"type": "list<double>",
+								"value": [
+									5,
+									38
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"link-style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#00ff00",
+									"stroke-dasharray": "",
+									"stroke-opacity": 1,
+									"arrow-start": "none",
+									"arrow-end": "classic-wide-long"
+								}
+							}
+						},
+						"__pLabelText": {
+							"position": {
+								"type": "list<double>",
+								"value": [
+									0,
+									0
+								]
+							},
+							"orientation": {
+								"type": "double",
+								"value": 0
+							},
+							"scale": {
+								"type": "list<double>",
+								"value": [
+									1,
+									1
+								]
+							},
+							"textContent": {
+								"type": "string",
+								"value": "#"
+							},
+							"style": {
+								"type": "map<string,string>",
+								"value": {
+									"stroke": "#6000ff",
+									"fill": "#6000ff",
+									"font-size": "15px",
+									"opacity": "1"
+								}
+							},
+							"mapper": {
+								"type": "code",
+								"value": "({'textContent':getAttr('__pLabel')})"
+							},
+							"parser": {
+								"type": "code",
+								"value": "({'__pLabel':getAttr('textContent')})"
+							},
+							"$type": "/Formalisms/__LanguageSyntax__/ConcreteSyntax/ConcreteSyntax/Text"
+						}
+					},
+					"edges": [
+						{
+							"src": "text",
+							"dest": "textBelowRect"
+						},
+						{
+							"src": "textBelowRect",
+							"dest": "rect"
+						}
+					]
+				}
+			},
+			{
+				"name": "$asuri",
+				"type": "string",
+				"default": "-1"
+			}
+		]
+	},
+	"constraints": [],
+	"actions": [],
+	"cardinalities": {
+		"__pOpenIcon": [],
+		"__pClosedIcon": [],
+		"__pTransitionLink": [],
+		"__pStateIcon": []
+	},
+	"legalConnections": {},
+	"connectorTypes": {},
+	"types2parentTypes": {
+		"__pOpenIcon": [],
+		"__pClosedIcon": [],
+		"__pTransitionLink": [],
+		"__pStateIcon": []
+	}
+}

+ 176 - 0
users/(default)/Formalisms/TrainDoor/TrainDoor.metamodel

@@ -0,0 +1,176 @@
+{
+	"types": {
+		"State": [
+			{
+				"name": "name",
+				"type": "string",
+				"default": ""
+			}
+		],
+		"Open": [
+			{
+				"name": "name",
+				"type": "string",
+				"default": ""
+			}
+		],
+		"Closed": [
+			{
+				"name": "name",
+				"type": "string",
+				"default": ""
+			}
+		],
+		"Transition": [
+			{
+				"name": "condition",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "event",
+				"type": "string",
+				"default": ""
+			}
+		]
+	},
+	"constraints": [
+		{
+			"name": "noAbstractInstances",
+			"event": "pre-create",
+			"code": "false",
+			"targetType": "State"
+		}
+	],
+	"actions": [],
+	"cardinalities": {
+		"State": [
+			{
+				"dir": "out",
+				"type": "Transition",
+				"min": "0",
+				"max": "Infinity"
+			},
+			{
+				"dir": "in",
+				"type": "Transition",
+				"min": "0",
+				"max": "Infinity"
+			}
+		],
+		"Open": [
+			{
+				"dir": "out",
+				"type": "Transition",
+				"min": "0",
+				"max": "Infinity"
+			},
+			{
+				"dir": "in",
+				"type": "Transition",
+				"min": "0",
+				"max": "Infinity"
+			}
+		],
+		"Closed": [
+			{
+				"dir": "out",
+				"type": "Transition",
+				"min": "0",
+				"max": "Infinity"
+			},
+			{
+				"dir": "in",
+				"type": "Transition",
+				"min": "0",
+				"max": "Infinity"
+			}
+		],
+		"Transition": [
+			{
+				"dir": "in",
+				"type": "State",
+				"min": "0",
+				"max": "1"
+			},
+			{
+				"dir": "out",
+				"type": "State",
+				"min": "0",
+				"max": "1"
+			},
+			{
+				"dir": "in",
+				"type": "Open",
+				"min": "0",
+				"max": "1"
+			},
+			{
+				"dir": "out",
+				"type": "Open",
+				"min": "0",
+				"max": "1"
+			},
+			{
+				"dir": "in",
+				"type": "Closed",
+				"min": "0",
+				"max": "1"
+			},
+			{
+				"dir": "out",
+				"type": "Closed",
+				"min": "0",
+				"max": "1"
+			}
+		]
+	},
+	"legalConnections": {
+		"State": {
+			"State": [
+				"Transition"
+			],
+			"Open": [
+				"Transition"
+			],
+			"Closed": [
+				"Transition"
+			]
+		},
+		"Open": {
+			"State": [
+				"Transition"
+			],
+			"Open": [
+				"Transition"
+			],
+			"Closed": [
+				"Transition"
+			]
+		},
+		"Closed": {
+			"State": [
+				"Transition"
+			],
+			"Open": [
+				"Transition"
+			],
+			"Closed": [
+				"Transition"
+			]
+		}
+	},
+	"connectorTypes": {
+		"Transition": "visual"
+	},
+	"types2parentTypes": {
+		"State": [],
+		"Open": [
+			"State"
+		],
+		"Closed": [
+			"State"
+		],
+		"Transition": []
+	}
+}

File diff suppressed because it is too large
+ 1747 - 0
users/(default)/Formalisms/TrainDoor/TrainDoor.model


+ 263 - 0
users/(default)/Formalisms/TrainDoor/TrainDoor.pattern.metamodel

@@ -0,0 +1,263 @@
+{
+	"types": {
+		"__pState": [
+			{
+				"name": "__pLabel",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotIn",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotOut",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pMatchSubtypes",
+				"type": "boolean",
+				"default": false
+			},
+			{
+				"name": "name",
+				"type": "code",
+				"default": "\"[PYTHON]\"\n\"Example:\t result = True\"\n\"Example:\t result = getAttr()\"\n\n\"[JAVASCRIPT]\"\n\"Example:\t true\"\n\"Example:\t getAttr()\""
+			}
+		],
+		"__pOpen": [
+			{
+				"name": "__pLabel",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotIn",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotOut",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pMatchSubtypes",
+				"type": "boolean",
+				"default": false
+			},
+			{
+				"name": "name",
+				"type": "code",
+				"default": "\"[PYTHON]\"\n\"Example:\t result = True\"\n\"Example:\t result = getAttr()\"\n\n\"[JAVASCRIPT]\"\n\"Example:\t true\"\n\"Example:\t getAttr()\""
+			}
+		],
+		"__pClosed": [
+			{
+				"name": "__pLabel",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotIn",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotOut",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pMatchSubtypes",
+				"type": "boolean",
+				"default": false
+			},
+			{
+				"name": "name",
+				"type": "code",
+				"default": "\"[PYTHON]\"\n\"Example:\t result = True\"\n\"Example:\t result = getAttr()\"\n\n\"[JAVASCRIPT]\"\n\"Example:\t true\"\n\"Example:\t getAttr()\""
+			}
+		],
+		"__pTransition": [
+			{
+				"name": "__pLabel",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotIn",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pPivotOut",
+				"type": "string",
+				"default": ""
+			},
+			{
+				"name": "__pMatchSubtypes",
+				"type": "boolean",
+				"default": false
+			},
+			{
+				"name": "condition",
+				"type": "code",
+				"default": "\"[PYTHON]\"\n\"Example:\t result = True\"\n\"Example:\t result = getAttr()\"\n\n\"[JAVASCRIPT]\"\n\"Example:\t true\"\n\"Example:\t getAttr()\""
+			},
+			{
+				"name": "event",
+				"type": "code",
+				"default": "\"[PYTHON]\"\n\"Example:\t result = True\"\n\"Example:\t result = getAttr()\"\n\n\"[JAVASCRIPT]\"\n\"Example:\t true\"\n\"Example:\t getAttr()\""
+			}
+		]
+	},
+	"constraints": [
+		{
+			"name": "noAbstractInstances",
+			"event": "pre-create",
+			"code": "/* comment next line to enable this constraint */\nthrow \"IgnoredConstraint\"\nfalse",
+			"targetType": "State"
+		}
+	],
+	"actions": [
+		{
+			"name": "distinctPLabels",
+			"event": "post-create",
+			"code": "if( getAttr(\"__pLabel\") == \"\" )\n{\n\tvar pLabels = getAllNodes().\n\t\t\t\t\t\t\tfilter( function(n) {return hasAttr(\"__pLabel\",n);} ).\n\t\t\t\t\t\t\t\tmap( function(n) {return getAttr(\"__pLabel\",n);} ),\n\t\t i\t\t\t= \"0\";\n\n\twhile( _utils.contains(pLabels,i) )\n\t\ti = String(parseInt(i)+1);\n\tsetAttr(\"__pLabel\",i);\n}",
+			"targetType": "*"
+		}
+	],
+	"cardinalities": {
+		"__pState": [
+			{
+				"dir": "out",
+				"type": "__pTransition",
+				"min": 0,
+				"max": "Infinity"
+			},
+			{
+				"dir": "in",
+				"type": "__pTransition",
+				"min": 0,
+				"max": "Infinity"
+			}
+		],
+		"__pOpen": [
+			{
+				"dir": "out",
+				"type": "__pTransition",
+				"min": 0,
+				"max": "Infinity"
+			},
+			{
+				"dir": "in",
+				"type": "__pTransition",
+				"min": 0,
+				"max": "Infinity"
+			}
+		],
+		"__pClosed": [
+			{
+				"dir": "out",
+				"type": "__pTransition",
+				"min": 0,
+				"max": "Infinity"
+			},
+			{
+				"dir": "in",
+				"type": "__pTransition",
+				"min": 0,
+				"max": "Infinity"
+			}
+		],
+		"__pTransition": [
+			{
+				"dir": "in",
+				"type": "__pState",
+				"min": 0,
+				"max": "1"
+			},
+			{
+				"dir": "out",
+				"type": "__pState",
+				"min": 0,
+				"max": "1"
+			},
+			{
+				"dir": "in",
+				"type": "__pOpen",
+				"min": 0,
+				"max": "1"
+			},
+			{
+				"dir": "out",
+				"type": "__pOpen",
+				"min": 0,
+				"max": "1"
+			},
+			{
+				"dir": "in",
+				"type": "__pClosed",
+				"min": 0,
+				"max": "1"
+			},
+			{
+				"dir": "out",
+				"type": "__pClosed",
+				"min": 0,
+				"max": "1"
+			}
+		]
+	},
+	"legalConnections": {
+		"__pState": {
+			"__pState": [
+				"__pTransition"
+			],
+			"__pOpen": [
+				"__pTransition"
+			],
+			"__pClosed": [
+				"__pTransition"
+			]
+		},
+		"__pOpen": {
+			"__pState": [
+				"__pTransition"
+			],
+			"__pOpen": [
+				"__pTransition"
+			],
+			"__pClosed": [
+				"__pTransition"
+			]
+		},
+		"__pClosed": {
+			"__pState": [
+				"__pTransition"
+			],
+			"__pOpen": [
+				"__pTransition"
+			],
+			"__pClosed": [
+				"__pTransition"
+			]
+		}
+	},
+	"connectorTypes": {
+		"__pTransition": "visual"
+	},
+	"types2parentTypes": {
+		"__pState": [],
+		"__pOpen": [
+			"__pState"
+		],
+		"__pClosed": [
+			"__pState"
+		],
+		"__pTransition": []
+	}
+}

+ 191 - 0
users/(default)/Formalisms/TrainDoor/closed.svg

@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="188.43304"
+   height="148.71875"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="open.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend"
+       style="overflow:visible">
+      <path
+         id="path3929"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-8"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-3"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-9"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-33"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-3"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-7"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-0"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-8"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-4"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-1"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="102.65447"
+     inkscape:cy="-97.693306"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1918"
+     inkscape:window-height="1422"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-172.02076,161.20429)">
+    <g
+       id="g3830"
+       transform="matrix(-1,0,0,1,547.34218,-601.07759)">
+      <g
+         id="g3769-0-1"
+         transform="translate(623.32785,-9.336608)" />
+    </g>
+    <g
+       id="g3838-8"
+       transform="translate(-15.322988,-355.57929)">
+      <g
+         id="g3769-71">
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect2985-8"
+           width="88.214287"
+           height="142.73372"
+           x="190.35715"
+           y="197.36218" />
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect3755-7"
+           width="61.42857"
+           height="61.42857"
+           x="203.75"
+           y="212.00504" />
+      </g>
+      <g
+         id="g3769-0-4"
+         transform="translate(94.214287,0)">
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect2985-2-8"
+           width="88.214287"
+           height="142.73372"
+           x="190.35715"
+           y="197.36218" />
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect3755-4-8"
+           width="61.42857"
+           height="61.42857"
+           x="203.75"
+           y="212.00504" />
+      </g>
+    </g>
+  </g>
+</svg>

File diff suppressed because it is too large
+ 2337 - 0
users/(default)/Formalisms/TrainDoor/instance.model


+ 185 - 0
users/(default)/Formalisms/TrainDoor/open.svg

@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="304.12863"
+   height="148.73372"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="statechart--.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend"
+       style="overflow:visible">
+      <path
+         id="path3929"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-8"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-3"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-9"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-33"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-3"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-7"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-0"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-8"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-4"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3929-1"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="237.1558"
+     inkscape:cy="-110.37949"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1918"
+     inkscape:window-height="1422"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-99.031816,270.59005)">
+    <g
+       id="g3830"
+       transform="matrix(-1,0,0,1,1003.9311,-455.61562)">
+      <g
+         id="g3769-7"
+         transform="translate(413.41351,-9.336608)">
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect2985-9"
+           width="88.214287"
+           height="142.73372"
+           x="190.35715"
+           y="197.36218" />
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect3755-1"
+           width="61.42857"
+           height="61.42857"
+           x="203.75"
+           y="212.00504" />
+      </g>
+      <g
+         id="g3769-0-1"
+         transform="translate(623.32785,-9.336608)">
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect2985-2-3"
+           width="88.214287"
+           height="142.73372"
+           x="190.35715"
+           y="197.36218" />
+        <rect
+           style="color:#000000;fill:none;stroke:#000000;stroke-width:6;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="rect3755-4-7"
+           width="61.42857"
+           height="61.42857"
+           x="203.75"
+           y="212.00504" />
+      </g>
+    </g>
+  </g>
+</svg>

File diff suppressed because it is too large
+ 1459 - 0
users/(default)/Formalisms/TrainDoor/rules/.autosave.R_closed_to_state.model


File diff suppressed because it is too large
+ 5671 - 0
users/(default)/Formalisms/TrainDoor/rules/.autosave.R_init.model


File diff suppressed because it is too large
+ 2298 - 0
users/(default)/Formalisms/TrainDoor/rules/.autosave.R_open_to_state.model


File diff suppressed because it is too large
+ 4187 - 0
users/(default)/Formalisms/TrainDoor/rules/.autosave.R_transitions.model


File diff suppressed because it is too large
+ 18200 - 0
users/(default)/Formalisms/TrainDoor/rules/.autosave.T_to_SCCD.model


File diff suppressed because it is too large
+ 2298 - 0
users/(default)/Formalisms/TrainDoor/rules/R_closed_to_state.model


File diff suppressed because it is too large
+ 5671 - 0
users/(default)/Formalisms/TrainDoor/rules/R_init.model


File diff suppressed because it is too large
+ 2298 - 0
users/(default)/Formalisms/TrainDoor/rules/R_open_to_state.model


File diff suppressed because it is too large
+ 4209 - 0
users/(default)/Formalisms/TrainDoor/rules/R_transitions.model


File diff suppressed because it is too large
+ 18200 - 0
users/(default)/Formalisms/TrainDoor/rules/T_to_SCCD.model