From b9603f4d11e502647121a12d24b44abf25c51c67 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 1 Dec 2013 20:02:47 +0100 Subject: [PATCH] constant fold in-tests against empty containers --HG-- extra : amend_source : 6fe9294d38a26b208899453b4a12739dcc496c16 --- Cython/Compiler/Optimize.py | 26 +++++++++++++++-------- tests/run/constant_folding.py | 48 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 549f70e..8135104 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -3121,6 +3121,10 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): except ValueError: return None + def _bool_node(self, node, value): + value = bool(value) + return ExprNodes.BoolNode(node.pos, value=value, constant_result=value) + def visit_ExprNode(self, node): self._calculate_const(node) return node @@ -3134,8 +3138,7 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): if not node.operand.is_literal: return node if node.operator == '!': - return ExprNodes.BoolNode(node.pos, value=bool(node.constant_result), - constant_result=bool(node.constant_result)) + return self._bool_node(node, node.constant_result) elif isinstance(node.operand, ExprNodes.BoolNode): return ExprNodes.IntNode(node.pos, value=str(int(node.constant_result)), type=PyrexTypes.c_int_type, @@ -3283,18 +3286,23 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): def visit_PrimaryCmpNode(self, node): self._calculate_const(node) - if node.constant_result is not ExprNodes.not_a_constant: - bool_result = bool(node.constant_result) - return ExprNodes.BoolNode(node.pos, value=bool_result, - constant_result=bool_result) + if node.has_constant_result(): + return self._bool_node(node, node.constant_result) if node.operator in ('in', 'not_in') and not node.cascade: - if isinstance(node.operand2, ExprNodes.ListNode): - node.operand2 = node.operand2.as_tuple() + if isinstance(node.operand2, (ExprNodes.ListNode, ExprNodes.TupleNode, + ExprNodes.SetNode)): + if not node.operand2.args: + return self._bool_node(node, node.operator == 'not_in') + if isinstance(node.operand2, ExprNodes.ListNode): + node.operand2 = node.operand2.as_tuple() + elif isinstance(node.operand2, ExprNodes.DictNode): + if not node.operand2.key_value_pairs: + return self._bool_node(node, node.operator == 'not_in') return node def visit_CondExprNode(self, node): self._calculate_const(node) - if node.test.constant_result is ExprNodes.not_a_constant: + if not node.test.has_constant_result(): return node if node.test.constant_result: return node.true_val diff --git a/tests/run/constant_folding.py b/tests/run/constant_folding.py index 1a65235..dc4d955 100644 --- a/tests/run/constant_folding.py +++ b/tests/run/constant_folding.py @@ -313,3 +313,51 @@ def zero_mult_list(): [] """ return 0 * [1, 2] * 0 + + +@cython.test_assert_path_exists( + "//BoolNode", +) +@cython.test_fail_if_path_exists( + "//PrimaryCmpNode", + "//MulNode", + "//ListNode//IntNode", +) +def in_mult_list(): + """ + >>> in_mult_list() + False + """ + return 5 in 100 * [1, 2] * 0 + + +@cython.test_assert_path_exists( + "//BoolNode", +) +@cython.test_fail_if_path_exists( + "//PrimaryCmpNode", + "//MulNode", + "//ListNode//IntNode", +) +def not_in_mult_list(): + """ + >>> not_in_mult_list() + True + """ + return 5 not in 100 * [1, 2] * 0 + + +@cython.test_assert_path_exists( + "//BoolNode", +) +@cython.test_fail_if_path_exists( + "//PrimaryCmpNode", + "//MulNode", + "//ListNode//IntNode", +) +def combined(): + """ + >>> combined() + True + """ + return 5 in 100 * [1, 2] * 0 or 5 not in 100 * [] * 10 -- 2.7.4