1.1 --- a/annotate.py Sat Nov 25 03:07:54 2006 +0100
1.2 +++ b/annotate.py Sun Nov 26 15:45:53 2006 +0100
1.3 @@ -141,12 +141,12 @@
1.4 else:
1.5 self.builtins_namespace = self.global_namespace
1.6
1.7 - return self.process_node(module)
1.8 + return self.process_node(module, self.global_namespace)
1.9
1.10 - def process_node(self, node, locals=None):
1.11 + def process_node(self, node, locals):
1.12
1.13 """
1.14 - Process a subprogram or module 'node', indicating any initial 'locals'.
1.15 + Process a subprogram or module 'node', indicating the initial 'locals'.
1.16 Return an annotated subprogram or module. Note that this method may
1.17 mutate nodes in the original program.
1.18 """
1.19 @@ -157,11 +157,8 @@
1.20
1.21 # Determine the namespace.
1.22
1.23 - if locals is not None:
1.24 - self.current_namespaces.append(self.namespace)
1.25 - self.namespace = locals
1.26 - else:
1.27 - self.namespace = self.global_namespace
1.28 + self.current_namespaces.append(self.namespace)
1.29 + self.namespace = locals
1.30
1.31 # Add namespace details to any structure involved.
1.32
1.33 @@ -191,8 +188,7 @@
1.34
1.35 # Restore the previous subprogram and namespace.
1.36
1.37 - if locals is not None:
1.38 - self.namespace = self.current_namespaces.pop()
1.39 + self.namespace = self.current_namespaces.pop()
1.40 self.current_subprograms.pop()
1.41
1.42 return result
1.43 @@ -610,14 +606,22 @@
1.44
1.45 if getattr(invoke, "share_locals", 0):
1.46 namespace = Namespace()
1.47 - namespace.merge_namespace(self.namespace)
1.48 + namespace.merge_namespace(self.namespace, no_return_locals=1)
1.49 + using_module_namespace = self.namespace is self.module.namespace
1.50 elif getattr(target, "structure", None):
1.51 namespace = Namespace()
1.52 + using_module_namespace = 0
1.53 else:
1.54 items = self.make_items(invoke, target, context)
1.55 namespace = self.make_namespace(items)
1.56 + using_module_namespace = 0
1.57
1.58 # Process the subprogram.
1.59 + # In order to keep global accesses working, the module namespace must be
1.60 + # adjusted.
1.61 +
1.62 + if using_module_namespace:
1.63 + self.module.namespace = namespace
1.64
1.65 self.process_node(target, namespace)
1.66
1.67 @@ -628,16 +632,26 @@
1.68 self.namespace.set_types(self.last_returns)
1.69 self.annotate(invoke)
1.70
1.71 - # Otherwise, assuming it is a normal block, merge the locals.
1.72 + # If it is a normal block, merge the locals.
1.73 + # This can happen in addition to the above because for things like
1.74 + # logical expressions, the namespace can be modified whilst values are
1.75 + # returned as results.
1.76
1.77 - elif getattr(invoke, "share_locals", 0):
1.78 + if getattr(invoke, "share_locals", 0):
1.79 + self.namespace.reset()
1.80 for locals in self.returned_locals:
1.81 - self.namespace.merge_namespace(locals)
1.82 + self.namespace.merge_namespace(locals, no_return_locals=1)
1.83
1.84 # Incorporate any raised exceptions.
1.85
1.86 combine(self.namespace.raises, self.last_raises)
1.87
1.88 + # In order to keep global accesses working, the module namespace must be
1.89 + # adjusted.
1.90 +
1.91 + if using_module_namespace:
1.92 + self.module.namespace = self.namespace
1.93 +
1.94 def process_args(self, invocation):
1.95
1.96 """
1.97 @@ -759,9 +773,13 @@
1.98
1.99 # Record the parameter types.
1.100
1.101 - subprogram.paramtypes = {}
1.102 + if not hasattr(subprogram, "paramtypes"):
1.103 + subprogram.paramtypes = {}
1.104 +
1.105 for param, types in items:
1.106 - subprogram.paramtypes[param] = types
1.107 + if not subprogram.paramtypes.has_key(param):
1.108 + subprogram.paramtypes[param] = []
1.109 + combine(subprogram.paramtypes[param], types)
1.110
1.111 return items
1.112
1.113 @@ -867,12 +885,13 @@
1.114 __getitem__ = load
1.115
1.116 def revoke(self, name, type):
1.117 - print "Revoke", type, "from", name
1.118 self.names[name].remove(type)
1.119
1.120 - def merge_namespace(self, namespace):
1.121 + def merge_namespace(self, namespace, no_return_locals=0):
1.122 self.merge_items(namespace.names.items())
1.123 combine(self.returns, namespace.returns)
1.124 + if not no_return_locals:
1.125 + combine(self.return_locals, namespace.return_locals)
1.126 combine(self.raises, namespace.raises)
1.127 self.temp = {}
1.128 self.temp.update(namespace.temp)
1.129 @@ -896,6 +915,12 @@
1.130 namespace.merge_namespace(self)
1.131 self.return_locals.append(namespace)
1.132
1.133 + def reset(self):
1.134 +
1.135 + "Reset a namespace in preparation for merging with returned locals."
1.136 +
1.137 + self.names = {}
1.138 +
1.139 def __repr__(self):
1.140 return repr(self.names)
1.141
2.1 --- a/simplify.py Sat Nov 25 03:07:54 2006 +0100
2.2 +++ b/simplify.py Sun Nov 26 15:45:53 2006 +0100
2.3 @@ -1059,7 +1059,7 @@
2.4 expr=LoadRef(ref=structure)
2.5 ),
2.6 InvokeBlock(
2.7 - share_locals=0,
2.8 + share_locals=0, # override the local sharing usually in InvokeBlock
2.9 expr=LoadRef(ref=subprogram)
2.10 )
2.11 ]