optimise 'int_val in string_literal' into a switch statement when x is an arbitrary...
authorStefan Behnel <scoder@users.berlios.de>
Sun, 14 Nov 2010 17:36:31 +0000 (18:36 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Sun, 14 Nov 2010 17:36:31 +0000 (18:36 +0100)
Cython/Compiler/Optimize.py
tests/run/py_unicode_type.pyx

index 8e31cc0beda8fbf356cb236dfb07d1e6d8056207..1c897e76a4357a15174cb8eff26134fc4becfbec 100644 (file)
@@ -702,28 +702,25 @@ class SwitchTransform(Visitor.VisitorTransform):
                 break
 
         if isinstance(cond, ExprNodes.PrimaryCmpNode):
-            if cond.cascade is None and not cond.is_python_comparison():
+            if cond.cascade is not None:
+                return self.NO_MATCH
+            elif cond.is_c_string_contains() and \
+                   isinstance(cond.operand2, (ExprNodes.UnicodeNode, ExprNodes.BytesNode)):
+                not_in = cond.operator == 'not_in'
+                if not_in and not allow_not_in:
+                    return self.NO_MATCH
+                if isinstance(cond.operand2, ExprNodes.UnicodeNode) and \
+                       cond.operand2.contains_surrogates():
+                    # dealing with surrogates leads to different
+                    # behaviour on wide and narrow Unicode
+                    # platforms => refuse to optimise this case
+                    return self.NO_MATCH
+                return not_in, cond.operand1, self.extract_in_string_conditions(cond.operand2)
+            elif not cond.is_python_comparison():
                 if cond.operator == '==':
                     not_in = False
                 elif allow_not_in and cond.operator == '!=':
                     not_in = True
-                elif cond.is_c_string_contains() and \
-                         isinstance(cond.operand2, (ExprNodes.UnicodeNode, ExprNodes.BytesNode)):
-                    not_in = cond.operator == 'not_in'
-                    if not_in and not allow_not_in:
-                        return self.NO_MATCH
-                    if isinstance(cond.operand2, ExprNodes.UnicodeNode) and \
-                           cond.operand2.contains_surrogates():
-                        # dealing with surrogates leads to different
-                        # behaviour on wide and narrow Unicode
-                        # platforms => refuse to optimise this case
-                        return self.NO_MATCH
-                    # this looks somewhat silly, but it does the right
-                    # checks for NameNode and AttributeNode
-                    if is_common_value(cond.operand1, cond.operand1):
-                        return not_in, cond.operand1, self.extract_in_string_conditions(cond.operand2)
-                    else:
-                        return self.NO_MATCH
                 else:
                     return self.NO_MATCH
                 # this looks somewhat silly, but it does the right
index 3febe4e5659f7d4fbaf378fa87e961804f275e9f..0465da9ecc258ed7c40f5a625c6ee1c17b118d2a 100644 (file)
@@ -162,3 +162,36 @@ def count_lower_case_characters(unicode ustring):
          if uchar.islower():
              count += 1
     return count
+
+@cython.test_assert_path_exists('//SwitchStatNode',
+                                '//ForFromStatNode')
+@cython.test_fail_if_path_exists('//ForInStatNode')
+def iter_and_in():
+    """
+    >>> iter_and_in()
+    a
+    b
+    e
+    f
+    h
+    """
+    for c in u'abcdefgh':
+        if c in u'abCDefGh':
+            print c
+
+@cython.test_assert_path_exists('//SwitchStatNode',
+                                '//ForFromStatNode')
+@cython.test_fail_if_path_exists('//ForInStatNode')
+def index_and_in():
+    """
+    >>> index_and_in()
+    1
+    3
+    4
+    7
+    8
+    """
+    cdef int i
+    for i in range(1,9):
+        if u'abcdefgh'[-i] in u'abCDefGh':
+            print i