Commits

Victor Stinner committed 398601d

add TODO list

  • Participants
  • Parent commits 91b537d

Comments (0)

Files changed (4)

 
    - ``while True: pass`` => ``while 1: pass``
    - ``for x in range(3): print(x)`` => ``x = 0; print(x); x = 1; print(x); x = 2; print(x)``
-   - ``for x in range(1000): pass`` => ``for x in xrange(1000): pass`` (Python 2)
+   - ``for x in range(1000): print(x)`` => ``for x in xrange(1000): print(x)`` (Python 2)
 
  * Optimize iterators, list, set and dict comprehension, and generators (need
    "builtin_funcs" feature). Examples:
 
  * Replace list with tuple (need "builtin_funcs" feature). Examples:
 
-   - ``for x in [x, y, z]: pass`` => ``for x in (x, y, z): pass``
+   - ``for x in [a, b, c]: print(x)`` => ``for x in (a, b, c): print(x)``
    - ``x in [1, 2, 3]`` => ``x in (1, 2, 3)``
    - ``list([x, y, z])`` => ``[x, y, z]``
    - ``set([1, 2, 3])`` => ``{1, 2, 3}`` (Python 2.7+)
 Misc
 ====
 
+ * remove empty loop: need to assign to the last value of the iterator
  * automatically detect pure functions: see pythran.analysis.PureFunctions of
    pythran project, depend on ArgumentEffects and GlobalEffects analysys
  * replace '(a and b) and c' (2 op) with 'a and b and c' (1 op),

File astoptimizer/optimizer.py

         if not was_unassigned:
             self.namespace._unassigned.remove(target_id)
 
+#       TODO: remove empty loop
+#        if (self.config.remove_dead_code
+#        and is_empty_body(node.body)):
+#            return UNSET
+
         unroll = []
         for cst in itercst:
             value = new_constant(node, cst)
         self.unassign(node.target)
         node.body = self.visit_list(node.body, conditional=True)
         node.orelse = self.visit_list(node.orelse, conditional=True)
+
+#       TODO: remove empty loop
+#       FIXME: assign target to the last iterm of iter
+#        if (self.config.remove_dead_code
+#        and is_empty_body(node.body)):
+#            self.log_node_removal(node)
+#            return self.if_block(node, node.orelse)
+
         return node
 
     def fullvisit_arguments(self, node):

File astoptimizer/tests.py

         self.check_pass('def f():\n pass\n pass')
         config = self.create_config()
         config.unroll_limit = 0
-        self.check_pass('for i in (1, 2, 3):\n pass\n pass', config=config)
+        self.check('for i in (1, 2, 3):\n pass\n print(x)\n pass',
+                   self.text_ast('for i in (1, 2, 3):\n print(x)'),
+                   config=config)
         self.check_pass('while x:\n pass\n pass')
 
         code = '\n'.join((
 
         # empty try/except
         self.check('try: pass\nexcept: func1()',
-                   self.text_ast('pass'))
+                   self.text_ast('pass'),
+                   info=re.compile('Remove dead code: Try'))
         self.check('try: pass\nexcept: func1()\nelse: func2()',
-                   self.text_ast('func2()'))
+                   self.text_ast('func2()'),
+                   info=re.compile('Remove dead code: Try'))
         self.check('try: pass\nfinally: func1()',
-                   self.text_ast('func1()'))
+                   self.text_ast('func1()'),
+                   info=re.compile('Remove dead code: Try'))
+        if PYTHON3:
+            infos = re.compile('Remove dead code: Try')
+        else:
+            infos = (re.compile('Remove dead code: Try'),
+                         re.compile('Remove dead code: Try'))
         self.check('try: pass\nexcept: func()\nfinally: func2()',
-                   self.text_ast('func2()'))
+                   self.text_ast('func2()'),
+                   info=infos)
         code = 'try: pass\nexcept: func1()\nelse: func2()\nfinally: func3()'
         self.check(code,
-                   self.text_ast('try: func2()\nfinally: func3()'))
+                   self.text_ast('try: func2()\nfinally: func3()'),
+                   info=re.compile('Remove dead code: Try'))
+
+        # For
+#       TODO: remove empty loop
+        #self.check('for x in (1, 2, 3): pass',
+        #           self.text_ast('pass'),
+        #           info=re.compile('Remove dead code: For'))
 
     def test_remove_docstring(self):
         keep_docstring = self.create_config()
 
     def test_For(self):
         # range => xrange
-        self.check_not_optimized('for x in range(n): pass')
+        self.check_not_optimized('for x in range(n): print(x)')
 
         config = self.create_config('builtin_funcs')
         config.unroll_limit = 0
-        self.check('for x in range(3): pass',
-                   self.text_ast('for x in (0, 1, 2): pass'),
+        self.check('for x in range(3): print(x)',
+                   self.text_ast('for x in (0, 1, 2): print(x)'),
                    config)
-        self.check('for x in list("abc"): pass',
-                   self.text_ast('for x in ("a", "b", "c"): pass'),
+        self.check('for x in list("abc"): print(x)',
+                   self.text_ast('for x in ("a", "b", "c"): print(x)'),
                    config)
-        self.check_not_optimized('for x in tuple(iterable): pass', config)
-        self.check_not_optimized('for x in list(iterable): pass', config)
+        self.check_not_optimized('for x in tuple(iterable): print(x)', config)
+        self.check_not_optimized('for x in list(iterable): print(x)', config)
         if PYTHON2:
-            self.check('for x in range(1000): pass',
-                       self.text_ast('for x in xrange(1000): pass'),
+            self.check('for x in range(1000): print(x)',
+                       self.text_ast('for x in xrange(1000): print(x)'),
                        config)
 
-        self.check('for x in [1, 2, 3]: pass',
-                   self.text_ast('for x in (1, 2, 3): pass'),
+        self.check('for x in [1, 2, 3]: print(x)',
+                   self.text_ast('for x in (1, 2, 3): print(x)'),
                    config)
         self.check('for x in "": pass', self.TEXT_PASS)
 
         config = self.create_config()
         config.max_tuple_length = 2
         config.unroll_limit = 0
-        self.check('for x in [1, 2]: pass',
-                   self.text_ast('for x in (1, 2): pass'), config)
-        self.check_not_optimized('for x in [1, 2, 3]: pass', config)
+        self.check('for x in [1, 2]: print(x)',
+                   self.text_ast('for x in (1, 2): print(x)'), config)
+        self.check_not_optimized('for x in [1, 2, 3]: print(x)', config)
 
     def test_For_unroll(self):
         no_unroll = self.create_config()
                    self.text_ast('i=1; print(i); i=2; print(i); i=3; print(i)'))
         self.check('for i in (1, 2, 3):\n pass\n pass',
                    self.text_ast('i=1; i=2; i=3'))
+#       TODO: remove empty loop
+        #self.check('for i in (1, 2, 3):\n pass\n pass',
+        #           self.text_ast('i=3'))
 
     def test_max_tuple_length(self):
         config = self.create_config('builtin_funcs')