From e559cf610e7b2e58d3d9688f01ba506c340d4d1e Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sat, 23 Feb 2013 13:02:40 +0100 Subject: [PATCH] fix expression node finding for bool and character values in constant folding --- Cython/Compiler/Optimize.py | 22 +++++++++++++++------- tests/run/constant_folding.py | 26 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index c6a9d19..56aae13 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -2991,8 +2991,8 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): import traceback, sys traceback.print_exc(file=sys.stdout) - NODE_TYPE_ORDER = [ExprNodes.CharNode, ExprNodes.IntNode, - ExprNodes.FloatNode] + NODE_TYPE_ORDER = [ExprNodes.BoolNode, ExprNodes.CharNode, + ExprNodes.IntNode, ExprNodes.FloatNode] def _widest_node_class(self, *nodes): try: @@ -3087,18 +3087,26 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): widest_type = PyrexTypes.widest_numeric_type(type1, type2) else: widest_type = PyrexTypes.py_object_type + target_class = self._widest_node_class(operand1, operand2) if target_class is None: return node - elif target_class is ExprNodes.IntNode: + if target_class is ExprNodes.BoolNode and node.operator in '+-//<<%**>>': + # C arithmetic results in at least an int type + target_class = ExprNodes.IntNode + if target_class is ExprNodes.CharNode and node.operator in '+-//<<%**>>&|^': + # C arithmetic results in at least an int type + target_class = ExprNodes.IntNode + + if target_class is ExprNodes.IntNode: unsigned = getattr(operand1, 'unsigned', '') and \ getattr(operand2, 'unsigned', '') longness = "LL"[:max(len(getattr(operand1, 'longness', '')), len(getattr(operand2, 'longness', '')))] new_node = ExprNodes.IntNode(pos=node.pos, - unsigned = unsigned, longness = longness, - value = str(node.constant_result), - constant_result = node.constant_result) + unsigned=unsigned, longness=longness, + value=str(int(node.constant_result)), + constant_result=int(node.constant_result)) # IntNode is smart about the type it chooses, so we just # make sure we were not smarter this time if widest_type.is_pyobject or new_node.type.is_pyobject: @@ -3106,7 +3114,7 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): else: new_node.type = PyrexTypes.widest_numeric_type(widest_type, new_node.type) else: - if isinstance(node, ExprNodes.BoolNode): + if target_class is ExprNodes.BoolNode: node_value = node.constant_result else: node_value = str(node.constant_result) diff --git a/tests/run/constant_folding.py b/tests/run/constant_folding.py index 7845a52..6d27322 100644 --- a/tests/run/constant_folding.py +++ b/tests/run/constant_folding.py @@ -60,3 +60,29 @@ def unop_bool(): minus3 = --- True mix = +-++-- True return not1, plus1, minus1, not3, plus3, minus3, mix + + +@cython.test_fail_if_path_exists( + "//AddNode", + "//SubNode", +) +def binop_bool(): + """ + >>> binop_bool() + (2, 1, 0, True, True, 1, False, 2, 2, -2, False, True, 1, False) + """ + plus1 = True + True + pmix1 = True + 0 + minus1 = True - True + and1 = True & True + or1 = True | True + ormix1 = True | 0 + xor1 = True ^ True + plus3 = False + True + False + True + pmix3 = False + True + 0 + True + minus3 = False - True - False - True + and3 = False & True & False & True + or3 = False | True | False | True + ormix3 = False | 0 | False | True + xor3 = False ^ True ^ False ^ True + return plus1, pmix1, minus1, and1, or1, ormix1, xor1, plus3, pmix3, minus3, and3, or3, ormix3, xor3 -- 2.7.4