[pypy-commit] pypy py3k: (antocuni, romain) Add support for the new unpacking at the ast level

rguillebert noreply at buildbot.pypy.org
Tue Jan 17 18:51:41 CET 2012


Author: Romain Guillebert <romain.py at gmail.com>
Branch: py3k
Changeset: r51410:fbf25d09b601
Date: 2012-01-17 18:51 +0100
http://bitbucket.org/pypy/pypy/changeset/fbf25d09b601/

Log:	(antocuni,romain) Add support for the new unpacking at the ast level
	fixed list comprehension

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
@@ -1507,6 +1507,11 @@
             for node in self.comparators:
                 node.sync_app_attrs(space)
 
+class Starred(expr):
+    def __init__(self, value, ctx, lineno, col_offset):
+        self.value = value
+        self.ctx = ctx
+        expr.__init__(self, lineno, col_offset)
 
 class Call(expr):
 
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
@@ -680,7 +680,7 @@
                 self.set_context(target_expr, ast.Store)
                 targets.append(target_expr)
             value_child = stmt.children[-1]
-            if value_child.type == syms.testlist or value_child.type == syms.testlist_star_expr:
+            if value_child.type == syms.testlist_star_expr:
                 value_expr = self.handle_testlist(value_child)
             else:
                 value_expr = self.handle_expr(value_child)
@@ -740,6 +740,8 @@
                     operands.append(self.handle_expr(expr_node.children[i + 1]))
                 return ast.Compare(expr, operators, operands, expr_node.lineno,
                                    expr_node.column)
+            elif expr_node_type == syms.star_expr:
+                return self.handle_star_expr(expr_node)
             elif expr_node_type == syms.expr or \
                     expr_node_type == syms.xor_expr or \
                     expr_node_type == syms.and_expr or \
@@ -766,6 +768,10 @@
             else:
                 raise AssertionError("unknown expr")
 
+    def handle_star_expr(self, star_expr_node):
+        expr = self.handle_expr(star_expr_node.children[1])
+        return ast.Starred(expr, ast.Load, star_expr_node.lineno, star_expr_node.column)
+
     def handle_lambdef(self, lambdef_node):
         expr = self.handle_expr(lambdef_node.children[-1])
         if len(lambdef_node.children) == 3:
@@ -1229,8 +1235,8 @@
         elt = self.handle_expr(listcomp_node.children[0])
         comps = self.comprehension_helper(listcomp_node.children[1],
                                           "handle_testlist",
-                                          syms.list_for, syms.list_if,
-                                          syms.list_iter,
+                                          syms.comp_for, syms.comp_if,
+                                          syms.comp_iter,
                                           comp_fix_unamed_tuple_location=True)
         return ast.ListComp(elt, comps, listcomp_node.lineno,
                             listcomp_node.column)
diff --git a/pypy/interpreter/astcompiler/asthelpers.py b/pypy/interpreter/astcompiler/asthelpers.py
--- a/pypy/interpreter/astcompiler/asthelpers.py
+++ b/pypy/interpreter/astcompiler/asthelpers.py
@@ -133,6 +133,13 @@
 
     _description = "comparison"
 
+class __extend__(ast.Starred):
+
+    _description = "starred expression"
+
+    def set_context(self, ctx):
+        self.ctx = ctx
+        self.value.set_context(ctx)
 
 class __extend__(ast.IfExp):
 
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
@@ -600,6 +600,17 @@
         assert isinstance(tup.elts[0], ast.Name)
         assert tup.elts[0].ctx == ast.Store
 
+    def test_assign_starred(self):
+        assign = self.get_first_stmt("*a, b = x")
+        assert isinstance(assign, ast.Assign)
+        assert len(assign.targets) == 1
+        names = assign.targets[0]
+        assert len(names.elts) == 2
+        assert isinstance(names.elts[0], ast.Starred)
+        assert isinstance(names.elts[1], ast.Name)
+        assert isinstance(names.elts[0].value, ast.Name)
+        assert names.elts[0].value.id == "a"
+
     def test_name(self):
         name = self.get_first_expr("hi")
         assert isinstance(name, ast.Name)
diff --git a/pypy/interpreter/pyparser/data/Grammar3.2 b/pypy/interpreter/pyparser/data/Grammar3.2
--- a/pypy/interpreter/pyparser/data/Grammar3.2
+++ b/pypy/interpreter/pyparser/data/Grammar3.2
@@ -127,11 +127,6 @@
 # The reason that keywords are test nodes instead of NAME is that using NAME
 # results in an ambiguity. ast.c makes sure it's a NAME.
 argument: test [comp_for] | test '=' test
-
-list_iter: list_for | list_if
-list_for: 'for' exprlist 'in' testlist_safe [list_iter]
-list_if: 'if' old_test [list_iter]
-
 comp_iter: comp_for | comp_if
 comp_for: 'for' exprlist 'in' or_test [comp_iter]
 comp_if: 'if' old_test [comp_iter]


More information about the pypy-commit mailing list