# HG changeset patch # User Paul Boddie # Date 1219521449 -7200 # Node ID 8ee002746854476408354a9ae1d13486687d225b # Parent 146c1f0da0d1e0e731910bf7acbff1023d2066d8 Fixed temp allocation, hopefully. Changed usage of _generateTestBoolean to involve a pre-allocated temporary storage slot. This also helps to resolve issues with logical operations, since the current value was previously being implicitly used to communicate the result of such operations. Split the logical test program into two. diff -r 146c1f0da0d1 -r 8ee002746854 micropython/ast.py --- a/micropython/ast.py Sat Aug 23 02:41:55 2008 +0200 +++ b/micropython/ast.py Sat Aug 23 21:57:29 2008 +0200 @@ -235,8 +235,7 @@ sequence of access instructions. """ - temp_position = self.reserve_temp() - position_in_frame = self.unit.local_usage + temp_position + position_in_frame = self.reserve_temp() self.new_op(StoreTemp(position_in_frame)) return LoadTemp(position_in_frame) @@ -247,12 +246,16 @@ temp_position = max(self.temp_positions) + 1 self.temp_positions.add(temp_position) self.max_temp_position = max(self.max_temp_position, temp_position) - return temp_position + return self.unit.local_usage + temp_position # position in frame def discard_temp(self, instruction=None): if isinstance(instruction, LoadTemp): - position_in_frame = instruction.attr - self.unit.local_usage - self.temp_positions.remove(position_in_frame) + temp_position = instruction.attr - self.unit.local_usage + self.free_temp(temp_position) + + def free_temp(self, temp_position): + if temp_position in self.temp_positions: + self.temp_positions.remove(temp_position) # Code writing methods. @@ -313,6 +316,13 @@ except IndexError: return None + def clear_active(self): + + "Prevent incorrect optimisation." + + self.active = None + self.active_value = None + # Optimisation tests. def _should_optimise_constant_storage(self): @@ -1302,15 +1312,13 @@ self.new_op(temp) self.discard_temp(temp) - def _generateTestBoolean(self, node): + def _generateTestBoolean(self, node, temp): """ Generate a test of the boolean status of the current value for the given program 'node'. """ - temp = self._optimise_temp_storage() - # Get method on temp. # NOTE: Using __bool__ instead of __nonzero__. @@ -1324,6 +1332,8 @@ self._doCallFunc(temp_method) self._endCallFunc(temp_method) + self.discard_temp(temp_method) + # Convert result to boolean (a StoreBoolean operation). self.new_op(TestIdentityAddress(self.get_builtin("True", node))) @@ -1353,20 +1363,28 @@ self._visitBinary(node, "__add__", "__radd__") def visitAnd(self, node): - next_label = self.new_label() + end_label = self.new_label() + temp_pos = self.reserve_temp() + temp = LoadTemp(temp_pos) for n in node.nodes[:-1]: self.dispatch(n) - self._generateTestBoolean(n) - self.new_op(JumpIfFalse(next_label)) + self.new_op(StoreTemp(temp_pos)) + + self._generateTestBoolean(n, temp) + self.new_op(JumpIfFalse(end_label)) self.dispatch(node.nodes[-1]) - self.set_label(next_label) + self.new_op(StoreTemp(temp_pos)) + + self.set_label(end_label) # Prevent incorrect optimisation. - self.active = None - self.active_value = None + self.clear_active() + + self.new_op(temp) + self.discard_temp(temp) def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert") @@ -1449,6 +1467,8 @@ """ end_label = self.new_label() + temp_pos = self.reserve_temp() + temp_result = LoadTemp(temp_pos) self.dispatch(node.expr) temp2 = self._optimise_temp_storage() @@ -1472,7 +1492,8 @@ # Generate method call using evaluated argument and next node. self._generateBinary(node, temp1, temp2, left_method, right_method) - self._generateTestBoolean(node) + self.new_op(StoreTemp(temp_pos)) + self._generateTestBoolean(node, temp_result) else: # Deal with the special operators. @@ -1504,7 +1525,9 @@ self._endCallFuncArgs(2) self._doCallFunc(temp_method) self._endCallFunc(temp_method) - self._generateTestBoolean(node) + + self.new_op(StoreTemp(temp_pos)) + self._generateTestBoolean(node, temp_result) if op_name.find("not") != -1: self.new_op(InvertBoolean()) @@ -1519,6 +1542,7 @@ self.discard_temp(temp1) self.discard_temp(temp2) + self.discard_temp(temp_result) self.set_label(end_label) # Yield the appropriate value. @@ -1758,34 +1782,42 @@ self._visitName(node, self.name_load_instructions) def visitNot(self, node): - next_label = self.new_label() - true_label = self.new_label() - self.dispatch(node.expr) - self._generateTestBoolean(node.expr) + + temp = self._optimise_temp_storage() + self._generateTestBoolean(node.expr, temp) + self.discard_temp(temp) + self.new_op(InvertBoolean()) self._generateLoadBoolean(node) # Prevent incorrect optimisation. - self.active = None - self.active_value = None + self.clear_active() def visitOr(self, node): - next_label = self.new_label() + end_label = self.new_label() + temp_pos = self.reserve_temp() + temp = LoadTemp(temp_pos) for n in node.nodes[:-1]: self.dispatch(n) - self._generateTestBoolean(n) - self.new_op(JumpIfTrue(next_label)) + self.new_op(StoreTemp(temp_pos)) + + self._generateTestBoolean(n, temp) + self.new_op(JumpIfTrue(end_label)) self.dispatch(node.nodes[-1]) - self.set_label(next_label) + self.new_op(StoreTemp(temp_pos)) + + self.set_label(end_label) # Prevent incorrect optimisation. - self.active = None - self.active_value = None + self.clear_active() + + self.new_op(temp) + self.discard_temp(temp) def visitPass(self, node): pass @@ -1933,8 +1965,7 @@ # Prevent incorrect optimisation. - self.active = None - self.active_value = None + self.clear_active() def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With") diff -r 146c1f0da0d1 -r 8ee002746854 tests/logical.py --- a/tests/logical.py Sat Aug 23 02:41:55 2008 +0200 +++ b/tests/logical.py Sat Aug 23 21:57:29 2008 +0200 @@ -4,6 +4,5 @@ b = 0 c = a and b d = a or b -e = a and b or not a and not b # vim: tabstop=4 expandtab shiftwidth=4 diff -r 146c1f0da0d1 -r 8ee002746854 tests/logical2.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/logical2.py Sat Aug 23 21:57:29 2008 +0200 @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +a = 1 +b = 0 +e = a and b or not a and not b + +# vim: tabstop=4 expandtab shiftwidth=4