# HG changeset patch # User Paul Boddie # Date 1216336702 -7200 # Node ID 160e3ccc7dd681d649eec861642df6d85d808e02 # Parent 915efb9687433c0e95cf52238d2798c0f5f1b589 Simplified temporary storage access instructions (using one instruction, not a sequence). Introduced exception handler stack instructions. Improved Raise node support. diff -r 915efb968743 -r 160e3ccc7dd6 micropython/ast.py --- a/micropython/ast.py Fri Jul 18 00:49:53 2008 +0200 +++ b/micropython/ast.py Fri Jul 18 01:18:22 2008 +0200 @@ -193,17 +193,16 @@ temp_position = self.reserve_temp(1) self.new_op(StoreTemp(temp_position)) - return [LoadTemp(temp_position)] + return LoadTemp(temp_position) def reserve_temp(self, n): temp_position = self.temp_position self.temp_position += n return temp_position - def discard_temp(self, instructions): - for temp in instructions: - if isinstance(temp, LoadTemp): - self.temp_position -= 1 + def discard_temp(self, instruction): + if isinstance(instruction, LoadTemp): + self.temp_position -= 1 # Code writing methods. @@ -220,16 +219,6 @@ self.code.append(op) self.active = op - def new_ops(self, ops): - - """ - Add copies of 'ops' to the generated code. This is typically used in - connection with sequences of temporary storage instructions. - """ - - for op in ops: - self.new_op(op.copy()) - def remove_op(self): "Remove the last instruction." @@ -392,7 +381,7 @@ # to be the context, load the context. if context is None or isinstance(context, Instance): - self.new_ops(temp) + self.new_op(temp) self.new_op(LoadContext()) self.new_op(StoreFrame(0)) @@ -573,14 +562,14 @@ else: self.new_op(CheckFrame()) - def _doCallFunc(self, instructions): + def _doCallFunc(self, instruction): "Make the invocation." - self.new_ops(instructions) + self.new_op(instruction) self.new_op(JumpWithFrame()) - def _endCallFunc(self, instructions=None): + def _endCallFunc(self, instruction=None): "Finish the invocation and tidy up afterwards." @@ -589,8 +578,8 @@ # Discard any temporary storage instructions. - if instructions is not None: - self.discard_temp(instructions) + if instruction is not None: + self.discard_temp(instruction) def _visitName(self, node, classes): @@ -710,8 +699,6 @@ If no optimisation can be achieved, a StoreTemp instruction is produced and the appropriate LoadTemp instruction is returned. - All returned instructions are provided in a list. - Restriction: for use only in situations where the source of the temporary data will not be disturbed between its first access and its subsequent use. @@ -722,7 +709,7 @@ last = self.last_op() self.remove_op() - return [last] + return last else: return self.get_temp() @@ -828,7 +815,7 @@ # Produce the invocation. self._startCallFunc() - self.new_ops(temp) + self.new_op(temp) # Get the method on temp. @@ -847,7 +834,7 @@ # Add arguments. # NOTE: No support for defaults. - self.new_ops(temp) # Explicit context as first argument. + self.new_op(temp) # Explicit context as first argument. self._doCallFunc(temp_method) self._endCallFunc(temp_method) self.new_op(Jump(end_label)) @@ -905,7 +892,7 @@ # Left method. self._startCallFunc() - self.new_ops(temp1) + self.new_op(temp1) # Get left method on temp1. @@ -924,8 +911,8 @@ # Add arguments. # NOTE: No support for defaults. - self.new_ops(temp1) # Explicit context as first argument. - self.new_ops(temp2) + self.new_op(temp1) # Explicit context as first argument. + self.new_op(temp2) self._doCallFunc(temp_method) self._endCallFunc(temp_method) @@ -945,7 +932,7 @@ self.set_label(right_label) self._startCallFunc() - self.new_ops(temp2) + self.new_op(temp2) # Get right method on temp2. @@ -964,8 +951,8 @@ # Add arguments. # NOTE: No support for defaults. - self.new_ops(temp2) # Explicit context as first argument. - self.new_ops(temp1) + self.new_op(temp2) # Explicit context as first argument. + self.new_op(temp1) self._doCallFunc(temp_method) self._endCallFunc(temp_method) @@ -1143,7 +1130,7 @@ # Use the iterator to get the next value. self._startCallFunc() - self.new_ops(temp_iterator) + self.new_op(temp_iterator) self._generateAttr(node, "next", self.attr_load_instructions) temp = self._generateCallFunc([], node) self._doCallFunc(temp) @@ -1325,8 +1312,18 @@ self.dispatch(node.expr1) if node.expr2 is not None: + temp = self._optimise_temp_storage() + self.dispatch(node.expr2) - self._doCallFunc() + temp_arg = self._optimise_temp_storage() + + self._startCallFunc() + self.new_op(temp_arg) + self.new_op(StoreFrame(0)) + self._doCallFunc(temp) + self._endCallFunc(temp) + + self.discard_temp(temp_arg) self.new_op(RaiseException()) @@ -1353,6 +1350,7 @@ def visitTryExcept(self, node): exit_label = self.new_label() + success_label = self.new_label() handler_label = self.new_label() self.add_exception_labels(handler_label, exit_label) @@ -1360,12 +1358,16 @@ # Try... # Produce the code, then jump to the exit. + self.new_op(PushHandler(handler_label)) self.dispatch(node.body) + self.new_op(PopHandler(handler_label)) self.new_op(Jump(exit_label)) # Start of handlers. self.set_label(handler_label) + self.new_op(PopHandler(handler_label)) + for name, assignment, handler in node.handlers: next_label = self.new_label() @@ -1393,15 +1395,12 @@ self.new_op(LoadException()) self.new_op(RaiseException()) - # After exception - - self.set_label(exit_label) - # Optional else clause. if node.else_ is not None: self.dispatch(node.else_) + self.set_label(exit_label) self.drop_exception_labels() def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally") diff -r 915efb968743 -r 160e3ccc7dd6 micropython/rsvp.py --- a/micropython/rsvp.py Fri Jul 18 00:49:53 2008 +0200 +++ b/micropython/rsvp.py Fri Jul 18 01:18:22 2008 +0200 @@ -187,6 +187,8 @@ class LoadException(Instruction): "Load the raised exception." class RaiseException(Instruction): "Raise an exception." class CheckException(Instruction): "Check the raised exception against another." +class PushHandler(Address): "Push an exception handler onto the handler stack." +class PopHandler(Address): "Pop an exception handler from the handler stack." # General instructions.