From 7c89ca3ef36d962cee91bfd8dc678e6e3d1dfe25 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Wed, 21 Aug 2013 20:53:17 +0200 Subject: [PATCH] simplify and extend in/not-in and is/is-not optimisation, add test --- Cython/Compiler/Optimize.py | 29 +++++++++--------- tests/run/isnot.pyx | 72 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 tests/run/isnot.pyx diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 05fc613..18575ee 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -19,6 +19,7 @@ from StringEncoding import EncodedString, BytesLiteral from Errors import error from ParseTreeTransforms import SkipDeclarations +import copy import codecs try: @@ -3068,21 +3069,21 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): return self._handle_UnaryMinusNode(node) return node + _negate_operator = { + 'in': 'not_in', + 'not_in': 'in', + 'is': 'is_not', + 'is_not': 'is' + }.get + def _handle_UnaryNotNode(self, node): - if isinstance(node.operand, ExprNodes.PrimaryCmpNode): - cmp_node = node.operand - if cmp_node.operator == 'in': - operator = 'not_in' - elif cmp_node.operator == 'is': - operator = 'is_not' - else: - return node - return ExprNodes.PrimaryCmpNode( - cmp_node.pos, - operand1=cmp_node.operand1, - operand2=cmp_node.operand2, - operator=operator, - cascade=cmp_node.cascade) + operand = node.operand + if isinstance(operand, ExprNodes.PrimaryCmpNode): + operator = self._negate_operator(operand.operator) + if operator: + node = copy.copy(operand) + node.operator = operator + node = self.visit_PrimaryCmpNode(node) return node def _handle_UnaryMinusNode(self, node): diff --git a/tests/run/isnot.pyx b/tests/run/isnot.pyx new file mode 100644 index 0000000..9baabbc --- /dev/null +++ b/tests/run/isnot.pyx @@ -0,0 +1,72 @@ +# mode: run +# tag: is_not + +cimport cython + +@cython.test_fail_if_path_exists('//NotNode') +def is_not(a, b): + """ + >>> is_not(1, 2) + True + >>> x = 1 + >>> is_not(x, x) + False + """ + return a is not b + + +@cython.test_fail_if_path_exists('//NotNode') +def not_is_not(a, b): + """ + >>> not_is_not(1, 2) + False + >>> x = 1 + >>> not_is_not(x, x) + True + """ + return not a is not b + + +@cython.test_fail_if_path_exists('//NotNode') +def not_is(a, b): + """ + >>> not_is(1, 2) + True + >>> x = 1 + >>> not_is(x, x) + False + """ + return not a is b + + +@cython.test_fail_if_path_exists('//NotNode') +def is_not_None(a): + """ + >>> is_not_None(1) + True + >>> is_not_None(None) + False + """ + return a is not None + + +@cython.test_fail_if_path_exists('//NotNode') +def not_is_not_None(a): + """ + >>> not_is_not_None(1) + False + >>> not_is_not_None(None) + True + """ + return not a is not None + + +@cython.test_fail_if_path_exists('//NotNode') +def not_is_None(a): + """ + >>> not_is_None(1) + True + >>> not_is_None(None) + False + """ + return not a is None -- 2.7.4