[pypy-commit] pypy default: Fix issue 793 (thanks mistuhiko). Generally allow visit_sequence()

arigo noreply at buildbot.pypy.org
Sun Jul 24 13:56:02 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r45934:4d416d3a6e38
Date: 2011-07-24 13:56 +0200
http://bitbucket.org/pypy/pypy/changeset/4d416d3a6e38/

Log:	Fix issue 793 (thanks mistuhiko). Generally allow visit_sequence()
	to be called on None.

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
@@ -2541,6 +2541,7 @@
 class ASTVisitor(object):
 
     def visit_sequence(self, seq):
+        if seq is not None:
         for node in seq:
             node.walkabout(self)
 
@@ -2673,33 +2674,25 @@
 class GenericASTVisitor(ASTVisitor):
 
     def visit_Module(self, node):
-        if node.body:
             self.visit_sequence(node.body)
 
     def visit_Interactive(self, node):
-        if node.body:
             self.visit_sequence(node.body)
 
     def visit_Expression(self, node):
         node.body.walkabout(self)
 
     def visit_Suite(self, node):
-        if node.body:
             self.visit_sequence(node.body)
 
     def visit_FunctionDef(self, node):
         node.args.walkabout(self)
-        if node.body:
             self.visit_sequence(node.body)
-        if node.decorator_list:
             self.visit_sequence(node.decorator_list)
 
     def visit_ClassDef(self, node):
-        if node.bases:
             self.visit_sequence(node.bases)
-        if node.body:
             self.visit_sequence(node.body)
-        if node.decorator_list:
             self.visit_sequence(node.decorator_list)
 
     def visit_Return(self, node):
@@ -2707,11 +2700,9 @@
             node.value.walkabout(self)
 
     def visit_Delete(self, node):
-        if node.targets:
             self.visit_sequence(node.targets)
 
     def visit_Assign(self, node):
-        if node.targets:
             self.visit_sequence(node.targets)
         node.value.walkabout(self)
 
@@ -2722,36 +2713,28 @@
     def visit_Print(self, node):
         if node.dest:
             node.dest.walkabout(self)
-        if node.values:
             self.visit_sequence(node.values)
 
     def visit_For(self, node):
         node.target.walkabout(self)
         node.iter.walkabout(self)
-        if node.body:
             self.visit_sequence(node.body)
-        if node.orelse:
             self.visit_sequence(node.orelse)
 
     def visit_While(self, node):
         node.test.walkabout(self)
-        if node.body:
             self.visit_sequence(node.body)
-        if node.orelse:
             self.visit_sequence(node.orelse)
 
     def visit_If(self, node):
         node.test.walkabout(self)
-        if node.body:
             self.visit_sequence(node.body)
-        if node.orelse:
             self.visit_sequence(node.orelse)
 
     def visit_With(self, node):
         node.context_expr.walkabout(self)
         if node.optional_vars:
             node.optional_vars.walkabout(self)
-        if node.body:
             self.visit_sequence(node.body)
 
     def visit_Raise(self, node):
@@ -2763,17 +2746,12 @@
             node.tback.walkabout(self)
 
     def visit_TryExcept(self, node):
-        if node.body:
             self.visit_sequence(node.body)
-        if node.handlers:
             self.visit_sequence(node.handlers)
-        if node.orelse:
             self.visit_sequence(node.orelse)
 
     def visit_TryFinally(self, node):
-        if node.body:
             self.visit_sequence(node.body)
-        if node.finalbody:
             self.visit_sequence(node.finalbody)
 
     def visit_Assert(self, node):
@@ -2782,11 +2760,9 @@
             node.msg.walkabout(self)
 
     def visit_Import(self, node):
-        if node.names:
             self.visit_sequence(node.names)
 
     def visit_ImportFrom(self, node):
-        if node.names:
             self.visit_sequence(node.names)
 
     def visit_Exec(self, node):
@@ -2812,7 +2788,6 @@
         pass
 
     def visit_BoolOp(self, node):
-        if node.values:
             self.visit_sequence(node.values)
 
     def visit_BinOp(self, node):
@@ -2832,34 +2807,27 @@
         node.orelse.walkabout(self)
 
     def visit_Dict(self, node):
-        if node.keys:
             self.visit_sequence(node.keys)
-        if node.values:
             self.visit_sequence(node.values)
 
     def visit_Set(self, node):
-        if node.elts:
             self.visit_sequence(node.elts)
 
     def visit_ListComp(self, node):
         node.elt.walkabout(self)
-        if node.generators:
             self.visit_sequence(node.generators)
 
     def visit_SetComp(self, node):
         node.elt.walkabout(self)
-        if node.generators:
             self.visit_sequence(node.generators)
 
     def visit_DictComp(self, node):
         node.key.walkabout(self)
         node.value.walkabout(self)
-        if node.generators:
             self.visit_sequence(node.generators)
 
     def visit_GeneratorExp(self, node):
         node.elt.walkabout(self)
-        if node.generators:
             self.visit_sequence(node.generators)
 
     def visit_Yield(self, node):
@@ -2868,14 +2836,11 @@
 
     def visit_Compare(self, node):
         node.left.walkabout(self)
-        if node.comparators:
             self.visit_sequence(node.comparators)
 
     def visit_Call(self, node):
         node.func.walkabout(self)
-        if node.args:
             self.visit_sequence(node.args)
-        if node.keywords:
             self.visit_sequence(node.keywords)
         if node.starargs:
             node.starargs.walkabout(self)
@@ -2902,11 +2867,9 @@
         pass
 
     def visit_List(self, node):
-        if node.elts:
             self.visit_sequence(node.elts)
 
     def visit_Tuple(self, node):
-        if node.elts:
             self.visit_sequence(node.elts)
 
     def visit_Const(self, node):
@@ -2924,7 +2887,6 @@
             node.step.walkabout(self)
 
     def visit_ExtSlice(self, node):
-        if node.dims:
             self.visit_sequence(node.dims)
 
     def visit_Index(self, node):
@@ -2933,7 +2895,6 @@
     def visit_comprehension(self, node):
         node.target.walkabout(self)
         node.iter.walkabout(self)
-        if node.ifs:
             self.visit_sequence(node.ifs)
 
     def visit_ExceptHandler(self, node):
@@ -2941,13 +2902,10 @@
             node.type.walkabout(self)
         if node.name:
             node.name.walkabout(self)
-        if node.body:
             self.visit_sequence(node.body)
 
     def visit_arguments(self, node):
-        if node.args:
             self.visit_sequence(node.args)
-        if node.defaults:
             self.visit_sequence(node.defaults)
 
     def visit_keyword(self, node):
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
@@ -295,15 +295,11 @@
     def visit_FunctionDef(self, func):
         self.update_position(func.lineno, True)
         # Load decorators first, but apply them after the function is created.
-        if func.decorator_list:
             self.visit_sequence(func.decorator_list)
         args = func.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
             self.visit_sequence(args.defaults)
-            num_defaults = len(args.defaults)
-        else:
-            num_defaults = 0
+        num_defaults = len(args.defaults) if args.defaults is not None else 0
         code = self.sub_scope(FunctionCodeGenerator, func.name, func,
                               func.lineno)
         self._make_function(code, num_defaults)
@@ -317,24 +313,17 @@
         self.update_position(lam.lineno)
         args = lam.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
             self.visit_sequence(args.defaults)
-            default_count = len(args.defaults)
-        else:
-            default_count = 0
+        default_count = len(args.defaults) if args.defaults is not None else 0
         code = self.sub_scope(LambdaCodeGenerator, "<lambda>", lam, lam.lineno)
         self._make_function(code, default_count)
 
     def visit_ClassDef(self, cls):
         self.update_position(cls.lineno, True)
-        if cls.decorator_list:
             self.visit_sequence(cls.decorator_list)
         self.load_const(self.space.wrap(cls.name))
-        if cls.bases:
-            bases_count = len(cls.bases)
             self.visit_sequence(cls.bases)
-        else:
-            bases_count = 0
+        bases_count = len(cls.bases) if cls.bases is not None else 0
         self.emit_op_arg(ops.BUILD_TUPLE, bases_count)
         code = self.sub_scope(ClassCodeGenerator, cls.name, cls, cls.lineno)
         self._make_function(code, 0)
@@ -446,7 +435,6 @@
         end = self.new_block()
         test_constant = if_.test.as_constant_truth(self.space)
         if test_constant == optimize.CONST_FALSE:
-            if if_.orelse:
                 self.visit_sequence(if_.orelse)
         elif test_constant == optimize.CONST_TRUE:
             self.visit_sequence(if_.body)
@@ -515,7 +503,6 @@
         self.use_next_block(cleanup)
         self.emit_op(ops.POP_BLOCK)
         self.pop_frame_block(F_BLOCK_LOOP, start)
-        if fr.orelse:
             self.visit_sequence(fr.orelse)
         self.use_next_block(end)
 
@@ -523,7 +510,6 @@
         self.update_position(wh.lineno, True)
         test_constant = wh.test.as_constant_truth(self.space)
         if test_constant == optimize.CONST_FALSE:
-            if wh.orelse:
                 self.visit_sequence(wh.orelse)
         else:
             end = self.new_block()
@@ -544,7 +530,6 @@
                 self.use_next_block(anchor)
                 self.emit_op(ops.POP_BLOCK)
             self.pop_frame_block(F_BLOCK_LOOP, loop)
-            if wh.orelse:
                 self.visit_sequence(wh.orelse)
             self.use_next_block(end)
 
@@ -581,7 +566,6 @@
             self.use_next_block(next_except)
         self.emit_op(ops.END_FINALLY)
         self.use_next_block(otherwise)
-        if te.orelse:
             self.visit_sequence(te.orelse)
         self.use_next_block(end)
 
@@ -893,26 +877,18 @@
 
     def visit_Tuple(self, tup):
         self.update_position(tup.lineno)
-        if tup.elts:
-            elt_count = len(tup.elts)
-        else:
-            elt_count = 0
+        elt_count = len(tup.elts) if tup.elts is not None else 0
         if tup.ctx == ast.Store:
             self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
-        if elt_count:
             self.visit_sequence(tup.elts)
         if tup.ctx == ast.Load:
             self.emit_op_arg(ops.BUILD_TUPLE, elt_count)
 
     def visit_List(self, l):
         self.update_position(l.lineno)
-        if l.elts:
-            elt_count = len(l.elts)
-        else:
-            elt_count = 0
+        elt_count = len(l.elts) if l.elts is not None else 0
         if l.ctx == ast.Store:
             self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
-        if elt_count:
             self.visit_sequence(l.elts)
         if l.ctx == ast.Load:
             self.emit_op_arg(ops.BUILD_LIST, elt_count)
@@ -944,10 +920,8 @@
         if self._optimize_method_call(call):
             return
         call.func.walkabout(self)
-        arg = 0
+        arg = len(call.args) if call.args is not None else 0
         call_type = 0
-        if call.args:
-            arg = len(call.args)
             self.visit_sequence(call.args)
         if call.keywords:
             self.visit_sequence(call.keywords)
@@ -984,16 +958,10 @@
         assert isinstance(attr_lookup, ast.Attribute)
         attr_lookup.value.walkabout(self)
         self.emit_op_name(ops.LOOKUP_METHOD, self.names, attr_lookup.attr)
-        if call.args:
             self.visit_sequence(call.args)
-            arg_count = len(call.args)
-        else:
-            arg_count = 0
-        if call.keywords:
+        arg_count = len(call.args) if call.args is not None else 0
             self.visit_sequence(call.keywords)
-            kwarg_count = len(call.keywords)
-        else:
-            kwarg_count = 0
+        kwarg_count = len(call.keywords) if call.keywords is not None else 0
         self.emit_op_arg(ops.CALL_METHOD, (kwarg_count << 8) | arg_count)
         return True
 
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
@@ -356,16 +356,11 @@
         # Function defaults and decorators happen in the outer scope.
         args = func.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
             self.visit_sequence(args.defaults)
-        if func.decorator_list:
             self.visit_sequence(func.decorator_list)
         new_scope = FunctionScope(func.name, func.lineno, func.col_offset)
         self.push_scope(new_scope, func)
         func.args.walkabout(self)
-        # func.body should never be empty (or else it contains one Pass)
-        # but it can be if we make an ast.FunctionDef() from app-level.
-        if func.body:
             self.visit_sequence(func.body)
         self.pop_scope()
 
@@ -375,9 +370,7 @@
 
     def visit_ClassDef(self, clsdef):
         self.note_symbol(clsdef.name, SYM_ASSIGNED)
-        if clsdef.bases:
             self.visit_sequence(clsdef.bases)
-        if clsdef.decorator_list:
             self.visit_sequence(clsdef.decorator_list)
         self.push_scope(ClassScope(clsdef), clsdef)
         self.visit_sequence(clsdef.body)
@@ -434,7 +427,6 @@
     def visit_Lambda(self, lamb):
         args = lamb.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
             self.visit_sequence(args.defaults)
         new_scope = FunctionScope("lambda", lamb.lineno, lamb.col_offset)
         self.push_scope(new_scope, lamb)
@@ -450,7 +442,6 @@
         self.push_scope(new_scope, node)
         self.implicit_arg(0)
         outer.target.walkabout(self)
-        if outer.ifs:
             self.visit_sequence(outer.ifs)
         self.visit_sequence(comps[1:])
         for item in list(consider):
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -221,8 +221,9 @@
         self.emit("class ASTVisitor(object):")
         self.emit("")
         self.emit("def visit_sequence(self, seq):", 1)
-        self.emit("for node in seq:", 2)
-        self.emit("node.walkabout(self)", 3)
+        self.emit("if seq is not None:", 2)
+        self.emit("for node in seq:", 3)
+        self.emit("node.walkabout(self)", 4)
         self.emit("")
         self.emit("def default_visitor(self, node):", 1)
         self.emit("raise NodeVisitorNotImplemented", 2)
@@ -280,15 +281,13 @@
     def visitField(self, field):
         if field.type.value not in asdl.builtin_types and \
                 field.type.value not in self.data.simple_types:
-            if field.seq or field.opt:
+            level = 2
+            template = "node.%s.walkabout(self)"
+            if field.seq:
+                template = "self.visit_sequence(node.%s)"
+            elif field.opt:
                 self.emit("if node.%s:" % (field.name,), 2)
                 level = 3
-            else:
-                level = 2
-            if field.seq:
-                template = "self.visit_sequence(node.%s)"
-            else:
-                template = "node.%s.walkabout(self)"
             self.emit(template % (field.name,), level)
             return True
         return False
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
@@ -274,3 +274,14 @@
         n.name = "foo"
         n.name = "foo"
         assert n.name == "foo"
+
+    def test_issue793(self):
+        import _ast as ast
+        body = ast.Module([
+            ast.TryExcept([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)
+        ])
+        exec compile(body, '<string>', 'exec')


More information about the pypy-commit mailing list