# HG changeset patch # User Paul Boddie # Date 1200960426 -3600 # Node ID 7ac7836d9625765ab87027f06243e912f467835f # Parent 560e0317e93535e77a0c094406a6a893e2382284 Added assignments statistics to Attr objects. Redefined StoreFrame to refer to positions within invocation frames, whereas StoreFrameIndex is a more complicated instruction using a parameter index/code together with callable details at run-time. Added a speculative optimisation for "constant" names and attributes involved in invocations. Improved the invocation test case. diff -r 560e0317e935 -r 7ac7836d9625 micropython/ast.py --- a/micropython/ast.py Sat Jan 19 01:06:21 2008 +0100 +++ b/micropython/ast.py Tue Jan 22 01:07:06 2008 +0100 @@ -122,6 +122,9 @@ def new_op(self, op): self.code.append(op) + def last_op(self): + return self.code[-1] + # Visitor methods. def default(self, node, *args): @@ -214,6 +217,14 @@ self.dispatch(node.node) + # NOTE: Only simple cases are used for optimisations. + + last = self.last_op() + if isinstance(last, (LoadName, LoadAttr)) and last.attr.assignments == 1: + target = last.attr.value + else: + target = None + # Evaluate the arguments. positional = 1 @@ -226,15 +237,27 @@ self.dispatch(arg.expr) - # Combine the target details with the name to get the location. - # See the access method on the Table class. + # Optimise where the target is known now. + + if target is not None: + pos = self.paramtable.table[target.full_name()][arg.name] + self.new_op(StoreFrame(pos)) + + # Otherwise, generate the code needed to obtain the details of + # the parameter location. + + else: - paramindex = self.paramtable.get_index(arg.name) - self.new_op(StoreFrame(paramindex)) + # Combine the target details with the name to get the location. + # See the access method on the List class. + + paramindex = self.paramtable.get_index(arg.name) - # use (callable+0)+paramindex+table - # checks embedded offset against (callable+0) - # moves the top of stack to frame+position + self.new_op(StoreFrameIndex(paramindex)) + + # use (callable+0)+paramindex+table + # checks embedded offset against (callable+0) + # moves the top of stack to frame+position else: self.dispatch(arg) diff -r 560e0317e935 -r 7ac7836d9625 micropython/inspect.py --- a/micropython/inspect.py Sat Jan 19 01:06:21 2008 +0100 +++ b/micropython/inspect.py Tue Jan 22 01:07:06 2008 +0100 @@ -131,13 +131,14 @@ "An attribute entry." - def __init__(self, position, parent, value=None): + def __init__(self, position, parent, assignments=None, value=None): self.position = position self.parent = parent + self.assignments = assignments self.value = value def __repr__(self): - return "Attr(%d, %r, %r)" % (self.position, self.parent, self.value) + return "Attr(%d, %r, %r, %r)" % (self.position, self.parent, self.assignments, self.value) class Const: @@ -212,7 +213,7 @@ self.classattr_names = self.keys() for i, name in enumerate(self.classattr_names): - self.classattr[name] = Attr(i, self, self[name]) + self.classattr[name] = Attr(i, self, self.assignments[name], self[name]) return self.classattr @@ -451,7 +452,7 @@ self.modattr = {} self.modattr_names = self.keys() for i, name in enumerate(self.modattr_names): - self.modattr[name] = Attr(i, self, self[name]) + self.modattr[name] = Attr(i, self, self.assignments[name], self[name]) return self.modattr diff -r 560e0317e935 -r 7ac7836d9625 micropython/rsvp.py --- a/micropython/rsvp.py Sat Jan 19 01:06:21 2008 +0100 +++ b/micropython/rsvp.py Tue Jan 22 01:07:06 2008 +0100 @@ -27,30 +27,34 @@ self.attr = attr def __repr__(self): - return "%s(%r)" % (self.__class__.__name__, self.attr) + if self.attr is not None: + return "%s(%r)" % (self.__class__.__name__, self.attr) + else: + return "%s()" % self.__class__.__name__ # Instructions operating on the value stack. -class LoadConst(Instruction): pass +class LoadConst(Instruction): "Load the constant from the specified location." # Access within an invocation frame. -class LoadName(Instruction): pass -class StoreName(Instruction): pass +class LoadName(Instruction): "Load the object from the given local attribute." +class StoreName(Instruction): "Store the object in the given local attribute." # Access to address-relative data. -class MakeObject(Instruction): pass -# ... DropObject not defined: assume garbage collection. -class LoadAttr(Instruction): pass -class StoreAttr(Instruction): pass +class MakeObject(Instruction): "Make a new object." +# ... DropObject not defined: Assume garbage collection. +class LoadAttr(Instruction): "Load the object from the given attribute." +class StoreAttr(Instruction): "Store the object in the given attribute." # Access to invocation frames in preparation. -class MakeFrame(Instruction): pass -class ReserveFrame(Instruction): pass -class DropFrame(Instruction): pass -class StoreFrame(Instruction): pass +class MakeFrame(Instruction): "Make a new invocation frame." +class ReserveFrame(Instruction): "Reserve the given number of entries for the invocation frame." +class DropFrame(Instruction): "Drop an invocation frame." +class StoreFrame(Instruction): "Store an argument at the given frame location." +class StoreFrameIndex(Instruction): "Store an argument for the parameter with the given index." # Invocation-related instructions. diff -r 560e0317e935 -r 7ac7836d9625 tests/call_func.py --- a/tests/call_func.py Sat Jan 19 01:06:21 2008 +0100 +++ b/tests/call_func.py Tue Jan 22 01:07:06 2008 +0100 @@ -7,4 +7,12 @@ f(1, b=2, c=3) f(c=3, b=2, a=1) +g = f +g(1, c=3, b=2) + +def g(a, c, b): + pass + +g(1, c=3, b=2) + # vim: tabstop=4 expandtab shiftwidth=4