From e157b663564095ac7828d09afa50ab54cd8c4e07 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 14 Nov 2010 18:36:31 +0100 Subject: [PATCH] optimise 'int_val in string_literal' into a switch statement when x is an arbitrary expression, not only a name --- Cython/Compiler/Optimize.py | 33 +++++++++++++++------------------ tests/run/py_unicode_type.pyx | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 8e31cc0b..1c897e76 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -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 diff --git a/tests/run/py_unicode_type.pyx b/tests/run/py_unicode_type.pyx index 3febe4e5..0465da9e 100644 --- a/tests/run/py_unicode_type.pyx +++ b/tests/run/py_unicode_type.pyx @@ -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 -- 2.26.2