Antonio Cuni avatar Antonio Cuni committed 06ea8ad

finish the work started in 97e1b1af67ce: run list comprehensions in their own scope, as we do for genexp, setcomp and dictcomp

Comments (0)

Files changed (4)

 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
+version of the same string
+
+re-enable BUILD_LIST_FROM_ARG: see the comment in astcompiler/codegen.py in
+ast.ListComp.build_container

pypy/interpreter/astcompiler/codegen.py

 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):
         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()

pypy/interpreter/astcompiler/test/test_compiler.py

 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)
             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
+

pypy/interpreter/test/test_generator.py

         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():
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.