javascript_generator.py 25 KB

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