Commit bfe7e783 authored by Stefan Behnel's avatar Stefan Behnel

fix repeated list multiplication

--HG--
extra : amend_source : 2797e0ad678cc0a33a2548a8a20b00475bc8a21b
parent 9793a1f5
...@@ -11,6 +11,9 @@ Features added ...@@ -11,6 +11,9 @@ Features added
Bugs fixed Bugs fixed
---------- ----------
* List/Tuple literals multiplied by more than one factor were only multiplied
by the last factor instead of all.
* In-place assignments to variables with inferred Python builtin/extension * In-place assignments to variables with inferred Python builtin/extension
types could fail with type errors if the result value type was incompatible types could fail with type errors if the result value type was incompatible
with the type of the previous value. with the type of the previous value.
......
...@@ -3379,19 +3379,30 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): ...@@ -3379,19 +3379,30 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
def visit_MulNode(self, node): def visit_MulNode(self, node):
self._calculate_const(node) self._calculate_const(node)
if isinstance(node.operand1, (ExprNodes.ListNode, ExprNodes.TupleNode)): if node.operand1.is_sequence_constructor:
return self._calculate_constant_seq(node.operand1, node.operand2) return self._calculate_constant_seq(node, node.operand1, node.operand2)
if isinstance(node.operand1, ExprNodes.IntNode) and \ if isinstance(node.operand1, ExprNodes.IntNode) and \
isinstance(node.operand2, (ExprNodes.ListNode, ExprNodes.TupleNode)): node.operand2.is_sequence_constructor:
return self._calculate_constant_seq(node.operand2, node.operand1) return self._calculate_constant_seq(node, node.operand2, node.operand1)
return self.visit_BinopNode(node) return self.visit_BinopNode(node)
def _calculate_constant_seq(self, sequence_node, factor): def _calculate_constant_seq(self, node, sequence_node, factor):
if factor.constant_result != 1 and sequence_node.args: if factor.constant_result != 1 and sequence_node.args:
if isinstance(factor.constant_result, (int, long)) and factor.constant_result <= 0: if isinstance(factor.constant_result, (int, long)) and factor.constant_result <= 0:
del sequence_node.args[:] del sequence_node.args[:]
factor = None sequence_node.mult_factor = None
sequence_node.mult_factor = factor elif sequence_node.mult_factor is not None:
if (isinstance(factor.constant_result, (int, long)) and
isinstance(sequence_node.mult_factor.constant_result, (int, long))):
value = sequence_node.mult_factor.constant_result * factor.constant_result
sequence_node.mult_factor = ExprNodes.IntNode(
sequence_node.mult_factor.pos,
value=str(value), constant_result=value)
else:
# don't know if we can combine the factors, so don't
return self.visit_BinopNode(node)
else:
sequence_node.mult_factor = factor
return sequence_node return sequence_node
def visit_PrimaryCmpNode(self, node): def visit_PrimaryCmpNode(self, node):
......
...@@ -291,6 +291,28 @@ def mult_empty_list(): ...@@ -291,6 +291,28 @@ def mult_empty_list():
return 5 * [] * 100 return 5 * [] * 100
@cython.test_fail_if_path_exists(
"//MulNode",
)
def mult_list_int_int():
"""
>>> mult_list_int_int()
[1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
"""
return [1, 2] * 2 * 3
@cython.test_fail_if_path_exists(
"//MulNode",
)
def mult_int_list_int():
"""
>>> mult_int_list_int()
[1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
"""
return 3 * [1, 2] * 2
@cython.test_fail_if_path_exists( @cython.test_fail_if_path_exists(
"//MulNode", "//MulNode",
"//ListNode//IntNode", "//ListNode//IntNode",
......
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