# HG changeset patch # User paulb@jeremy # Date 1161987752 -7200 # Node ID 6319a2435d8c1cd04048a103c64cfbb514786008 # Parent 7d18913dbebca4f1b2d4061209299c8cf0a3f9bf Changed attributes on subprograms (acquire_locals -> internal), added a share_locals attribute to replace acquire_locals. Improved annotation of invocations. Added better exception raising support. diff -r 7d18913dbebc -r 6319a2435d8c annotate.py --- a/annotate.py Sat Oct 28 00:20:33 2006 +0200 +++ b/annotate.py Sat Oct 28 00:22:32 2006 +0200 @@ -313,6 +313,28 @@ self.annotate(loadtemp) return loadtemp + def visitRaise(self, raise_): + raise_.traceback = self.dispatch(raise_.traceback) + raise_.expr = self.dispatch(raise_.expr) + + # Handle bare name exceptions by converting any classes to instances. + + if not isinstance(raise_.expr, InvokeFunction): + raise_.pos_args = [] + raise_.kw_args = {} + raise_.star = None + raise_.dstar = None + types = [] + for attr in self.namespace.types: + if isinstance(attr.type, Class): + self._visitInvoke(raise_, [attr], have_args=0) + types += self.namespace.types + else: + types = self.namespace.types + + combine(self.namespace.raises, types) + return raise_ + def visitReleaseTemp(self, releasetemp): index = getattr(releasetemp, "index", None) try: @@ -360,7 +382,15 @@ # Invocations are a chapter of their own. - def visitInvoke(self, invoke): + def visitInvokeBlock(self, invoke): + + # First find the callables. + + invoke.expr = self.dispatch(invoke.expr) + invocation_types = self.namespace.types + return self._visitInvoke(invoke, invocation_types, have_args=0) + + def visitInvokeFunction(self, invoke): # First find the callables. @@ -370,8 +400,9 @@ # Invocation processing starts with making sure that the arguments have # been processed. - if isinstance(invoke, InvokeFunction): - self.process_args(invoke) + return self._visitInvoke(invoke, invocation_types, have_args=self.process_args(invoke)) + + def _visitInvoke(self, invoke, invocation_types, have_args): # Now locate and invoke the subprogram. This can be complicated because # the target may be a class or object, and there may be many different @@ -435,14 +466,22 @@ elif not isinstance(attr.type, Class): print "Invocation type is None for", accessor - # Special case: initialisation. + else: - if isinstance(attr.type, Class): + # Test to see if no arguments were supplied in cases where no + # initialiser was found. + + if have_args: + raise AnnotationMessage, "No initialiser found for '%s' with arguments." % attr.type - # Associate the instance with the result of this invocation. + # Special case: initialisation. + + if isinstance(attr.type, Class): - self.namespace.set_types([Attribute(None, instance)]) - self.annotate(invoke) + # Associate the instance with the result of this invocation. + + self.namespace.set_types([Attribute(None, instance)]) + self.annotate(invoke) # Remember the invocations that were found, along with the return type # information. @@ -451,9 +490,6 @@ self.namespace.set_types(getattr(invoke, "types", [])) return invoke - visitInvokeFunction = visitInvoke - visitInvokeBlock = visitInvoke - # Utility methods. def new_instance(self, node, reason, target, type): @@ -505,9 +541,11 @@ # Provide the correct namespace for the invocation. - if isinstance(invoke, InvokeBlock): + if getattr(invoke, "share_locals", 0): namespace = Namespace() namespace.merge_namespace(self.namespace) + elif getattr(target, "structure", None): + namespace = Namespace() else: items = self.make_items(invoke, target, context) namespace = self.make_namespace(items) @@ -523,15 +561,18 @@ self.namespace.set_types(self.last_returns) self.annotate(invoke) - # Otherwise, if it is a normal block, merge the locals. + # Otherwise, assuming it is a normal block, merge the locals. - elif isinstance(invoke, InvokeBlock): + elif getattr(invoke, "share_locals", 0): for locals in self.returned_locals: self.namespace.merge_namespace(locals) def process_args(self, invocation): - "Process the arguments associated with an 'invocation'." + """ + Process the arguments associated with an 'invocation'. Return whether + any arguments were processed. + """ invocation.pos_args = self.dispatches(invocation.pos_args) invocation.kw_args = self.dispatch_dict(invocation.kw_args) @@ -548,6 +589,11 @@ default = self.dispatch(default) invocation.dstar = param, default + if invocation.pos_args or invocation.kw_args or invocation.star or invocation.dstar: + return 1 + else: + return 0 + def make_items(self, invocation, subprogram, context): """ @@ -732,6 +778,7 @@ self.names = {} self.returns = [] self.return_locals = [] + self.raises = [] self.temp = {} self.types = [] diff -r 7d18913dbebc -r 6319a2435d8c fixnames.py --- a/fixnames.py Sat Oct 28 00:20:33 2006 +0200 +++ b/fixnames.py Sat Oct 28 00:22:32 2006 +0200 @@ -129,7 +129,7 @@ # Internal subprograms are skipped here and processed specially via # Invoke nodes. - if not getattr(subprogram, "acquire_locals", 0): + if not getattr(subprogram, "internal", 0): self.subprograms.append(self.process_node(subprogram)) # Ultimately, we redefine the list of subprograms on the visitor. diff -r 7d18913dbebc -r 6319a2435d8c simplified.py --- a/simplified.py Sat Oct 28 00:20:33 2006 +0200 +++ b/simplified.py Sat Oct 28 00:22:32 2006 +0200 @@ -228,8 +228,8 @@ if hasattr(self, "dstar") and self.dstar: name, default = self.dstar self._pprint(indent + 2, "( ", "%s default %s" % (name, default), stream=stream) - if getattr(self, "acquire_locals", 0): - self._pprint(indent + 2, "( ", "acquiring locals", stream=stream) + if getattr(self, "internal", 0): + self._pprint(indent + 2, "( ", "internal", stream=stream) if getattr(self, "structure", 0): self._pprint(indent + 2, "( ", "structure '%s'" % self.structure.name, stream=stream) @@ -309,9 +309,10 @@ "A function or method invocation." def __init__(self, *args, **kw): - Node.__init__(self, *args, **kw) + Invoke.__init__(self, *args, **kw) if hasattr(self, "args"): self.set_args(self.args) + self.share_locals = 0 def set_args(self, args): @@ -332,7 +333,13 @@ else: raise TypeError, "Positional argument appears after keyword arguments in '%s'." % self -class InvokeBlock(Invoke): "A block or loop invocation." +class InvokeBlock(Invoke): + + "A block or loop invocation." + + def __init__(self, *args, **kw): + self.share_locals = 1 + Invoke.__init__(self, *args, **kw) # Named nodes are those which can be referenced in some way. diff -r 7d18913dbebc -r 6319a2435d8c simplify.py --- a/simplify.py Sat Oct 28 00:20:33 2006 +0200 +++ b/simplify.py Sat Oct 28 00:22:32 2006 +0200 @@ -213,11 +213,20 @@ return result def visitRaise(self, raise_): - result = Raise(raise_, 1, expr=self.dispatch(raise_.expr1), traceback=None) - if raise_.expr2 is not None: - result.args = [self.dispatch(raise_.expr2)] + result = Raise(raise_, 1) + if raise_.expr2 is None: + result.expr = self.dispatch(raise_.expr1) + else: + result.expr = InvokeFunction( + expr=self.dispatch(raise_.expr1), + args=[self.dispatch(raise_.expr2)], + star=None, + dstar=None + ) if raise_.expr3 is not None: result.traceback = self.dispatch(raise_.expr3) + else: + result.traceback = None return result def _visitBuiltin(self, builtin, name): @@ -398,7 +407,7 @@ (else) -> ... """ - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None) + subprogram = Subprogram(name=None, internal=1, returns_value=1, params=[], star=None, dstar=None) self.current_subprograms.append(subprogram) # In the subprogram, make instructions which invoke a method on the @@ -503,7 +512,7 @@ (else) -> ... """ - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None) + subprogram = Subprogram(name=None, internal=1, returns_value=1, params=[], star=None, dstar=None) self.current_subprograms.append(subprogram) # In the subprogram, make instructions which store each operand, test @@ -563,7 +572,7 @@ (else) -> ... """ - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=1, params=[], star=None, dstar=None) + subprogram = Subprogram(name=None, internal=1, returns_value=1, params=[], star=None, dstar=None) self.current_subprograms.append(subprogram) # In the subprogram, make instructions which store each operand, test @@ -1030,6 +1039,7 @@ expr=LoadRef(ref=structure) ), InvokeBlock( + share_locals=0, expr=LoadRef(ref=subprogram) ) ] @@ -1106,7 +1116,7 @@ (dstar) """ - subprogram = Subprogram(name=function.name, acquire_locals=0, returns_value=1, star=None, dstar=None) + subprogram = Subprogram(name=function.name, internal=0, returns_value=1, star=None, dstar=None) self.current_subprograms.append(subprogram) subprogram.code = self.dispatch(function.code) + [Return()] self.current_subprograms.pop() @@ -1122,7 +1132,7 @@ # Make a subprogram for the function and record it outside the main # tree. - subprogram = Subprogram(name=None, acquire_locals=0, returns_value=1, star=None, dstar=None) + subprogram = Subprogram(name=None, internal=0, returns_value=1, star=None, dstar=None) self.current_subprograms.append(subprogram) subprogram.code = [Return(expr=self.dispatch(lambda_.code))] self.current_subprograms.pop() @@ -1157,7 +1167,7 @@ (else) -> ... """ - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None) + subprogram = Subprogram(name=None, internal=1, returns_value=0, params=[], star=None, dstar=None) self.current_subprograms.append(subprogram) # Include a conditional statement in the subprogram. @@ -1213,7 +1223,7 @@ (else) -> ... """ - subprogram = Subprogram(name=None, acquire_locals=1, returns_value=0, params=[], star=None, dstar=None) + subprogram = Subprogram(name=None, internal=1, returns_value=0, params=[], star=None, dstar=None) self.current_subprograms.append(subprogram) # Always return from conditional sections/subprograms. @@ -1246,8 +1256,9 @@ # Inside the conditional, add a recursive invocation to the subprogram # if the test condition was satisfied. - continuation = InvokeBlock() - continuation.expr = LoadRef(ref=subprogram) + continuation = InvokeBlock( + expr=LoadRef(ref=subprogram) + ) try_except.body = [assign] + self.dispatch(for_.body) + [continuation] subprogram.code = [try_except, Return()]