%PDF- %PDF-
Direktori : /lib/python3/dist-packages/pythran/analyses/ |
Current File : //lib/python3/dist-packages/pythran/analyses/locals_analysis.py |
""" Locals computes the value of locals() """ from pythran.passmanager import ModuleAnalysis import pythran.metadata as md import gast as ast class Locals(ModuleAnalysis): """ Statically compute the value of locals() before each statement Yields a dictionary binding every node to the set of variable names defined *before* this node. Following snippet illustrates its behavior: >>> import gast as ast >>> from pythran import passmanager >>> pm = passmanager.PassManager('test') >>> code = ''' ... def b(n): ... m = n + 1 ... def b(n): ... return n + 1 ... return b(m)''' >>> tree = ast.parse(code) >>> l = pm.gather(Locals, tree) >>> sorted(l[tree.body[0].body[0]]) ['n'] >>> sorted(l[tree.body[0].body[1]]) ['b', 'm', 'n'] """ def __init__(self): self.result = dict() self.locals = set() self.nesting = 0 super(Locals, self).__init__() def generic_visit(self, node): super(Locals, self).generic_visit(node) if node not in self.result: self.result[node] = self.result[self.expr_parent] def store_and_visit(self, node): self.expr_parent = node self.result[node] = self.locals.copy() self.generic_visit(node) def visit_Module(self, node): self.expr_parent = node self.result[node] = self.locals self.generic_visit(node) def visit_FunctionDef(self, node): # special case for nested functions if self.nesting: self.locals.add(node.name) self.nesting += 1 self.expr_parent = node self.result[node] = self.locals.copy() parent_locals = self.locals.copy() for default in node.args.defaults: self.visit(default) for arg in node.args.args: if arg.annotation: self.visit(arg.annotation) if node.returns: self.visit(node.returns) self.locals.update(arg.id for arg in node.args.args) for stmt in node.body: self.visit(stmt) self.locals = parent_locals self.nesting -= 1 def visit_Assign(self, node): self.expr_parent = node self.result[node] = self.locals.copy() md.visit(self, node) self.visit(node.value) self.locals.update(t.id for t in node.targets if isinstance(t, ast.Name)) for target in node.targets: self.visit(target) def visit_For(self, node): self.expr_parent = node self.result[node] = self.locals.copy() md.visit(self, node) self.visit(node.iter) self.locals.add(node.target.id) for stmt in node.body: self.visit(stmt) for stmt in node.orelse: self.visit(stmt) def visit_Import(self, node): self.result[node] = self.locals.copy() self.locals.update(alias.name for alias in node.names) def visit_ImportFrom(self, node): self.result[node] = self.locals.copy() self.locals.update(alias.name for alias in node.names) def visit_ExceptHandler(self, node): self.expr_parent = node self.result[node] = self.locals.copy() if node.name: self.locals.add(node.name.id) node.type and self.visit(node.type) for stmt in node.body: self.visit(stmt) # statements that do not define a new variable visit_Return = store_and_visit visit_Yield = store_and_visit visit_Try = store_and_visit visit_AugAssign = store_and_visit visit_Print = store_and_visit visit_While = store_and_visit visit_If = store_and_visit visit_Raise = store_and_visit visit_Assert = store_and_visit visit_Expr = store_and_visit visit_Pass = store_and_visit visit_Break = store_and_visit visit_Continue = store_and_visit