Author: Antonio Cuni <[email protected]>
Branch: py3k
Changeset: r58396:06ea8add5a80
Date: 2012-10-24 12:18 +0200
http://bitbucket.org/pypy/pypy/changeset/06ea8add5a80/
Log: finish the work started in 97e1b1af67ce: run list comprehensions in
their own scope, as we do for genexp, setcomp and dictcomp
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -18,4 +18,7 @@
unskip numpypy tests in module/test_lib_pypy/numpypy/
optimize W_UnicodeObject, right now it stores both an unicode and an utf8
-version of the same string
\ No newline at end of file
+version of the same string
+
+re-enable BUILD_LIST_FROM_ARG: see the comment in astcompiler/codegen.py in
+ast.ListComp.build_container
\ No newline at end of file
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
@@ -121,6 +121,10 @@
class __extend__(ast.ListComp):
def build_container(self, codegen):
+ # XXX: this is suboptimal: if we use BUILD_LIST_FROM_ARG it's faster
+ # because it preallocates the list; however, we cannot use it because
+ # at this point we only have the iterator, not the original iterable
+ # object
codegen.emit_op_arg(ops.BUILD_LIST, 0)
def get_generators(self):
@@ -1059,52 +1063,10 @@
self.emit_op_arg(ops.CALL_METHOD, (kwarg_count << 8) | arg_count)
return True
- def _listcomp_generator(self, gens, gen_index, elt, single=False):
- start = self.new_block()
- skip = self.new_block()
- if_cleanup = self.new_block()
- anchor = self.new_block()
- gen = gens[gen_index]
- assert isinstance(gen, ast.comprehension)
- gen.iter.walkabout(self)
- if single:
- self.emit_op_arg(ops.BUILD_LIST_FROM_ARG, 0)
- self.emit_op(ops.GET_ITER)
- self.use_next_block(start)
- self.emit_jump(ops.FOR_ITER, anchor)
- self.use_next_block()
- gen.target.walkabout(self)
- if gen.ifs:
- if_count = len(gen.ifs)
- for if_ in gen.ifs:
- if_.accept_jump_if(self, False, if_cleanup)
- self.use_next_block()
- else:
- if_count = 0
- gen_index += 1
- if gen_index < len(gens):
- self._listcomp_generator(gens, gen_index, elt)
- else:
- elt.walkabout(self)
- self.emit_op_arg(ops.LIST_APPEND, gen_index + 1)
- self.use_next_block(skip)
- self.use_next_block(if_cleanup)
- self.emit_jump(ops.JUMP_ABSOLUTE, start, True)
- self.use_next_block(anchor)
-
def visit_ListComp(self, lc):
self._compile_comprehension(lc, "<listcomp>",
ComprehensionCodeGenerator)
- ## def visit_ListComp(self, lc):
- ## self.update_position(lc.lineno)
- ## if len(lc.generators) != 1 or lc.generators[0].ifs:
- ## single = False
- ## self.emit_op_arg(ops.BUILD_LIST, 0)
- ## else:
- ## single = True
- ## self._listcomp_generator(lc.generators, 0, lc.elt, single=single)
-
def _comp_generator(self, node, generators, gen_index):
start = self.new_block()
skip = self.new_block()
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
@@ -877,7 +877,6 @@
class TestOptimizations:
def count_instructions(self, source):
code, blocks = generate_function_code(source, self.space)
- import pdb;pdb.set_trace()
instrs = []
for block in blocks:
instrs.extend(block.instructions)
@@ -988,17 +987,4 @@
return d['f'](5)
""")
assert 'generator' in space.str_w(space.repr(w_generator))
-
- def test_list_comprehension(self):
- source = "def f(): [i for i in l]"
- source2 = "def f(): [i for i in l for j in l]"
- source3 = "def f(): [i for i in l if i]"
- counts = self.count_instructions(source)
- assert ops.BUILD_LIST not in counts
- assert counts[ops.BUILD_LIST_FROM_ARG] == 1
- counts = self.count_instructions(source2)
- assert counts[ops.BUILD_LIST] == 1
- assert ops.BUILD_LIST_FROM_ARG not in counts
- counts = self.count_instructions(source3)
- assert counts[ops.BUILD_LIST] == 1
- assert ops.BUILD_LIST_FROM_ARG not in counts
+
diff --git a/pypy/interpreter/test/test_generator.py
b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -254,11 +254,11 @@
exec("""
def f():
total = sum(i for i in [x for x in z])
- return total, x
+ return total
z = [1, 2, 7]
res = f()
""", d, d)
- assert d['res'] == (10, 7)
+ assert d['res'] == 10
def test_repr(self):
def myFunc():
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit