patch for ticket 203 by Prajwal Suhas P
authorStefan Behnel <scoder@users.berlios.de>
Fri, 20 Mar 2009 16:36:35 +0000 (17:36 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Fri, 20 Mar 2009 16:36:35 +0000 (17:36 +0100)
Cython/Compiler/Nodes.py
tests/bugs/rangeOptimization_T203.pyx [new file with mode: 0644]

index f69cd3a214cb2f0696892bc6eccea33dbc6d7cc2..757055f7c1c43c1eabcabf1b7130363a8fe2a3ef 100644 (file)
@@ -3967,17 +3967,26 @@ class ForFromStatNode(LoopNode, StatNode):
             decop = "%s=%s" % (decop[0], step)
         loopvar_name = self.loopvar_node.result()
         if from_range:
+            temp_range_bound = code.funcstate.allocate_temp(self.bound2.type, manage_ref=False)
+            code.putln("%s = %s;" % (temp_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, self.bound2.result()
+            self.bound1.result(), offset, self.relation2, temp_range_bound
             ))
-        code.putln(
-            "for (%s = %s%s; %s %s %s; %s%s) {" % (
-                loopvar_name,
-                self.bound1.result(), offset,
-                loopvar_name, self.relation2, self.bound2.result(),
-                loopvar_name, incop))
+            code.putln(
+                "for (%s = %s%s; %s %s %s; %s%s) {" % (
+                    loopvar_name,
+                    self.bound1.result(), offset,
+                    loopvar_name, self.relation2, temp_range_bound,
+                    loopvar_name, incop))
+        else:
+            code.putln(
+                "for (%s = %s%s; %s %s %s; %s%s) {" % (
+                    loopvar_name,
+                    self.bound1.result(), offset,
+                    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)
@@ -3988,6 +3997,7 @@ class ForFromStatNode(LoopNode, StatNode):
             code.putln("} %s%s;" % (loopvar_name, decop))
             # End the outer if statement:
             code.putln("} /* end if */")
+            code.funcstate.release_temp(temp_range_bound)
         else:
             code.putln("}")
         break_label = code.break_label
diff --git a/tests/bugs/rangeOptimization_T203.pyx b/tests/bugs/rangeOptimization_T203.pyx
new file mode 100644 (file)
index 0000000..3388c2d
--- /dev/null
@@ -0,0 +1,60 @@
+__doc__ = u"""
+>>> test_var(10, 5)
+at 0
+at 1
+at 2
+at 3
+at 4
+5
+>>> test_func(5)
+get_bound(5)
+at 0
+at 1
+at 2
+at 3
+at 4
+5
+>>> test_f()
+9
+>>> f()
+g called
+0
+1
+2
+2
+"""
+
+cdef int get_bound(int m):
+    print "get_bound(%s)"%m
+    return m
+
+def test_var(int n, int m):
+    cdef int i
+    for i from 0 <= i < n:
+        print "at", i
+        n = m
+    return i
+
+def test_func(int n):
+    cdef int i
+    for i from 0 <= i < get_bound(n):
+        print "at", i
+    return i
+
+def test_f():
+    cdef int i,n
+    n = 10
+    for i in range(n):
+      if i == 5: n *= 2
+    print i
+
+cdef int g():
+    print "g called"
+    return 3
+
+def f():
+    cdef int i
+    for i in range(g()):
+        print i
+    print i
+