fix expression node finding for bool and character values in constant folding
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Feb 2013 12:02:40 +0000 (13:02 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Feb 2013 12:02:40 +0000 (13:02 +0100)
Cython/Compiler/Optimize.py
tests/run/constant_folding.py

index c6a9d19..56aae13 100644 (file)
@@ -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)
index 7845a52..6d27322 100644 (file)
@@ -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