Commit 657a0066 authored by Stefan Behnel's avatar Stefan Behnel

make item types of tuple/array unpacking inferable and institutionalise the...

make item types of tuple/array unpacking inferable and institutionalise the IndexNode creation for the inference
parent 0cccf2ab
...@@ -476,6 +476,14 @@ class ExprNode(Node): ...@@ -476,6 +476,14 @@ class ExprNode(Node):
# can't be modified as part of globals or closures. # can't be modified as part of globals or closures.
return self.is_literal or self.is_temp or self.type.is_array or self.type.is_cfunction return self.is_literal or self.is_temp or self.type.is_array or self.type.is_cfunction
def inferable_item_node(self, index=0):
"""
Return a node that represents the (type) result of an indexing operation,
e.g. for tuple unpacking or iteration.
"""
return IndexNode(self.pos, base=self, index=IntNode(
self.pos, value=str(index), constant_result=index, type=PyrexTypes.c_py_ssize_t_type))
# --------------- Type Analysis ------------------ # --------------- Type Analysis ------------------
def analyse_as_module(self, env): def analyse_as_module(self, env):
...@@ -3846,6 +3854,10 @@ class SliceIndexNode(ExprNode): ...@@ -3846,6 +3854,10 @@ class SliceIndexNode(ExprNode):
return PyrexTypes.c_array_type(base_type.base_type, None) return PyrexTypes.c_array_type(base_type.base_type, None)
return py_object_type return py_object_type
def inferable_item_node(self, index=0):
# slicing shouldn't change the result type of the base
return self.base.inferable_item_node(index)
def may_be_none(self): def may_be_none(self):
base_type = self.base.type base_type = self.base.type
if base_type: if base_type:
......
...@@ -776,9 +776,9 @@ class ControlFlowAnalysis(CythonTransform): ...@@ -776,9 +776,9 @@ class ControlFlowAnalysis(CythonTransform):
if entry is None: # TODO: This shouldn't happen... if entry is None: # TODO: This shouldn't happen...
return return
self.flow.mark_assignment(lhs, rhs, entry) self.flow.mark_assignment(lhs, rhs, entry)
elif isinstance(lhs, ExprNodes.SequenceNode): elif lhs.is_sequence_constructor:
for arg in lhs.args: for i, arg in enumerate(lhs.args):
self.mark_assignment(arg) self.mark_assignment(arg, rhs.inferable_item_node(i) if rhs else None)
else: else:
self._visit(lhs) self._visit(lhs)
......
...@@ -61,8 +61,8 @@ class MarkParallelAssignments(EnvTransform): ...@@ -61,8 +61,8 @@ class MarkParallelAssignments(EnvTransform):
parallel_node.assigned_nodes.append(lhs) parallel_node.assigned_nodes.append(lhs)
elif isinstance(lhs, ExprNodes.SequenceNode): elif isinstance(lhs, ExprNodes.SequenceNode):
for arg in lhs.args: for i, arg in enumerate(lhs.args):
self.mark_assignment(arg, object_expr) self.mark_assignment(arg, rhs.inferable_item_node(i))
else: else:
# Could use this info to infer cdef class attributes... # Could use this info to infer cdef class attributes...
pass pass
......
# mode: run # mode: run
cimport cython
def test_literal_list(): def test_literal_list():
""" """
>>> test_literal_list() >>> test_literal_list()
...@@ -141,6 +143,8 @@ def test_ptr_literal_list_slice_end(): ...@@ -141,6 +143,8 @@ def test_ptr_literal_list_slice_end():
a[:5] = [1,2,3,4,5] a[:5] = [1,2,3,4,5]
return (a[0], a[1], a[2], a[3], a[4]) return (a[0], a[1], a[2], a[3], a[4])
@cython.test_assert_path_exists('//ReturnStatNode//CoerceToPyTypeNode')
def test_multiple_from_slice(): def test_multiple_from_slice():
""" """
>>> test_multiple_from_slice() >>> test_multiple_from_slice()
...@@ -150,6 +154,7 @@ def test_multiple_from_slice(): ...@@ -150,6 +154,7 @@ def test_multiple_from_slice():
x, y, z = a[1:4] x, y, z = a[1:4]
return x, y, z return x, y, z
def test_slice_from_multiple(): def test_slice_from_multiple():
""" """
>>> test_slice_from_multiple() >>> test_slice_from_multiple()
......
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