From bc6cf350c2e9d6442498d607a815a54fbbd6773d Mon Sep 17 00:00:00 2001 From: David Halter Date: Mon, 13 Aug 2012 11:38:54 +0200 Subject: [PATCH] weakrefs also for parent_stmt --- dynamic.py | 8 ++++---- evaluate.py | 18 ++++++++++-------- functions.py | 2 +- helpers.py | 8 +++++++- parsing.py | 6 +++--- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/dynamic.py b/dynamic.py index 1f958c49..e302a840 100644 --- a/dynamic.py +++ b/dynamic.py @@ -90,7 +90,7 @@ def search_params(param): def check_array_additions(array): """ Just a mapper function for the internal _check_array_additions """ is_list = array._array.type == 'list' - current_module = array._array.parent_stmt.get_parent_until() + current_module = array._array.parent_stmt().get_parent_until() return _check_array_additions(array, current_module, is_list) @@ -124,8 +124,8 @@ def _check_array_additions(compare_array, module, is_list): continue backtrack_path = iter(call_path[:separate_index]) - position = c.parent_stmt.start_pos - scope = c.parent_stmt.parent() + position = c.parent_stmt().start_pos + scope = c.parent_stmt().parent() e = evaluate.follow_call_path(backtrack_path, scope, position) if not compare_array in e: # the `append`, etc. belong to other arrays @@ -193,7 +193,7 @@ class ArrayInstance(parsing.Base): continue items += evaluate.handle_iterators([array]) - module = self.var_args.parent_stmt.get_parent_until() + module = self.var_args.parent_stmt().get_parent_until() is_list = str(self.instance.name) == 'list' items += _check_array_additions(self.instance, module, is_list) return items diff --git a/evaluate.py b/evaluate.py index 67588c31..8189de9d 100644 --- a/evaluate.py +++ b/evaluate.py @@ -204,8 +204,8 @@ class Instance(Executable): if args is None: args = helpers.generate_param_array([]) method = self.get_subscope_by_name(name) - if args.parent_stmt is None: - args.parent_stmt = method + if args.parent_stmt() is None: + args.parent_stmt = weakref.ref(method) return Execution(method, args).get_return_types() def get_descriptor_return(self, obj): @@ -275,11 +275,12 @@ class InstanceElement(object): def get_assignment_calls(self): # Copy and modify the array. origin = self.var.get_assignment_calls() - origin.parent_stmt, temp = None, origin.parent_stmt # Delete parent, because it isn't used anymore. new = helpers.fast_parent_copy(origin) - origin.parent_stmt = temp - new.parent_stmt = InstanceElement(self.instance, temp) + par = InstanceElement(self.instance, origin.parent_stmt()) + new.parent_stmt = weakref.ref(par) + faked_scopes.append(par) + faked_scopes.append(new) return new def __getattr__(self, name): @@ -382,6 +383,7 @@ class Function(parsing.Base): # Create param array. old_func = Function(f, is_decorated=True) params = helpers.generate_param_array([old_func], old_func) + faked_scopes.append(old_func) wrappers = Execution(decorator, params).get_return_types() if not len(wrappers): @@ -483,7 +485,7 @@ class Execution(Executable): """ Create a param with the original scope (of varargs) as parent. """ - parent_stmt = self.var_args.parent_stmt + parent_stmt = self.var_args.parent_stmt() calls = parsing.Array(parsing.Array.NOARRAY, parent_stmt) calls.values = values calls.keys = keys @@ -1180,10 +1182,10 @@ def follow_call_list(call_list): def follow_call(call): """ Follow a call is following a function, variable, string, etc. """ - scope = call.parent_stmt.parent() + scope = call.parent_stmt().parent() path = call.generate_call_path() - position = call.parent_stmt.start_pos + position = call.parent_stmt().start_pos return follow_call_path(path, scope, position) diff --git a/functions.py b/functions.py index ed3c43b4..cedaa3c1 100644 --- a/functions.py +++ b/functions.py @@ -319,8 +319,8 @@ def set_debug_function(func_cb): def _clear_caches(): evaluate.clear_caches() - import gc return + import gc #gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS) #gc.collect() count = 0 diff --git a/helpers.py b/helpers.py index 76404f42..8fa47058 100644 --- a/helpers.py +++ b/helpers.py @@ -2,6 +2,7 @@ import copy import weakref import parsing +import evaluate import debug import builtin @@ -106,6 +107,9 @@ def fast_parent_copy2(obj): #print new_obj.__dict__ for key, value in new_obj.__dict__.items(): + #if key in ['_parent_stmt', 'parent_stmt', '_parent', 'parent']: print key, value + if key in ['parent', '_parent']: + continue if isinstance(value, list): new_obj.__dict__[key] = list_rec(value) elif isinstance(value, classes): @@ -133,4 +137,6 @@ def generate_param_array(args_tuple, parent_stmt=None): values.append([]) else: values.append([arg]) - return parsing.Array(parsing.Array.TUPLE, parent_stmt, values=values) + arr = parsing.Array(parsing.Array.TUPLE, parent_stmt, values=values) + evaluate.faked_scopes.append(arr) + return arr diff --git a/parsing.py b/parsing.py index 1bd6a7c6..470c46bb 100644 --- a/parsing.py +++ b/parsing.py @@ -781,16 +781,16 @@ class Call(object): self.next = None self.execution = None - self._parent_stmt = parent_stmt + self._parent_stmt = weakref.ref(parent_stmt) if parent_stmt else None @property def parent_stmt(self): - if self._parent_stmt: + if self._parent_stmt is not None: return self._parent_stmt elif self.parent: return self.parent.parent_stmt else: - return None + return lambda: None @parent_stmt.setter def parent_stmt(self, value):