1.1 --- a/annotate.py Sun Oct 08 23:53:35 2006 +0200
1.2 +++ b/annotate.py Sun Oct 08 23:54:56 2006 +0200
1.3 @@ -253,7 +253,10 @@
1.4
1.5 def visitLoadTemp(self, loadtemp):
1.6 index = getattr(loadtemp, "index", None)
1.7 - self.namespace.set_types(self.namespace.temp[index][-1])
1.8 + try:
1.9 + self.namespace.set_types(self.namespace.temp[index][-1])
1.10 + except KeyError:
1.11 + raise AnnotationMessage, "Temporary store index '%s' not defined." % index
1.12 self.annotate(loadtemp)
1.13 return loadtemp
1.14
1.15 @@ -267,7 +270,12 @@
1.16
1.17 def visitReleaseTemp(self, releasetemp):
1.18 index = getattr(releasetemp, "index", None)
1.19 - self.namespace.temp[index].pop()
1.20 + try:
1.21 + self.namespace.temp[index].pop()
1.22 + except KeyError:
1.23 + raise AnnotationMessage, "Temporary store index '%s' not defined." % index
1.24 + except IndexError:
1.25 + pass #raise AnnotationMessage, "Temporary store index '%s' is empty." % index
1.26 return releasetemp
1.27
1.28 def visitLoadAttr(self, loadattr):
1.29 @@ -329,7 +337,7 @@
1.30 def visitReturn(self, return_):
1.31 if hasattr(return_, "expr"):
1.32 return_.expr = self.dispatch(return_.expr)
1.33 - self.namespace.returns += self.namespace.types
1.34 + combine(self.namespace.returns, self.namespace.types)
1.35 self.annotate(return_)
1.36 self.namespace.snapshot()
1.37 return return_
1.38 @@ -385,7 +393,7 @@
1.39
1.40 instance = Instance()
1.41 instance.namespace = Namespace()
1.42 - instance.namespace.store("__class__", [attr.type])
1.43 + instance.namespace.store("__class__", [Attribute(None, attr.type)])
1.44
1.45 # For instantiations, switch the context.
1.46
1.47 @@ -548,17 +556,45 @@
1.48 param, default = params[0]
1.49 if kw_args.has_key(param):
1.50 arg = kw_args[param]
1.51 + del kw_args[param]
1.52 elif default is None:
1.53 raise AnnotationMessage, "No argument supplied in '%s' for parameter '%s'." % (subprogram, param)
1.54 items.append((param, arg.types))
1.55 params = params[1:]
1.56
1.57 + dstar_args = kw_args
1.58 +
1.59 + # Construct temporary objects.
1.60 +
1.61 + if star_args:
1.62 + list_type = self.builtins_namespace.load("list")[0] # NOTE: Hack to get list type.
1.63 + star = Instance()
1.64 + star.namespace = Namespace()
1.65 + star.namespace.store("__class__", [Attribute(None, list_type)])
1.66 + star_types = [Attribute(None, star)]
1.67 + else:
1.68 + star_types = None
1.69 +
1.70 + if dstar_args:
1.71 + dict_type = self.builtins_namespace.load("dict")[0] # NOTE: Hack to get dict type.
1.72 + dstar = Instance()
1.73 + dstar.namespace = Namespace()
1.74 + dstar.namespace.store("__class__", [Attribute(None, dict_type)])
1.75 + dstar_types = [Attribute(None, dstar)]
1.76 + else:
1.77 + dstar_types = None
1.78 +
1.79 + # NOTE: Merge the objects properly.
1.80 +
1.81 + star_types = star_types or invocation.star and invocation.star.types
1.82 + dstar_types = dstar_types or invocation.dstar and invocation.dstar.types
1.83 +
1.84 # Add star and dstar.
1.85
1.86 - if star_args or invocation.star is not None:
1.87 + if star_types is not None:
1.88 if subprogram.star is not None:
1.89 param, default = subprogram.star
1.90 - items.append((param, invocation.star.types))
1.91 + items.append((param, star_types))
1.92 else:
1.93 raise AnnotationMessage, "Invocation provides unwanted *args."
1.94 elif subprogram.star is not None:
1.95 @@ -566,10 +602,10 @@
1.96 arg = self.dispatch(default) # NOTE: Review reprocessing.
1.97 items.append((param, arg.types))
1.98
1.99 - if kw_args or invocation.dstar is not None:
1.100 + if dstar_types is not None:
1.101 if subprogram.dstar is not None:
1.102 param, default = subprogram.dstar
1.103 - items.append((param, invocation.dstar.types))
1.104 + items.append((param, dstar_types))
1.105 else:
1.106 raise AnnotationMessage, "Invocation provides unwanted **args."
1.107 elif subprogram.dstar is not None:
1.108 @@ -619,7 +655,8 @@
1.109
1.110 def merge_namespace(self, namespace):
1.111 self.merge_items(namespace.names.items())
1.112 - self.returns += namespace.returns
1.113 + combine(self.returns, namespace.returns)
1.114 + self.temp = namespace.temp
1.115
1.116 def merge_items(self, items):
1.117 for name, types in items:
1.118 @@ -630,9 +667,7 @@
1.119 self.names[name] = types[:]
1.120 else:
1.121 existing = self.names[name]
1.122 - for type in types:
1.123 - if type not in existing:
1.124 - existing.append(type)
1.125 + combine(existing, types)
1.126
1.127 def snapshot(self):
1.128
1.129 @@ -666,6 +701,11 @@
1.130 def __init__(self, attribute):
1.131 self.types = [attribute]
1.132
1.133 +def combine(target, additions):
1.134 + for addition in additions:
1.135 + if addition not in target:
1.136 + target.append(addition)
1.137 +
1.138 def find_attributes(structure, name):
1.139
1.140 """
1.141 @@ -693,11 +733,10 @@
1.142 # Investigate any instance's implementing class.
1.143
1.144 if isinstance(structure, Instance):
1.145 - for cls in structure.namespace.load("__class__"):
1.146 + for attr in structure.namespace.load("__class__"):
1.147 + cls = attr.type
1.148 l = get_attributes(cls, name)
1.149 - for attribute in l:
1.150 - if attribute not in attributes:
1.151 - attributes.append(attribute)
1.152 + combine(attributes, l)
1.153
1.154 # Investigate any class's base classes.
1.155
1.156 @@ -719,11 +758,9 @@
1.157
1.158 for base_ref in base_refs:
1.159 l = get_attributes(base_ref, name)
1.160 - for attribute in l:
1.161 - if attribute not in base_attributes:
1.162 - base_attributes.append(attribute)
1.163 + combine(base_attributes, l)
1.164
1.165 - attributes += base_attributes
1.166 + combine(attributes, base_attributes)
1.167
1.168 return attributes
1.169