def visit_If(self, node): if self.isompdirective(node.test): self.visit(ast.Expr(node.test)) return self.visit( ast.If(ast.Constant(1, None), node.body, node.orelse)) else: return self.attach_data(node)
def visit_If(self, node): self.generic_visit(node) try: if ast.literal_eval(node.test): if not metadata.get(node, OMPDirective): self.update = True return node.body else: if not metadata.get(node, OMPDirective): self.update = True return node.orelse except ValueError: # not a constant expression pass have_body = any(not isinstance(x, ast.Pass) for x in node.body) have_else = any(not isinstance(x, ast.Pass) for x in node.orelse) # If the "body" is empty but "else content" is useful, switch branches # and remove else content if not have_body and have_else: test = ast.UnaryOp(op=ast.Not(), operand=node.test) self.update = True return ast.If(test=test, body=node.orelse, orelse=list()) # if neither "if" and "else" are useful, keep test if it is not pure elif not have_body: self.update = True if node.test in self.pure_expressions: return ast.Pass() else: node = ast.Expr(value=node.test) self.generic_visit(node) return node
def visit_Lambda(self, node): op = issimpleoperator(node) if op is not None: if mangle('operator') not in self.global_declarations: import_ = ast.Import( [ast.alias('operator', mangle('operator'))]) self.imports.append(import_) operator_module = MODULES['operator'] self.global_declarations[mangle('operator')] = operator_module return ast.Attribute( ast.Name(mangle('operator'), ast.Load(), None, None), op, ast.Load()) self.generic_visit(node) forged_name = "{0}_lambda{1}".format(self.prefix, len(self.lambda_functions)) ii = self.gather(ImportedIds, node) ii.difference_update(self.lambda_functions) # remove current lambdas binded_args = [ ast.Name(iin, ast.Load(), None, None) for iin in sorted(ii) ] node.args.args = ( [ast.Name(iin, ast.Param(), None, None) for iin in sorted(ii)] + node.args.args) for patternname, pattern in self.patterns.items(): if issamelambda(pattern, node): proxy_call = ast.Name(patternname, ast.Load(), None, None) break else: duc = ExtendedDefUseChains() nodepattern = deepcopy(node) duc.visit(ast.Module([ast.Expr(nodepattern)], [])) self.patterns[forged_name] = nodepattern, duc forged_fdef = ast.FunctionDef(forged_name, copy(node.args), [ast.Return(node.body)], [], None, None) metadata.add(forged_fdef, metadata.Local()) self.lambda_functions.append(forged_fdef) self.global_declarations[forged_name] = forged_fdef proxy_call = ast.Name(forged_name, ast.Load(), None, None) if binded_args: if MODULES['functools'] not in self.global_declarations.values(): import_ = ast.Import( [ast.alias('functools', mangle('functools'))]) self.imports.append(import_) functools_module = MODULES['functools'] self.global_declarations[mangle( 'functools')] = functools_module return ast.Call( ast.Attribute( ast.Name(mangle('functools'), ast.Load(), None, None), "partial", ast.Load()), [proxy_call] + binded_args, []) else: return proxy_call
def visit_Assert(self, node): convert_assert_node = gast.parse( 'fluid.dygraph.dygraph_to_static.convert_operators.convert_assert({test}, {msg})' .format(test=ast_to_source_code(node.test), msg=ast_to_source_code(node.msg) if node.msg else "")).body[0].value return gast.Expr(value=convert_assert_node)
def visit_Assert(self, node): convert_assert_node = gast.parse( 'paddle.jit.dy2static.convert_assert({test}, {msg})'.format( test=ast_to_source_code(node.test), msg=ast_to_source_code(node.msg) if node.msg else "")).body[0].value return gast.Expr(value=convert_assert_node)
def visit_Assign(self, node): node.targets = [target for target in node.targets if self.used_target(target)] if node.targets: return node self.update = True if node.value in self.pure_expressions: return ast.Pass() else: return ast.Expr(value=node.value)
def create_convert_ifelse_node(return_name_ids, pred, true_func, false_func, is_if_expr=False): """ Create `paddle.jit.dy2static.convert_ifelse( pred, true_fn, false_fn, true_args, false_args, return_vars)` to replace original `python if/else` statement. """ def create_name_nodes(name_ids): if not name_ids: return gast.Tuple(elts=[], ctx=gast.Load()) gast_names = [ gast.Name(id=name_id, ctx=gast.Load(), annotation=None, type_comment=None) for name_id in name_ids ] name_node = gast.Tuple(elts=gast_names, ctx=gast.Load()) return name_node if is_if_expr: true_args = gast.Tuple(elts=[], ctx=gast.Load()) false_args = gast.Tuple(elts=[], ctx=gast.Load()) true_func_source = "lambda : {}".format(ast_to_source_code(true_func)) false_func_source = "lambda : {}".format( ast_to_source_code(false_func)) else: true_args = gast.Tuple(elts=true_func.args.args, ctx=gast.Load()) false_args = gast.Tuple(elts=false_func.args.args, ctx=gast.Load()) true_func_source = true_func.name false_func_source = false_func.name return_vars = create_name_nodes(return_name_ids) convert_ifelse_layer = gast.parse( 'paddle.jit.dy2static.convert_ifelse(' '{pred}, {true_fn}, {false_fn}, {true_args}, {false_args}, {return_vars})' .format(pred=ast_to_source_code(pred), true_fn=true_func_source, false_fn=false_func_source, true_args=ast_to_source_code(true_args), false_args=ast_to_source_code(false_args), return_vars=ast_to_source_code(return_vars))).body[0].value if return_name_ids: _, cond_node = create_assign_node(return_name_ids, convert_ifelse_layer) else: # No variables can be returned if no assign statement in if.body. cond_node = gast.Expr(value=convert_ifelse_layer) return cond_node
def visit_Print(self, node): self.generic_visit(node) for n in node.values: n.ctx = gast.Param() call_node = gast.Call(func=gast.Name('print', gast.Load(), None), args=node.values, keywords=[]) anno.setanno(call_node.func, 'live_val', print) anno.setanno(call_node.func, 'fqn', 'print') anno.setanno(call_node, 'args_scope', anno.getanno(node, 'args_scope')) node = gast.Expr(call_node) return node
def visit_Assert(self, node): if not self.static_analysis_visitor.is_tensor_node(node.test): return node cast_node = gast.Call( func=gast.parse("fluid.layers.cast").body[0].value, args=[node.test, gast.Constant(value="bool", kind=None)], keywords=[]) assert_node = gast.Call( func=gast.parse("fluid.layers.Assert").body[0].value, args=[cast_node], keywords=[]) return gast.Expr(value=assert_node)
def test_statement_replace(): def f(body): body body = [ gast.Expr(value=gast.Name(id=var, ctx=gast.Load(), annotation=None)) for var in 'xy' ] new_body = template.replace(f, body=body) assert len(new_body) == 2 assert isinstance(new_body[0], gast.Expr) compile_.compile_function(_wrap(new_body))
def visit_Return(self, node): """Intercepts return statements. Args: node: An `ast.AST` node representing the `return` statement to convert. Returns: node: A node representing the result. """ node = templates.replace_as_expression( '_tfp_autobatching_context_.return_(value)', value=self._to_reference(node.value)) return gast.Expr(node)
def visit_AnyComp(self, node, comp_type, *path): self.update = True node.elt = self.visit(node.elt) name = "{0}_comprehension{1}".format(comp_type, self.count) self.count += 1 args = self.gather(ImportedIds, node) self.count_iter = 0 starget = "__target" body = reduce(self.nest_reducer, reversed(node.generators), ast.Expr( ast.Call( reduce(lambda x, y: ast.Attribute(x, y, ast.Load()), path[1:], ast.Name(path[0], ast.Load(), None, None)), [ast.Name(starget, ast.Load(), None, None), node.elt], [], ) ) ) # add extra metadata to this node metadata.add(body, metadata.Comprehension(starget)) init = ast.Assign( [ast.Name(starget, ast.Store(), None, None)], ast.Call( ast.Attribute( ast.Name('builtins', ast.Load(), None, None), comp_type, ast.Load() ), [], [],) ) result = ast.Return(ast.Name(starget, ast.Load(), None, None)) sargs = [ast.Name(arg, ast.Param(), None, None) for arg in args] fd = ast.FunctionDef(name, ast.arguments(sargs, [], None, [], [], None, []), [init, body, result], [], None, None) metadata.add(fd, metadata.Local()) self.ctx.module.body.append(fd) return ast.Call( ast.Name(name, ast.Load(), None, None), [ast.Name(arg.id, ast.Load(), None, None) for arg in sargs], [], ) # no sharing !
def dispatch(self, tree): """Dispatcher function, dispatching tree type T to method _T.""" # display omp directive in python dump for omp in metadata.get(tree, openmp.OMPDirective): deps = list() for dep in omp.deps: old_file = self.f self.f = io.StringIO() self.dispatch(dep) deps.append(self.f.getvalue()) self.f = old_file directive = omp.s.format(*deps) self._Expr(ast.Expr(ast.Constant(directive, None))) if isinstance(tree, list): for t in tree: self.dispatch(t) return meth = getattr(self, "_" + tree.__class__.__name__) meth(tree)
def visit_GeneratorExp(self, node): self.update = True node.elt = self.visit(node.elt) name = "generator_expression{0}".format(self.count) self.count += 1 args = self.passmanager.gather(ImportedIds, node, self.ctx) self.count_iter = 0 body = reduce(self.nest_reducer, reversed(node.generators), ast.Expr(ast.Yield(node.elt))) sargs = [ast.Name(arg, ast.Param(), None) for arg in args] fd = ast.FunctionDef(name, ast.arguments(sargs, None, [], [], None, []), [body], [], None) self.ctx.module.body.append(fd) return ast.Call( ast.Name(name, ast.Load(), None), [ast.Name(arg.id, ast.Load(), None) for arg in sargs], [], ) # no sharing !
def create_cond_node(return_name_ids, pred, true_func, false_func, is_if_expr=False): """ Create `fluid.layers.cond(pred, true_fn, false_fn)` to replace original `python if/else` statement. """ def create_lambda_node(func_or_expr_node, is_if_expr=False): body = func_or_expr_node if not is_if_expr: body = gast.Call(func=gast.Name(id=func_or_expr_node.name, ctx=gast.Load(), annotation=None, type_comment=None), args=[func_or_expr_node.args], keywords=[]) lambda_node = gast.Lambda(args=gast.arguments(args=[], posonlyargs=[], vararg=None, kwonlyargs=[], kw_defaults=None, kwarg=None, defaults=[]), body=body) return lambda_node cond_api = gast.parse('fluid.layers.cond').body[0].value true_func_lambda = create_lambda_node(true_func, is_if_expr) false_func_lambda = create_lambda_node(false_func, is_if_expr) cond_layer = gast.Call(func=cond_api, args=[pred, true_func_lambda, false_func_lambda], keywords=[]) if return_name_ids: _, cond_node = create_assign_node(return_name_ids, cond_layer) else: # No variables can be returned if no assign statement in if.body. cond_node = gast.Expr(value=cond_layer) return cond_node
def test_usub(self): orig_ast = gast.ast_to_gast(ast.parse("-3")) target_ast = gast.Module( body=[gast.Expr(value=gast.Constant(value=-3, kind=None))], type_ignores=[]) assert compare_ast(self.canonicalizer.visit(orig_ast), target_ast)
import gast from .recompile import compile_function, code_to_ast def pushmask(mask_expr): return gast.Expr( gast.Call( gast.Attribute(gast.Name('matchbox', gast.Load(), None), gast.Name('push_execution_mask', gast.Load(), None), gast.Load()), [mask_expr], [])) popmask = gast.Expr( gast.Call( gast.Attribute(gast.Name('matchbox', gast.Load(), None), gast.Name('pop_execution_mask', gast.Load(), None), gast.Load()), [], [])) def any_active(mask_expr): return gast.Call( gast.Attribute( # TODO any over dim 0 mask_expr, gast.Name('any', gast.Load(), None), gast.Load()), [], []) class FuseAttributes(gast.NodeTransformer): '''Transform foo.bar to foo_DOT_bar''' def visit_Attribute(self, node):
def pushmask(mask_expr): return gast.Expr( gast.Call( gast.Attribute(gast.Name('matchbox', gast.Load(), None), gast.Name('push_execution_mask', gast.Load(), None), gast.Load()), [mask_expr], []))
def visit_Print(self, node): var = self._get_print_var(node) print_call_node = self._construct_print_node(var) return gast.Expr(value=print_call_node)
def visit_Print(self, node): convert_print_node = self._create_print_node(node.values) return gast.Expr(value=convert_print_node)
def visit_If(self, node): if node.test not in self.static_expressions: return self.generic_visit(node) imported_ids = self.gather(ImportedIds, node) assigned_ids_left = self.escaping_ids(node, node.body) assigned_ids_right = self.escaping_ids(node, node.orelse) assigned_ids_both = assigned_ids_left.union(assigned_ids_right) imported_ids.update(i for i in assigned_ids_left if i not in assigned_ids_right) imported_ids.update(i for i in assigned_ids_right if i not in assigned_ids_left) imported_ids = sorted(imported_ids) assigned_ids = sorted(assigned_ids_both) fbody = self.make_fake(node.body) true_has_return = self.gather(HasReturn, fbody) true_has_break = self.gather(HasBreak, fbody) true_has_cont = self.gather(HasContinue, fbody) felse = self.make_fake(node.orelse) false_has_return = self.gather(HasReturn, felse) false_has_break = self.gather(HasBreak, felse) false_has_cont = self.gather(HasContinue, felse) has_return = true_has_return or false_has_return has_break = true_has_break or false_has_break has_cont = true_has_cont or false_has_cont self.generic_visit(node) func_true = outline(self.true_name(), imported_ids, assigned_ids, node.body, has_return, has_break, has_cont) func_false = outline(self.false_name(), imported_ids, assigned_ids, node.orelse, has_return, has_break, has_cont) self.new_functions.extend((func_true, func_false)) actual_call = self.make_dispatcher(node.test, func_true, func_false, imported_ids) # variable modified within the static_if expected_return = [ast.Name(ii, ast.Store(), None, None) for ii in assigned_ids] self.update = True # name for various variables resulting from the static_if n = len(self.new_functions) status_n = "$status{}".format(n) return_n = "$return{}".format(n) cont_n = "$cont{}".format(n) if has_return: cfg = self.cfgs[-1] always_return = all(isinstance(x, (ast.Return, ast.Yield)) for x in cfg[node]) always_return &= true_has_return and false_has_return fast_return = [ast.Name(status_n, ast.Store(), None, None), ast.Name(return_n, ast.Store(), None, None), ast.Name(cont_n, ast.Store(), None, None)] if always_return: return [ast.Assign([ast.Tuple(fast_return, ast.Store())], actual_call, None), ast.Return(ast.Name(return_n, ast.Load(), None, None))] else: cont_ass = self.make_control_flow_handlers(cont_n, status_n, expected_return, has_cont, has_break) cmpr = ast.Compare(ast.Name(status_n, ast.Load(), None, None), [ast.Eq()], [ast.Constant(EARLY_RET, None)]) return [ast.Assign([ast.Tuple(fast_return, ast.Store())], actual_call, None), ast.If(cmpr, [ast.Return(ast.Name(return_n, ast.Load(), None, None))], cont_ass)] elif has_break or has_cont: cont_ass = self.make_control_flow_handlers(cont_n, status_n, expected_return, has_cont, has_break) fast_return = [ast.Name(status_n, ast.Store(), None, None), ast.Name(cont_n, ast.Store(), None, None)] return [ast.Assign([ast.Tuple(fast_return, ast.Store())], actual_call, None)] + cont_ass elif expected_return: return ast.Assign([ast.Tuple(expected_return, ast.Store())], actual_call, None) else: return ast.Expr(actual_call)
def visit_If(self, node): self.generic_visit(node) if node.test not in self.static_expressions: return node imported_ids = self.passmanager.gather(ImportedIds, node, self.ctx) assigned_ids_left = set( self.passmanager.gather(IsAssigned, self.make_fake(node.body), self.ctx).keys()) assigned_ids_right = set( self.passmanager.gather(IsAssigned, self.make_fake(node.orelse), self.ctx).keys()) assigned_ids_both = assigned_ids_left.union(assigned_ids_right) imported_ids.update(i for i in assigned_ids_left if i not in assigned_ids_right) imported_ids.update(i for i in assigned_ids_right if i not in assigned_ids_left) imported_ids = sorted(imported_ids) assigned_ids = sorted(assigned_ids_both) true_has_return = self.passmanager.gather(HasReturn, self.make_fake(node.body), self.ctx) false_has_return = self.passmanager.gather(HasReturn, self.make_fake(node.orelse), self.ctx) has_return = true_has_return or false_has_return func_true = outline(self.true_name(), imported_ids, assigned_ids, node.body, has_return) func_false = outline(self.false_name(), imported_ids, assigned_ids, node.orelse, has_return) self.new_functions.extend((func_true, func_false)) actual_call = self.make_dispatcher(node.test, func_true, func_false, imported_ids) expected_return = [ ast.Name(ii, ast.Load(), None) for ii in assigned_ids ] if has_return: n = len(self.new_functions) fast_return = [ ast.Name("$status{}".format(n), ast.Load(), None), ast.Name("$return{}".format(n), ast.Load(), None), ast.Name("$cont{}".format(n), ast.Load(), None) ] if expected_return: cont_ass = [ ast.Assign([ast.Tuple(expected_return, ast.Store())], ast.Name("$cont{}".format(n), ast.Load(), None)) ] else: cont_ass = [] return [ ast.Assign([ast.Tuple(fast_return, ast.Store())], actual_call), ast.If(ast.Name("$status{}".format(n), ast.Load(), None), [ ast.Return( ast.Name("$return{}".format(n), ast.Load(), None)) ], cont_ass) ] elif expected_return: return ast.Assign([ast.Tuple(expected_return, ast.Store())], actual_call) else: return ast.Expr(actual_call)
def test_usub(self): orig_ast = gast.ast_to_gast(ast.parse("-3")) target_ast = gast.Module(body=[gast.Expr(value=gast.Num(n=-3))]) assert compare_ast(self.canonicalizer.visit(orig_ast), target_ast)
def build(v): return gast.Expr(value=gast.Call( func=make_name("print"), args=[v], keywords=[]))