cython-devel
changeset 2953:4b2e6c18fe38
enable for-in iteration also for C arrays of known size
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Thu Feb 11 20:42:35 2010 +0100 (24 months ago) |
| parents | 8a1b906ddf39 |
| children | 9b979c860ef9 |
| files | Cython/Compiler/ExprNodes.py Cython/Compiler/Optimize.py tests/run/carray_slicing.pyx |
line diff
1.1 --- a/Cython/Compiler/ExprNodes.py Wed Feb 10 15:59:36 2010 -0800
1.2 +++ b/Cython/Compiler/ExprNodes.py Thu Feb 11 20:42:35 2010 +0100
1.3 @@ -1557,7 +1557,13 @@
1.4
1.5 def analyse_types(self, env):
1.6 self.sequence.analyse_types(env)
1.7 - self.sequence = self.sequence.coerce_to_pyobject(env)
1.8 + if isinstance(self.sequence, SliceIndexNode) and \
1.9 + (self.sequence.base.type.is_array or self.sequence.base.type.is_ptr) \
1.10 + or self.sequence.type.is_array and self.sequence.type.size is not None:
1.11 + # C array iteration will be transformed later on
1.12 + pass
1.13 + else:
1.14 + self.sequence = self.sequence.coerce_to_pyobject(env)
1.15 self.is_temp = 1
1.16
1.17 gil_message = "Iterating over Python object"
2.1 --- a/Cython/Compiler/Optimize.py Wed Feb 10 15:59:36 2010 -0800
2.2 +++ b/Cython/Compiler/Optimize.py Thu Feb 11 20:42:35 2010 +0100
2.3 @@ -89,10 +89,12 @@
2.4 return self._transform_dict_iteration(
2.5 node, dict_obj=iterator, keys=True, values=False)
2.6
2.7 - # C array slice iteration?
2.8 + # C array (slice) iteration?
2.9 if isinstance(iterator, ExprNodes.SliceIndexNode) and \
2.10 (iterator.base.type.is_array or iterator.base.type.is_ptr):
2.11 return self._transform_carray_iteration(node, iterator)
2.12 + elif iterator.type.is_array:
2.13 + return self._transform_carray_iteration(node, iterator)
2.14 elif not isinstance(iterator, ExprNodes.SimpleCallNode):
2.15 return node
2.16
2.17 @@ -131,13 +133,26 @@
2.18 return node
2.19
2.20 def _transform_carray_iteration(self, node, slice_node):
2.21 - start = slice_node.start
2.22 - stop = slice_node.stop
2.23 - step = None
2.24 - if not stop:
2.25 + if isinstance(slice_node, ExprNodes.SliceIndexNode):
2.26 + slice_base = slice_node.base
2.27 + start = slice_node.start
2.28 + stop = slice_node.stop
2.29 + step = None
2.30 + if not stop:
2.31 + return node
2.32 + elif slice_node.type.is_array and slice_node.type.size is not None:
2.33 + slice_base = slice_node
2.34 + start = None
2.35 + stop = ExprNodes.IntNode(
2.36 + slice_node.pos, value=str(slice_node.type.size))
2.37 + step = None
2.38 + else:
2.39 return node
2.40
2.41 - carray_ptr = slice_node.base.coerce_to_simple(self.current_scope)
2.42 + ptr_type = slice_base.type
2.43 + if ptr_type.is_array:
2.44 + ptr_type = ptr_type.element_ptr_type()
2.45 + carray_ptr = slice_base.coerce_to_simple(self.current_scope)
2.46
2.47 if start and start.constant_result != 0:
2.48 start_ptr_node = ExprNodes.AddNode(
2.49 @@ -145,7 +160,7 @@
2.50 operand1=carray_ptr,
2.51 operator='+',
2.52 operand2=start,
2.53 - type=carray_ptr.type)
2.54 + type=ptr_type)
2.55 else:
2.56 start_ptr_node = carray_ptr
2.57
2.58 @@ -154,13 +169,13 @@
2.59 operand1=carray_ptr,
2.60 operator='+',
2.61 operand2=stop,
2.62 - type=carray_ptr.type
2.63 + type=ptr_type
2.64 ).coerce_to_simple(self.current_scope)
2.65
2.66 - counter = UtilNodes.TempHandle(carray_ptr.type)
2.67 + counter = UtilNodes.TempHandle(ptr_type)
2.68 counter_temp = counter.ref(node.target.pos)
2.69
2.70 - if slice_node.base.type.is_string and node.target.type.is_pyobject:
2.71 + if slice_base.type.is_string and node.target.type.is_pyobject:
2.72 # special case: char* -> bytes
2.73 target_value = ExprNodes.SliceIndexNode(
2.74 node.target.pos,
2.75 @@ -181,7 +196,7 @@
2.76 type=PyrexTypes.c_int_type),
2.77 base=counter_temp,
2.78 is_buffer_access=False,
2.79 - type=carray_ptr.type.base_type)
2.80 + type=ptr_type.base_type)
2.81
2.82 if target_value.type != node.target.type:
2.83 target_value = target_value.coerce_to(node.target.type,
3.1 --- a/tests/run/carray_slicing.pyx Wed Feb 10 15:59:36 2010 -0800
3.2 +++ b/tests/run/carray_slicing.pyx Thu Feb 11 20:42:35 2010 +0100
3.3 @@ -111,21 +111,32 @@
3.4 ############################################################
3.5 # tests for int* slicing
3.6
3.7 -## cdef int cints[6]
3.8 -## for i in range(6):
3.9 -## cints[i] = i
3.10 +cdef int cints[6]
3.11 +for i in range(6):
3.12 + cints[i] = i
3.13
3.14 -## @cython.test_assert_path_exists("//ForFromStatNode",
3.15 -## "//ForFromStatNode//IndexNode")
3.16 -## @cython.test_fail_if_path_exists("//ForInStatNode")
3.17 -## def slice_intptr_for_loop_c():
3.18 -## """
3.19 -## >>> slice_intptr_for_loop_c()
3.20 -## [0, 1, 2]
3.21 -## [1, 2, 3, 4]
3.22 -## [4, 5]
3.23 -## """
3.24 -## cdef int i
3.25 -## print [ i for i in cints[:3] ]
3.26 -## print [ i for i in cints[1:5] ]
3.27 -## print [ i for i in cints[4:6] ]
3.28 +@cython.test_assert_path_exists("//ForFromStatNode",
3.29 + "//ForFromStatNode//IndexNode")
3.30 +@cython.test_fail_if_path_exists("//ForInStatNode")
3.31 +def slice_intptr_for_loop_c():
3.32 + """
3.33 + >>> slice_intptr_for_loop_c()
3.34 + [0, 1, 2]
3.35 + [1, 2, 3, 4]
3.36 + [4, 5]
3.37 + """
3.38 + cdef int i
3.39 + print [ i for i in cints[:3] ]
3.40 + print [ i for i in cints[1:5] ]
3.41 + print [ i for i in cints[4:6] ]
3.42 +
3.43 +@cython.test_assert_path_exists("//ForFromStatNode",
3.44 + "//ForFromStatNode//IndexNode")
3.45 +@cython.test_fail_if_path_exists("//ForInStatNode")
3.46 +def iter_intptr_for_loop_c():
3.47 + """
3.48 + >>> iter_intptr_for_loop_c()
3.49 + [0, 1, 2, 3, 4, 5]
3.50 + """
3.51 + cdef int i
3.52 + print [ i for i in cints ]
