From 0973a78c0ea4e7cb048dcfc2604b9ad63642ac8b Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Wed, 25 Mar 2009 05:28:20 -0700 Subject: [PATCH] fix most loop tests --- Cython/Compiler/Nodes.py | 46 ++++++++++++--------------- Cython/Compiler/Optimize.py | 1 - tests/run/range_optimisation_T203.pyx | 25 +++++++++------ 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index a5170317..3275ba17 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -3840,6 +3840,7 @@ class ForFromStatNode(LoopNode, StatNode): # # Used internally: # + # from_range bool # is_py_target bool # loopvar_node ExprNode (usually a NameNode or temp node) # py_loopvar_node PyTempNode or None @@ -3848,6 +3849,7 @@ class ForFromStatNode(LoopNode, StatNode): is_py_target = False loopvar_node = None py_loopvar_node = None + from_range = False def analyse_declarations(self, env): self.target.analyse_target_declaration(env) @@ -3866,13 +3868,15 @@ class ForFromStatNode(LoopNode, StatNode): else: self.bound1 = self.bound1.coerce_to_integer(env) self.bound2 = self.bound2.coerce_to_integer(env) + if not self.bound2.is_literal: + self.bound2 = self.bound2.coerce_to_temp(env) if self.step is not None: if isinstance(self.step, ExprNodes.UnaryMinusNode): warning(self.step.pos, "Probable infinite loop in for-from-by statment. Consider switching the directions of the relations.", 2) self.step.analyse_types(env) self.step = self.step.coerce_to_integer(env) - if not (self.bound2.is_name or self.bound2.is_literal): - self.bound2 = self.bound2.coerce_to_temp(env) + if not self.step.is_literal: + self.step = self.step.coerce_to_temp(env) target_type = self.target.type if not (target_type.is_pyobject or target_type.is_numeric): error(self.target.pos, @@ -3916,49 +3920,37 @@ class ForFromStatNode(LoopNode, StatNode): def generate_execution_code(self, code): old_loop_labels = code.new_loop_labels() - from_range = getattr(self, "from_range", False) + from_range = self.from_range self.bound1.generate_evaluation_code(code) self.bound2.generate_evaluation_code(code) offset, incop = self.relation_table[self.relation1] - if incop == "++": - decop = "--" - else: - decop = "++" if self.step is not None: self.step.generate_evaluation_code(code) step = self.step.result() incop = "%s=%s" % (incop[0], step) - decop = "%s=%s" % (decop[0], step) - loopvar_name = self.loopvar_node.result() if from_range: - range_bound = code.funcstate.allocate_temp(self.bound2.type, manage_ref=False) - code.putln("%s = %s;" % (range_bound, self.bound2.result())) - # Skip the loop entirely (and avoid assigning to the loopvar) if - # the loop is empty: - code.putln("if (%s%s %s %s) {" % ( - self.bound1.result(), offset, self.relation2, range_bound - )) + loopvar_name = code.funcstate.allocate_temp(self.target.type, False) else: - range_bound = self.bound2.result() + loopvar_name = self.loopvar_node.result() code.putln( "for (%s = %s%s; %s %s %s; %s%s) {" % ( loopvar_name, self.bound1.result(), offset, - loopvar_name, self.relation2, range_bound, + loopvar_name, self.relation2, self.bound2.result(), loopvar_name, incop)) if self.py_loopvar_node: self.py_loopvar_node.generate_evaluation_code(code) self.target.generate_assignment_code(self.py_loopvar_node, code) + elif from_range: + code.putln("%s = %s;" % ( + self.target.result(), loopvar_name)) self.body.generate_execution_code(code) code.put_label(code.continue_label) - if from_range: - # Undo last increment to maintain Python semantics: - code.putln("} %s%s;" % (loopvar_name, decop)) - # End the outer if statement: - code.putln("} /* end if */") - code.funcstate.release_temp(range_bound) - else: - code.putln("}") + if self.py_loopvar_node: + + self.py_loopvar_node.generate_evaluation_code(code) + self.target.generate_assignment_code(self.py_loopvar_node, code) + code.putln("}") break_label = code.break_label code.set_loop_labels(old_loop_labels) if self.else_clause: @@ -3973,6 +3965,8 @@ class ForFromStatNode(LoopNode, StatNode): if self.step is not None: self.step.generate_disposal_code(code) self.step.free_temps(code) + if from_range: + code.funcstate.release_temp(loopvar_name) relation_table = { # {relop : (initial offset, increment op)} diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index 8dc06e21..e483494f 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -144,7 +144,6 @@ class IterationTransform(Visitor.VisitorTransform): relation2=relation2, bound2=bound2, step=step, body=node.body, else_clause=node.else_clause, - loopvar_node=node.target, from_range=True) return for_node diff --git a/tests/run/range_optimisation_T203.pyx b/tests/run/range_optimisation_T203.pyx index 3e31bae3..eadfde12 100644 --- a/tests/run/range_optimisation_T203.pyx +++ b/tests/run/range_optimisation_T203.pyx @@ -17,6 +17,11 @@ at 5 at 7 at 9 9 +>>> for_from_range(-5, -10) +range(-5) +range(-5, -10) +range(-5, -10, 2) +100 >>> for_from_bound_reassignment(5, 1) at 0 at 1 @@ -62,8 +67,12 @@ at 3 at 4 5 """ +cdef int get_bound(int m): + print "get_bound(%s)"%m + return m + def for_from_range(a, b): - cdef int i + cdef int i = 100 print "range(%s)" % a for i in range(a): print "at", i @@ -75,26 +84,22 @@ def for_from_range(a, b): print "at", i return i -cdef int get_bound(int m): - print "get_bound(%s)"%m - return m - def for_from_bound_reassignment(int bound, int fake_bound): - cdef int i + cdef int i = 100 for i from 0 <= i < bound: print "at", i bound = fake_bound return i def for_from_step_reassignment(int bound, int step, int fake_step): - cdef int i + cdef int i = 100 for i from 0 <= i < bound by step: print "at", i step = fake_step return i def for_from_target_reassignment(int bound, int factor): - cdef int i + cdef int i = 100 for i from 0 <= i < bound: print "at", i i *= factor @@ -108,14 +113,14 @@ def for_from_py_target_reassignment(int bound, int factor): return i def for_in_target_reassignment(int bound, int factor): - cdef int i + cdef int i = 100 for i in range(bound): print "at", i i *= factor return i def test_func(int n): - cdef int i + cdef int i = 100 for i from 0 <= i < get_bound(n): print "at", i return i -- 2.26.2