fix constant folding for repeated negation
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Feb 2013 10:28:10 +0000 (11:28 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 23 Feb 2013 10:28:10 +0000 (11:28 +0100)
Cython/Compiler/Optimize.py
tests/run/constant_folding.py [new file with mode: 0644]

index 869d7a6..d888e40 100644 (file)
@@ -3025,20 +3025,27 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
         return node
 
     def _handle_UnaryMinusNode(self, node):
+        def _negate(value):
+            if value.startswith('-'):
+                value = value[1:]
+            else:
+                value = '-' + value
+            return value
+
         if isinstance(node.operand, ExprNodes.LongNode):
-            return ExprNodes.LongNode(node.pos, value = '-' + node.operand.value,
-                                      constant_result = node.constant_result)
+            return ExprNodes.LongNode(node.pos, value=_negate(node.operand.value),
+                                      constant_result=node.constant_result)
         if isinstance(node.operand, ExprNodes.FloatNode):
             # this is a safe operation
-            return ExprNodes.FloatNode(node.pos, value = '-' + node.operand.value,
-                                       constant_result = node.constant_result)
+            return ExprNodes.FloatNode(node.pos, value=_negate(node.operand.value),
+                                       constant_result=node.constant_result)
         node_type = node.operand.type
         if node_type.is_int and node_type.signed or \
-               isinstance(node.operand, ExprNodes.IntNode) and node_type.is_pyobject:
-            return ExprNodes.IntNode(node.pos, value = '-' + node.operand.value,
-                                     type = node_type,
-                                     longness = node.operand.longness,
-                                     constant_result = node.constant_result)
+                isinstance(node.operand, ExprNodes.IntNode) and node_type.is_pyobject:
+            return ExprNodes.IntNode(node.pos, value=_negate(node.operand.value),
+                                     type=node_type,
+                                     longness=node.operand.longness,
+                                     constant_result=node.constant_result)
         return node
 
     def _handle_UnaryPlusNode(self, node):
diff --git a/tests/run/constant_folding.py b/tests/run/constant_folding.py
new file mode 100644 (file)
index 0000000..f3ca3bc
--- /dev/null
@@ -0,0 +1,38 @@
+# mode: run
+# tag: constant_folding
+
+import cython
+
+
+@cython.test_fail_if_path_exists(
+    "//UnaryMinusNode",
+    "//UnaryPlusNode",
+)
+def unop_floats():
+    """
+    >>> unop_floats()
+    (1.0, -1.0, 1.0, -1.0, -1.0)
+    """
+    plus1  = + 1.0
+    minus1 = - 1.0
+    plus3  = +++ 1.0
+    minus3 = --- 1.0
+    mix    = +-++-- 1.0
+    return plus1, minus1, plus3, minus3, mix
+
+
+@cython.test_fail_if_path_exists(
+    "//UnaryMinusNode",
+    "//UnaryPlusNode",
+)
+def unop_ints():
+    """
+    >>> unop_ints()
+    (1, -1, 1, -1, -1)
+    """
+    plus1  = + 1
+    minus1 = - 1
+    plus3  = +++ 1
+    minus3 = --- 1
+    mix    = +-++-- 1
+    return plus1, minus1, plus3, minus3, mix