def visit_For(self, for_loop): # Initialize loop variable self.visit_Assignment(for_loop.init) # Visit loop statement to get all the written variables for_written_set = set() body_ast = AST_C(self.simplify) # Use the current loop number incremented by one if there is a nested loop inside body_ast.set_num_loops(self.num_loops + 1) body_ast.visit(for_loop.stmt) for_written_set.update(body_ast.written_set) self.written_set += body_ast.written_set self.read_set += body_ast.read_set # The next statement counts as a write for_written_set.update(body_ast.written_set) for_written_set.add(for_loop.next.lvalue.name) increment_id = func.ID(for_loop.next.lvalue.name) increment_expr = self.expr(for_loop.next.rvalue.__class__, for_loop.next.rvalue) self.written_set.append(for_loop.next.lvalue.name) self.written_set.append(for_loop.next.lvalue.name) outer_id = func.ReturnTuple(for_written_set) if len(for_written_set) > 1 else func.ID(next(iter(for_written_set))) inner_id = func.ArgsRecList("loop{}".format(self.num_loops), for_written_set) self.num_loops += 1 # Use a recursive style if statement to replace loop # If the condition from the loop condition is true, then run the loop body with the increment at the end # Ignore simplfication for now cond = self.expr(for_loop.cond.__class__, for_loop.cond) body_ast.tail_binding.expr2 = func.Binding(increment_id, increment_expr, inner_id) # Otherwise, return the written variables if_expr = func.If(cond, body_ast.head_binding, outer_id) rec_expr = func.RecursiveFunction(inner_id, if_expr, inner_id) self.__create_binding(outer_id, rec_expr, None)
def visit_If(self, condition): # Get condition cond_expr = self.expr(condition.cond.__class__, condition.cond) self.visit(condition.cond) iftrue_ast = None iffalse_ast = None if_written_set = set() # When the iftrue or iffalse blocks are not None then visit that branch # and update the written_set and read_set. if not condition.iftrue is None: iftrue_ast = AST_C(self.simplify) iftrue_ast.visit(condition.iftrue) self.written_set += iftrue_ast.written_set self.read_set += iftrue_ast.read_set if_written_set.update(iftrue_ast.written_set) if not condition.iffalse is None: iffalse_ast = AST_C(self.simplify) iffalse_ast.visit(condition.iffalse) self.written_set += iffalse_ast.written_set self.read_set += iffalse_ast.read_set if_written_set.update(iffalse_ast.written_set) # Create functional node lhs = func.ReturnTuple(if_written_set) if len(if_written_set) > 1 else func.ID(next(iter(if_written_set))) # Set the expression to be the same as the left hand side assignment if the iftrue or iffalse blocks are None. # Otherwise, set the tail binding's second expression to be the left hand side assignment and set the expression # as the binding of the associated branch. if condition.iftrue is None: iftrue_expr = lhs else: iftrue_expr = self.simplify_binding(iftrue_ast.head_binding, iftrue_ast.written_set, iftrue_ast.read_set, if_written_set) if condition.iffalse is None: iffalse_expr = lhs else: iffalse_expr = self.simplify_binding(iffalse_ast.head_binding, iffalse_ast.written_set, iffalse_ast.read_set, if_written_set) # Create functional condition node and binding if_expr = func.If(cond_expr, iftrue_expr, iffalse_expr) self.__create_binding(lhs, if_expr, None)
def visit_Assignment(self, assignment): self.visit(assignment.rvalue) expr1 = self.expr(assignment.rvalue.__class__, assignment.rvalue) if isinstance(assignment.lvalue, ID): written_var = func.ID(assignment.lvalue.name) self.written_set.append(assignment.lvalue.name) else: written_var = self.expr(assignment.lvalue.__class__, assignment.lvalue) # Written Variable is the array name, all the subscripts are read self.visit_ArrayRef(assignment.lvalue) expr = assignment.lvalue while not isinstance(expr, ID): expr = expr.name self.written_set.append(expr.name) self.__create_binding(written_var, expr1, None)
def expr(self, _class, value): return { Constant: (lambda orig: func.Constant(orig.value)), ID: (lambda orig: func.ID(orig.name)), ArrayRef: (lambda orig: func.ArrayRef( self.expr(orig.name.__class__, orig.name), self.expr(orig.subscript.__class__, orig.subscript))), ExprList: (lambda orig: func.ArgsList([self.expr(x.__class__, x) for x in orig.exprs])), FuncCall: (lambda orig: func.FuncCall( self.expr(orig.name.__class__, orig.name), self.expr(orig.args.__class__, orig.args))), UnaryOp: (lambda orig: func.UnaryOp( orig.op, self.expr(orig.expr.__class__, orig.expr) )), BinaryOp: (lambda orig: func.BinaryOp(orig.op, self.expr(orig.left.__class__ , orig.left), self.expr(orig.right.__class__, orig.right))), TernaryOp: (lambda orig: func.If( self.expr(orig.cond.__class__, orig.cond), self.expr(orig.iftrue.__class__, orig.iftrue), self.expr(orig.iffalse.__class__, orig.iffalse) )) }.get(_class)(value)
def visit_While(self, while_loop): # Do not need to worry about incrementation and initialization in while loop. Assume they're there and loop can terminate. # Visit loop statement to get all the written variables while_written_set = set() body_ast = AST_C(self.simplify) body_ast.set_num_loops(self.num_loops + 1) body_ast.visit(while_loop.stmt) while_written_set.update(body_ast.written_set) self.written_set += body_ast.written_set self.read_set += body_ast.read_set outer_id = func.ReturnTuple(while_written_set) if len(while_written_set) > 1 else func.ID(next(iter(while_written_set))) inner_id = func.ArgsRecList("loop{}".format(self.num_loops), while_written_set) self.num_loops += 1 # Use a recursive style if statement to replace loop # If the condition from the loop condition is true, then run the loop body with the increment at the end # Ignore simplfication for now cond = self.expr(while_loop.cond.__class__, while_loop.cond) body_ast.tail_binding.expr2 = inner_id if_expr = func.If(cond, body_ast.head_binding, outer_id) rec_expr = func.RecursiveFunction(inner_id, if_expr, inner_id) self.__create_binding(outer_id, rec_expr, None)