Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3.3
Changeset: r75197:41f2d5146ca3
Date: 2015-01-01 16:05 +0100
http://bitbucket.org/pypy/pypy/changeset/41f2d5146ca3/

Log:    Implement CPython Issue #12199: The TryExcept and TryFinally and AST
        nodes have been unified into a Try node.

diff --git a/pypy/interpreter/astcompiler/ast.py 
b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -334,10 +334,8 @@
             return With.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Raise):
             return Raise.from_object(space, w_node)
-        if space.isinstance_w(w_node, get(space).w_TryExcept):
-            return TryExcept.from_object(space, w_node)
-        if space.isinstance_w(w_node, get(space).w_TryFinally):
-            return TryFinally.from_object(space, w_node)
+        if space.isinstance_w(w_node, get(space).w_Try):
+            return Try.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Assert):
             return Assert.from_object(space, w_node)
         if space.isinstance_w(w_node, get(space).w_Import):
@@ -1009,16 +1007,17 @@
 State.ast_type('Raise', 'stmt', ['exc', 'cause'])
 
 
-class TryExcept(stmt):
-
-    def __init__(self, body, handlers, orelse, lineno, col_offset):
+class Try(stmt):
+
+    def __init__(self, body, handlers, orelse, finalbody, lineno, col_offset):
         self.body = body
         self.handlers = handlers
         self.orelse = orelse
+        self.finalbody = finalbody
         stmt.__init__(self, lineno, col_offset)
 
     def walkabout(self, visitor):
-        visitor.visit_TryExcept(self)
+        visitor.visit_Try(self)
 
     def mutate_over(self, visitor):
         if self.body:
@@ -1027,10 +1026,12 @@
             visitor._mutate_sequence(self.handlers)
         if self.orelse:
             visitor._mutate_sequence(self.orelse)
-        return visitor.visit_TryExcept(self)
+        if self.finalbody:
+            visitor._mutate_sequence(self.finalbody)
+        return visitor.visit_Try(self)
 
     def to_object(self, space):
-        w_node = space.call_function(get(space).w_TryExcept)
+        w_node = space.call_function(get(space).w_Try)
         if self.body is None:
             body_w = []
         else:
@@ -1049,57 +1050,6 @@
             orelse_w = [node.to_object(space) for node in self.orelse] # stmt
         w_orelse = space.newlist(orelse_w)
         space.setattr(w_node, space.wrap('orelse'), w_orelse)
-        w_lineno = space.wrap(self.lineno)  # int
-        space.setattr(w_node, space.wrap('lineno'), w_lineno)
-        w_col_offset = space.wrap(self.col_offset)  # int
-        space.setattr(w_node, space.wrap('col_offset'), w_col_offset)
-        return w_node
-
-    @staticmethod
-    def from_object(space, w_node):
-        w_body = get_field(space, w_node, 'body', False)
-        w_handlers = get_field(space, w_node, 'handlers', False)
-        w_orelse = get_field(space, w_node, 'orelse', False)
-        w_lineno = get_field(space, w_node, 'lineno', False)
-        w_col_offset = get_field(space, w_node, 'col_offset', False)
-        body_w = space.unpackiterable(w_body)
-        _body = [stmt.from_object(space, w_item) for w_item in body_w]
-        handlers_w = space.unpackiterable(w_handlers)
-        _handlers = [excepthandler.from_object(space, w_item) for w_item in 
handlers_w]
-        orelse_w = space.unpackiterable(w_orelse)
-        _orelse = [stmt.from_object(space, w_item) for w_item in orelse_w]
-        _lineno = space.int_w(w_lineno)
-        _col_offset = space.int_w(w_col_offset)
-        return TryExcept(_body, _handlers, _orelse, _lineno, _col_offset)
-
-State.ast_type('TryExcept', 'stmt', ['body', 'handlers', 'orelse'])
-
-
-class TryFinally(stmt):
-
-    def __init__(self, body, finalbody, lineno, col_offset):
-        self.body = body
-        self.finalbody = finalbody
-        stmt.__init__(self, lineno, col_offset)
-
-    def walkabout(self, visitor):
-        visitor.visit_TryFinally(self)
-
-    def mutate_over(self, visitor):
-        if self.body:
-            visitor._mutate_sequence(self.body)
-        if self.finalbody:
-            visitor._mutate_sequence(self.finalbody)
-        return visitor.visit_TryFinally(self)
-
-    def to_object(self, space):
-        w_node = space.call_function(get(space).w_TryFinally)
-        if self.body is None:
-            body_w = []
-        else:
-            body_w = [node.to_object(space) for node in self.body] # stmt
-        w_body = space.newlist(body_w)
-        space.setattr(w_node, space.wrap('body'), w_body)
         if self.finalbody is None:
             finalbody_w = []
         else:
@@ -1115,18 +1065,24 @@
     @staticmethod
     def from_object(space, w_node):
         w_body = get_field(space, w_node, 'body', False)
+        w_handlers = get_field(space, w_node, 'handlers', False)
+        w_orelse = get_field(space, w_node, 'orelse', False)
         w_finalbody = get_field(space, w_node, 'finalbody', False)
         w_lineno = get_field(space, w_node, 'lineno', False)
         w_col_offset = get_field(space, w_node, 'col_offset', False)
         body_w = space.unpackiterable(w_body)
         _body = [stmt.from_object(space, w_item) for w_item in body_w]
+        handlers_w = space.unpackiterable(w_handlers)
+        _handlers = [excepthandler.from_object(space, w_item) for w_item in 
handlers_w]
+        orelse_w = space.unpackiterable(w_orelse)
+        _orelse = [stmt.from_object(space, w_item) for w_item in orelse_w]
         finalbody_w = space.unpackiterable(w_finalbody)
         _finalbody = [stmt.from_object(space, w_item) for w_item in 
finalbody_w]
         _lineno = space.int_w(w_lineno)
         _col_offset = space.int_w(w_col_offset)
-        return TryFinally(_body, _finalbody, _lineno, _col_offset)
-
-State.ast_type('TryFinally', 'stmt', ['body', 'finalbody'])
+        return Try(_body, _handlers, _orelse, _finalbody, _lineno, _col_offset)
+
+State.ast_type('Try', 'stmt', ['body', 'handlers', 'orelse', 'finalbody'])
 
 
 class Assert(stmt):
@@ -3651,9 +3607,7 @@
         return self.default_visitor(node)
     def visit_Raise(self, node):
         return self.default_visitor(node)
-    def visit_TryExcept(self, node):
-        return self.default_visitor(node)
-    def visit_TryFinally(self, node):
+    def visit_Try(self, node):
         return self.default_visitor(node)
     def visit_Assert(self, node):
         return self.default_visitor(node)
@@ -3818,13 +3772,10 @@
         if node.cause:
             node.cause.walkabout(self)
 
-    def visit_TryExcept(self, node):
+    def visit_Try(self, node):
         self.visit_sequence(node.body)
         self.visit_sequence(node.handlers)
         self.visit_sequence(node.orelse)
-
-    def visit_TryFinally(self, node):
-        self.visit_sequence(node.body)
         self.visit_sequence(node.finalbody)
 
     def visit_Assert(self, node):
diff --git a/pypy/interpreter/astcompiler/astbuilder.py 
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -399,20 +399,15 @@
             else:
                 otherwise = self.handle_suite(try_node.children[-1])
                 except_count -= 1
+        handlers = []
         if except_count:
-            handlers = []
             for i in range(except_count):
                 base_offset = i * 3
                 exc = try_node.children[3 + base_offset]
                 except_body = try_node.children[5 + base_offset]
                 handlers.append(self.handle_except_clause(exc, except_body))
-            except_ast = ast.TryExcept(body, handlers, otherwise,
-                                       try_node.lineno, try_node.column)
-            if finally_suite is None:
-                return except_ast
-            body = [except_ast]
-        return ast.TryFinally(body, finally_suite, try_node.lineno,
-                              try_node.column)
+        return ast.Try(body, handlers, otherwise, finally_suite,
+                       try_node.lineno, try_node.column)
 
     def handle_with_stmt(self, with_node):
         body = self.handle_suite(with_node.children[-1])
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
@@ -599,20 +599,20 @@
             self.visit_sequence(wh.orelse)
             self.use_next_block(end)
 
-    def visit_TryExcept(self, te):
-        self.update_position(te.lineno, True)
+    def _visit_try_except(self, tr):
+        self.update_position(tr.lineno, True)
         exc = self.new_block()
         otherwise = self.new_block()
         end = self.new_block()
         self.emit_jump(ops.SETUP_EXCEPT, exc)
         body = self.use_next_block()
         self.push_frame_block(F_BLOCK_EXCEPT, body)
-        self.visit_sequence(te.body)
+        self.visit_sequence(tr.body)
         self.emit_op(ops.POP_BLOCK)
         self.pop_frame_block(F_BLOCK_EXCEPT, body)
         self.emit_jump(ops.JUMP_FORWARD, otherwise)
         self.use_next_block(exc)
-        for handler in te.handlers:
+        for handler in tr.handlers:
             assert isinstance(handler, ast.ExceptHandler)
             self.update_position(handler.lineno, True)
             next_except = self.new_block()
@@ -672,26 +672,35 @@
         self.emit_op(ops.END_FINALLY)   # this END_FINALLY will always re-raise
         self.is_dead_code()
         self.use_next_block(otherwise)
-        self.visit_sequence(te.orelse)
+        self.visit_sequence(tr.orelse)
         self.use_next_block(end)
 
-    def visit_TryFinally(self, tf):
-        self.update_position(tf.lineno, True)
+    def _visit_try_finally(self, tr):
+        self.update_position(tr.lineno, True)
         end = self.new_block()
         self.emit_jump(ops.SETUP_FINALLY, end)
         body = self.use_next_block()
         self.push_frame_block(F_BLOCK_FINALLY, body)
-        self.visit_sequence(tf.body)
+        if tr.handlers:
+            self._visit_try_except(tr)
+        else:
+            self.visit_sequence(tr.body)
         self.emit_op(ops.POP_BLOCK)
         self.pop_frame_block(F_BLOCK_FINALLY, body)
         # Indicates there was no exception.
         self.load_const(self.space.w_None)
         self.use_next_block(end)
         self.push_frame_block(F_BLOCK_FINALLY_END, end)
-        self.visit_sequence(tf.finalbody)
+        self.visit_sequence(tr.finalbody)
         self.emit_op(ops.END_FINALLY)
         self.pop_frame_block(F_BLOCK_FINALLY_END, end)
 
+    def visit_Try(self, tr):
+        if tr.finalbody:
+            return self._visit_try_finally(tr)
+        else:
+            return self._visit_try_except(tr)
+
     def _import_as(self, alias):
         source_name = alias.name
         dot = source_name.find(".")
diff --git a/pypy/interpreter/astcompiler/symtable.py 
b/pypy/interpreter/astcompiler/symtable.py
--- a/pypy/interpreter/astcompiler/symtable.py
+++ b/pypy/interpreter/astcompiler/symtable.py
@@ -557,15 +557,10 @@
             role = SYM_ASSIGNED
         self.note_symbol(name.id, role)
 
-    def visit_TryExcept(self, node):
+    def visit_Try(self, node):
         self.scope.note_try_start(node)
         self.visit_sequence(node.body)
         self.scope.note_try_end(node)
         self.visit_sequence(node.handlers)
         self.visit_sequence(node.orelse)
-
-    def visit_TryFinally(self, node):
-        self.scope.note_try_start(node)
-        self.visit_sequence(node.body)
-        self.scope.note_try_end(node)
         self.visit_sequence(node.finalbody)
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py 
b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -306,14 +306,15 @@
     def test_try(self):
         tr = self.get_first_stmt("try: x" + "\n" +
                                  "finally: pass")
-        assert isinstance(tr, ast.TryFinally)
+        assert isinstance(tr, ast.Try)
         assert len(tr.body) == 1
         assert isinstance(tr.body[0].value, ast.Name)
         assert len(tr.finalbody) == 1
         assert isinstance(tr.finalbody[0], ast.Pass)
+        assert tr.orelse is None
         tr = self.get_first_stmt("try: x" + "\n" +
                                  "except: pass")
-        assert isinstance(tr, ast.TryExcept)
+        assert isinstance(tr, ast.Try)
         assert len(tr.body) == 1
         assert isinstance(tr.body[0].value, ast.Name)
         assert len(tr.handlers) == 1
@@ -324,6 +325,7 @@
         assert len(handler.body) == 1
         assert isinstance(handler.body[0], ast.Pass)
         assert tr.orelse is None
+        assert tr.finalbody is None
         tr = self.get_first_stmt("try: x" + "\n" +
                                  "except Exception: pass")
         assert len(tr.handlers) == 1
@@ -375,32 +377,27 @@
         tr = self.get_first_stmt("try: x" + "\n" +
                                  "except: 4" + "\n" +
                                  "finally: pass")
-        assert isinstance(tr, ast.TryFinally)
+        assert isinstance(tr, ast.Try)
         assert len(tr.finalbody) == 1
         assert isinstance(tr.finalbody[0], ast.Pass)
+        assert len(tr.handlers) == 1
+        assert len(tr.handlers[0].body) == 1
+        assert isinstance(tr.handlers[0].body[0].value, ast.Num)
         assert len(tr.body) == 1
-        exc = tr.body[0]
-        assert isinstance(exc, ast.TryExcept)
-        assert len(exc.handlers) == 1
-        assert len(exc.handlers[0].body) == 1
-        assert isinstance(exc.handlers[0].body[0].value, ast.Num)
-        assert len(exc.body) == 1
-        assert isinstance(exc.body[0].value, ast.Name)
+        assert isinstance(tr.body[0].value, ast.Name)
         tr = self.get_first_stmt("try: x" + "\n" +
                                  "except: 4" + "\n" +
                                  "else: 'hi'" + "\n" +
                                  "finally: pass")
-        assert isinstance(tr, ast.TryFinally)
+        assert isinstance(tr, ast.Try)
         assert len(tr.finalbody) == 1
         assert isinstance(tr.finalbody[0], ast.Pass)
         assert len(tr.body) == 1
-        exc = tr.body[0]
-        assert isinstance(exc, ast.TryExcept)
-        assert len(exc.orelse) == 1
-        assert isinstance(exc.orelse[0].value, ast.Str)
-        assert len(exc.body) == 1
-        assert isinstance(exc.body[0].value, ast.Name)
-        assert len(exc.handlers) == 1
+        assert len(tr.orelse) == 1
+        assert isinstance(tr.orelse[0].value, ast.Str)
+        assert len(tr.body) == 1
+        assert isinstance(tr.body[0].value, ast.Name)
+        assert len(tr.handlers) == 1
 
     def test_with(self):
         wi = self.get_first_stmt("with x: pass")
diff --git a/pypy/interpreter/astcompiler/tools/Python.asdl 
b/pypy/interpreter/astcompiler/tools/Python.asdl
--- a/pypy/interpreter/astcompiler/tools/Python.asdl
+++ b/pypy/interpreter/astcompiler/tools/Python.asdl
@@ -31,8 +31,7 @@
           | With(withitem* items, stmt* body)
 
           | Raise(expr? exc, expr? cause)
-          | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
-          | TryFinally(stmt* body, stmt* finalbody)
+          | Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* 
finalbody)
           | Assert(expr test, expr? msg)
 
           | Import(alias* names)
diff --git a/pypy/interpreter/astcompiler/validate.py 
b/pypy/interpreter/astcompiler/validate.py
--- a/pypy/interpreter/astcompiler/validate.py
+++ b/pypy/interpreter/astcompiler/validate.py
@@ -240,15 +240,12 @@
         elif node.cause:
             raise ValidationError("Raise with cause but no exception")
 
-    def visit_TryExcept(self, node):
-        self._validate_body(node.body, "TryExcept")
+    def visit_Try(self, node):
+        self._validate_body(node.body, "Try")
         for handler in node.handlers:
             handler.walkabout(self)
         self._validate_stmts(node.orelse)
-
-    def visit_TryFinally(self, node):
-        self._validate_body(node.body, "TryFinally")
-        self._validate_body(node.finalbody, "TryFinally")
+        self._validate_stmts(node.finalbody)
 
     def visit_ExceptHandler(self, node):
         if node.type:
diff --git a/pypy/module/_ast/test/test_ast.py 
b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -359,11 +359,12 @@
     def test_issue793(self):
         import _ast as ast
         body = ast.Module([
-            ast.TryExcept([ast.Pass(lineno=2, col_offset=4)],
+            ast.Try([ast.Pass(lineno=2, col_offset=4)],
                 [ast.ExceptHandler(ast.Name('Exception', ast.Load(),
                                             lineno=3, col_offset=0),
-                                   None, [], lineno=4, col_offset=0)],
-                [], lineno=1, col_offset=0)
+                                   None, [ast.Pass(lineno=4, col_offset=0)],
+                                   lineno=4, col_offset=0)],
+                [], [], lineno=1, col_offset=0)
         ])
         exec(compile(body, '<string>', 'exec'))
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to