Author: Benjamin Peterson <[email protected]>
Branch: py3k
Changeset: r53622:3661bb9780f8
Date: 2012-03-14 18:02 -0500
http://bitbucket.org/pypy/pypy/changeset/3661bb9780f8/
Log: complete extended unpacking implementation
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
@@ -883,36 +883,46 @@
ifexp.orelse.walkabout(self)
self.use_next_block(end)
- def visit_Tuple(self, tup):
- self.update_position(tup.lineno)
- elt_count = len(tup.elts) if tup.elts is not None else 0
- if tup.ctx == ast.Store:
- star_pos = -1
+ def _visit_list_or_tuple(self, node, elts, ctx, op):
+ elt_count = len(elts) if elts else 0
+ star_pos = -1
+ if ctx == ast.Store:
if elt_count > 0:
- for i, elt in enumerate(tup.elts):
+ for i, elt in enumerate(elts):
if isinstance(elt, ast.Starred):
if star_pos != -1:
- self.error("two starred expressions in
assignment", tup)
+ msg = "too many starred expressions in assignment"
+ self.error(msg, node)
star_pos = i
- if star_pos > -1:
+ if star_pos != -1:
self.emit_op_arg(ops.UNPACK_EX, star_pos |
(elt_count-star_pos-1)<<8)
else:
self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
- self.visit_sequence(tup.elts)
- if tup.ctx == ast.Load:
- self.emit_op_arg(ops.BUILD_TUPLE, elt_count)
+ if elt_count > 0:
+ if star_pos != -1:
+ for elt in elts:
+ if isinstance(elt, ast.Starred):
+ elt.value.walkabout(self)
+ else:
+ elt.walkabout(self)
+ else:
+ self.visit_sequence(elts)
+ if ctx == ast.Load:
+ self.emit_op_arg(op, elt_count)
def visit_Starred(self, star):
- star.value.walkabout(self)
+ if star.ctx != ast.Store:
+ self.error("can use starred expression only as assignment target",
+ star)
+ self.error("starred assignment must be in list or tuple", star)
+
+ def visit_Tuple(self, tup):
+ self.update_position(tup.lineno)
+ self._visit_list_or_tuple(tup, tup.elts, tup.ctx, ops.BUILD_TUPLE)
def visit_List(self, l):
self.update_position(l.lineno)
- 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)
- self.visit_sequence(l.elts)
- if l.ctx == ast.Load:
- self.emit_op_arg(ops.BUILD_LIST, elt_count)
+ self._visit_list_or_tuple(l, l.elts, l.ctx, ops.BUILD_LIST)
def visit_Dict(self, d):
self.update_position(d.lineno)
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -827,12 +827,29 @@
yield self.st, test, "f()", 42
# This line is needed for py.code to find the source.
- def test_tuple_unpacking(self):
+ def test_extended_unpacking(self):
func = """def f():
(a, *b, c) = 1, 2, 3, 4, 5
return a, b, c
"""
yield self.st, func, "f()", (1, [2, 3, 4], 5)
+ func = """def f():
+ [a, *b, c] = 1, 2, 3, 4, 5
+ return a, b, c
+ """
+ yield self.st, func, "f()", (1, [2, 3, 4], 5)
+ func = """def f():
+ *a, = [1, 2, 3]
+ return a
+ """
+ yield self.st, func, "f()", [1, 2, 3]
+ py.test.raises(SyntaxError, self.simple_test, "*a, *b = [1, 2]",
+ None, None)
+ py.test.raises(SyntaxError, self.simple_test, "a = [*b, c]",
+ None, None)
+ py.test.raises(SyntaxError, self.simple_test, "for *a in x: pass",
+ None, None)
+
class AppTestCompiler:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit