cython-devel

changeset 1673:5730e9a933ef

Fix for #196
author Magnus Lie Hetland
date Fri Jan 30 15:53:16 2009 +0100 (3 years ago)
parents 41ac022ba25c
children 55c8d03e36e1
files Cython/Compiler/Nodes.py Cython/Compiler/Optimize.py tests/run/for_decrement.pyx
line diff
1.1 --- a/Cython/Compiler/Nodes.py Fri Jan 30 10:54:11 2009 +0100 1.2 +++ b/Cython/Compiler/Nodes.py Fri Jan 30 15:53:16 2009 +0100 1.3 @@ -3904,9 +3904,15 @@ 1.4 self.bound1.generate_evaluation_code(code) 1.5 self.bound2.generate_evaluation_code(code) 1.6 offset, incop = self.relation_table[self.relation1] 1.7 + if incop == "++": 1.8 + decop = "--" 1.9 + else: 1.10 + decop = "++" 1.11 if self.step is not None: 1.12 self.step.generate_evaluation_code(code) 1.13 - incop = "%s=%s" % (incop[0], self.step.result()) 1.14 + step = self.step.result() 1.15 + incop = "%s=%s" % (incop[0], step) 1.16 + decop = "%s=%s" % (decop[0], step) 1.17 loopvar_name = self.loopvar_node.result() 1.18 code.putln( 1.19 "for (%s = %s%s; %s %s %s; %s%s) {" % ( 1.20 @@ -3919,7 +3925,11 @@ 1.21 self.target.generate_assignment_code(self.py_loopvar_node, code) 1.22 self.body.generate_execution_code(code) 1.23 code.put_label(code.continue_label) 1.24 - code.putln("}") 1.25 + if getattr(self, "from_range", False): 1.26 + # Undo last increment to maintain Python semantics: 1.27 + code.putln("} %s%s;" % (loopvar_name, decop)) 1.28 + else: 1.29 + code.putln("}") 1.30 break_label = code.break_label 1.31 code.set_loop_labels(old_loop_labels) 1.32 if self.else_clause:
2.1 --- a/Cython/Compiler/Optimize.py Fri Jan 30 10:54:11 2009 +0100 2.2 +++ b/Cython/Compiler/Optimize.py Fri Jan 30 15:53:16 2009 +0100 2.3 @@ -144,7 +144,8 @@ 2.4 relation2=relation2, bound2=bound2, 2.5 step=step, body=node.body, 2.6 else_clause=node.else_clause, 2.7 - loopvar_node=node.target) 2.8 + loopvar_node=node.target, 2.9 + from_range=True) 2.10 return for_node 2.11 2.12 def _transform_dict_iteration(self, node, dict_obj, keys, values):
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tests/run/for_decrement.pyx Fri Jan 30 15:53:16 2009 +0100 3.3 @@ -0,0 +1,43 @@ 3.4 +""" 3.5 +>>> range_loop_indices() 3.6 +** Calculating step ** 3.7 +(9, 9, 8, 1, 2) 3.8 +>>> from_loop_indices() 3.9 +** Calculating step ** 3.10 +** Calculating step ** 3.11 +** Calculating step ** 3.12 +** Calculating step ** 3.13 +** Calculating step ** 3.14 +(10, 10, 0) 3.15 +""" 3.16 + 3.17 +cdef int get_step(): 3.18 + """ 3.19 + This should only be called once, when used in range(). 3.20 + """ 3.21 + print "** Calculating step **" 3.22 + return 2 3.23 + 3.24 +def range_loop_indices(): 3.25 + """ 3.26 + Optimized integer for loops using range() should follow Python behavior, 3.27 + and leave the index variable with the last value of the range. 3.28 + """ 3.29 + cdef int i, j, k, l, m 3.30 + for i in range(10): pass 3.31 + for j in range(2,10): pass 3.32 + for k in range(0,10,get_step()): pass 3.33 + for l in range(10,0,-1): pass 3.34 + for m in range(10,0,-2): pass 3.35 + return i, j, k, l, m 3.36 + 3.37 +def from_loop_indices(): 3.38 + """ 3.39 + for-from-loops should follow C behavior, and leave the index variable 3.40 + incremented one step after the last iteration. 3.41 + """ 3.42 + cdef int i, j, k 3.43 + for i from 0 <= i < 10 by get_step(): pass 3.44 + for j from 0 <= j < 10: pass 3.45 + for k from 10 > k > 0: pass 3.46 + return i, j, k 3.47 \ No newline at end of file