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