1.1 --- a/micropython/trans.py Sat Aug 07 02:06:15 2010 +0200
1.2 +++ b/micropython/trans.py Mon Aug 09 01:23:05 2010 +0200
1.3 @@ -244,6 +244,12 @@
1.4 on the 'extend' instruction.
1.5 """
1.6
1.7 + # Remove any ExtendFrame instructions which do nothing.
1.8 +
1.9 + if self.last_op() is extend:
1.10 + self.remove_op()
1.11 + return
1.12 +
1.13 ntemp = self.max_temp_position + 1
1.14 extend.attr = ntemp + node.unit.local_usage # NOTE: See get_code for similar code.
1.15
1.16 @@ -1055,12 +1061,12 @@
1.17
1.18 self.new_op(CheckFrame((nparams, ndefaults)))
1.19
1.20 - if fn.is_dynamic():
1.21 - self.new_op(LoadTemp(0)) # context provides storage
1.22 - else:
1.23 - self.new_op(LoadFunction(fn))
1.24 + if ndefaults > 0:
1.25 + if fn.is_dynamic():
1.26 + self.new_op(LoadTemp(0)) # context provides storage
1.27 + else:
1.28 + self.new_op(LoadFunction(fn))
1.29
1.30 - if ndefaults > 0:
1.31 self.new_op(FillDefaults((nparams, ndefaults)))
1.32
1.33 # Produce the body.
1.34 @@ -1208,78 +1214,32 @@
1.35 def _visitUnary(self, node):
1.36
1.37 """
1.38 - _t = node.expr
1.39 - try:
1.40 - _result = _t.__pos__()
1.41 - except AttributeError:
1.42 - raise TypeError
1.43 + Invoke the appropriate operator module function for the operation
1.44 + represented by 'node'.
1.45 """
1.46
1.47 - method = unary_methods[node.__class__.__name__]
1.48 + temp_fn = self._getOperatorFunction(node)
1.49 + self._visitUnaryCall(node, temp_fn, node.expr)
1.50 + self.discard_temp(temp_fn)
1.51 +
1.52 + def _visitUnaryCall(self, node, temp_fn, expr):
1.53
1.54 - handler_block = self.new_block()
1.55 - else_block = self.new_block()
1.56 - end_block = self.new_block()
1.57 + """
1.58 + Invoke the appropriate operator module function for the operation
1.59 + represented by 'node', given a 'temp_fn' reference to a function, along
1.60 + with the 'expr' operand node.
1.61 + """
1.62
1.63 # Evaluate and store the operand in temporary storage.
1.64
1.65 - self.dispatch(node.expr)
1.66 + self.dispatch(expr)
1.67 temp = self.optimiser.optimise_temp_storage()
1.68
1.69 - self.new_op(temp)
1.70 -
1.71 - # Try to get the attribute, handling exceptions.
1.72 -
1.73 - self.new_op(PushHandler(handler_block))
1.74 -
1.75 - # Get the method on temp.
1.76 -
1.77 - self._generateAttr(node, method, self.attribute_load_instructions)
1.78 - temp_method = self.optimiser.optimise_temp_storage()
1.79 -
1.80 - # Finish handling any attribute access exceptions.
1.81 -
1.82 - have_handler = self.new_op(PopHandler())
1.83 -
1.84 - # Add arguments.
1.85 - # NOTE: No support for defaults.
1.86 -
1.87 - self._startCallFunc()
1.88 - self.new_op(temp) # Explicit context as first argument.
1.89 - self.new_op(StoreFrame(0))
1.90 - self._endCallFuncArgs(1)
1.91 - self._doCallFunc(temp_method)
1.92 - self._endCallFunc(temp_method)
1.93 -
1.94 - # Store the result.
1.95 -
1.96 - temp_out = self.get_temp()
1.97 - self.new_op(Jump(end_block))
1.98 -
1.99 - # End method attempt.
1.100 -
1.101 - self.set_block(handler_block)
1.102 -
1.103 - if have_handler:
1.104 - self.new_op(PopHandler())
1.105 - self._handleAttributeError(node, temp_method, else_block)
1.106 -
1.107 - # Raise a TypeError.
1.108 -
1.109 - self.set_block(else_block)
1.110 - self.make_exception("TypeError", node)
1.111 - self.new_op(StoreException())
1.112 - self.new_op(RaiseException())
1.113 -
1.114 - # Produce the result.
1.115 -
1.116 - self.set_block(end_block)
1.117 - self.new_op(temp_out)
1.118 + self._generateInvocation(temp_fn, (temp,))
1.119
1.120 # Compilation duties...
1.121
1.122 self.discard_temp(temp)
1.123 - self.discard_temp(temp_out)
1.124
1.125 def _visitBinaryBit(self, node):
1.126
1.127 @@ -1289,36 +1249,34 @@
1.128 bitwise operators.
1.129 """
1.130
1.131 + temp_fn = self._getOperatorFunction(node)
1.132 left = None
1.133
1.134 for right in node.nodes:
1.135 if left is not None:
1.136 - self._visitBinaryMethods(node, left, right)
1.137 + self._visitBinaryCall(node, temp_fn, left, right)
1.138 left = right
1.139
1.140 + self.discard_temp(temp_fn)
1.141 +
1.142 def _visitBinary(self, node):
1.143
1.144 """
1.145 - _t1 = node.left
1.146 - _t2 = node.right
1.147 - try:
1.148 - _result = _t1.__add__(_t2)
1.149 - if _result is NotImplemented:
1.150 - raise AttributeError
1.151 - except AttributeError:
1.152 - try:
1.153 - _result = _t2.__radd__(_t1)
1.154 - if _result is NotImplemented:
1.155 - raise AttributeError
1.156 - except AttributeError:
1.157 - raise TypeError
1.158 + Invoke the appropriate operator module function for the operation
1.159 + represented by 'node'.
1.160 """
1.161
1.162 - self._visitBinaryMethods(node, node.left, node.right)
1.163 + temp_fn = self._getOperatorFunction(node)
1.164 + self._visitBinaryCall(node, temp_fn, node.left, node.right)
1.165 + self.discard_temp(temp_fn)
1.166 +
1.167 + def _visitBinaryCall(self, node, temp_fn, left, right):
1.168
1.169 - def _visitBinaryMethods(self, node, left, right):
1.170 -
1.171 - left_method, right_method = binary_methods[node.__class__.__name__]
1.172 + """
1.173 + Invoke the appropriate operator module function for the operation
1.174 + represented by 'node', given a 'temp_fn' reference to a function, along
1.175 + with the 'left' and 'right' operand nodes.
1.176 + """
1.177
1.178 # Evaluate and store the left operand in temporary storage.
1.179
1.180 @@ -1330,117 +1288,59 @@
1.181 self.dispatch(right)
1.182 temp2 = self.optimiser.optimise_temp_storage()
1.183
1.184 - temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method)
1.185 -
1.186 - # Produce the result.
1.187 -
1.188 - self.new_op(temp_out)
1.189 + self._generateInvocation(temp_fn, (temp1, temp2))
1.190
1.191 # Compilation duties...
1.192
1.193 self.discard_temp(temp1)
1.194 self.discard_temp(temp2)
1.195 - self.discard_temp(temp_out)
1.196
1.197 - def _generateBinary(self, node, temp1, temp2, left_method, right_method):
1.198 -
1.199 - """
1.200 - For the given 'node', generate the binary operator pattern for the
1.201 - operands 'temp1' and 'temp2', employing 'left_method' and 'right_method'
1.202 - as defined for binary operators, but also used in comparisons (for which
1.203 - this method is provided).
1.204 -
1.205 - A temporary storage reference is returned from this method.
1.206 - """
1.207 -
1.208 - right_block = self.new_block()
1.209 - left_else_block = self.new_block()
1.210 - right_else_block = self.new_block()
1.211 - end_block = self.new_block()
1.212 -
1.213 - # Left method.
1.214 -
1.215 - temp_out = self._generateOpMethod(node, temp1, temp2, left_method, left_else_block, right_block, end_block)
1.216 - self.discard_temp(temp_out) # NOTE: Will re-use the same storage.
1.217 -
1.218 - self.set_block(left_else_block)
1.219 - self.new_op(ClearException())
1.220 -
1.221 - # Right method.
1.222 -
1.223 - self.set_block(right_block)
1.224 - temp_out = self._generateOpMethod(node, temp2, temp1, right_method, right_else_block, right_else_block, end_block)
1.225 -
1.226 - # Raise a TypeError.
1.227 -
1.228 - self.set_block(right_else_block)
1.229 - self.make_exception("TypeError", node)
1.230 - self.new_op(StoreException())
1.231 - self.new_op(RaiseException())
1.232 -
1.233 - self.set_block(end_block)
1.234 - return temp_out
1.235 -
1.236 - def _generateOpMethod(self, node, temp1, temp2, method_name, handled_block, next_method_block, end_block):
1.237 + def _generateInvocation(self, temp_fn, temp_list):
1.238
1.239 """
1.240 - For the given 'node', generate the operator method invocation using the
1.241 - operands 'temp1' and 'temp2', employing the given 'method_name', and
1.242 - jumping appropriately to 'handled_block' where an AttributeError was
1.243 - handled, to 'next_method_block' where a NotImplemented result is
1.244 - returned, or to 'end_block' if the method call was successful.
1.245 -
1.246 - A temporary storage reference is returned from this method.
1.247 + Invoke the function 'temp_fn' using the operands from 'temp_list' as
1.248 + arguments.
1.249 """
1.250
1.251 - handler_block = self.new_block()
1.252 -
1.253 - # Try to get the attribute, handling exceptions.
1.254 -
1.255 - self.new_op(PushHandler(handler_block))
1.256 - self.new_op(temp1)
1.257 -
1.258 - # Get method on temp1.
1.259 -
1.260 - self._generateAttr(node, method_name, self.attribute_load_instructions)
1.261 - temp_method = self.optimiser.optimise_temp_storage()
1.262 -
1.263 - # Finish handling any attribute access exceptions.
1.264 -
1.265 - have_handler = self.new_op(PopHandler())
1.266 -
1.267 - # Add arguments.
1.268 - # NOTE: No support for defaults.
1.269 -
1.270 self._startCallFunc()
1.271 - self.new_op(temp1)
1.272 - self.new_op(StoreFrame(0))
1.273 - self.new_op(temp2)
1.274 - self.new_op(StoreFrame(1))
1.275 - self._endCallFuncArgs(2)
1.276 - self._doCallFunc(temp_method)
1.277 - self._endCallFunc(temp_method)
1.278 +
1.279 + for i, temp in enumerate(temp_list):
1.280 + self.new_op(temp)
1.281 + self.new_op(StoreFrame(i))
1.282
1.283 - # Store the result.
1.284 + self._endCallFuncArgs(len(temp_list))
1.285 + self._doCallFunc(temp_fn)
1.286 + self._endCallFunc(temp_fn)
1.287 +
1.288 + def _getOperatorFunction(self, node):
1.289
1.290 - temp_out = self.get_temp()
1.291 + "Return an operator function reference for the given 'node'."
1.292 +
1.293 + return self._generateOperatorFunction(node.__class__.__name__)
1.294 +
1.295 + def _getOperatorAugAssignFunction(self, node):
1.296
1.297 - # Test for NotImplemented.
1.298 - # Don't actually raise an exception.
1.299 + """
1.300 + Return an operator augmented assignment function reference for the given
1.301 + 'node'.
1.302 + """
1.303
1.304 - self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("NotImplemented")))
1.305 - self.new_op(JumpIfTrue(next_method_block))
1.306 - self.new_op(Jump(end_block))
1.307 + return self._generateOperatorFunction(node.op)
1.308 +
1.309 + def _generateOperatorFunction(self, opname):
1.310 +
1.311 + "Return an operator function reference for the given 'opname'."
1.312
1.313 - # End method attempt.
1.314 + operator_fn = operator_functions[opname]
1.315
1.316 - self.set_block(handler_block)
1.317 + # Get the operator module.
1.318
1.319 - if have_handler:
1.320 - self.new_op(PopHandler())
1.321 - self._handleAttributeError(node, temp_method, handled_block)
1.322 + operator_module = self.importer.get_module("operator")
1.323
1.324 - return temp_out
1.325 + # Get the appropriate function from the operator module.
1.326 +
1.327 + self.new_op(LoadAddress(operator_module[operator_fn]))
1.328 + return self.optimiser.optimise_temp_storage()
1.329
1.330 def _handleAttributeError(self, node, temp_method, handled_block):
1.331
1.332 @@ -1515,12 +1415,7 @@
1.333 self._generateAttr(node, "__bool__", self.attribute_load_instructions)
1.334 temp_method = self.optimiser.optimise_temp_storage()
1.335
1.336 - self._startCallFunc()
1.337 - self.new_op(temp)
1.338 - self.new_op(StoreFrame(0))
1.339 - self._endCallFuncArgs(1)
1.340 - self._doCallFunc(temp_method)
1.341 - self._endCallFunc(temp_method)
1.342 + self._generateInvocation(temp_method, (temp,))
1.343
1.344 self.discard_temp(temp_method)
1.345