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 ]