# HG changeset patch # User Paul Boddie # Date 1222039974 -7200 # Node ID e267cf7cc9be2c85efc8f58580a4a1421acd7cc2 # Parent a57568d6dfc85306d3b5ef2d0fc1b178329602f4 Added some support for augmented assignment. Attempted to fix unary and binary operations to actually produce results: the result from each successful call was not being retained and produced for further use. diff -r a57568d6dfc8 -r e267cf7cc9be micropython/ast.py --- a/micropython/ast.py Sun Sep 21 21:48:17 2008 +0200 +++ b/micropython/ast.py Mon Sep 22 01:32:54 2008 +0200 @@ -1248,7 +1248,7 @@ raise TypeError """ - end_call_label = self.new_label() + type_error_label = self.new_label() end_label = self.new_label() # Evaluate and store the operand in temporary storage. @@ -1256,9 +1256,6 @@ self.dispatch(node.expr) temp = self.optimiser.optimise_temp_storage() - # Produce the invocation. - - self._startCallFunc() self.new_op(temp) # Get the method on temp. @@ -1266,7 +1263,7 @@ self._generateAttr(node, method, self.attribute_load_instructions) temp_method = self.optimiser.optimise_temp_storage() - self._handleAttributeError(node, end_call_label) + self._handleAttributeError(node, type_error_label) # Add arguments. # NOTE: No support for defaults. @@ -1278,19 +1275,23 @@ self._endCallFunc(temp_method) self.new_op(Jump(end_label)) - # End method attempt. - - self.set_label(end_call_label) - self._endCallFunc() # From the method call. + # Store the result. + + temp_out = self.get_temp() # Raise a TypeError. + self.set_label(type_error_label) self.load_builtin("TypeError", node) self.new_op(StoreException()) self.new_op(RaiseException()) self.set_label(end_label) + # Produce the result. + + self.new_op(temp_out) + # Compilation duties... self.discard_temp(temp) @@ -1323,7 +1324,11 @@ self.dispatch(node.right) temp2 = self.optimiser.optimise_temp_storage() - self._generateBinary(node, temp1, temp2, left_method, right_method) + temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) + + # Produce the result. + + self.new_op(temp_out) # Compilation duties... @@ -1345,12 +1350,13 @@ # Left method. - self._generateOpMethod(node, temp1, temp2, left_method, right_label, end_label) + temp_out = self._generateOpMethod(node, temp1, temp2, left_method, right_label, end_label) + self.discard_temp(temp_out) # NOTE: Will re-use the same storage. # Right method. self.set_label(right_label) - self._generateOpMethod(node, temp2, temp1, right_method, type_error_label, end_label) + temp_out = self._generateOpMethod(node, temp2, temp1, right_method, type_error_label, end_label) # Raise a TypeError. @@ -1360,6 +1366,7 @@ self.new_op(RaiseException()) self.set_label(end_label) + return temp_out def _generateOpMethod(self, node, temp1, temp2, method_name, next_method_label, end_label): @@ -1393,6 +1400,10 @@ self._doCallFunc(temp_method) self._endCallFunc(temp_method) + # Store the result. + + temp_out = self.get_temp() + # Test for NotImplemented. # Don't actually raise an exception. @@ -1403,6 +1414,7 @@ # End method attempt. self.set_label(end_attempt_label) + return temp_out def _handleAttributeError(self, node, end_call_label): @@ -1556,7 +1568,50 @@ visitAssTuple = visitAssList - def visitAugAssign(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign") + def visitAugAssign(self, node): + use_binary_label = self.new_label() + end_label = self.new_label() + + # Evaluate the expression. + + self.dispatch(node.expr) + temp2 = self.optimiser.optimise_temp_storage() + + # Evaluate the target. + + self.dispatch(node.node) + temp1 = self.optimiser.optimise_temp_storage() + + # Find the augmented assignment method and attempt to use it. + + aug_method, (left_method, right_method) = self.augassign_methods[node.op] + temp_out = self._generateOpMethod(node, temp1, temp2, aug_method, use_binary_label, end_label) + self.discard_temp(temp_out) # NOTE: Will re-use the same storage. + + # Where no such method exists, use the binary operator methods. + + self.set_label(use_binary_label) + temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) + + # Assign the result to the name. + + self.set_label(end_label) + self.new_op(temp_out) + self.record_value(1) + + if isinstance(node.node, compiler.ast.Name): + self.visitAssName(node.node) + elif isinstance(node.node, compiler.ast.Getattr): + self.visitAssAttr(node.node) + else: + raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign(Slice or Subscript)") + + self.discard_value() + + # Compilation duties... + + self.discard_temp(temp1) + self.discard_temp(temp2) def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote") @@ -1614,8 +1669,6 @@ """ end_label = self.new_label() - temp_pos = self.reserve_temp() - temp_result = LoadTemp(temp_pos) self.dispatch(node.expr) temp2 = self.optimiser.optimise_temp_storage() @@ -1638,9 +1691,9 @@ # Generate method call using evaluated argument and next node. - self._generateBinary(node, temp1, temp2, left_method, right_method) - self.new_op(StoreTemp(temp_pos)) + temp_result = self._generateBinary(node, temp1, temp2, left_method, right_method) self._generateTestBoolean(node, temp_result) + self.discard_temp(temp_result) else: # Deal with the special operators. @@ -1673,8 +1726,9 @@ self._doCallFunc(temp_method) self._endCallFunc(temp_method) - self.new_op(StoreTemp(temp_pos)) + temp_result = self.get_temp() self._generateTestBoolean(node, temp_result) + self.discard_temp(temp_result) if op_name.find("not") != -1: self.new_op(InvertBoolean()) @@ -1689,7 +1743,6 @@ self.discard_temp(temp1) self.discard_temp(temp2) - self.discard_temp(temp_result) self.set_label(end_label) # Yield the appropriate value. @@ -2176,4 +2229,18 @@ "not in" : None } + augassign_methods = { + "+=" : ("__iadd__", ("__add__", "__radd__")), + "-=" : ("__isub__", ("__sub__", "__rsub__")), + "*=" : ("__imul__", ("__mul__", "__rmul__")), + "/=" : ("__idiv__", ("__div__", "__rdiv__")), + "%=" : ("__imod__", ("__mod__", "__rmod__")), + "**=" : ("__ipow__", ("__pow__", "__rpow__")), + "<<=" : ("__ilshift__", ("__lshift__", "__rlshift__")), + ">>=" : ("__irshift__", ("__rshift__", "__rrshift__")), + "&=" : ("__iand__", ("__and__", "__rand__")), + "^=" : ("__ixor__", ("__xor__", "__rxor__")), + "|=" : ("__ior__", ("__or__", "__ror__")) + } + # vim: tabstop=4 expandtab shiftwidth=4 diff -r a57568d6dfc8 -r e267cf7cc9be tests/op_iadd.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/op_iadd.py Mon Sep 22 01:32:54 2008 +0200 @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +def f(a, b): + a += b + +a = 1 +b = 2 +a += b + +# vim: tabstop=4 expandtab shiftwidth=4