Commit 034db9bb authored by Stefan Behnel's avatar Stefan Behnel

better integer handling in constant folding, including type promotion

parent eccbee09
...@@ -2984,29 +2984,36 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -2984,29 +2984,36 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
except AttributeError: except AttributeError:
return node return node
if type1 is type2: if type1.is_numeric and type2.is_numeric:
new_node = node.operand1
else:
widest_type = PyrexTypes.widest_numeric_type(type1, type2) widest_type = PyrexTypes.widest_numeric_type(type1, type2)
if type(node.operand1) is type(node.operand2): else:
new_node = node.operand1 widest_type = PyrexTypes.py_object_type
new_node.type = widest_type target_class = self._widest_node_class(node.operand1, node.operand2)
elif type1 is widest_type:
new_node = node.operand1
elif type2 is widest_type:
new_node = node.operand2
else:
target_class = self._widest_node_class(
node.operand1, node.operand2)
if target_class is None: if target_class is None:
return node return node
new_node = target_class(pos=node.pos, type = widest_type) elif target_class is ExprNodes.IntNode:
unsigned = getattr(node.operand1, 'unsigned', '') and \
new_node.constant_result = node.constant_result 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:
new_node.type = PyrexTypes.widest_numeric_type(widest_type, new_node.type)
else:
if isinstance(node, ExprNodes.BoolNode): if isinstance(node, ExprNodes.BoolNode):
new_node.value = node.constant_result node_value = node.constant_result
else: else:
new_node.value = str(node.constant_result) 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 return new_node
def visit_PrimaryCmpNode(self, node): def visit_PrimaryCmpNode(self, node):
......
...@@ -3,11 +3,18 @@ __doc__ = u""" ...@@ -3,11 +3,18 @@ __doc__ = u"""
(1, 1L, -1L, 18446744073709551615L) (1, 1L, -1L, 18446744073709551615L)
>>> py_longs() >>> py_longs()
(1, 1L, 100000000000000000000000000000000L, -100000000000000000000000000000000L) (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 from cython cimport typeof
import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
__doc__ = __doc__.replace(u'L', u'') __doc__ = __doc__.replace(u'L', u'')
...@@ -27,6 +34,25 @@ def c_longs(): ...@@ -27,6 +34,25 @@ def c_longs():
def py_longs(): def py_longs():
return 1, 1L, 100000000000000000000000000000000, -100000000000000000000000000000000 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(): def large_literal():
""" """
>>> type(large_literal()) is int >>> type(large_literal()) is int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment