def test_while_break(self): def f(x): while x: if True: break return x with graph_factory(): expected = G( C(START_TICK, "x", 1, "$test"), C(START_TICK, "x", 1, "x"), T( 1, tasks.WhileTask( False, False, G( "body", C(START_TICK, "x", 2, "$test"), C(START_TICK, "x", 2, "x"), T(1, tasks.ConstTask(True), {'quick': True}), C(1, "value", 2, "$breaked"), T( 2, tasks.WhileTask(True, True, G("body"), G("else"))), ), G("else"))), C(START_TICK, "x", FINAL_TICK, "retval")) callee = translator.translate_function(f, "scheduler", False) utils.assert_graph_equal(expected, callee.graph)
def test_while(self): def f(x): while x: pass return x with graph_factory(): expected = G( C(START_TICK, "x", 1, "$test"), C(START_TICK, "x", 1, "x"), T( 1, tasks.WhileTask( False, False, G( "body", C(START_TICK, "x", 1, "$test"), C(START_TICK, "x", 1, "x"), T( 1, tasks.WhileTask(True, False, G("body"), G("else"))), ), G("else"))), C(START_TICK, "x", FINAL_TICK, "retval")) callee = translator.translate_function(f, "scheduler", False) utils.assert_graph_equal(expected, callee.graph)
def test_refine_body_twice(self): # def f(x): # while x: # pass # return x with graph_factory(): g = G( C(START_TICK, "x", 1, "$test"), C(START_TICK, "x", 1, "x"), T(1, tasks.WhileTask(False, False, G("body", C(START_TICK, "x", 1 , "$test"), C(START_TICK, "x", 1 , "x"), T(1, tasks.WhileTask(True, False, G("body"), G("else"))), ), G("else"))), C(START_TICK, "x", FINAL_TICK, "retval") ) target = g.get_task(START_TICK + 1) target.refine(g, START_TICK + 1, {"$test":True}) target = g.get_task(Tick.parse_tick((1,1,1))) target.refine(g, Tick.parse_tick((1,1,1)), {"$test":True}) with graph_factory(): expected = G( C(START_TICK, "x", (1,2,1), "$test"), C(START_TICK, "x", (1,2,1), "x"), T((1,2,1), tasks.WhileTask(True, False, G("body", C(START_TICK, "x", 1 , "$test"), C(START_TICK, "x", 1 , "x"), T(1, tasks.WhileTask(True, False, G("body"), G("else"))), ), G("else"))), C(START_TICK, "x", FINAL_TICK, "retval") ) utils.assert_graph_equal(expected, g)
def visit_While(self, node): # Get rid of `break` but remember the AST expression that tells us when it executes body_statements, break_condition = _extract_break(node.body) # Factory for the body body_factory = GraphFactory( unassinged_local_strategy=UnassignedLocalStrategy.MAKE_GRAPH_INPUT) # Create the body graph. This still lacks the tail-recursive task, though. self.factory_stack.append(body_factory) for stmt in body_statements: self.visit(stmt) # Visit break if break_condition: breaked = self.visit(break_condition) else: breaked = None # Condition for next iteration inner_condition = self.visit(node.test) self.factory_stack.pop() body_factory.make_assigned_vars_outputs() body_graph = body_factory.get_graph() # Create the graph for orelse. orelse_factory = GraphFactory( unassinged_local_strategy=UnassignedLocalStrategy.MAKE_GRAPH_INPUT) self.factory_stack.append(orelse_factory) for stmt in node.orelse: self.visit(stmt) self.factory_stack.pop() orelse_factory.make_assigned_vars_outputs() orelse_graph = orelse_factory.get_graph() # We create the tail-recursive loop task. It stores the incomplete body graph # but that is ok, we'll change that graph in-place. inner_task = tasks.WhileTask(True, breaked is not None, body_graph, orelse_graph) inner_task_inputs = [(inner_condition, "$test")] if breaked: inner_task_inputs.append((breaked, "$breaked")) # Add the nested loop task body_factory.exec_task(inner_task, inputs=inner_task_inputs, autoconnect=True) # we messed with the body graph since we did this the last time, we have to redo this. body_factory.make_assigned_vars_outputs() # -- body and orelse graphs are complete -- # -- add the task for the complete loop to the current graph -- # Even before the loop, get an iterator from the iterable. test = self.visit(node.test) # Finally we can add the loop task. whiletask = tasks.WhileTask(False, False, body_graph, orelse_graph) self.factory_stack[-1].exec_task(whiletask, inputs=[(test, "$test")], autoconnect=True)