1.1 --- a/annotate.py Fri Feb 23 01:29:50 2007 +0100
1.2 +++ b/annotate.py Sun Feb 25 01:50:23 2007 +0100
1.3 @@ -131,7 +131,7 @@
1.4 types possible when the means of constructing the namespace may depend on
1.5 run-time behaviour.
1.6
1.7 - Covered: Assign, CheckType, Conditional, Global, Import, InvokeBlock,
1.8 + Covered: Assign, CheckType, Conditional, Global, Import, InvokeRef,
1.9 InvokeFunction, LoadAttr, LoadExc, LoadName, LoadRef, LoadTemp,
1.10 Module, Not, Pass, Raise, ReleaseTemp, ReturnFromBlock,
1.11 ReturnFromFunction, StoreAttr, StoreName, StoreTemp, Subprogram,
1.12 @@ -160,6 +160,7 @@
1.13 self.subprograms = []
1.14 self.current_subprograms = []
1.15 self.current_namespaces = []
1.16 + self.rerun_subprograms = {}
1.17 self.namespace = None
1.18 self.module = module
1.19
1.20 @@ -188,6 +189,14 @@
1.21 mutate nodes in the original program.
1.22 """
1.23
1.24 + # Recursion test.
1.25 +
1.26 + if node in self.current_subprograms:
1.27 + if not self.rerun_subprograms.has_key(node):
1.28 + self.rerun_subprograms[node] = []
1.29 + self.rerun_subprograms[node].append(locals)
1.30 + return node
1.31 +
1.32 # Record the current subprogram and namespace.
1.33
1.34 self.current_subprograms.append(node)
1.35 @@ -215,6 +224,15 @@
1.36
1.37 node.namespace = self.namespace
1.38 result = self.dispatch(node)
1.39 +
1.40 + while self.rerun_subprograms.has_key(node):
1.41 + all_rerun_locals = self.rerun_subprograms[node]
1.42 + del self.rerun_subprograms[node]
1.43 + for rerun_locals in all_rerun_locals:
1.44 + print "Re-running", node, "with", rerun_locals
1.45 + node.namespace = self.namespace = rerun_locals
1.46 + result = self.dispatch(node)
1.47 +
1.48 result.namespace = self.namespace
1.49 if not hasattr(result, "raises"):
1.50 result.raises = []
1.51 @@ -479,6 +497,10 @@
1.52 if attribute is not None:
1.53 attribute = Attribute(instance, attribute.type)
1.54
1.55 + # Request an instance-specific initialiser.
1.56 +
1.57 + attribute = attr.type.get_attribute_for_instance(attribute, instance)
1.58 +
1.59 # Skip cases where no callable is found.
1.60
1.61 if attribute is not None:
1.62 @@ -516,15 +538,25 @@
1.63 self.namespace.set_types(getattr(invoke, "types", []))
1.64 return invoke
1.65
1.66 - def visitInvokeBlock(self, invoke):
1.67 + def visitInvokeRef(self, invoke):
1.68
1.69 """
1.70 Return the processed 'invoke' node, first finding the callables
1.71 - indicated by the expression.
1.72 + indicated by the reference.
1.73 """
1.74
1.75 - invoke.expr = self.dispatch(invoke.expr)
1.76 - invocation_types = self.namespace.types
1.77 + # Where the invocation belongs to an instance but the invoked subprogram
1.78 + # does not, request a special copy.
1.79 +
1.80 + instance = getattr(invoke, "instance", None)
1.81 + if instance is not None and getattr(invoke.ref, "instance", None) is None:
1.82 + if invoke.ref.copies.has_key(instance):
1.83 + invoke.ref = invoke.ref.copies[instance]
1.84 + else:
1.85 + invoke.ref = invoke.ref.copy(instance)
1.86 + print "Created", invoke.ref, "for", getattr(invoke.ref, "instance", None)
1.87 + invoke.ref.module.simplifier.subnames[invoke.ref.full_name()] = invoke.ref
1.88 + invocation_types = [Attribute(None, invoke.ref)]
1.89 return self._visitInvoke(invoke, invocation_types, have_args=0)
1.90
1.91 def visitInvokeFunction(self, invoke):
1.92 @@ -1169,12 +1201,18 @@
1.93 invocation.stars = {}
1.94
1.95 if not invocation.stars.has_key(subprogram.full_name()):
1.96 + instance = getattr(invocation, "instance", None)
1.97 +
1.98 code=[
1.99 StoreTemp(
1.100 + instance=instance,
1.101 expr=InvokeFunction(
1.102 invocation.original,
1.103 + instance=instance,
1.104 expr=LoadAttr(
1.105 + instance=instance,
1.106 expr=LoadRef(
1.107 + instance=instance,
1.108 ref=self.builtins
1.109 ),
1.110 name="list",
1.111 @@ -1191,8 +1229,12 @@
1.112 code.append(
1.113 InvokeFunction(
1.114 invocation.original,
1.115 + instance=instance,
1.116 expr=LoadAttr(
1.117 - expr=LoadTemp(),
1.118 + instance=instance,
1.119 + expr=LoadTemp(
1.120 + instance=instance
1.121 + ),
1.122 name="append"
1.123 ),
1.124 args=[arg],
1.125 @@ -1202,21 +1244,27 @@
1.126 )
1.127
1.128 code += [
1.129 - Return(expr=LoadTemp(release=1))
1.130 + Return(
1.131 + instance=instance,
1.132 + expr=LoadTemp(
1.133 + instance=instance,
1.134 + release=1
1.135 + )
1.136 + )
1.137 ]
1.138
1.139 - invocation.stars[subprogram.full_name()] = InvokeBlock(
1.140 + invocation.stars[subprogram.full_name()] = InvokeRef(
1.141 invocation.original,
1.142 + instance=instance,
1.143 produces_result=1,
1.144 - expr=LoadRef(
1.145 - ref=Subprogram(
1.146 - name=None,
1.147 - returns_value=1,
1.148 - params=[],
1.149 - star=None,
1.150 - dstar=None,
1.151 - code=code
1.152 - )
1.153 + ref=Subprogram(
1.154 + instance=instance,
1.155 + name=None,
1.156 + returns_value=1,
1.157 + params=[],
1.158 + star=None,
1.159 + dstar=None,
1.160 + code=code
1.161 )
1.162 )
1.163
1.164 @@ -1233,12 +1281,18 @@
1.165 invocation.dstars = {}
1.166
1.167 if not invocation.dstars.has_key(subprogram.full_name()):
1.168 + instance = getattr(invocation, "instance", None)
1.169 +
1.170 code=[
1.171 StoreTemp(
1.172 + instance=instance,
1.173 expr=InvokeFunction(
1.174 invocation.original,
1.175 + instance=instance,
1.176 expr=LoadAttr(
1.177 + instance=instance,
1.178 expr=LoadRef(
1.179 + instance=instance,
1.180 ref=self.builtins
1.181 ),
1.182 name="dict",
1.183 @@ -1252,22 +1306,31 @@
1.184
1.185 # NOTE: Constant not added to table.
1.186
1.187 - constant = Constant(name=repr(arg), value=arg, namespace=Namespace())
1.188 + constant = Constant(
1.189 + instance=instance,
1.190 + name=repr(arg), value=arg, namespace=Namespace()
1.191 + )
1.192 #constant.namespace.store("__class__", self.get_builtin_instances(invocation, constant.typename))
1.193 code += [
1.194 StoreTemp(
1.195 + instance=instance,
1.196 expr=LoadRef(
1.197 + instance=instance,
1.198 ref=constant
1.199 ),
1.200 index="const"
1.201 ),
1.202 StoreAttr(
1.203 + instance=instance,
1.204 lvalue=LoadTemp(
1.205 + instance=instance,
1.206 index="const"
1.207 ),
1.208 name="__class__",
1.209 expr=LoadAttr(
1.210 + instance=instance,
1.211 expr=LoadRef(
1.212 + instance=instance,
1.213 ref=self.builtins
1.214 ),
1.215 name=constant.typename,
1.216 @@ -1276,12 +1339,17 @@
1.217 ),
1.218 InvokeFunction(
1.219 invocation.original,
1.220 + instance=instance,
1.221 expr=LoadAttr(
1.222 - expr=LoadTemp(),
1.223 + instance=instance,
1.224 + expr=LoadTemp(
1.225 + instance=instance
1.226 + ),
1.227 name="__setitem__"
1.228 ),
1.229 args=[
1.230 LoadTemp(
1.231 + instance=instance,
1.232 index="const",
1.233 release=1
1.234 ),
1.235 @@ -1291,21 +1359,27 @@
1.236 ]
1.237
1.238 code += [
1.239 - Return(expr=LoadTemp(release=1))
1.240 + Return(
1.241 + instance=instance,
1.242 + expr=LoadTemp(
1.243 + instance=instance,
1.244 + release=1
1.245 + )
1.246 + )
1.247 ]
1.248
1.249 - invocation.dstars[subprogram.full_name()] = InvokeBlock(
1.250 + invocation.dstars[subprogram.full_name()] = InvokeRef(
1.251 invocation.original,
1.252 + instance=instance,
1.253 produces_result=1,
1.254 - expr=LoadRef(
1.255 - ref=Subprogram(
1.256 - name=None,
1.257 - returns_value=1,
1.258 - params=[],
1.259 - star=None,
1.260 - dstar=None,
1.261 - code=code
1.262 - )
1.263 + ref=Subprogram(
1.264 + instance=instance,
1.265 + name=None,
1.266 + returns_value=1,
1.267 + params=[],
1.268 + star=None,
1.269 + dstar=None,
1.270 + code=code
1.271 )
1.272 )
1.273