diff --git a/evaluate.py b/evaluate.py index c232b063..67588c31 100644 --- a/evaluate.py +++ b/evaluate.py @@ -165,7 +165,7 @@ class Instance(Executable): return None def get_self_properties(self): - def add_self_name(name): + def add_self_dot_name(name): n = copy.copy(name) n.names = n.names[1:] names.append(InstanceElement(self, n)) @@ -187,7 +187,7 @@ class Instance(Executable): # It is also important, that they have a len() of 2, # because otherwise, they are just something else if n.names[0] == self_name and len(n.names) == 2: - add_self_name(n) + add_self_dot_name(n) for s in self.base.get_super_classes(): names += Instance(s).get_self_properties() @@ -247,7 +247,7 @@ class Instance(Executable): (self.__class__.__name__, self.base, len(self.var_args or [])) -class InstanceElement(): +class InstanceElement(object): def __init__(self, instance, var): if isinstance(var, parsing.Function): var = Function(var) @@ -261,10 +261,6 @@ class InstanceElement(): par = InstanceElement(self.instance, par) return par - def get_var(self): - pass - #if self.var - def get_parent_until(self, *classes): scope = self.var.get_parent_until(*classes) return InstanceElement(self.instance, scope) @@ -656,12 +652,14 @@ class Execution(Executable): objects = [] for element in attr: temp, element.parent = element.parent, None - copied = copy.deepcopy(element) + #copied = copy.deepcopy(element) + copied = helpers.fast_parent_copy2(element) element.parent = temp copied.parent = weakref.ref(self) if isinstance(copied, parsing.Function): copied = Function(copied) objects.append(copied) + faked_scopes.append(copied) return objects def __getattr__(self, name): @@ -1000,7 +998,6 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): def descriptor_check(result): res_new = [] - #print 'descc', scope, result, name_str for r in result: if isinstance(scope, (Instance, Class)) \ and hasattr(r, 'get_descriptor_return'): diff --git a/functions.py b/functions.py index 921b6992..ed3c43b4 100644 --- a/functions.py +++ b/functions.py @@ -71,6 +71,14 @@ class Definition(object): """ The definition of a function """ self.definition = definition + par = self.definition + while True: + if par.parent() is not None: + par = par.parent() + else: + break + self.module_path = str(par.path) + def get_name(self): try: # is a func / class @@ -91,17 +99,6 @@ class Definition(object): except ValueError: return path - @property - def module_path(self): - par = self.definition - while True: - if par.parent() is not None: - par = par.parent() - else: - break - - return str(par.path) - def in_builtin_module(self): return not self.module_path.endswith('.py') diff --git a/helpers.py b/helpers.py index 04b2165f..76404f42 100644 --- a/helpers.py +++ b/helpers.py @@ -1,4 +1,5 @@ import copy +import weakref import parsing import debug @@ -87,6 +88,42 @@ def fast_parent_copy(obj): return copied_list return recursion(obj) +def fast_parent_copy2(obj): + """ + Much, much faster than deepcopy, but just for the elements in `classes`. + """ + new_elements = {} + classes = (parsing.Simple) + + def recursion(obj): + new_obj = copy.copy(obj) + new_elements[obj] = new_obj + if obj.parent is not None: + try: + new_obj.parent = weakref.ref(new_elements[obj.parent()]) + except KeyError: + pass + + #print new_obj.__dict__ + for key, value in new_obj.__dict__.items(): + if isinstance(value, list): + new_obj.__dict__[key] = list_rec(value) + elif isinstance(value, classes): + new_obj.__dict__[key] = recursion(value) + return new_obj + + def list_rec(list_obj): + copied_list = list_obj[:] # lists, tuples, strings, unicode + for i, el in enumerate(copied_list): + if isinstance(el, classes): + copied_list[i] = recursion(el) + elif isinstance(el, list): + copied_list[i] = list_rec(el) + elif isinstance(el, parsing.Call): + copied_list[i] = fast_parent_copy(el) + return copied_list + return recursion(obj) + def generate_param_array(args_tuple, parent_stmt=None): """ This generates an array, that can be used as a param """ diff --git a/parsing.py b/parsing.py index a33c629d..1bd6a7c6 100644 --- a/parsing.py +++ b/parsing.py @@ -378,9 +378,9 @@ class Flow(Scope): :type set_vars: list """ def __init__(self, command, inits, start_pos, set_vars=None): - super(Flow, self).__init__(start_pos, '') self.next = None - #self.top_flow = weakref.ref(self) + super(Flow, self).__init__(start_pos, '') + self._parent = None self.command = command # These have to be statements, because of with, which takes multiple. self.inits = inits @@ -393,14 +393,15 @@ class Flow(Scope): for s in self.set_vars: s.parent = weakref.ref(self) - """ + @property def parent(self): - if self._parent is None: - return self.top_flow().parent() - else: - return self._parent() - # TODO REMOVE - """ + return self._parent + + @parent.setter + def parent(self, value): + self._parent = value + if self.next: + self.next.parent = value def set_parent(self, value): """ @@ -459,7 +460,6 @@ class Flow(Scope): else: self.next = next self.next.parent = self.parent - #next.top_flow = self.top_flow return next @@ -534,7 +534,7 @@ class Import(Simple): return [self.alias] if len(self.namespace) > 1: o = self.namespace - n = Name([o.names[0]], o.start_pos, o.end_pos, parent=o.parent) + n = Name([o.names[0]], o.start_pos, o.end_pos, parent=o.parent()) return [n] else: return [self.namespace]