1.1 --- a/annotate.py Sat Oct 14 02:17:40 2006 +0200
1.2 +++ b/annotate.py Sun Oct 15 01:03:44 2006 +0200
1.3 @@ -149,11 +149,6 @@
1.4 mutate nodes in the original program.
1.5 """
1.6
1.7 - # Prevent infinite recursion.
1.8 -
1.9 - if node in self.current_subprograms:
1.10 - return node
1.11 -
1.12 # Determine the namespace.
1.13
1.14 if locals is not None:
1.15 @@ -282,17 +277,22 @@
1.16 loadattr.expr = self.dispatch(loadattr.expr)
1.17 types = []
1.18 accesses = {}
1.19 + non_accesses = {}
1.20 for attr in self.namespace.types:
1.21 - if not accesses.has_key(attr.type):
1.22 - accesses[attr.type] = []
1.23 for attribute, accessor in get_attributes(attr.type, loadattr.name):
1.24 if attribute is not None:
1.25 types.append(attribute)
1.26 + if not accesses.has_key(attr.type):
1.27 + accesses[attr.type] = []
1.28 + accesses[attr.type].append((attribute, accessor))
1.29 else:
1.30 - print "Empty attribute via accessor", accessor
1.31 - accesses[attr.type].append((attribute, accessor))
1.32 + print "Empty attribute", loadattr.name, "via accessor", accessor
1.33 + if not non_accesses.has_key(attr.type):
1.34 + non_accesses[attr.type] = []
1.35 + non_accesses[attr.type].append((attribute, accessor))
1.36 self.namespace.set_types(types)
1.37 loadattr.accesses = accesses
1.38 + loadattr.non_accesses = non_accesses
1.39 self.annotate(loadattr)
1.40 return loadattr
1.41
1.42 @@ -391,9 +391,7 @@
1.43 # Instantiate the class.
1.44 # NOTE: Should probably only allocate a single instance.
1.45
1.46 - instance = Instance()
1.47 - instance.namespace = Namespace()
1.48 - instance.namespace.store("__class__", [Attribute(None, attr.type)])
1.49 + instance = self.new_instance(invoke, "new", attr.type.full_name(), attr.type)
1.50
1.51 # For instantiations, switch the context.
1.52
1.53 @@ -410,9 +408,11 @@
1.54 if attribute.type not in invocations:
1.55 invocations.append(attribute.type)
1.56
1.57 - else:
1.58 + elif not isinstance(attr.type, Class):
1.59 print "Invocation type is None for", accessor
1.60
1.61 + # Special case: initialisation.
1.62 +
1.63 if isinstance(attr.type, Class):
1.64
1.65 # Associate the instance with the result of this invocation.
1.66 @@ -429,17 +429,35 @@
1.67
1.68 # Utility methods.
1.69
1.70 + def new_instance(self, node, reason, target, type):
1.71 +
1.72 + "Create, on the given 'node', a new instance with the given 'type'."
1.73 +
1.74 + if not hasattr(node, "instances"):
1.75 + node.instances = {}
1.76 +
1.77 + if not node.instances.has_key((reason, target, type)):
1.78 + instance = Instance()
1.79 + instance.namespace = Namespace()
1.80 + instance.namespace.store("__class__", [Attribute(None, type)])
1.81 + node.instances[(reason, target, type)] = instance
1.82 +
1.83 + return node.instances[(reason, target, type)]
1.84 +
1.85 def invoke_subprogram(self, invoke, subprogram):
1.86
1.87 - """
1.88 - Invoke using the given 'invoke' node the given 'subprogram'.
1.89 - """
1.90 + "Invoke using the given 'invoke' node the given 'subprogram'."
1.91
1.92 # Test to see if anything has changed.
1.93
1.94 if hasattr(invoke, "syscount") and invoke.syscount == self.system.count:
1.95 return
1.96
1.97 + # Remember the state of the system.
1.98 +
1.99 + else:
1.100 + invoke.syscount = self.system.count
1.101 +
1.102 # Test for context information, making it into a real attribute.
1.103
1.104 if subprogram.context is not None:
1.105 @@ -472,10 +490,6 @@
1.106 for locals in self.returned_locals:
1.107 self.namespace.merge_namespace(locals)
1.108
1.109 - # Remember the state of the system.
1.110 -
1.111 - invoke.syscount = self.system.count
1.112 -
1.113 def process_args(self, invoke):
1.114
1.115 # NOTE: Consider initialiser invocation for classes.
1.116 @@ -568,18 +582,14 @@
1.117
1.118 if star_args:
1.119 list_type = self.builtins_namespace.load("list")[0] # NOTE: Hack to get list type.
1.120 - star = Instance()
1.121 - star.namespace = Namespace()
1.122 - star.namespace.store("__class__", [Attribute(None, list_type.type)])
1.123 + star = self.new_instance(invocation, "star", subprogram.full_name(), list_type.type)
1.124 star_types = [Attribute(None, star)]
1.125 else:
1.126 star_types = None
1.127
1.128 if dstar_args:
1.129 dict_type = self.builtins_namespace.load("dict")[0] # NOTE: Hack to get dict type.
1.130 - dstar = Instance()
1.131 - dstar.namespace = Namespace()
1.132 - dstar.namespace.store("__class__", [Attribute(None, dict_type.type)])
1.133 + dstar = self.new_instance(invocation, "dstar", subprogram.full_name(), dict_type.type)
1.134 dstar_types = [Attribute(None, dstar)]
1.135 else:
1.136 dstar_types = None