Fix fast_parent_copy. The caching is now more solid than before (and doesn't produce weird side effects. This also solves an issue with Lambdas. However, by fixing all of this we have broken some other things.

This commit is contained in:
Dave Halter
2014-08-15 01:55:43 +02:00
parent 1965469050
commit 89ab0ba137
5 changed files with 25 additions and 7 deletions

View File

@@ -92,8 +92,13 @@ class NameFinder(object):
# Exclude `arr[1] =` from the result set.
if not self._name_is_array_assignment(name):
# TODO we ignore a lot of elements here that should not be
# ignored. But then again flow_analysis also stops when the
# input scope is reached. This is not correct: variables
# might still have conditions if defined outside of the
# current scope.
if isinstance(stmt, (pr.Param, pr.Import)) \
or isinstance(name_list_scope, (pr.ListComprehension, er.Instance, InterpreterNamespace)) \
or isinstance(name_list_scope, (pr.Lambda, pr.ListComprehension, er.Instance, InterpreterNamespace)) \
or isinstance(scope, compiled.CompiledObject) \
or isinstance(stmt, pr.Statement) and stmt.is_global():
# Always reachable.

View File

@@ -11,6 +11,7 @@ def fast_parent_copy(obj):
"""
new_elements = {}
accept = (pr.Simple, pr.NamePart)
start=obj
def recursion(obj):
if isinstance(obj, pr.Statement):
@@ -48,7 +49,7 @@ def fast_parent_copy(obj):
elif isinstance(value, (list, tuple)):
setattr(new_obj, key, list_or_tuple_rec(value))
elif isinstance(value, accept):
try: # because of the circular Flow.previous/Flow.next
try:
setattr(new_obj, key, new_elements[value])
except KeyError:
setattr(new_obj, key, recursion(value))
@@ -61,6 +62,9 @@ def fast_parent_copy(obj):
copied_array = array_obj[:] # lists, tuples, strings, unicode
for i, el in enumerate(copied_array):
if isinstance(el, accept):
try:
copied_array[i] = new_elements[el]
except KeyError:
copied_array[i] = recursion(el)
elif isinstance(el, (tuple, list)):
copied_array[i] = list_or_tuple_rec(el)

View File

@@ -551,6 +551,7 @@ class FunctionExecution(Executed):
else:
copied = helpers.fast_parent_copy(element)
copied.parent = self._scope_copy(copied.parent)
# TODO remove? Doesn't make sense, at least explain.
if isinstance(copied, pr.Function):
copied = Function(self._evaluator, copied)
objects.append(copied)

View File

@@ -1107,8 +1107,7 @@ class Statement(Simple, DocstringMixin):
return None, tok
# Since Lambda is a Function scope, it needs Scope parents.
parent = self.get_parent_scope()
lambd = Lambda(self._sub_module, params, start_pos, parent)
lambd = Lambda(self._sub_module, params, start_pos, self)
ret, tok = parse_stmt(token_iterator)
if ret is not None:
@@ -1278,7 +1277,7 @@ class StatementElement(Simple):
def set_next(self, call):
""" Adds another part of the statement"""
call.parent = self
call.parent = self.parent
if self.next is not None:
self.next.set_next(call)
else:
@@ -1289,7 +1288,7 @@ class StatementElement(Simple):
An execution is nothing else than brackets, with params in them, which
shows access on the internals of this name.
"""
call.parent = self
call.parent = self.parent
if self.next is not None:
self.next.set_execution(call)
elif self.execution is not None:

View File

@@ -61,6 +61,15 @@ class C():
C().a()
def xy(param):
def ret(a, b):
return a + b
return lambda b: ret(param, b)
#? int()
xy(1)(2)
# -----------------
# lambda param (#379)
# -----------------