1.1 --- a/micropython/ast.py Mon Apr 28 21:19:42 2008 +0200
1.2 +++ b/micropython/ast.py Fri May 02 01:47:19 2008 +0200
1.3 @@ -48,7 +48,7 @@
1.4
1.5 "A translated module."
1.6
1.7 - supported_optimisations = ["constant_storage", "known_target", "self_access", "temp_storage"]
1.8 + supported_optimisations = ["constant_storage", "known_target", "self_access", "temp_storage", "constant_test"]
1.9
1.10 def __init__(self, module, importer, optimisations=None):
1.11
1.12 @@ -541,6 +541,9 @@
1.13 def _should_optimise_constant_storage(self):
1.14 return "constant_storage" in self.optimisations
1.15
1.16 + def _should_optimise_constant_test(self):
1.17 + return "constant_test" in self.optimisations
1.18 +
1.19 def _should_optimise_known_target(self):
1.20 return "known_target" in self.optimisations
1.21
1.22 @@ -568,7 +571,7 @@
1.23 last = self.last_op()
1.24 # NOTE: Should expand to cover LoadAttr and LoadAttrIndex, but this
1.25 # NOTE: would require inspection of the stack operands.
1.26 - return isinstance(last, (LoadName, LoadTemp, LoadAddress))
1.27 + return isinstance(last, (LoadName, LoadTemp, LoadAddress, LoadConst))
1.28
1.29 # Optimisation methods. See the supported_optimisations class attribute.
1.30
1.31 @@ -607,6 +610,24 @@
1.32 else:
1.33 return 0
1.34
1.35 + def _optimise_constant_test(self, instruction):
1.36 +
1.37 + """
1.38 + Where this operation tests the topmost stack value which happens to be
1.39 + a constant against another stack value, merge the last instruction which
1.40 + loaded the constant into the current 'instruction'.
1.41 + """
1.42 +
1.43 + if self._should_optimise_constant_test() and \
1.44 + instruction is TestIdentity and \
1.45 + self._have_constant_input(0):
1.46 +
1.47 + last = self.last_op()
1.48 + self.replace_op(TestIdentityAddress(last.attr))
1.49 + return 1
1.50 + else:
1.51 + return 0
1.52 +
1.53 def _optimise_known_target(self):
1.54
1.55 """
1.56 @@ -666,12 +687,21 @@
1.57 _t1 = node.left
1.58 _t2 = node.right
1.59 try:
1.60 - _t1.__add__(_t2)
1.61 + _result = _t1.__add__(_t2)
1.62 + if _result is NotImplemented:
1.63 + raise AttributeError
1.64 except AttributeError:
1.65 - _t2.__radd__(_t1)
1.66 + try:
1.67 + _result = _t2.__radd__(_t1)
1.68 + if _result is NotImplemented:
1.69 + raise AttributeError
1.70 + except AttributeError:
1.71 + raise TypeError
1.72 """
1.73
1.74 + end_left_label = self.new_label()
1.75 right_label = self.new_label()
1.76 + type_error_label = self.new_label()
1.77 end_label = self.new_label()
1.78
1.79 # NOTE: Potentially remove the reservation if optimised storage is used.
1.80 @@ -696,27 +726,73 @@
1.81
1.82 self._startCallFunc()
1.83 self.new_op(temp1)
1.84 +
1.85 + # Get left method on temp1.
1.86 +
1.87 self._generateAttr(node, left_method, (LoadAddress, LoadAttr, LoadAttrIndex))
1.88 + self.dispatch(compiler.ast.Name("AttributeError"))
1.89 + self.new_op(CheckException())
1.90 + self.new_op(JumpIfTrue(end_left_label))
1.91 +
1.92 + # Add arguments.
1.93 +
1.94 self.new_op(temp1) # Explicit context as first argument.
1.95 self.new_op(temp2)
1.96 self._endCallFunc()
1.97
1.98 - self.dispatch(compiler.ast.Name("AttributeError"))
1.99 - self.new_op(CheckException())
1.100 - self.new_op(JumpIfFalse(end_label))
1.101 + # Test for NotImplemented.
1.102 + # Don't actually raise an exception.
1.103 +
1.104 + self.dispatch(compiler.ast.Name("NotImplemented"))
1.105 + if not self._optimise_constant_test(TestIdentity):
1.106 + self.new_op(TestIdentity())
1.107 + self.new_op(JumpIfTrue(right_label))
1.108 + self.new_op(Jump(end_label))
1.109 +
1.110 + # End left method attempt.
1.111 +
1.112 + self.set_label(end_left_label)
1.113 + self.new_op(DropFrame()) # From the left method call.
1.114
1.115 # Right method.
1.116
1.117 self.set_label(right_label)
1.118 self._startCallFunc()
1.119 self.new_op(temp2)
1.120 +
1.121 + # Get right method on temp2.
1.122 +
1.123 self._generateAttr(node, right_method, (LoadAddress, LoadAttr, LoadAttrIndex))
1.124 + self.dispatch(compiler.ast.Name("AttributeError"))
1.125 + self.new_op(CheckException())
1.126 + self.new_op(JumpIfTrue(type_error_label))
1.127 +
1.128 + # Add arguments.
1.129 +
1.130 self.new_op(temp2) # Explicit context as first argument.
1.131 self.new_op(temp1)
1.132 self._endCallFunc()
1.133
1.134 + # Test for NotImplemented.
1.135 + # Don't actually raise an exception.
1.136 +
1.137 + self.dispatch(compiler.ast.Name("NotImplemented"))
1.138 + if not self._optimise_constant_test(TestIdentity):
1.139 + self.new_op(TestIdentity())
1.140 + self.new_op(JumpIfTrue(type_error_label))
1.141 + self.new_op(Jump(end_label))
1.142 +
1.143 + # Raise a TypeError.
1.144 +
1.145 + self.set_label(type_error_label)
1.146 + self.dispatch(compiler.ast.Name("TypeError"))
1.147 + self.new_op(RaiseException())
1.148 +
1.149 self.set_label(end_label)
1.150
1.151 + # Compilation duties...
1.152 + # NOTE: Potentially remove this when optimised away.
1.153 +
1.154 self.discard_temp(2)
1.155
1.156 def visitAdd(self, node):
2.1 --- a/micropython/rsvp.py Mon Apr 28 21:19:42 2008 +0200
2.2 +++ b/micropython/rsvp.py Fri May 02 01:47:19 2008 +0200
2.3 @@ -157,4 +157,9 @@
2.4 class Return(Instruction): "Return a value from a subprogram."
2.5 class CheckException(Instruction): "Check the raised exception against another."
2.6
2.7 +# General instructions.
2.8 +
2.9 +class TestIdentity(Instruction): "Test whether the two topmost stack values are identical."
2.10 +class TestIdentityAddress(Address): "Test whether the topmost stack value is identical to the given address."
2.11 +
2.12 # vim: tabstop=4 expandtab shiftwidth=4