class ReversedRangePattern(Pattern): # __builtin__.reversed(__builtin__.xrange(X)) => # __builtin__.xrange(X-1, -1, -1) # FIXME : We should do it even when begin/end/step are given pattern = ast.Call(func=ast.Attribute(value=ast.Name(id='__builtin__', ctx=ast.Load(), annotation=None, type_comment=None), attr="reversed", ctx=ast.Load()), args=[ast.Call( func=ast.Attribute( value=ast.Name(id='__builtin__', ctx=ast.Load(), annotation=None, type_comment=None), attr=range_name, ctx=ast.Load()), args=[Placeholder(0)], keywords=[])], keywords=[]) @staticmethod def sub(): return ast.Call( func=ast.Attribute(value=ast.Name(id='__builtin__', ctx=ast.Load(), annotation=None, type_comment=None), attr=range_name, ctx=ast.Load()), args=[ast.BinOp(left=Placeholder(0), op=ast.Sub(), right=ast.Constant(1, None)), ast.Constant(-1, None), ast.Constant(-1, None)], keywords=[])
def visit_Raise(self, node): ntype = self._visit(node.type) ninst = self._visit(node.inst) ntback = self._visit(node.tback) what = ntype if ninst is not None: what = gast.Call(ntype, [ninst], []) gast.copy_location(what, node) what.end_lineno = what.end_col_offset = None if ntback is not None: attr = gast.Attribute(what, 'with_traceback', gast.Load()) gast.copy_location(attr, node) attr.end_lineno = attr.end_col_offset = None what = gast.Call(attr, [ntback], []) gast.copy_location(what, node) what.end_lineno = what.end_col_offset = None new_node = gast.Raise(what, None) gast.copy_location(new_node, node) new_node.end_lineno = new_node.end_col_offset = None return new_node
class TupleListPattern(Pattern): # __builtin__.tuple(__builtin__.list(X)) => __builtin__.tuple(X) pattern = ast.Call( func=ast.Attribute(value=ast.Name('__builtin__', ast.Load(), None, None), attr="tuple", ctx=ast.Load()), args=[ ast.Call(func=ast.Attribute(value=ast.Name('__builtin__', ast.Load(), None, None), attr="list", ctx=ast.Load()), args=[Placeholder(0)], keywords=[]) ], keywords=[]) @staticmethod def sub(): return ast.Call(func=ast.Attribute(value=ast.Name(id='__builtin__', ctx=ast.Load(), annotation=None, type_comment=None), attr="tuple", ctx=ast.Load()), args=[Placeholder(0)], keywords=[])
class AbsSqrPattern(Pattern): # __builtin__.abs(X) ** 2 => __builtin__.pythran.abssqr(X) pattern = ast.Call(func=ast.Attribute(value=ast.Name(id=mangle('numpy'), ctx=ast.Load(), annotation=None, type_comment=None), attr="square", ctx=ast.Load()), args=[ ast.Call(func=ast.Attribute(value=ast.Name( id='__builtin__', ctx=ast.Load(), annotation=None, type_comment=None), attr="abs", ctx=ast.Load()), args=[Placeholder(0)], keywords=[]) ], keywords=[]) @staticmethod def sub(): return ast.Call(func=ast.Attribute(value=ast.Attribute(value=ast.Name( id='__builtin__', ctx=ast.Load(), annotation=None, type_comment=None), attr="pythran", ctx=ast.Load()), attr="abssqr", ctx=ast.Load()), args=[Placeholder(0)], keywords=[])
class LenRangePattern(Pattern): # builtins.len(builtins.range(X)) => max(0, X) pattern = ast.Call( func=ast.Attribute(value=ast.Name('builtins', ast.Load(), None, None), attr="len", ctx=ast.Load()), args=[ ast.Call(func=ast.Attribute(value=ast.Name('builtins', ast.Load(), None, None), attr="range", ctx=ast.Load()), args=[Placeholder(0)], keywords=[]) ], keywords=[]) @staticmethod def sub(): return ast.Call(func=ast.Attribute(value=ast.Name( 'builtins', ast.Load(), None, None), attr="max", ctx=ast.Load()), args=[ast.Constant(0, None), Placeholder(0)], keywords=[])
def visit_Raise(self, node): ntype = self._visit(node.type) ninst = self._visit(node.inst) ntback = self._visit(node.tback) what = ntype if ninst is not None: what = gast.Call(ntype, [ninst], []) ast.copy_location(what, node) if ntback is not None: attr = gast.Attribute(what, 'with_traceback', gast.Load()) ast.copy_location(attr, node) what = gast.Call( attr, [ntback], [] ) ast.copy_location(what, node) new_node = gast.Raise(what, None) ast.copy_location(new_node, node) return new_node
class LenSetPattern(Pattern): # __builtin__.len(__builtin__.set(X)) => __builtin__.pythran.len_set(X) pattern = ast.Call( func=ast.Attribute(value=ast.Name('__builtin__', ast.Load(), None, None), attr="len", ctx=ast.Load()), args=[ ast.Call(func=ast.Attribute(value=ast.Name('__builtin__', ast.Load(), None, None), attr="set", ctx=ast.Load()), args=[Placeholder(0)], keywords=[]) ], keywords=[]) @staticmethod def sub(): return ast.Call(func=ast.Attribute(value=ast.Attribute(value=ast.Name( '__builtin__', ast.Load(), None, None), attr="pythran", ctx=ast.Load()), attr="len_set", ctx=ast.Load()), args=[Placeholder(0)], keywords=[])
def visit_loop(self, node, update_mask=gast.NameConstant(value=None)): node = FuseAttributes().visit(node) loads, stores = defaultdict(list), set() for child in node.body: for n in gast.walk(child): if isinstance(n, gast.Name) and isinstance(n.ctx, gast.Load): loads[n.id].append(n) if isinstance(child, gast.Assign): if len(child.targets) > 1: raise NotImplementedError("cannot process LCD that is " "part of multiple assignment") name = child.targets[0].id if name in loads: if name in stores: raise NotImplementedError("cannot process LCD " "stored to twice") # $var = $expr -> $var = $var._update($expr) child.value = gast.Call( gast.Attribute(gast.Name(name, gast.Load(), None), gast.Name('_update', gast.Load(), None), None), [child.value, update_mask], []) stores.add(name) node = SplitAttributes().visit(node) synchronizes = [] for name in stores: synchronize = gast.Assign( [gast.Name(name, gast.Store(), None)], gast.Call( gast.Attribute( gast.Name(name, gast.Load(), None), gast.Name('_synchronize', gast.Load(), None), None), [], [])) synchronizes.append(synchronize) node.body.extend(synchronizes) return node
def visit_Assign(self, node): if len(node.targets) > 1: raise NotImplementedError("cannot process multiple assignment") if not isinstance(node.targets[0], gast.Name): raise NotImplementedError("cannot process indexed assignment") # $lhs = $lhs.update_($rhs, matchbox.EXECUTION_MASK) if (lhs in vars() # or lhs in globals()) and isinstance($lhs, (matchbox.MaskedBatch, # matchbox.TENSOR_TYPE)) else $rhs node.value = gast.IfExp( gast.BoolOp( gast.And(), [ gast.BoolOp(gast.Or(), [ gast.Compare(gast.Str( node.targets[0].id), [gast.In()], [ gast.Call(gast.Name('vars', gast.Load, None), [], []) ]), gast.Compare(gast.Str( node.targets[0].id), [gast.In()], [ gast.Call( gast.Name('globals', gast.Load, None), [], []) ]) ]), # gast.Compare( # gast.Attribute( # gast.Name('matchbox', gast.Load(), None), # gast.Name('EXECUTION_MASK', gast.Load(), None), # gast.Load()), # [gast.IsNot()], # [gast.NameConstant(None)]), gast.Call(gast.Name('isinstance', gast.Load(), None), [ node.targets[0], gast.Tuple([ gast.Attribute( gast.Name('matchbox', gast.Load(), None), gast.Name('MaskedBatch', gast.Load(), None), gast.Load()), gast.Attribute( gast.Name('matchbox', gast.Load(), None), gast.Name('TENSOR_TYPE', gast.Load(), None), gast.Load()) ], gast.Load()) ], []) ]), gast.Call( gast.Attribute( gast.Name(node.targets[0].id, gast.Load(), None), gast.Name('_update', gast.Load(), None), gast.Load()), [ node.value, gast.Attribute( gast.Name('matchbox', gast.Load(), None), gast.Name('EXECUTION_MASK', gast.Load(), None), gast.Load()) ], []), node.value) return node
def visit_Attribute(self, node): node = self.generic_visit(node) # method name -> not a getattr if node.attr in methods: # Make sure parent is'nt a call, it's already handled in visit_Call for parent in reversed(self.ancestors.get(node, ())): if isinstance(parent, ast.Attribute): continue if isinstance(parent, ast.Call): return node break # we have a bound method which is not a call obj = self.baseobj(node) if obj is not None: self.update = True mod = methods[node.attr][0] self.to_import.add(mangle(mod[0])) func = self.attr_to_func(node) z = ast.Call( ast.Attribute( ast.Name(mangle('functools'), ast.Load(), None, None), "partial", ast.Load()), [func, obj], []) return z else: return node # imported module -> not a getattr elif (isinstance(node.value, ast.Name) and node.value.id in self.imports): module_id = self.imports[node.value.id] if node.attr not in MODULES[self.renamer(module_id, MODULES)[1]]: msg = ("`" + node.attr + "' is not a member of " + demangle(module_id) + " or Pythran does not support it") raise PythranSyntaxError(msg, node) node.value.id = module_id # patch module aliasing self.update = True return node # not listed as attributed -> not a getattr elif node.attr not in attributes: return node # A getattr ! else: self.update = True call = ast.Call( ast.Attribute(ast.Name('builtins', ast.Load(), None, None), 'getattr', ast.Load()), [node.value, ast.Constant(node.attr, None)], []) if isinstance(node.ctx, ast.Store): # the only situation where this arises is for real/imag of # a ndarray. As a call is not valid for a store, add a slice # to ends up with a valid lhs assert node.attr in ('real', 'imag'), "only store to imag/real" return ast.Subscript(call, ast.Slice(None, None, None), node.ctx) else: return call
def makeattr(*args): r = ast.Attribute(value=ast.Name(id='builtins', ctx=ast.Load(), annotation=None, type_comment=None), attr='map', ctx=ast.Load()) r = ast.Call(r, list(args), []) r = ast.Call( ast.Attribute(ast.Name('builtins', ast.Load(), None, None), 'list', ast.Load()), [r], []) return r
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 makeattr(*args): r = ast.Attribute(value=ast.Name(id='__builtin__', ctx=ast.Load(), annotation=None), attr='map', ctx=ast.Load()) r = ast.Call(r, list(args), []) if sys.version_info.major == 3: r = ast.Call( ast.Attribute(ast.Name('__builtin__', ast.Load(), None), 'list', ast.Load()), [r], []) return r
def build(maxval, body): return gast.For(target=make_name(fresh_name), iter=gast.Call(func=make_name("range"), args=[ gast.Call(func=make_name("int"), args=[maxval], keywords=[]) ], keywords=[]), body=body, orelse=[], type_comment=None)
def size_container_folding(value): """ Convert value to ast expression if size is not too big. Converter for sized container. """ def size(x): return len(getattr(x, 'flatten', lambda: x)()) if size(value) < MAX_LEN: if isinstance(value, list): return ast.List([to_ast(elt) for elt in value], ast.Load()) elif isinstance(value, tuple): return ast.Tuple([to_ast(elt) for elt in value], ast.Load()) elif isinstance(value, set): if value: return ast.Set([to_ast(elt) for elt in value]) else: return ast.Call(func=ast.Attribute( ast.Name(mangle('builtins'), ast.Load(), None, None), 'set', ast.Load()), args=[], keywords=[]) elif isinstance(value, dict): keys = [to_ast(elt) for elt in value.keys()] values = [to_ast(elt) for elt in value.values()] return ast.Dict(keys, values) elif isinstance(value, np.ndarray): if len(value) == 0: return ast.Call( func=ast.Attribute( ast.Name(mangle('numpy'), ast.Load(), None, None), 'empty', ast.Load()), args=[to_ast(value.shape), dtype_to_ast(value.dtype.name)], keywords=[]) else: return ast.Call(func=ast.Attribute( ast.Name(mangle('numpy'), ast.Load(), None, None), 'array', ast.Load()), args=[ to_ast(totuple(value.tolist())), dtype_to_ast(value.dtype.name) ], keywords=[]) else: raise ConversionError() else: raise ToNotEval()
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 can_use_c_for(self, node): """ Check if a for loop can use classic C syntax. To use C syntax: - target should not be assign in the loop - range should be use as iterator - order have to be known at compile time """ assert isinstance(node.target, ast.Name) pattern_range = ast.Call(func=ast.Attribute(value=ast.Name( 'builtins', ast.Load(), None, None), attr='range', ctx=ast.Load()), args=AST_any(), keywords=[]) is_assigned = set() for stmt in node.body: is_assigned.update({n.id for n in self.gather(IsAssigned, stmt)}) nodes = ASTMatcher(pattern_range).search(node.iter) if node.iter not in nodes or node.target.id in is_assigned: return False args = node.iter.args if len(args) < 3: return True if isnum(args[2]): return True return False
def visit_Call(self, node): # try to get all aliases of the function, if possible # else use [] as a fallback func_aliases = self.aliases[node.func] # expand argument if any func_aliases = reduce( # all funcs lambda x, y: x + (list(self.node_to_functioneffect.keys()) if isinstance(y, ast.Name) else [y]), func_aliases, list()) for func_alias in func_aliases: # special hook for bound functions if isinstance(func_alias, ast.Call): fake_call = ast.Call(func_alias.args[0], func_alias.args[1:], []) self.visit(fake_call) continue # conservative choice if func_alias not in self.node_to_functioneffect: func_alias = intrinsic.UnboundValue func_alias = self.node_to_functioneffect[func_alias] self.result.add_edge(self.current_function, func_alias) self.generic_visit(node)
def can_use_c_for(self, node): """ Check if a for loop can use classic C syntax. To use C syntax: - target should not be assign in the loop - xrange should be use as iterator - order have to be known at compile time """ assert isinstance(node.target, ast.Name) pattern = ast.Call(func=ast.Attribute(value=ast.Name(id='__builtin__', ctx=ast.Load(), annotation=None), attr='xrange', ctx=ast.Load()), args=AST_any(), keywords=[]) is_assigned = {node.target.id: False} [ is_assigned.update(self.passmanager.gather(IsAssigned, stmt)) for stmt in node.body ] if (node.iter not in ASTMatcher(pattern).search(node.iter) or is_assigned[node.target.id]): return False args = node.iter.args if len(args) < 3: return True if isinstance(args[2], ast.Num): return True return False
def create_while_node(condition_name, body_name, loop_var_names): while_args = [] while_args.append( gast.Name(id=condition_name, ctx=gast.Param(), annotation=None, type_comment=None)) while_args.append( gast.Name(id=body_name, ctx=gast.Param(), annotation=None, type_comment=None)) assign_targets = [ gast.Name(id=var_name, ctx=gast.Param(), annotation=None, type_comment=None) for var_name in loop_var_names ] while_args.append(gast.List(elts=assign_targets, ctx=gast.Param())) while_func_id = gast.parse('fluid.layers.while_loop').body[0].value while_node = gast.Call(func=while_func_id, args=while_args, keywords=[]) assign_node = gast.Assign( targets=[gast.Tuple(elts=assign_targets, ctx=gast.Store())], value=while_node) return assign_node
def can_use_c_for(self, node): """ Check if a for loop can use classic C syntax. To use C syntax: - target should not be assign in the loop - xrange should be use as iterator - order have to be known at compile time """ assert isinstance(node.target, ast.Name) if sys.version_info.major == 3: range_name = 'range' else: range_name = 'xrange' pattern_range = ast.Call(func=ast.Attribute(value=ast.Name( id='__builtin__', ctx=ast.Load(), annotation=None), attr=range_name, ctx=ast.Load()), args=AST_any(), keywords=[]) is_assigned = set() for stmt in node.body: is_assigned.update(self.gather(IsAssigned, stmt)) nodes = ASTMatcher(pattern_range).search(node.iter) if node.iter not in nodes or node.target.id in is_assigned: return False args = node.iter.args if len(args) < 3: return True if isinstance(args[2], ast.Num): return True return False
def visit_Attribute(self, node): node = self.generic_visit(node) # storing in an attribute -> not a getattr if not isinstance(node.ctx, ast.Load): return node # method name -> not a getattr elif node.attr in methods: return node # imported module -> not a getattr elif (isinstance(node.value, ast.Name) and node.value.id in self.imports): module_id = self.imports[node.value.id] if node.attr not in MODULES[self.renamer(module_id, MODULES)[1]]: msg = ("`" + node.attr + "' is not a member of " + module_id + " or Pythran does not support it") raise PythranSyntaxError(msg, node) node.value.id = module_id # patch module aliasing self.update = True return node # not listed as attributed -> not a getattr elif node.attr not in attributes: return node # A getattr ! else: self.update = True return ast.Call( ast.Attribute(ast.Name('__builtin__', ast.Load(), None), 'getattr', ast.Load()), [node.value, ast.Str(node.attr)], [])
def visit_UnaryOp(self, node): node = self.generic_visit(node) if isinstance(node.op, gast.Not): tf_function = parser.parse_str(self.op_mapping[type( node.op)]).body[0].value node = gast.Call(func=tf_function, args=[node.operand], keywords=[]) return node
def visit_Attribute(self, node): node = self.generic_visit(node) # method name -> not a getattr if node.attr in methods: return node # imported module -> not a getattr elif (isinstance(node.value, ast.Name) and node.value.id in self.imports): module_id = self.imports[node.value.id] if node.attr not in MODULES[self.renamer(module_id, MODULES)[1]]: msg = ("`" + node.attr + "' is not a member of " + module_id + " or Pythran does not support it") raise PythranSyntaxError(msg, node) node.value.id = module_id # patch module aliasing self.update = True return node # not listed as attributed -> not a getattr elif node.attr not in attributes: return node # A getattr ! else: self.update = True call = ast.Call( ast.Attribute(ast.Name('builtins', ast.Load(), None, None), 'getattr', ast.Load()), [node.value, ast.Constant(node.attr, None)], []) if isinstance(node.ctx, ast.Store): # the only situation where this arises is for real/imag of # a ndarray. As a call is not valid for a store, add a slice # to ends up with a valid lhs assert node.attr in ('real', 'imag'), "only store to imag/real" return ast.Subscript(call, ast.Slice(None, None, None), node.ctx) else: return call
def size_container_folding(value): """ Convert value to ast expression if size is not too big. Converter for sized container. """ if len(value) < MAX_LEN: if isinstance(value, list): return ast.List([to_ast(elt) for elt in value], ast.Load()) elif isinstance(value, tuple): return ast.Tuple([to_ast(elt) for elt in value], ast.Load()) elif isinstance(value, set): return ast.Set([to_ast(elt) for elt in value]) elif isinstance(value, dict): keys = [to_ast(elt) for elt in value.keys()] values = [to_ast(elt) for elt in value.values()] return ast.Dict(keys, values) elif isinstance(value, numpy.ndarray): return ast.Call(func=ast.Attribute( ast.Name(mangle('numpy'), ast.Load(), None), 'array', ast.Load()), args=[to_ast(value.tolist())], keywords=[]) else: raise ConversionError() else: raise ToNotEval()
def visit_FunctionDef(self, node): self.update = True if MODULES['functools'] not in self.global_declarations.values(): import_ = ast.Import([ast.alias('functools', mangle('functools'))]) self.ctx.module.body.insert(0, import_) functools_module = MODULES['functools'] self.global_declarations[mangle('functools')] = functools_module self.ctx.module.body.append(node) former_name = node.name seed = 0 new_name = "pythran_{}{}" while new_name.format(former_name, seed) in self.identifiers: seed += 1 new_name = new_name.format(former_name, seed) self.identifiers.add(new_name) ii = self.gather(ImportedIds, node) 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) metadata.add(node, metadata.Local()) class Renamer(ast.NodeTransformer): def visit_Call(self, node): self.generic_visit(node) if (isinstance(node.func, ast.Name) and node.func.id == former_name): node.func.id = new_name node.args = ([ ast.Name(iin, ast.Load(), None, None) for iin in sorted(ii) ] + node.args) return node Renamer().visit(node) node.name = new_name self.global_declarations[node.name] = node proxy_call = ast.Name(new_name, ast.Load(), None, None) new_node = ast.Assign([ast.Name(former_name, ast.Store(), None, None)], ast.Call( ast.Attribute( ast.Name(mangle('functools'), ast.Load(), None, None), "partial", ast.Load()), [proxy_call] + binded_args, [], )) self.generic_visit(node) return new_node
def visit_Call(self, node): if sys.version_info.minor < 5: if node.starargs: star = gast.Starred(self._visit(node.starargs), gast.Load()) gast.copy_location(star, node) starred = [star] else: starred = [] if node.kwargs: kw = gast.keyword(None, self._visit(node.kwargs)) gast.copy_location(kw, node.kwargs) kwargs = [kw] else: kwargs = [] else: starred = kwargs = [] new_node = gast.Call( self._visit(node.func), self._visit(node.args) + starred, self._visit(node.keywords) + kwargs, ) gast.copy_location(new_node, node) return new_node
def visit_ListComp(self, node): def makeattr(*args): r = ast.Attribute(value=ast.Name(id='builtins', ctx=ast.Load(), annotation=None, type_comment=None), attr='map', ctx=ast.Load()) r = ast.Call(r, list(args), []) r = ast.Call( ast.Attribute(ast.Name('builtins', ast.Load(), None, None), 'list', ast.Load()), [r], []) return r if isinstance(node.elt, ast.Constant) and len(node.generators) == 1: gen = node.generators[0] if not gen.ifs and isinstance(gen.iter, ast.Call): try: path = attr_to_path(gen.iter.func)[1] range_path = 'pythonic', 'builtins', 'functor', 'range' if path == range_path and len(gen.iter.args) == 1: self.update = True return ast.BinOp( ast.List([node.elt], ast.Load()), ast.Mult(), ast.Call(path_to_attr(('builtins', 'len')), [gen.iter], [])) except TypeError: pass return self.visitComp(node, makeattr)
def trivialize_slice(self, node): if isinstance(node, gast.Slice): name = self.namer.name(node) target = gast.Name(id=name, ctx=gast.Store(), annotation=None) stmt = gast.Assign(targets=[target], value=None) self.prepend(stmt) stmt.value = gast.Call( func=gast.Name(id='slice', ctx=gast.Load(), annotation=None), args=[ self.trivialize(arg) if arg else gast.Name( id='None', ctx=gast.Load(), annotation=None) for arg in [node.lower, node.upper, node.step] ], keywords=[]) return gast.Name(id=name, ctx=gast.Load(), annotation=None) elif isinstance(node, gast.ExtSlice): name = self.namer.name(node) target = gast.Name(id=name, ctx=gast.Store(), annotation=None) stmt = gast.Assign(targets=[target], value=None) self.prepend(stmt) dim_names = [self.trivialize_slice(s).id for s in node.dims] stmt.value = gast.Tuple(elts=[ gast.Name(id=n, ctx=gast.Load(), annotation=None) for n in dim_names ], ctx=gast.Load()) return gast.Name(id=name, ctx=gast.Load(), annotation=None) elif isinstance(node, gast.Index): return self.trivialize(node.value) else: raise ValueError(node)
def visit_Lambda(self, node): 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 self.generic_visit(node) forged_name = "{0}_lambda{1}".format(self.prefix, len(self.lambda_functions)) ii = self.passmanager.gather(ImportedIds, node, self.ctx) ii.difference_update(self.lambda_functions) # remove current lambdas binded_args = [ast.Name(iin, ast.Load(), None) for iin in sorted(ii)] node.args.args = ( [ast.Name(iin, ast.Param(), None) for iin in sorted(ii)] + node.args.args) forged_fdef = ast.FunctionDef(forged_name, copy(node.args), [ast.Return(node.body)], [], None) self.lambda_functions.append(forged_fdef) self.global_declarations[forged_name] = forged_fdef proxy_call = ast.Name(forged_name, ast.Load(), None) if binded_args: return ast.Call( ast.Attribute(ast.Name(mangle('functools'), ast.Load(), None), "partial", ast.Load()), [proxy_call] + binded_args, []) else: return proxy_call