strip down for-in-loops with empty iterables
authorStefan Behnel <stefan_ml@behnel.de>
Mon, 11 Mar 2013 10:00:02 +0000 (11:00 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Mon, 11 Mar 2013 10:00:02 +0000 (11:00 +0100)
Cython/Compiler/Optimize.py
tests/run/constant_folding.py
tests/run/constant_folding_cy.pyx

index 3ea542f..a68dc67 100644 (file)
@@ -3235,8 +3235,15 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
 
     def visit_ForInStatNode(self, node):
         self.visitchildren(node)
-        # iterating over a list literal? => tuples are more efficient
         sequence = node.iterator.sequence
+        if isinstance(sequence, ExprNodes.SequenceNode):
+            if not sequence.args:
+                if node.else_clause:
+                    return node.else_clause
+                else:
+                    # don't break list comprehensions
+                    return Nodes.StatListNode(node.pos, stats=[])
+        # iterating over a list literal? => tuples are more efficient
         if isinstance(sequence, ExprNodes.ListNode):
             node.iterator.sequence = sequence.as_tuple()
         return node
index 1040bd6..d88978a 100644 (file)
@@ -185,3 +185,71 @@ def while_true():
         return True
     else:
         print("FAIL")
+
+
+@cython.test_fail_if_path_exists(
+    "//ForInStatNode",
+)
+def for_in_empty():
+    """
+    >>> for_in_empty()
+    """
+    for i in []:
+        print("LOOP")
+
+
+@cython.test_fail_if_path_exists(
+    "//ForInStatNode",
+)
+def for_in_empty_else():
+    """
+    >>> for_in_empty_else()
+    True
+    """
+    for i in []:
+        print("LOOP")
+    else:
+        return True
+
+
+@cython.test_fail_if_path_exists(
+    "//ForInStatNode",
+)
+@cython.test_assert_path_exists(
+    "//ComprehensionNode",
+)
+def for_in_empty_listcomp():
+    """
+    >>> for_in_empty_listcomp()
+    []
+    """
+    return [i for i in []]
+
+
+@cython.test_fail_if_path_exists(
+    "//ForInStatNode",
+)
+@cython.test_assert_path_exists(
+    "//ComprehensionNode",
+)
+def for_in_empty_nested_listcomp():
+    """
+    >>> for_in_empty_nested_listcomp()
+    []
+    """
+    return [x for _ in [] for x in [1, 2, 3]]
+
+
+@cython.test_fail_if_path_exists(
+    "//ForInStatNode//ForInStatNode",
+    )
+@cython.test_assert_path_exists(
+    "//ForInStatNode",
+    "//ComprehensionNode",
+)
+def for_in_nested_listcomp():
+    """
+    >>> for_in_nested_listcomp()
+    []
+    """
+    return [x for x in [1, 2, 3] for _ in []]
index 3700a05..da9a935 100644 (file)
@@ -80,3 +80,20 @@ def unicode_slicing_safe_surrogates2():
     """
     ustring = u'abc\U00010000def'[:2]
     return ustring
+
+
+@cython.test_fail_if_path_exists(
+    "//ForInStatNode",
+)
+@cython.test_assert_path_exists(
+    "//ComprehensionNode",
+)
+def for_in_empty_setcomp():
+    """
+    >>> s = for_in_empty_setcomp()
+    >>> isinstance(s, set)
+    True
+    >>> len(s)
+    0
+    """
+    return {i for i in []}