csharp_generator.py 29 KB

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