From 034db9bb547f1c461cb982eda37d251ffc04e206 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 12 Nov 2010 23:03:10 +0100 Subject: [PATCH] better integer handling in constant folding, including type promotion --- Cython/Compiler/Optimize.py | 47 +++++++++++++++++++++---------------- tests/run/int_literals.pyx | 28 +++++++++++++++++++++- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 460b6024..9e4c66ef 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -2984,29 +2984,36 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): except AttributeError: return node - if type1 is type2: - new_node = node.operand1 - else: + if type1.is_numeric and type2.is_numeric: widest_type = PyrexTypes.widest_numeric_type(type1, type2) - if type(node.operand1) is type(node.operand2): - new_node = node.operand1 - new_node.type = widest_type - elif type1 is widest_type: - new_node = node.operand1 - elif type2 is widest_type: - new_node = node.operand2 + else: + widest_type = PyrexTypes.py_object_type + target_class = self._widest_node_class(node.operand1, node.operand2) + if target_class is None: + return node + elif target_class is ExprNodes.IntNode: + unsigned = getattr(node.operand1, 'unsigned', '') and \ + getattr(node.operand2, 'unsigned', '') + longness = "LL"[:max(len(getattr(node.operand1, 'longness', '')), + len(getattr(node.operand2, 'longness', '')))] + new_node = ExprNodes.IntNode(pos=node.pos, + unsigned = unsigned, longness = longness, + value = str(node.constant_result), + constant_result = 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: + new_node.type = PyrexTypes.py_object_type else: - target_class = self._widest_node_class( - node.operand1, node.operand2) - if target_class is None: - return node - new_node = target_class(pos=node.pos, type = widest_type) - - new_node.constant_result = node.constant_result - if isinstance(node, ExprNodes.BoolNode): - new_node.value = node.constant_result + new_node.type = PyrexTypes.widest_numeric_type(widest_type, new_node.type) else: - new_node.value = str(node.constant_result) + if isinstance(node, ExprNodes.BoolNode): + node_value = node.constant_result + else: + node_value = str(node.constant_result) + new_node = target_class(pos=node.pos, type = widest_type, + value = node_value, + constant_result = node.constant_result) return new_node def visit_PrimaryCmpNode(self, node): diff --git a/tests/run/int_literals.pyx b/tests/run/int_literals.pyx index b5aa67cb..511aef5c 100644 --- a/tests/run/int_literals.pyx +++ b/tests/run/int_literals.pyx @@ -3,11 +3,18 @@ __doc__ = u""" (1, 1L, -1L, 18446744073709551615L) >>> py_longs() (1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L) + +>>> py_huge_calculated_long() +1606938044258990275541962092341162602522202993782792835301376L +>>> py_huge_computation_small_result_neg() +(-2535301200456458802993406410752L, -2535301200456458802993406410752L) """ -import sys +cimport cython from cython cimport typeof +import sys + if sys.version_info[0] >= 3: __doc__ = __doc__.replace(u'L', u'') @@ -27,6 +34,25 @@ def c_longs(): def py_longs(): return 1, 1L, 100000000000000000000000000000000, -100000000000000000000000000000000 +@cython.test_fail_if_path_exists("//NumBinopNode", "//IntBinopNode") +@cython.test_assert_path_exists("//ReturnStatNode/IntNode") +def py_huge_calculated_long(): + return 1 << 200 + +@cython.test_fail_if_path_exists("//NumBinopNode", "//IntBinopNode") +@cython.test_assert_path_exists("//ReturnStatNode/IntNode") +def py_huge_computation_small_result(): + """ + >>> py_huge_computation_small_result() + 2 + """ + return (1 << 200) >> 199 + +@cython.test_fail_if_path_exists("//NumBinopNode", "//IntBinopNode") +#@cython.test_assert_path_exists("//ReturnStatNode/IntNode") +def py_huge_computation_small_result_neg(): + return -(2 ** 101), (-2) ** 101 + def large_literal(): """ >>> type(large_literal()) is int -- 2.26.2