1.1 --- a/annotate.py Sun Aug 13 19:31:12 2006 +0200
1.2 +++ b/annotate.py Sun Aug 13 22:23:54 2006 +0200
1.3 @@ -41,7 +41,6 @@
1.4 if type not in node.types:
1.5 node.types.append(type)
1.6 self.count += 1
1.7 - print self.count
1.8
1.9 system = System()
1.10
1.11 @@ -75,10 +74,6 @@
1.12 self.subprograms = []
1.13 self.current_subprograms = []
1.14 self.current_namespaces = []
1.15 - self.current_returns = []
1.16 - self.current_return_locals = []
1.17 - self.current_temps = []
1.18 - self.current_types = []
1.19
1.20 # Give constants their own namespace.
1.21
1.22 @@ -113,22 +108,6 @@
1.23
1.24 self.current_subprograms.append(node)
1.25 self.current_namespaces.append(self.namespace)
1.26 - self.current_returns.append([])
1.27 - self.current_return_locals.append([])
1.28 - self.current_temps.append({})
1.29 - self.current_types.append([])
1.30 -
1.31 - # Record the namespace on the node.
1.32 - # NOTE: This may eventually be a specialisation node.
1.33 -
1.34 - node.namespace = self.namespace
1.35 -
1.36 - # Remember return values and locals snapshots.
1.37 -
1.38 - self.return_locals = []
1.39 - self.returns = self.current_returns[-1]
1.40 - self.temp = self.current_temps[-1]
1.41 - self.types = self.current_types[-1]
1.42
1.43 # Add namespace details to any structure involved.
1.44
1.45 @@ -141,12 +120,19 @@
1.46 base_refs = []
1.47 for base in node.structure.bases:
1.48 self.dispatch(base)
1.49 - base_refs.append(self.types)
1.50 + base_refs.append(self.namespace.types)
1.51 node.structure.base_refs = base_refs
1.52
1.53 # Dispatch to the code itself.
1.54
1.55 + node.namespace = self.namespace
1.56 result = self.dispatch(node)
1.57 + result.namespace = self.namespace
1.58 +
1.59 + # Obtain the return values.
1.60 +
1.61 + self.last_returns = self.namespace.returns
1.62 + self.returned_locals = self.namespace.return_locals
1.63
1.64 # Restore the previous subprogram and namespace.
1.65
1.66 @@ -154,22 +140,6 @@
1.67 if self.current_namespaces:
1.68 self.namespace = self.current_namespaces[-1]
1.69
1.70 - self.current_types.pop()
1.71 - if self.current_types:
1.72 - self.types = self.current_types[-1]
1.73 -
1.74 - self.current_temps.pop()
1.75 - if self.current_temps:
1.76 - self.temp = self.current_temps[-1]
1.77 -
1.78 - self.last_returns = self.current_returns.pop()
1.79 - if self.current_returns:
1.80 - self.returns = self.current_returns[-1]
1.81 -
1.82 - self.returned_locals = self.current_return_locals.pop()
1.83 - if self.current_return_locals:
1.84 - self.return_locals = self.current_return_locals[-1]
1.85 -
1.86 self.current_subprograms.pop()
1.87
1.88 return result
1.89 @@ -178,15 +148,7 @@
1.90
1.91 "Annotate the given 'node' in the system."
1.92
1.93 - self.system.annotate(node, self.types)
1.94 -
1.95 - def add_locals_snapshot(self):
1.96 -
1.97 - "Make a snapshot of the locals and remember them."
1.98 -
1.99 - namespace = Namespace()
1.100 - namespace.merge_namespace(self.namespace)
1.101 - self.return_locals.append(namespace)
1.102 + self.system.annotate(node, self.namespace.types)
1.103
1.104 # Visitor methods.
1.105
1.106 @@ -215,79 +177,69 @@
1.107 raise
1.108
1.109 def visitLoadRef(self, loadref):
1.110 - self.types = [loadref.ref]
1.111 + self.namespace.set_types([Attribute(None, loadref.ref)])
1.112 self.annotate(loadref)
1.113 return loadref
1.114
1.115 def visitLoadName(self, loadname):
1.116 - self.types = self.namespace.load(loadname.name)
1.117 + self.namespace.set_types(self.namespace.load(loadname.name))
1.118 result = loadname
1.119 self.annotate(result)
1.120 return result
1.121
1.122 def visitStoreName(self, storename):
1.123 storename.expr = self.dispatch(storename.expr)
1.124 - self.namespace.store(storename.name, self.types)
1.125 + self.namespace.store(storename.name, self.namespace.types)
1.126 return storename
1.127
1.128 - def visitLoadGlobal(self, loadglobal):
1.129 - self.types = self.global_namespace.load(loadglobal.name)
1.130 - self.annotate(loadglobal)
1.131 - return loadglobal
1.132 -
1.133 - def visitLoadBuiltin(self, loadbuiltin):
1.134 - self.types = self.builtins_namespace.load(loadbuiltin.name)
1.135 - self.annotate(loadbuiltin)
1.136 - return loadbuiltin
1.137 -
1.138 - def visitStoreGlobal(self, storeglobal):
1.139 - storeglobal.expr = self.dispatch(storeglobal.expr)
1.140 - self.global_namespace.merge(storeglobal.name, self.types)
1.141 - return storeglobal
1.142 -
1.143 def visitLoadTemp(self, loadtemp):
1.144 index = getattr(loadtemp, "index", None)
1.145 - self.types = self.temp[index][-1]
1.146 + self.namespace.set_types(self.namespace.temp[index][-1])
1.147 self.annotate(loadtemp)
1.148 return loadtemp
1.149
1.150 def visitStoreTemp(self, storetemp):
1.151 storetemp.expr = self.dispatch(storetemp.expr)
1.152 index = getattr(storetemp, "index", None)
1.153 - if not self.temp.has_key(index):
1.154 - self.temp[index] = []
1.155 - self.temp[index].append(self.types)
1.156 + if not self.namespace.temp.has_key(index):
1.157 + self.namespace.temp[index] = []
1.158 + self.namespace.temp[index].append(self.namespace.types)
1.159 return storetemp
1.160
1.161 def visitReleaseTemp(self, releasetemp):
1.162 index = getattr(releasetemp, "index", None)
1.163 - self.temp[index].pop()
1.164 + self.namespace.temp[index].pop()
1.165 return releasetemp
1.166
1.167 def visitLoadAttr(self, loadattr):
1.168 loadattr.expr = self.dispatch(loadattr.expr)
1.169 types = []
1.170 accesses = {}
1.171 - for ref in self.types:
1.172 - if not accesses.has_key(ref):
1.173 - accesses[ref] = []
1.174 - for attribute, accessor in get_attributes(ref, loadattr.name):
1.175 - if attribute.type is not None:
1.176 - types.append(type)
1.177 - accesses[ref].append((attribute, accessor))
1.178 - self.types = types
1.179 + for attr in self.namespace.types:
1.180 + if not accesses.has_key(attr.type):
1.181 + accesses[attr.type] = []
1.182 + for attribute, accessor in get_attributes(attr.type, loadattr.name):
1.183 + if attribute is not None:
1.184 + types.append(attribute)
1.185 + else:
1.186 + print "Empty attribute via accessor", accessor
1.187 + accesses[attr.type].append((attribute, accessor))
1.188 + self.namespace.set_types(types)
1.189 loadattr.accesses = accesses
1.190 self.annotate(loadattr)
1.191 return loadattr
1.192
1.193 def visitStoreAttr(self, storeattr):
1.194 storeattr.expr = self.dispatch(storeattr.expr)
1.195 - expr = self.types
1.196 + expr = self.namespace.types
1.197 storeattr.lvalue = self.dispatch(storeattr.lvalue)
1.198 accesses = {}
1.199 - for ref in self.types:
1.200 - ref.namespace.store(storeattr.name, expr)
1.201 - accesses[ref] = ref.namespace.load(storeattr.name)
1.202 + for attr in self.namespace.types:
1.203 + if attr is None:
1.204 + print "Empty attribute storage attempt"
1.205 + continue
1.206 + attr.type.namespace.store(storeattr.name, expr)
1.207 + accesses[attr.type] = attr.type.namespace.load(storeattr.name)
1.208 storeattr.accesses = accesses
1.209 return storeattr
1.210
1.211 @@ -318,13 +270,13 @@
1.212 def visitReturn(self, return_):
1.213 if hasattr(return_, "expr"):
1.214 return_.expr = self.dispatch(return_.expr)
1.215 - self.returns += self.types
1.216 - self.add_locals_snapshot()
1.217 + self.namespace.returns += self.namespace.types
1.218 + self.namespace.snapshot()
1.219 return return_
1.220
1.221 def visitInvoke(self, invoke):
1.222 invoke.expr = self.dispatch(invoke.expr)
1.223 - expr = self.types
1.224 + invocation_types = self.namespace.types
1.225
1.226 # NOTE: Consider initialiser invocation for classes.
1.227
1.228 @@ -335,7 +287,7 @@
1.229
1.230 for arg in invoke.args:
1.231 args.append(self.dispatch(arg))
1.232 - types.append(self.types)
1.233 + types.append(self.namespace.types)
1.234
1.235 # Get type information for star and dstar arguments.
1.236
1.237 @@ -361,44 +313,47 @@
1.238
1.239 # Visit each callable in turn, finding subprograms.
1.240
1.241 - for callable in expr:
1.242 + for attr in invocation_types:
1.243
1.244 # Deal with class invocations by providing instance objects.
1.245 # Here, each class is queried for the __init__ method, which may
1.246 # exist for some combinations of classes in a hierarchy but not for
1.247 # others.
1.248
1.249 - if isinstance(callable, Class):
1.250 - attributes = get_attributes(callable, "__init__")
1.251 + if isinstance(attr.type, Class):
1.252 + attributes = get_attributes(attr.type, "__init__")
1.253
1.254 # Deal with object invocations by using __call__ methods.
1.255
1.256 - elif isinstance(callable, Instance):
1.257 - attributes = get_attributes(callable, "__call__")
1.258 + elif isinstance(attr.type, Instance):
1.259 + attributes = get_attributes(attr.type, "__call__")
1.260
1.261 # Normal functions or methods are more straightforward.
1.262 # Here, we model them using an attribute with no context and with
1.263 # no associated accessor.
1.264
1.265 else:
1.266 - attributes = [(Attribute(None, callable), None)]
1.267 + attributes = [(attr, None)]
1.268
1.269 # Inspect each attribute and extract the subprogram.
1.270
1.271 for attribute, accessor in attributes:
1.272 + if attribute is None:
1.273 + print "Invocation type is None"
1.274 + continue
1.275 +
1.276 subprogram = attribute.type
1.277
1.278 # If a subprogram is defined, invoke it.
1.279
1.280 - if subprogram is not None:
1.281 - self.invoke_subprogram(invoke, subprogram)
1.282 - invocations[callable] = subprogram
1.283 + self.invoke_subprogram(invoke, subprogram)
1.284 + invocations[callable] = subprogram
1.285
1.286 # If a class is involved, presume that it must create a new
1.287 # object.
1.288
1.289 - if isinstance(callable, Class):
1.290 - self.types = [attribute.context]
1.291 + if isinstance(attr.type, Class):
1.292 + self.namespace.set_types([Attribute(None, attribute.context)])
1.293 self.annotate(invoke)
1.294
1.295 invoke.invocations = invocations
1.296 @@ -443,7 +398,7 @@
1.297 # NOTE: Improve and verify this.
1.298
1.299 if getattr(subprogram, "returns_value", 0):
1.300 - self.types = self.last_returns
1.301 + self.namespace.set_types(self.last_returns)
1.302 self.annotate(invoke)
1.303
1.304 if getattr(invoke, "same_frame", 0):
1.305 @@ -536,6 +491,14 @@
1.306
1.307 def __init__(self):
1.308 self.names = {}
1.309 + self.returns = []
1.310 + self.return_locals = []
1.311 + self.temp = {}
1.312 + self.types = []
1.313 +
1.314 + def set_types(self, types):
1.315 + print "Setting", types
1.316 + self.types = types
1.317
1.318 def store(self, name, types):
1.319 self.names[name] = types
1.320 @@ -559,6 +522,14 @@
1.321 for name, types in items:
1.322 self.merge(name, types)
1.323
1.324 + def snapshot(self):
1.325 +
1.326 + "Make a snapshot of the locals and remember them."
1.327 +
1.328 + namespace = Namespace()
1.329 + namespace.merge_namespace(self)
1.330 + self.return_locals.append(namespace)
1.331 +
1.332 def __repr__(self):
1.333 return repr(self.names)
1.334
1.335 @@ -638,7 +609,7 @@
1.336
1.337 attributes += base_attributes
1.338
1.339 - return attributes
1.340 + return attributes
1.341
1.342 def get_attributes(structure, name):
1.343
1.344 @@ -653,9 +624,6 @@
1.345
1.346 if isinstance(structure, Attribute):
1.347 structure = structure.type
1.348 - attributes = find_attributes(structure, name)
1.349 - for i, (attribute, accessor) in enumerate(attributes):
1.350 - attributes[i] = Attribute(structure, attribute), accessor
1.351 - return attributes
1.352 + return find_attributes(structure, name)
1.353
1.354 # vim: tabstop=4 expandtab shiftwidth=4