javascript_generator.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. import time
  2. from constructs import FormalParameter
  3. from code_generation import CodeGenerator, Platforms
  4. class JavascriptGenerator(CodeGenerator):
  5. def __init__(self):
  6. self.supported_platforms = [Platforms.Threads, Platforms.GameLoop]
  7. def visit_ClassDiagram(self, class_diagram):
  8. # header
  9. self.fOut.write("/**");
  10. self.fOut.write(" * Statechart compiler by Glenn De Jonghe")
  11. self.fOut.write(" * Javascript generator by Joeri Exelmans")
  12. self.fOut.write(" * ")
  13. self.fOut.write(" * Date: " + time.asctime())
  14. if class_diagram.name or class_diagram.author or class_diagram.description:
  15. self.fOut.write(" * ")
  16. if class_diagram.author:
  17. self.fOut.write(" * Model author: " + class_diagram.author)
  18. if class_diagram.name:
  19. self.fOut.write(" * Model name: " + class_diagram.name)
  20. if class_diagram.description.strip():
  21. self.fOut.write(" * Model description:")
  22. self.fOut.indent()
  23. self.fOut.write(class_diagram.description.strip())
  24. self.fOut.dedent()
  25. self.fOut.write(" */")
  26. self.fOut.write()
  27. self.fOut.write("// put everything in an object (serves as \"namespace\")")
  28. self.fOut.write(class_diagram.name + " = {};")
  29. self.fOut.write()
  30. self.fOut.write("// closure scope")
  31. self.fOut.write("(function() {")
  32. self.fOut.write()
  33. #visit children
  34. for c in class_diagram.classes :
  35. c.accept(self)
  36. self.fOut.write("// put class in global diagram object")
  37. self.fOut.write(class_diagram.name + '.' + c.name + ' = ' + c.name + ';')
  38. self.fOut.write()
  39. #writing out ObjectManager
  40. self.fOut.write('var ObjectManager = function(controller) {')
  41. self.fOut.indent()
  42. self.fOut.write("ObjectManagerBase.call(this, controller);")
  43. self.fOut.dedent()
  44. self.fOut.write("};")
  45. self.fOut.write()
  46. self.fOut.write("ObjectManager.prototype = new ObjectManagerBase();")
  47. self.fOut.write()
  48. self.fOut.write('ObjectManager.prototype.instantiate = function(class_name, construct_params) {')
  49. self.fOut.indent()
  50. for index, c in enumerate(class_diagram.classes) :
  51. if index == 0 :
  52. self.fOut.write()
  53. else :
  54. self.fOut.extendWrite(' else ')
  55. self.fOut.extendWrite('if (class_name === "' + c.name + '") {')
  56. self.fOut.indent()
  57. if c.statechart :
  58. self.fOut.write('var instance = new ' + c.name + '(this.controller')
  59. param_count = 0
  60. for p in c.constructors[0].parameters:
  61. self.fOut.extendWrite(', construct_params[' + str(param_count) + ']')
  62. param_count += 1
  63. self.fOut.extendWrite(');')
  64. else :
  65. self.fOut.write('var instance = new ' + c.name + '(')
  66. param_count = 0
  67. for p in c.constructors[0].parameters:
  68. if (param_count != 0):
  69. self.fOut.extendWrite(', ')
  70. self.fOut.extendWrite('construct_params[' + str(param_count) + ']')
  71. param_count += 1
  72. self.fOut.extendWrite(');');
  73. self.fOut.write('instance.associations = new Object();')
  74. for a in c.associations :
  75. a.accept(self)
  76. self.fOut.dedent()
  77. self.fOut.write('}')
  78. self.fOut.write('return instance;')
  79. self.fOut.dedent()
  80. self.fOut.write("};")
  81. self.fOut.write()
  82. self.fOut.write("// put in global diagram object")
  83. self.fOut.write(class_diagram.name + '.ObjectManager = ObjectManager;')
  84. self.fOut.write()
  85. if self.platform == Platforms.Threads :
  86. controller_sub_class = "JsEventLoopControllerBase"
  87. elif self.platform == Platforms.GameLoop :
  88. controller_sub_class = "GameLoopControllerBase"
  89. # write out __init__ method
  90. if class_diagram.default_class.constructors :
  91. self.writeControllerConstructor(class_diagram, controller_sub_class, class_diagram.default_class.constructors[0].parameters)
  92. else :
  93. self.writeControllerConstructor(class_diagram, controller_sub_class)
  94. self.fOut.write("Controller.prototype = new " + controller_sub_class + "();")
  95. self.fOut.write()
  96. self.fOut.write("// put in global diagram object")
  97. self.fOut.write(class_diagram.name + '.Controller = Controller;')
  98. self.fOut.write()
  99. self.fOut.write("})();")
  100. self.fOut.write()
  101. #helper method
  102. def writeControllerConstructor(self, class_diagram, controller_sub_class, parameters = []):
  103. self.writeConstructorSignature("Controller", parameters + [FormalParameter("keep_running", "", "true"), FormalParameter("finished_callback", "", None)])
  104. self.fOut.indent()
  105. self.fOut.write(controller_sub_class + ".call(this, new ObjectManager(this), keep_running, finished_callback);")
  106. for i in class_diagram.inports:
  107. self.fOut.write('this.addInputPort("' + i + '");')
  108. for i in class_diagram.outports:
  109. self.fOut.write('this.addOutputPort("' + i + '");')
  110. actual_parameters = [p.getIdent() for p in parameters]
  111. self.fOut.write('this.object_manager.createInstance("'+ class_diagram.default_class.name +'", [' + ', '.join(actual_parameters)+ ']);')
  112. self.fOut.dedent()
  113. self.fOut.write('};')
  114. self.fOut.write()
  115. def visit_Class(self, class_node):
  116. """
  117. Generate code for Class construct
  118. """
  119. if class_node.super_classes:
  120. super_classes = []
  121. for super_class in class_node.super_classes:
  122. super_classes.append(super_class)
  123. else:
  124. super_classes = ["RuntimeClassBase"]
  125. #visit children
  126. for i in class_node.constructors :
  127. i.accept(self)
  128. self.fOut.write()
  129. self.fOut.write(class_node.name + ".prototype = new " + super_classes[0] + "();")
  130. self.fOut.write()
  131. if class_node.statechart is not None:
  132. # assign each node a unique ID
  133. self.fOut.write("// Unique IDs for all statechart nodes")
  134. for (i,node) in enumerate(class_node.statechart.composites + class_node.statechart.basics):
  135. self.fOut.write(class_node.name + ".prototype." + node.full_name + " = " + str(i) + ";")
  136. self.fOut.write()
  137. #visit children
  138. for i in class_node.destructors :
  139. i.accept(self)
  140. for i in class_node.methods :
  141. i.accept(self)
  142. if class_node.statechart is not None:
  143. class_node.statechart.accept(self)
  144. self.writeMethodSignature(class_node.name, "user_defined_constructor", class_node.constructors[0].getParams())
  145. self.fOut.indent()
  146. for super_class in class_node.super_classes:
  147. self.fOut.write(super_class + ".prototype.user_defined_constructor.call(this")
  148. for p in class_node.constructors[0].super_class_parameters[super_class]:
  149. self.fOut.extendWrite(", " + p)
  150. self.fOut.extendWrite(");")
  151. self.writeCodeCorrectIndent(class_node.constructors[0].body)
  152. self.fOut.dedent()
  153. self.fOut.write("};")
  154. self.fOut.write()
  155. self.writeMethodSignature(class_node.name, "start")
  156. self.fOut.indent()
  157. self.fOut.write(super_classes[0] + ".prototype.start.call(this);")
  158. for default_node in class_node.statechart.root.defaults:
  159. if default_node.is_composite:
  160. self.fOut.write("this.enterDefault_" + default_node.full_name + "();")
  161. elif default_node.is_basic:
  162. self.fOut.write("this.enter_" + default_node.full_name + "();")
  163. self.fOut.dedent()
  164. self.fOut.write("};")
  165. self.fOut.write()
  166. #helper method
  167. def writeConstructorSignature(self, prototype_name, parameters = []):
  168. self.fOut.write("var " + prototype_name + " = function(")
  169. for param in parameters :
  170. if parameters.index(param) != 0:
  171. self.fOut.extendWrite(', ')
  172. param.accept(self)
  173. self.fOut.extendWrite(") {")
  174. self.fOut.indent()
  175. for param in parameters :
  176. if param.hasDefault() :
  177. self.fOut.write("if (" + param.getIdent() + " === undefined) " +
  178. param.getIdent() + " = " + param.getDefault() + ";")
  179. self.fOut.dedent()
  180. #helper method
  181. def writeMethodSignature(self, prototype_name, method_name, parameters = []):
  182. self.fOut.write(prototype_name + ".prototype." + method_name + " = function(")
  183. for param in parameters :
  184. if parameters.index(param) != 0 :
  185. self.fOut.extendWrite(', ')
  186. param.accept(self)
  187. self.fOut.extendWrite(") {")
  188. self.fOut.indent()
  189. for param in parameters :
  190. if param.hasDefault() :
  191. self.fOut.write("if (!" + param.getIdent() + ") " +
  192. param.getIdent() + " = " + param.getDefault() + ";")
  193. self.fOut.dedent()
  194. #helper method
  195. def writeMethod(self, prototype_name, name, parameters, return_type, body):
  196. self.writeMethodSignature(prototype_name, name, parameters)
  197. self.fOut.indent()
  198. if body.strip():
  199. self.writeCodeCorrectIndent(body)
  200. self.fOut.write()
  201. self.fOut.dedent()
  202. self.fOut.write("};");
  203. def visit_FormalParameter(self, formal_parameter):
  204. self.fOut.extendWrite(formal_parameter.getIdent())
  205. def visit_Constructor(self, constructor):
  206. self.fOut.write("// Constructor")
  207. parameters = [FormalParameter("controller", "", None)] + constructor.getParams()
  208. self.writeConstructorSignature(constructor.parent_class.name, parameters)
  209. self.fOut.indent()
  210. if constructor.parent_class.super_classes:
  211. self.fOut.write(constructor.parent_class.super_classes[0] + ".call(this);")
  212. else:
  213. self.fOut.write("RuntimeClassBase.call(this);")
  214. self.fOut.write()
  215. self.fOut.write("if (controller) {")
  216. self.fOut.indent()
  217. #visit input, output ports
  218. self.fOut.write("// User defined input ports")
  219. self.fOut.write("this.inports = new Object();")
  220. for p in constructor.parent_class.inports:
  221. self.fOut.write("this.inports[\""+p+"\"] = controller.addInputPort(\""+p+"\", this);")
  222. #for p in class_node.outports:
  223. # write attributes
  224. if constructor.parent_class.attributes:
  225. self.fOut.write()
  226. self.fOut.write("// User defined attributes")
  227. for attribute in constructor.parent_class.attributes:
  228. if attribute.init_value is None :
  229. self.fOut.write("this." + attribute.name + " = null;")
  230. else :
  231. self.fOut.write("this." + attribute.name + " = " + attribute.init_value + ";")
  232. self.fOut.write()
  233. # if there is a statechart
  234. if constructor.parent_class.statechart is not None:
  235. self.fOut.write("this.controller = controller;")
  236. self.fOut.write("this.object_manager = controller.object_manager;")
  237. self.fOut.write("this.current_state = new Object();")
  238. self.fOut.write("this.history_state = new Object();")
  239. if constructor.parent_class.statechart.nr_of_after_transitions:
  240. self.fOut.write("this.timers = new Object();")
  241. self.fOut.write()
  242. self.fOut.write("// Initialize statechart")
  243. if constructor.parent_class.statechart.histories:
  244. for node in constructor.parent_class.statechart.combined_history_parents:
  245. self.fOut.write("this.history_state[" + constructor.parent_class.name + "." + node.full_name + "] = new Array();")
  246. self.fOut.write()
  247. for c in constructor.parent_class.statechart.composites :
  248. self.fOut.write("this.current_state[this." + c.full_name + "] = new Array();")
  249. self.fOut.write()
  250. self.fOut.write("// Call user defined constructor")
  251. self.fOut.write(constructor.parent_class.name + ".prototype.user_defined_constructor.call(this")
  252. for p in constructor.getParams():
  253. self.fOut.extendWrite(", ")
  254. p.accept(self)
  255. self.fOut.extendWrite(");")
  256. self.fOut.dedent()
  257. self.fOut.write("}")
  258. self.fOut.dedent()
  259. self.fOut.write("};")
  260. self.fOut.write()
  261. def visit_Destructor(self, destructor):
  262. self.fOut.write("// User defined destructor")
  263. self.writeMethodSignature(destructor.parent_class.name, "user_defined_destructor", [])
  264. self.fOut.indent()
  265. if destructor.body.strip():
  266. self.writeCodeCorrectIndent(destructor.body)
  267. if destructor.parent_class.super_classes:
  268. self.fOut.write()
  269. self.fOut.write("// Call super class destructors")
  270. for super_class in destructor.parent_class.super_classes:
  271. self.fOut.write(super_class + ".prototype.user_defined_destructor.call(this);")
  272. self.fOut.dedent()
  273. self.fOut.write("};");
  274. self.fOut.write()
  275. def visit_Method(self, method):
  276. self.fOut.write("// User defined method")
  277. self.writeMethod(method.parent_class.name, method.name, method.parameters, method.return_type, method.body)
  278. def visit_Association(self, association):
  279. self.fOut.write('instance.associations["' + association.name + '"] = new Association("' + association.to_class + '", ' + str(association.min) + ', ' + str(association.max) + ');')
  280. #helper method
  281. def writeTransitionsRecursively(self, current_node):
  282. self.writeMethodSignature(current_node.statechart.class_obj.name, "transition_" + current_node.full_name, [FormalParameter("event", "event")])
  283. self.fOut.indent()
  284. valid_children = []
  285. for child in current_node.children :
  286. if child.is_composite or child.is_basic :
  287. valid_children.append(child)
  288. self.fOut.write("var catched = false;")
  289. do_dedent = False
  290. if current_node.solves_conflict_outer :
  291. self.writeFromTransitions(current_node)
  292. if current_node.is_parallel_state or current_node.is_composite :
  293. self.fOut.write("if (!catched) {")
  294. self.fOut.indent()
  295. do_dedent = True
  296. if current_node.is_parallel_state:
  297. for child in valid_children :
  298. self.fOut.write("catched = this.transition_" + child.full_name + "(event) || catched")
  299. elif current_node.is_composite:
  300. for i, child in enumerate(valid_children) :
  301. if i > 0 :
  302. self.fOut.write("else ")
  303. else :
  304. self.fOut.write()
  305. self.fOut.extendWrite("if (this.current_state[this." + current_node.full_name + "][0] === this." + child.full_name + ") {")
  306. self.fOut.indent()
  307. self.fOut.write("catched = this.transition_" + child.full_name + "(event);")
  308. self.fOut.dedent()
  309. self.fOut.write("}")
  310. if current_node.solves_conflict_outer :
  311. if do_dedent :
  312. self.fOut.dedent()
  313. self.fOut.write("}")
  314. elif len(current_node.transitions) > 0 :
  315. self.fOut.write("if (!catched) {")
  316. self.fOut.indent()
  317. self.writeFromTransitions(current_node)
  318. self.fOut.dedent()
  319. self.fOut.write("}");
  320. self.fOut.write("return catched;")
  321. self.fOut.dedent()
  322. self.fOut.write("};");
  323. self.fOut.write();
  324. for child in valid_children :
  325. self.writeTransitionsRecursively(child)
  326. #helper method
  327. def writeFromTransitions(self, current_node):
  328. # get all transition out of this state
  329. out_transitions = current_node.transitions
  330. if len(out_transitions) == 0 :
  331. return
  332. self.fOut.write('var enableds = new Array();')
  333. for index, transition in enumerate(out_transitions, start=1):
  334. self.writeTransitionCondition(transition, index)
  335. self.fOut.write("if (enableds.length > 1) {")
  336. self.fOut.indent()
  337. 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.")')
  338. self.fOut.dedent()
  339. self.fOut.write("}")
  340. self.fOut.write()
  341. self.fOut.write("if (enableds.length > 0) {")
  342. self.fOut.indent()
  343. self.fOut.write('var enabled = enableds[0];')
  344. for index, transition in enumerate(out_transitions, start=1):
  345. self.writeTransitionAction(transition, index)
  346. self.fOut.write('catched = true;')
  347. self.fOut.dedent()
  348. self.fOut.write("}")
  349. self.fOut.write()
  350. def visit_FormalEventParameter(self, formal_event_parameter):
  351. self.fOut.extendWrite(formal_event_parameter.name)
  352. def writeFormalEventParameters(self, transition):
  353. parameters = transition.getTrigger().getParameters()
  354. if(len(parameters) > 0) :
  355. self.fOut.write('var parameters = event.parameters;')
  356. for index, parameter in enumerate(parameters):
  357. self.fOut.write()
  358. self.fOut.write("var ")
  359. parameter.accept(self)
  360. self.fOut.extendWrite(' = parameters[' + str(index) + '];')
  361. def writeTransitionAction(self, transition, index):
  362. if index > 1 :
  363. self.fOut.write("else ")
  364. else :
  365. self.fOut.write()
  366. self.fOut.extendWrite("if (enabled === " + str(index) + ") {")
  367. self.fOut.indent()
  368. # handle parameters to actually use them
  369. self.writeFormalEventParameters(transition)
  370. exits = transition.getExitNodes()
  371. # write out exit actions
  372. if not exits[-1].is_basic:
  373. self.fOut.write("this.exit_" + exits[-1].full_name + "();")
  374. else:
  375. for node in exits:
  376. if node.is_basic:
  377. self.fOut.write("this.exit_" + node.full_name + "();")
  378. # write out trigger actions
  379. transition.getAction().accept(self)
  380. for (entering_node, is_ending_node) in transition.getEnterNodes() :
  381. if is_ending_node :
  382. if entering_node.is_composite:
  383. self.fOut.write("this.enterDefault_" + entering_node.full_name + "();")
  384. elif entering_node.is_history:
  385. if (entering_node.is_history_deep) :
  386. self.fOut.write("this.enterHistoryDeep_" + entering_node.parent.full_name + "();")
  387. else :
  388. self.fOut.write("this.enterHistoryShallow_" + entering_node.parent.full_name + "();")
  389. else:
  390. self.fOut.write("this.enter_" + entering_node.full_name + "();")
  391. else :
  392. if entering_node.is_composite:
  393. self.fOut.write("this.enter_" + entering_node.full_name + "();")
  394. self.fOut.dedent()
  395. self.fOut.write("}")
  396. def writeTransitionCondition(self, transition, index):
  397. trigger = transition.getTrigger()
  398. if not trigger.isUC():
  399. self.fOut.write('if (event.name === "' + trigger.getEvent() + '"' + ((' && event.port === "' + trigger.getPort()+'"') if trigger.getPort() != "" else '') + ') {')
  400. self.fOut.indent()
  401. # evaluate guard
  402. if transition.hasGuard() :
  403. # handle parameters for guard evaluation
  404. self.writeFormalEventParameters(transition)
  405. self.fOut.write('if (')
  406. transition.getGuard().accept(self)
  407. self.fOut.extendWrite(') {')
  408. self.fOut.indent()
  409. self.fOut.write("enableds.push(" + str(index) + ");")
  410. if transition.hasGuard() :
  411. self.fOut.dedent()
  412. self.fOut.write("}")
  413. if not trigger.isUC() :
  414. self.fOut.dedent()
  415. self.fOut.write("}")
  416. self.fOut.write()
  417. def visit_EnterAction(self, enter_method):
  418. parent_node = enter_method.parent_node
  419. self.writeMethodSignature(parent_node.statechart.class_obj.name, "enter_" + parent_node.full_name, [])
  420. self.fOut.indent()
  421. # take care of any AFTER events
  422. for transition in parent_node.transitions :
  423. trigger = transition.getTrigger()
  424. if trigger.isAfter() :
  425. self.fOut.write("this.timers[" + str(trigger.getAfterIndex()) + "] = ")
  426. trigger.after.accept(self)
  427. self.fOut.extendWrite(" * 1000.0; /* convert ms to s */")
  428. if enter_method.action:
  429. enter_method.action.accept(self)
  430. self.fOut.write("this.current_state[this." + parent_node.parent.full_name + "].push(this." + parent_node.full_name + ");")
  431. self.fOut.dedent()
  432. self.fOut.write("};")
  433. self.fOut.write()
  434. #helper method
  435. def writeEnterDefault(self, entered_node):
  436. self.writeMethodSignature(entered_node.statechart.class_obj.name, "enterDefault_" + entered_node.full_name, [])
  437. self.fOut.indent()
  438. self.fOut.write("this.enter_" + entered_node.full_name + "();")
  439. if entered_node.is_composite:
  440. l = entered_node.defaults
  441. for i in l:
  442. if i.is_composite:
  443. self.fOut.write("this.enterDefault_" + i.full_name + "();")
  444. elif i.is_basic:
  445. self.fOut.write("this.enter_" + i.full_name + "();")
  446. self.fOut.dedent()
  447. self.fOut.write("};")
  448. self.fOut.write()
  449. def visit_ExitAction(self, exit_method):
  450. exited_node = exit_method.parent_node
  451. self.writeMethodSignature(exited_node.statechart.class_obj.name, "exit_" + exited_node.full_name, [])
  452. self.fOut.indent()
  453. #If the exited node is composite take care of potential history and the leaving of descendants
  454. if exited_node.is_composite :
  455. #handle history
  456. if exited_node.save_state_on_exit :
  457. self.fOut.write("this.history_state[this." + exited_node.full_name + "] = this.current_state[this." + exited_node.full_name + "];")
  458. #Take care of leaving children
  459. children = exited_node.children
  460. if exited_node.is_parallel_state:
  461. for child in children:
  462. if not child.is_history :
  463. self.fOut.write("this.exit_" + child.full_name + "();")
  464. else:
  465. for child in children:
  466. if not child.is_history :
  467. self.fOut.write("if (this.current_state[this." + exited_node.full_name + "].indexOf(this." + child.full_name + ") !== -1) {")
  468. self.fOut.indent()
  469. self.fOut.write("this.exit_" + child.full_name + "();")
  470. self.fOut.dedent()
  471. self.fOut.write("}")
  472. # take care of any AFTER events
  473. for transition in exited_node.transitions :
  474. trigger = transition.getTrigger()
  475. if trigger.isAfter() :
  476. self.fOut.write("delete this.timers[" + str(trigger.getAfterIndex()) + "];")
  477. #Execute user-defined exit action if present
  478. if exit_method.action:
  479. exit_method.action.accept(self)
  480. #Adjust state
  481. self.fOut.write("this.current_state[this." + exited_node.parent.full_name + "] = new Array();") # SPECIAL CASE FOR ORTHOGONAL??
  482. self.fOut.dedent()
  483. self.fOut.write("};")
  484. self.fOut.write()
  485. #helper method
  486. def writeEnterHistory(self, entered_node, is_deep):
  487. self.writeMethodSignature(entered_node.statechart.class_obj.name, "enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + entered_node.full_name, [])
  488. self.fOut.indent()
  489. self.fOut.write("if (this.history_state[this." + entered_node.full_name + "].length === 0) {")
  490. self.fOut.indent()
  491. defaults = entered_node.defaults
  492. for node in defaults:
  493. if node.is_basic :
  494. self.fOut.write("this.enter_" + node.full_name + "();")
  495. elif node.is_composite :
  496. self.fOut.write("this.enterDefault_" + node.full_name + "();")
  497. self.fOut.dedent()
  498. self.fOut.write("} else {")
  499. self.fOut.indent()
  500. children = entered_node.children
  501. if entered_node.is_parallel_state:
  502. for child in children:
  503. if not child.is_history :
  504. self.fOut.write("this.enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + child.full_name + "();")
  505. else:
  506. for child in children:
  507. if not child.is_history :
  508. self.fOut.write("if (this.history_state[this." + entered_node.full_name + "].indexOf(this." + child.full_name + ") !== -1) {")
  509. self.fOut.indent()
  510. if child.is_composite:
  511. if is_deep :
  512. self.fOut.write("this.enter_" + child.full_name + "()")
  513. self.fOut.write("this.enterHistoryDeep_" + child.full_name + "()")
  514. else :
  515. self.fOut.write("this.enterDefault_" + child.full_name + "()")
  516. else:
  517. self.fOut.write("this.enter_" + child.full_name + "()")
  518. self.fOut.dedent()
  519. self.fOut.write("}")
  520. self.fOut.dedent()
  521. self.fOut.write("}")
  522. self.fOut.dedent()
  523. self.fOut.write("};")
  524. self.fOut.write()
  525. def visit_StateChart(self, statechart):
  526. self.fOut.write("// Statechart enter/exit action method(s) :")
  527. self.fOut.write()
  528. #visit enter and exit action of children
  529. for i in statechart.composites + statechart.basics:
  530. if i is not statechart.root :
  531. i.enter_action.accept(self)
  532. i.exit_action.accept(self)
  533. # write out statecharts methods for enter/exit state
  534. if len(statechart.composites) > 1 :
  535. self.fOut.write("// Statechart enter/exit default method(s) :")
  536. self.fOut.write()
  537. for i in statechart.composites :
  538. if i is not statechart.root :
  539. self.writeEnterDefault(i)
  540. # write out statecharts methods for enter/exit history
  541. if statechart.histories:
  542. self.fOut.write("// Statechart enter/exit history method(s) :")
  543. self.fOut.write()
  544. for i in statechart.shallow_history_parents:
  545. self.writeEnterHistory(i, False)
  546. for i in statechart.deep_history_parents:
  547. self.writeEnterHistory(i, True)
  548. self.fOut.write("// Statechart transitions :")
  549. self.fOut.write()
  550. self.writeTransitionsRecursively(statechart.root)
  551. # write out transition function
  552. self.fOut.write("// Execute transitions")
  553. self.writeMethodSignature(statechart.class_obj.name, "transition", [FormalParameter("event", "Event", "new Event()")])
  554. self.fOut.indent()
  555. self.fOut.write("this.state_changed = this.transition_" + statechart.root.full_name + "(event);")
  556. self.fOut.dedent()
  557. self.fOut.write("};");
  558. self.fOut.write()
  559. # write out inState function
  560. self.fOut.write("// inState method for statechart")
  561. self.writeMethodSignature(statechart.class_obj.name, "inState", [FormalParameter("nodes", "Array")])
  562. #self.fOut.write("def inState(self, nodes):")
  563. self.fOut.indent()
  564. self.fOut.write("for (var c in this.current_state) {")
  565. self.fOut.indent()
  566. self.fOut.write("if (!this.current_state.hasOwnProperty(c)) continue;")
  567. self.fOut.write("var new_nodes = new Array();")
  568. self.fOut.write("for (var n in nodes) {")
  569. self.fOut.indent()
  570. self.fOut.write("if (!nodes.hasOwnProperty(n)) continue;")
  571. self.fOut.write("if (this.current_state[c].indexOf(nodes[n]) === -1) {")
  572. self.fOut.indent()
  573. self.fOut.write("new_nodes.push(nodes[n]);")
  574. self.fOut.dedent()
  575. self.fOut.write("}")
  576. self.fOut.dedent()
  577. self.fOut.write("}")
  578. self.fOut.write("nodes = new_nodes;")
  579. self.fOut.write("if (nodes.length === 0) {")
  580. self.fOut.indent()
  581. self.fOut.write("return true;")
  582. self.fOut.dedent()
  583. self.fOut.write("}")
  584. self.fOut.dedent()
  585. self.fOut.write("}")
  586. self.fOut.write("return false;")
  587. self.fOut.dedent()
  588. self.fOut.write("};")
  589. self.fOut.write()
  590. def visit_ExpressionPartString(self, bare_string):
  591. self.fOut.extendWrite(bare_string.string)
  592. def visit_SelfReference(self, self_reference):
  593. self.fOut.extendWrite("this")
  594. def visit_StateReference(self, state_ref):
  595. self.fOut.extendWrite("[" + ",".join(["this." + node.full_name for node in state_ref.getNodes()]) + "]")
  596. def visit_InStateCall(self, in_state_call):
  597. self.fOut.extendWrite("this.inState(")
  598. in_state_call.target.accept(self)
  599. self.fOut.extendWrite(")")
  600. def visit_RaiseEvent(self, raise_event):
  601. if raise_event.isNarrow() or raise_event.isBroad():
  602. self.fOut.write('var send_event = new Event("' + raise_event.getEventName() + '", null, [')
  603. elif raise_event.isLocal():
  604. self.fOut.write('this.addEvent(new Event("' + raise_event.getEventName() + '", null, [')
  605. elif raise_event.isOutput():
  606. self.fOut.write('this.controller.outputEvent(new Event("' + raise_event.getEventName() + '", "' + raise_event.getPort() + '", [')
  607. elif raise_event.isCD():
  608. self.fOut.write('this.object_manager.addEvent(new Event("' + raise_event.getEventName() + '", null, [this, ')
  609. first_param = True
  610. for param in raise_event.getParameters() :
  611. if first_param :
  612. first_param = False
  613. else :
  614. self.fOut.extendWrite(',')
  615. param.accept(self)
  616. if raise_event.isNarrow():
  617. self.fOut.extendWrite(']);')
  618. self.fOut.write('this.object_manager.addEvent(new Event("narrow_cast", null, [this, ' + raise_event.getTarget() + ' , send_event]));')
  619. elif raise_event.isBroad():
  620. self.fOut.extendWrite(']);')
  621. self.fOut.write('this.object_manager.addEvent(new Event("broad_cast", null, [send_event]));')
  622. else :
  623. self.fOut.extendWrite(']));')
  624. def visit_Script(self, script):
  625. self.writeCodeCorrectIndent(script.code)
  626. def visit_Log(self, log):
  627. self.fOut.write('console.log("' + log.message + '");')
  628. def visit_Assign(self, assign):
  629. self.fOut.write()
  630. assign.lvalue.accept(self)
  631. self.fOut.extendWrite(" = ")
  632. assign.expression.accept(self)