Author: Antonio Cuni <[email protected]>
Branch: py3k
Changeset: r55008:f9ef9c856d38
Date: 2012-05-09 11:02 +0200
http://bitbucket.org/pypy/pypy/changeset/f9ef9c856d38/

Log:    generate the very same code as cpython for try/except blocks. In
        particular, make sure to delete the local variable which contains
        the exception after we exit the except: block

diff --git a/pypy/interpreter/astcompiler/codegen.py 
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -576,12 +576,50 @@
                 self.emit_jump(ops.POP_JUMP_IF_FALSE, next_except, True)
             self.emit_op(ops.POP_TOP)
             if handler.name:
-                self.name_op(handler.name, ast.Store);
+                ## generate the equivalent of:
+                ## 
+                ## try:
+                ##     # body
+                ## except type as name:
+                ##     try:
+                ##         # body
+                ##     finally:
+                ##         name = None
+                ##         del name
+                #
+                cleanup_end = self.new_block()
+                self.name_op(handler.name, ast.Store)
+                self.emit_op(ops.POP_TOP)
+                # second try
+                self.emit_jump(ops.SETUP_FINALLY, cleanup_end)
+                cleanup_body = self.use_next_block()
+                self.push_frame_block(F_BLOCK_FINALLY, cleanup_body)
+                # second # body
+                self.visit_sequence(handler.body)
+                self.emit_op(ops.POP_BLOCK)
+                self.emit_op(ops.POP_EXCEPT)
+                self.pop_frame_block(F_BLOCK_FINALLY, cleanup_body)
+                # finally
+                self.load_const(self.space.w_None)
+                self.use_next_block(cleanup_end)
+                self.push_frame_block(F_BLOCK_FINALLY_END, cleanup_end)
+                # name = None
+                self.load_const(self.space.w_None)
+                self.name_op(handler.name, ast.Store)
+                # del name
+                self.name_op(handler.name, ast.Del)
+                #
+                self.emit_op(ops.END_FINALLY)
+                self.pop_frame_block(F_BLOCK_FINALLY_END, cleanup_end)
             else:
                 self.emit_op(ops.POP_TOP)
-            self.emit_op(ops.POP_TOP)
-            self.visit_sequence(handler.body)
-            self.emit_op(ops.POP_EXCEPT)
+                self.emit_op(ops.POP_TOP)
+                cleanup_body = self.use_next_block()
+                self.push_frame_block(F_BLOCK_FINALLY, cleanup_body)
+                self.visit_sequence(handler.body)
+                self.emit_op(ops.POP_EXCEPT)
+                self.pop_frame_block(F_BLOCK_FINALLY, cleanup_body)
+            #
             self.emit_jump(ops.JUMP_FORWARD, end)
             self.use_next_block(next_except)
         self.emit_op(ops.END_FINALLY)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to