1.1 --- a/micropython/ast.py Sun May 04 02:42:03 2008 +0200
1.2 +++ b/micropython/ast.py Sun May 04 20:11:46 2008 +0200
1.3 @@ -184,8 +184,10 @@
1.4 self.unit.stack_temp_usage = max(self.unit.stack_temp_usage, self.temp_position)
1.5 return temp_position
1.6
1.7 - def discard_temp(self, n):
1.8 - self.temp_position -= n
1.9 + def discard_temp(self, instructions):
1.10 + for temp in instructions:
1.11 + if isinstance(temp, LoadTemp):
1.12 + self.temp_position -= 1
1.13
1.14 def new_op(self, op):
1.15
1.16 @@ -315,6 +317,10 @@
1.17 else:
1.18 target, context = None, None
1.19
1.20 + # Store the target in temporary storage for subsequent referencing.
1.21 +
1.22 + temp = self._optimise_temp_storage()
1.23 +
1.24 # Where a target is known and has a known context, avoid generating any
1.25 # first argument. Instance methods do not have a known target since they
1.26 # are accessed via an instance whose identity cannot generally be known
1.27 @@ -472,16 +478,19 @@
1.28 else:
1.29 self.new_op(CheckFrame())
1.30
1.31 - def _endCallFunc(self):
1.32 + return temp
1.33 +
1.34 + def _endCallFunc(self, temp):
1.35
1.36 "Make the invocation and tidy up afterwards."
1.37
1.38 - self.new_op(LoadCallable()) # uses the start of the frame to get the callable
1.39 + self.new_op(temp)
1.40 self.new_op(JumpWithFrame())
1.41
1.42 # NOTE: Exception handling required.
1.43
1.44 self.new_op(DropFrame())
1.45 + self.discard_temp([temp])
1.46
1.47 def _visitName(self, node, classes):
1.48
1.49 @@ -580,9 +589,12 @@
1.50
1.51 """
1.52 Where the next operation would involve storing a value into temporary
1.53 - storage, record and remove any simple instruction which produced the
1.54 - value such that instead of subsequently accessing the temporary storage,
1.55 - that instruction is substituted.
1.56 + storage at 'temp_position', record and remove any simple instruction
1.57 + which produced the value to be stored such that instead of subsequently
1.58 + accessing the temporary storage, that instruction is substituted.
1.59 +
1.60 + If no optimisation can be achieved, a StoreTemp instruction is produced
1.61 + and the appropriate LoadTemp instruction is returned.
1.62 """
1.63
1.64 if self._should_optimise_temp_storage() and \
1.65 @@ -592,7 +604,9 @@
1.66 self.remove_ops(1)
1.67 return last
1.68 else:
1.69 - return None
1.70 + temp_position = self.reserve_temp(1)
1.71 + self.new_op(StoreTemp(temp_position))
1.72 + return LoadTemp(temp_position)
1.73
1.74 def _optimise_constant_storage(self, instruction, n):
1.75
1.76 @@ -703,23 +717,15 @@
1.77 type_error_label = self.new_label()
1.78 end_label = self.new_label()
1.79
1.80 - # NOTE: Potentially remove the reservation if optimised storage is used.
1.81 -
1.82 - temp_position = self.reserve_temp(2)
1.83 + # Evaluate and store the left operand in temporary storage.
1.84
1.85 self.dispatch(node.left)
1.86 + temp1 = self._optimise_temp_storage()
1.87
1.88 - temp1 = self._optimise_temp_storage()
1.89 - if not temp1:
1.90 - self.new_op(StoreTemp(temp_position))
1.91 - temp1 = LoadTemp(temp_position)
1.92 + # Evaluate and store the right operand in temporary storage.
1.93
1.94 self.dispatch(node.right)
1.95 -
1.96 temp2 = self._optimise_temp_storage()
1.97 - if not temp2:
1.98 - self.new_op(StoreTemp(temp_position + 1))
1.99 - temp2 = LoadTemp(temp_position + 1)
1.100
1.101 # Left method.
1.102
1.103 @@ -729,6 +735,7 @@
1.104 # Get left method on temp1.
1.105
1.106 self._generateAttr(node, left_method, (LoadAddress, LoadAttr, LoadAttrIndex))
1.107 + temp_method = self._optimise_temp_storage()
1.108
1.109 if not self._optimise_known_target():
1.110 self.dispatch(compiler.ast.Name("AttributeError"))
1.111 @@ -739,7 +746,7 @@
1.112
1.113 self.new_op(temp1) # Explicit context as first argument.
1.114 self.new_op(temp2)
1.115 - self._endCallFunc()
1.116 + self._endCallFunc(temp_method)
1.117
1.118 # Test for NotImplemented.
1.119 # Don't actually raise an exception.
1.120 @@ -764,6 +771,7 @@
1.121 # Get right method on temp2.
1.122
1.123 self._generateAttr(node, right_method, (LoadAddress, LoadAttr, LoadAttrIndex))
1.124 + temp_method = self._optimise_temp_storage()
1.125
1.126 if not self._optimise_known_target():
1.127 self.dispatch(compiler.ast.Name("AttributeError"))
1.128 @@ -774,7 +782,7 @@
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 + self._endCallFunc(temp_method)
1.134
1.135 # Test for NotImplemented.
1.136 # Don't actually raise an exception.
1.137 @@ -796,7 +804,7 @@
1.138 # Compilation duties...
1.139 # NOTE: Potentially remove this when optimised away.
1.140
1.141 - self.discard_temp(2)
1.142 + self.discard_temp([temp1, temp2])
1.143
1.144 def visitAdd(self, node):
1.145 self._visitBinary(node, "__add__", "__radd__")
1.146 @@ -845,8 +853,8 @@
1.147
1.148 self._startCallFunc()
1.149 self.dispatch(node.node)
1.150 - self._generateCallFunc(node.args, node)
1.151 - self._endCallFunc()
1.152 + temp = self._generateCallFunc(node.args, node)
1.153 + self._endCallFunc(temp)
1.154
1.155 def visitClass(self, node):
1.156 unit = self.unit
1.157 @@ -905,8 +913,8 @@
1.158 self._startCallFunc()
1.159 self.dispatch(node.list)
1.160 self._generateAttr(node, "__iter__", (LoadAddress, LoadAttr, LoadAttrIndex))
1.161 - self._generateCallFunc([], node)
1.162 - self._endCallFunc()
1.163 + temp = self._generateCallFunc([], node)
1.164 + self._endCallFunc(temp)
1.165
1.166 # Iterator on stack.
1.167
1.168 @@ -919,8 +927,8 @@
1.169 self._startCallFunc()
1.170 self.new_op(Duplicate())
1.171 self._generateAttr(node, "next", (LoadAddress, LoadAttr, LoadAttrIndex))
1.172 - self._generateCallFunc([], node)
1.173 - self._endCallFunc()
1.174 + temp = self._generateCallFunc([], node)
1.175 + self._endCallFunc(temp)
1.176
1.177 # Test for StopIteration.
1.178