Another for..from fix when target is a python global
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 9 Apr 2009 23:58:05 +0000 (16:58 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 9 Apr 2009 23:58:05 +0000 (16:58 -0700)
Cython/Compiler/Nodes.py
tests/run/range_optimisation_T203.pyx

index a51027c6d8c61b57bde3315579f0b2c6adc24238..e912d98ec04aad37855b2e031fe48ec2c7821722 100644 (file)
@@ -4002,12 +4002,28 @@ class ForFromStatNode(LoopNode, StatNode):
         self.body.generate_execution_code(code)
         code.put_label(code.continue_label)
         if self.py_loopvar_node:
-            # Reassign py variable to loop var here.
-            # (For consistancy, should rarely come up in practice.)
+            # This mess is to make for..from loops with python targets behave 
+            # exactly like those with C targets with regards to re-assignment 
+            # of the loop variable. 
             import ExprNodes
-            from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, self.target, None)
+            if self.target.entry.is_pyglobal:
+                # We know target is a NameNode, this is the only ugly case. 
+                target_node = ExprNodes.PyTempNode(self.target.pos, None)
+                target_node.result_code = code.funcstate.allocate_temp(py_object_type, False)
+                code.putln("%s = __Pyx_GetName(%s, %s); %s" % (
+                                target_node.result_code,
+                                Naming.module_cname, 
+                                self.target.entry.interned_cname,
+                                code.error_goto_if_null(target_node.result_code, self.target.pos)))
+                code.put_gotref(target_node.result_code)
+            else:
+                target_node = self.target
+            from_py_node = ExprNodes.CoerceFromPyTypeNode(self.loopvar_node.type, target_node, None)
             from_py_node.temp_code = loopvar_name
             from_py_node.generate_result_code(code)
+            if self.target.entry.is_pyglobal:
+                code.put_decref_clear(target_node.result_code, py_object_type)
+                code.funcstate.release_temp(target_node.result_code)
         code.putln("}")
         if self.py_loopvar_node:
             # This is potentially wasteful, but we don't want the semantics to 
index eadfde1288b095e530f391a4791f78c80cb4012e..00e94a970e5077dd53ead3ec3576c97d6874133f 100644 (file)
@@ -46,6 +46,12 @@ at 1
 at 3
 at 7
 15
+>>> for_from_py_global_target_reassignment(10, 2)
+at 0
+at 1
+at 3
+at 7
+15
 >>> for_in_target_reassignment(10, 2)
 at 0
 at 1
@@ -112,6 +118,13 @@ def for_from_py_target_reassignment(int bound, int factor):
         i *= factor
     return i
 
+def for_from_py_global_target_reassignment(int bound, int factor):
+    global g_var
+    for g_var from 0 <= g_var < bound:
+        print "at", g_var
+        g_var *= factor
+    return g_var
+
 def for_in_target_reassignment(int bound, int factor):
     cdef int i = 100
     for i in range(bound):