analyses.devirtualization: look up functions in outer scopes.

This commit is contained in:
whitequark 2015-10-09 01:32:05 +03:00
parent 844d37ff18
commit 6922bd5638
1 changed files with 13 additions and 10 deletions

View File

@ -22,19 +22,20 @@ class FunctionResolver(algorithm.Visitor):
def __init__(self, variable_map): def __init__(self, variable_map):
self.variable_map = variable_map self.variable_map = variable_map
self.in_assign = False
self.scope_map = dict() self.scope_map = dict()
self.scope = None
self.queue = [] self.queue = []
self.in_assign = False
self.current_scopes = []
def finalize(self): def finalize(self):
for thunk in self.queue: for thunk in self.queue:
thunk() thunk()
def visit_scope(self, node): def visit_scope(self, node):
old_scope, self.scope = self.scope, node self.current_scopes.append(node)
self.generic_visit(node) self.generic_visit(node)
self.scope = old_scope self.current_scopes.pop()
def visit_in_assign(self, node): def visit_in_assign(self, node):
self.in_assign = True self.in_assign = True
@ -64,20 +65,22 @@ class FunctionResolver(algorithm.Visitor):
self.visit_scope(node) self.visit_scope(node)
def visit_FunctionDefT(self, node): def visit_FunctionDefT(self, node):
_advance(self.scope_map, (self.scope, node.name), node) _advance(self.scope_map, (self.current_scopes[-1], node.name), node)
self.visit_scope(node) self.visit_scope(node)
def visit_NameT(self, node): def visit_NameT(self, node):
if self.in_assign: if self.in_assign:
# Just give up if we assign anything at all to a variable, and # Just give up if we assign anything at all to a variable, and
# assume it diverges. # assume it diverges.
_advance(self.scope_map, (self.scope, node.id), None) _advance(self.scope_map, (self.current_scopes[-1], node.id), None)
else: else:
# Copy the final value in scope_map into variable_map. # Look up the final value in scope_map and copy it into variable_map.
key = (self.scope, node.id) keys = [(scope, node.id) for scope in reversed(self.current_scopes)]
def thunk(): def thunk():
if key in self.scope_map: for key in keys:
self.variable_map[node] = self.scope_map[key] if key in self.scope_map:
self.variable_map[node] = self.scope_map[key]
return
self.queue.append(thunk) self.queue.append(thunk)
class MethodResolver(algorithm.Visitor): class MethodResolver(algorithm.Visitor):