Hi,

Magnus Lie Hetland wrote:
> Should I upload a patch to the tracker?

Sure, that will allow us to take a look at it and compare it to the
while-loop alternative. Just use "hg export" to keep the meta data.


> it occurred to me that it might be
> cleaner to just ditch the for loop than to undo its semantics. It  
> won't help on the extra check needed to see if we assign to the loop  
> variable at all (i.e., what I'm doing here), but by using a while-loop  
> with the proper test, we should be able to avoid the spurious  
> increment and the "undo" operation. Worth a shot?

That's my impression, too. I attached an old (incomplete) patch I had lying
around, don't know if it's still any good. Generating a straight
WhileStatNode instead might already do the right thing (and be less
invasive, given that we are nearing a release). See the methods of the
IterationTransform class in Optimize.py for that.


> Or do C compilers  
> somehow rely on the use of for loops for some kind of optimization  
> inference or something?

No idea. But I doubt that a while loop would be slower than the equivalent
for loop. Plus, we need to fix the semantics here, which is more important
than the last bit of performance.


> there also seemed to be a problem when running  
> with the refnanny.

Could you be a bit more specific here? :)


> the tests work without the refnanny (except for
> the NumPy stuff, which all fails because I haven't properly installed
> NumPy at the moment;

It should actually check for numpy being installed and just skip the test
if not. At least, that's what it does here.

Stefan
diff -r 9234404eed45 Cython/Compiler/Nodes.py
--- a/Cython/Compiler/Nodes.py	Tue Dec 23 10:42:06 2008 +0100
+++ b/Cython/Compiler/Nodes.py	Tue Dec 23 15:03:35 2008 +0100
@@ -3619,7 +3619,80 @@ class LoopNode:
             self.else_clause.analyse_control_flow(env)
         env.finish_branching(self.end_pos())
 
-    
+
+class GeneralLoopNode(LoopNode, StatNode):
+    # for-in or while loop
+    #
+    # This node is created by transforms.  It is like a while-loop
+    # with 0-n preparation statements and 0-m conditions.  If no
+    # condition is provided, it should have at least one break
+    # statement in its body.
+    #
+    #  preparations      StatNode or None
+    #  while_conditions  [ExprNode]
+    #  body              StatNode
+    #  else_clause       StatNode or None
+    #  is_for_loop       boolean           (for code beauty only)
+
+    is_for_loop = False
+    preparations = []
+    conditions = []
+    child_attrs = ["preparations", "conditions", "body", "else_clause"]
+
+    def analyse_declarations(self, env):
+        for preparation in self.preparations:
+            preparation.analyse_declarations(env)
+        self.body.analyse_declarations(env)
+        if self.else_clause:
+            self.else_clause.analyse_declarations(env)
+    
+    def analyse_expressions(self, env):
+        for preparation in self.preparations:
+            preparation.analyse_expressions(env)
+        conditions = []
+        for condition in self.while_conditions:
+            condition = condition.analyse_temp_boolean_expression(env)
+            condition.release_temp(env)
+            conditions.append(condition)
+        self.while_conditions = conditions
+        self.body.analyse_expressions(env)
+        if self.else_clause:
+            self.else_clause.analyse_expressions(env)
+    
+    def generate_execution_code(self, code):
+        old_loop_labels = code.new_loop_labels()
+        for preparation in self.preparations:
+            preparation.generate_execution_code(code)
+        if self.is_for_loop:
+            code.putln("for (;;) {")
+        else:
+            code.putln("while (1) {")
+        for condition in self.while_conditions:
+            condition.generate_evaluation_code(code)
+            condition.generate_disposal_code(code)
+            code.putln(
+                "if (!%s) break;" %
+                condition.result())
+            condition.free_temps(code)
+        self.body.generate_execution_code(code)
+        code.put_label(code.continue_label)
+        code.putln("}")
+        break_label = code.break_label
+        code.set_loop_labels(old_loop_labels)
+        if self.else_clause:
+            code.putln("/*else*/ {")
+            self.else_clause.generate_execution_code(code)
+            code.putln("}")
+        code.put_label(break_label)
+
+    def annotate(self, code):
+        for condition in self.while_conditions:
+            condition.annotate(code)
+        self.body.annotate(code)
+        if self.else_clause:
+            self.else_clause.annotate(code)
+
+
 class WhileStatNode(LoopNode, StatNode):
     #  while statement
     #
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to