def test_function_call_with_arguments(self): arguments = [ code.SimpleVariable("a"), code.SimpleVariable("b"), code.BooleanLiteral(False) ] self.unit.select("test", "dec") \ .append(code.FunctionCall("some_func", arguments)) self.assertEqualToSource(self.unit, "some_func(a, b, FALSE);")
def after_visit_VariableExp(self, var): type = self.code.pop() id = self.code.pop() # a variable is self-declaring on first-use, we stored this on the stack if self.code.pop(): self.code.append(code.VariableDecl(id, type)) else: self.code.append(code.SimpleVariable(id, var.type))
def create_when_execution(self, execution): if execution.event.name == "receive": f = self.generator.unit.find(execution.executed.name + "_decl") if not f is None and len(f.children) > 0: # if children are single CaseStatement, it will be handled by Transform if not isinstance(f.children[0], code.CaseStatement): # else we need to register a catch-all handlers self.generator.unit.find("init").append( code.FunctionCall( "payload_parser_register_all", [code.SimpleVariable(execution.executed.name)])) return # Case-based receiving is handled by Transform # TODO: generalize: only supported = after transmit for all nodes assert execution.timing == "after" assert execution.event.name == "transmit" assert isinstance(execution.scope, AllNodes) # wire transmit handler self.generator.unit.find("init").append( code.FunctionCall("mesh_on_transmit", [code.SimpleVariable("handle_transmit")])) # setup transforming handle_transmit self.generator.unit.find("nodes_main").select("dec").append( code.Function( "handle_transmit", params=[ code.Parameter("from", code.IntegerType()), code.Parameter("hop", code.IntegerType()), code.Parameter("to", code.IntegerType()), code.Parameter("size", code.ByteType()), code.Parameter("payload", code.ManyType(code.ByteType())) ]).contains( code.FunctionCall( execution.executed.name, arguments=[ code.FunctionCall( "nodes_lookup", type=code.ObjectType("node"), arguments=[code.SimpleVariable("from")]), code.FunctionCall( "nodes_lookup", type=code.ObjectType("node"), arguments=[code.SimpleVariable("hop")]), code.FunctionCall( "nodes_lookup", type=code.ObjectType("node"), arguments=[code.SimpleVariable("to")]), code.FunctionCall( "make_payload", type=code.ObjectType("payload"), arguments=[ code.SimpleVariable("payload"), code.SimpleVariable("size") ]), ])))
def create_every_execution(self, execution): if isinstance(execution.scope, AllNodes): name = "nodes_schedule_all" else: name = "nodes_schedule_own" self.generator.unit.find("nodes_scheduler_init").append( code.FunctionCall(name, arguments=[ self._translate(execution.interval), code.SimpleVariable(execution.executed.name) ]))
def prepare(self): """ Prepares the definition of the node type. """ # this is a generator for the Nodes domain, let's get it ;-) self.domain = SemanticNodes() # we need a translator self.translator = Translator() node_type = code.StructuredType("nodes").tag("node_type_def") node_type.append(code.Comment("domain properties"), code.Property("id", code.ByteType()), code.Property("address", code.LongType())) # the node type module = self.generator.unit.append(structure.Module("node_t")) module.select("def").append(code.Import("moose/bool")) module.select("def").append(code.Comment("THE node type"), node_type).tag("node_t-start") # provide init_node to initialise module-specific properties module.select("dec").append( code.Import("node_t"), code.Function("init_node", params=[ code.Parameter("node", type=code.ObjectType("node")) ]).tag("init_node") # filled when creating node_t ) # TODO: remove this redundant header file module = self.generator.unit.append(structure.Module("nodes")) module.select("def").append(code.Import("includes")) # add more imports to includes anchor = self.generator.unit.select("includes").select("def").find( "foo-lib-start") code.Import("nodes").insert_before(anchor).tag("requires-tuples") code.Import("node_t").insert_before(anchor) code.Import("foo-lib/nodes").insert_before(anchor) code.Import("foo-lib/payload").insert_before(anchor) # initialiase nodes and add handling of receive packets self.generator.unit.find("init").append( code.FunctionCall("nodes_init"), code.FunctionCall("mesh_on_receive", [code.SimpleVariable("payload_parser_parse")]))
def visit_CaseStatement(self, stmt): """ CaseStatements may be used to handle incoming payloads. These should be centralized in the processing of incoming payloads. Payload references are found in the case.expression.type == semantic.Nodes.payload_t. We now support the typical case with a contains() function. For each of these we generate a function based on the consequence, accepting a payload, positioned where it contains information following the case condition. The case condition's literals are added as to-find literals and a reference to the handling function is also registered with a general purpose byte- stream parser/state machine. """ # TODO: take into account execution strategy # TODO: only supported now: SimpleVariable if isinstance(stmt.expression, code.SimpleVariable): if stmt.expression.info == SemanticNodes.payload_t: # move handling to centralized processing of incoming data for case, consequence in zip(stmt.cases, stmt.consequences): # create a function that processes matched payload handler = code.Function( "nodes_process_incoming_case_" + str(Transformer.processors), params=[ code.Parameter("me", code.ObjectType("node")), code.Parameter("sender", code.ObjectType("node")), code.Parameter("from", code.ObjectType("node")), code.Parameter("hop", code.ObjectType("node")), code.Parameter("to", code.ObjectType("node")), code.Parameter( "payload", self.translate( self.domain.get_type("payload"))) ]) Transformer.processors += 1 handler.append( code.Comment("extract variables from payload")) # declare matching local variables from case # NOTE: these are inside a ListLiteral for arg in case.arguments[0]: if isinstance(arg, code.Variable): code_type = self.translate(arg.info) # TODO: generalize this more code_type_name = { "NamedType {'name': 'timestamp'}": lambda: code_type.name, "ByteType": lambda: "byte", # TODO: amount has type, should be recursively extracted # TODO: size "AmountType {}": lambda: "bytes", "ObjectType {'name': 'nodes'}": lambda: code_type.name[:-1], "FloatType": lambda: "float" }[str(code_type)]() # TODO: size should be generalized args = [code.IntegerLiteral(code_type.size)] \ if code_type_name == "bytes" else [] if isinstance(code_type, code.AmountType): code_type = code.ManyType(code.ByteType()) handler.append( code.Assign( code.VariableDecl(arg.name, code_type), code.FunctionCall( "payload_parser_consume_" + code_type_name, type=code_type, arguments=args))) # add consequence handler.append(code.Comment("perform handling actions")) for statement in consequence: handler.append(statement) self.stack[0].find("nodes_main").select("dec").append( handler) # register the handle for the literals in the case arguments = code.ListLiteral() for arg in case.arguments[0]: if isinstance(arg, code.Literal): arguments.append(arg) registration = code.FunctionCall( "payload_parser_register", [code.SimpleVariable(handler.name), arguments]) self.stack[0].find("init").append(registration) # if there is an else case, also generate it and register it if not stmt.case_else == None: handler = code.Function( "nodes_process_incoming_else", params=[ code.Parameter("sender", code.ObjectType("node")), code.Parameter("from", code.ObjectType("node")), code.Parameter("hop", code.ObjectType("node")), code.Parameter("to", code.ObjectType("node")), code.Parameter( "payload", self.translate( self.domain.get_type("payload"))) ]) handler.append(self.translate(stmt.case_else)) self.stack[0].find("nodes_main").select("dec").append( handler) registration = code.FunctionCall( "payload_parser_register_else", [code.SimpleVariable(handler.name)]) self.stack[0].find("init").append(registration) # remove the case self.stack[-2].remove_child(self.child)