%PDF- %PDF-
Direktori : /lib/python3/dist-packages/pythran/transformations/ |
Current File : //lib/python3/dist-packages/pythran/transformations/remove_lambdas.py |
""" RemoveLambdas turns lambda into regular functions. """ from pythran.analyses import GlobalDeclarations, ImportedIds from pythran.passmanager import Transformation from pythran.tables import MODULES from pythran.conversion import mangle import pythran.metadata as metadata from copy import copy import gast as ast class _LambdaRemover(ast.NodeTransformer): def __init__(self, parent, prefix): super(_LambdaRemover, self).__init__() self.prefix = prefix self.parent = parent def __getattr__(self, attr): return getattr(self.parent, attr) 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.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) 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: return ast.Call( ast.Attribute( ast.Name(mangle('functools'), ast.Load(), None, None), "partial", ast.Load() ), [proxy_call] + binded_args, []) else: return proxy_call class RemoveLambdas(Transformation): """ Turns lambda into top-level functions. >>> import gast as ast >>> from pythran import passmanager, backend >>> node = ast.parse("def foo(y): lambda x:y+x") >>> pm = passmanager.PassManager("test") >>> _, node = pm.apply(RemoveLambdas, node) >>> print(pm.dump(backend.Python, node)) import functools as __pythran_import_functools def foo(y): __pythran_import_functools.partial(foo_lambda0, y) def foo_lambda0(y, x): return (y + x) """ def __init__(self): super(RemoveLambdas, self).__init__(GlobalDeclarations) def visit_Module(self, node): self.lambda_functions = list() self.imports = list() self.generic_visit(node) node.body = self.imports + node.body + self.lambda_functions self.update |= bool(self.imports) or bool(self.lambda_functions) return node def visit_FunctionDef(self, node): lr = _LambdaRemover(self, node.name) node.body = [lr.visit(n) for n in node.body] return node