def writeState(s, i): self.writer.addVSpace() self.writer.addComment( "state %s" % ("<root>" if s.is_root else s.new_full_name)) index_expr = GLC.MapIndexedExpression(GLC.SelfProperty("states"), GLC.String(s.new_full_name)) clazz = "State" if s.is_parallel_state: clazz = "ParallelState" elif s.is_history: if s.is_history_deep: clazz = "DeepHistoryState" else: clazz = "ShallowHistoryState" self.writer.addAssignment( index_expr, GLC.NewExpression(clazz, [ str(i), GLC.String(s.new_full_name), GLC.SelfExpression() ])) if not s.is_root: if s.enter_action.action or s.has_timers: self.writer.add( GLC.FunctionCall( GLC.Property(index_expr, "setEnter"), [GLC.SelfProperty(s.friendly_name + "_enter")])) if s.exit_action.action or s.has_timers: self.writer.add( GLC.FunctionCall( GLC.Property(index_expr, "setExit"), [GLC.SelfProperty(s.friendly_name + "_exit")]))
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) ]))
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 class_node.constructors[0].accept(self) # visit destructor class_node.destructors[0].accept(self) # visit methods for i in class_node.methods: i.accept(self) # compile and initialize Statechart if class_node.statechart: class_node.statechart.accept(self) self.writer.beginMethod("initializeStatechart") self.writer.beginMethodBody() self.writer.addComment("enter default state") # get effective target of initial transition self.writer.addAssignment( GLC.SelfProperty("default_targets"), GLC.FunctionCall( GLC.Property( GLC.MapIndexedExpression( GLC.SelfProperty("states"), GLC.String(class_node.statechart.root.initial)), "getEffectiveTargetStates"))) self.writer.add( GLC.SuperClassMethodCall("RuntimeClassBase", "initializeStatechart", [])) self.writer.endMethodBody() self.writer.endMethod() self.writer.endClass()
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.FunctionCall(GLC.SelfProperty("getOutPortName"), [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( [GLC.SelfExpression(), new_event_expr]) ]) ]))
def visit_StateChart(self, statechart): self.writer.addVSpace() self.writer.beginMethod("build_statechart_structure", "builds Statechart structure") self.writer.beginMethodBody() def writeState(s, i): self.writer.addVSpace() self.writer.addComment( "state %s" % ("<root>" if s.is_root else s.new_full_name)) index_expr = GLC.MapIndexedExpression(GLC.SelfProperty("states"), GLC.String(s.new_full_name)) clazz = "State" if s.is_parallel_state: clazz = "ParallelState" elif s.is_history: if s.is_history_deep: clazz = "DeepHistoryState" else: clazz = "ShallowHistoryState" self.writer.addAssignment( index_expr, GLC.NewExpression(clazz, [ str(i), GLC.String(s.new_full_name), GLC.SelfExpression() ])) if not s.is_root: if s.enter_action.action or s.has_timers: self.writer.add( GLC.FunctionCall( GLC.Property(index_expr, "setEnter"), [GLC.SelfProperty(s.friendly_name + "_enter")])) if s.exit_action.action or s.has_timers: self.writer.add( GLC.FunctionCall( GLC.Property(index_expr, "setExit"), [GLC.SelfProperty(s.friendly_name + "_exit")])) # write all states for (i, s) in enumerate(statechart.states): writeState(s, i) # add children to composite states self.writer.addVSpace() self.writer.addComment("add children") for (i, s) in enumerate(statechart.composites): for c in s.children: self.writer.add( GLC.FunctionCall( GLC.Property( GLC.MapIndexedExpression( GLC.SelfProperty("states"), GLC.String(s.new_full_name)), "addChild"), [ GLC.MapIndexedExpression( GLC.SelfProperty("states"), GLC.String(c.new_full_name)) ])) # fix tree at root, such that 'descendants' and 'ancestors' fields are filled in self.writer.add( GLC.FunctionCall( GLC.Property( GLC.MapIndexedExpression(GLC.SelfProperty("states"), GLC.String("")), "fixTree"))) # defaults for (i, s) in enumerate(statechart.composites): if not s.is_parallel_state: self.writer.addAssignment( GLC.Property( GLC.MapIndexedExpression(GLC.SelfProperty("states"), GLC.String(s.new_full_name)), "default_state"), GLC.MapIndexedExpression(GLC.SelfProperty("states"), GLC.String(s.initial))) # transitions for s in statechart.basics + statechart.composites: if s.transitions: self.writer.addVSpace() self.writer.addComment("transition %s" % s.new_full_name) for (i, t) in enumerate(s.transitions + s.else_transitions): # instantiate new Transition instance self.writer.addAssignment( GLC.LocalVariableDeclaration("%s_%i" % (s.friendly_name, i)), GLC.NewExpression("Transition", [ GLC.SelfExpression(), GLC.MapIndexedExpression( GLC.SelfProperty("states"), GLC.String(s.new_full_name), ), GLC.ArrayExpression([ GLC.MapIndexedExpression( GLC.SelfProperty("states"), GLC.String(target_node.new_full_name)) for target_node in t.target.target_nodes ]) ])) # if any action associated with transition: set executable_content to correct function (generated later) if t.action.sub_actions: self.writer.add( GLC.FunctionCall( GLC.Property("%s_%i" % (s.friendly_name, i), "setAction"), [ GLC.SelfProperty("%s_%i_exec" % (s.friendly_name, i)) ])) # if any trigger associated with transition: instantiate correct Event instance trigger = None if t.trigger.is_after: trigger = GLC.NewExpression( "Event", [GLC.String("_%iafter" % (t.trigger.getAfterIndex()))]) elif t.trigger.event: trigger = GLC.NewExpression("Event", [ GLC.String(t.trigger.event), GLC.NoneExpression() if t.trigger.port is None else GLC.FunctionCall(GLC.SelfProperty("getInPortName"), [GLC.String(t.trigger.port)]) ]) else: trigger = GLC.NoneExpression() if trigger: self.writer.add( GLC.FunctionCall( GLC.Property("%s_%i" % (s.friendly_name, i), "setTrigger"), [trigger])) # if any guard associated with transition: set guard to correct function (generated later) if t.guard: self.writer.add( GLC.FunctionCall( GLC.Property("%s_%i" % (s.friendly_name, i), "setGuard"), [ GLC.SelfProperty("%s_%i_guard" % (s.friendly_name, i)) ])) self.writer.add( GLC.FunctionCall( GLC.Property( GLC.MapIndexedExpression( GLC.SelfProperty("states"), GLC.String(s.new_full_name)), "addTransition"), ["%s_%i" % (s.friendly_name, i)])) self.writer.endMethodBody() self.writer.endMethod() # enter/exit actions for (i, s) in enumerate(statechart.composites + statechart.basics): if not s.is_root: if s.enter_action.action or s.has_timers: s.enter_action.accept(self) if s.exit_action.action or s.has_timers: s.exit_action.accept(self) # transition actions and guards for s in statechart.composites + statechart.basics: for (i, t) in enumerate(s.transitions): if t.action.sub_actions: self.writeTransitionAction(t, i) if t.hasGuard(): self.writeTransitionGuard(t, i)
def visit_ClassDiagram(self, class_diagram): header = ( "Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)\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.beginElse() self.writer.add( GLC.ThrowExceptionStatement( GLC.AdditionExpression(GLC.String("Cannot instantiate class "), "class_name"))) self.writer.endElse() 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()) self.writer.addFormalParameter("behind_schedule_callback", GLC.NoneExpression()) elif self.platform == Platforms.Threads: self.writer.addFormalParameter("keep_running", GLC.TrueExpression()) self.writer.addFormalParameter("behind_schedule_callback", GLC.NoneExpression()) 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") self.writer.addActualParameter("behind_schedule_callback") elif self.platform == Platforms.Threads: self.writer.addActualParameter("keep_running") self.writer.addActualParameter("behind_schedule_callback") 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_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() 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()])) for p in constructor.parent_class.outports: self.writer.addAssignment( GLC.MapIndexedExpression(GLC.SelfProperty("outports"), GLC.String(p)), GLC.FunctionCall( GLC.Property("controller", "addOutputPort"), [GLC.String(p), GLC.SelfExpression()])) 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")) self.writer.addVSpace() self.writer.addComment("build Statechart structure") self.writer.add( GLC.FunctionCall( GLC.SelfProperty("build_statechart_structure"), [])) 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() # user defined constructor self.writer.beginMethod("user_defined_constructor") for p in constructor.getParams(): p.accept(self) self.writer.beginMethodBody() for super_class in constructor.parent_class.super_classes: # begin call if super_class in constructor.parent_class.super_class_objs: self.writer.beginSuperClassMethodCall( super_class, "user_defined_constructor") else: self.writer.beginSuperClassConstructorCall(super_class) # write actual parameters if super_class in constructor.super_class_parameters: for p in constructor.super_class_parameters[super_class]: self.writer.addActualParameter(p) # end call if super_class in constructor.parent_class.super_class_objs: self.writer.endSuperClassMethodCall() else: self.writer.endSuperClassConstructorCall() self.writer.addRawCode(constructor.body) self.writer.endMethodBody() self.writer.endMethod()