Start replacing TempBlockNode with LetNode/EvalWithTempExprNode
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Tue, 19 May 2009 20:01:32 +0000 (22:01 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Tue, 19 May 2009 20:01:32 +0000 (22:01 +0200)
Cython/Compiler/Optimize.py
Cython/Compiler/UtilNodes.py

index ea1c6b283b5f8e71407a50fa0eb04810798eacc1..884a215b1958ed05dc6eff3313f39c3faf12ebbf 100644 (file)
@@ -148,12 +148,11 @@ class IterationTransform(Visitor.VisitorTransform):
             # nothing we can do here, I guess
             return node
 
-        temp = UtilNodes.TempHandle(counter_type)
-        init_val = ExprNodes.IntNode(enumerate_function.pos, value='0',
-                                     type=counter_type)
+        temp = UtilNodes.LetRefNode(ExprNodes.IntNode(enumerate_function.pos, value='0',
+                                                      type=counter_type))
         inc_expression = ExprNodes.AddNode(
             enumerate_function.pos,
-            operand1 = temp.ref(enumerate_target.pos),
+            operand1 = temp,
             operand2 = ExprNodes.IntNode(node.pos, value='1',
                                          type=counter_type),
             operator = '+',
@@ -165,10 +164,10 @@ class IterationTransform(Visitor.VisitorTransform):
             Nodes.SingleAssignmentNode(
                 pos = enumerate_target.pos,
                 lhs = enumerate_target,
-                rhs = temp.ref(enumerate_target.pos)),
+                rhs = temp),
             Nodes.SingleAssignmentNode(
                 pos = enumerate_target.pos,
-                lhs = temp.ref(enumerate_target.pos),
+                lhs = temp,
                 rhs = inc_expression)
             ]
 
@@ -184,22 +183,7 @@ class IterationTransform(Visitor.VisitorTransform):
         node.iterator.sequence = enumerate_function.arg_tuple.args[0]
 
         # recurse into loop to check for further optimisations
-        node = self._optimise_for_loop(node)
-
-        statements = [
-            Nodes.SingleAssignmentNode(
-                pos = enumerate_target.pos,
-                lhs = temp.ref(enumerate_target.pos),
-                rhs = init_val),
-            node
-            ]
-
-        return UtilNodes.TempsBlockNode(
-            node.pos, temps=[temp],
-            body=Nodes.StatListNode(
-                node.pos,
-                stats = statements
-                ))
+        return UtilNodes.LetNode(temp, self._optimise_for_loop(node)) 
 
     def _transform_range_iteration(self, node, range_function):
         args = range_function.arg_tuple.args
index 091a8f542b1c9065fe3b5bc4f5ee5780a496e688..79d4b78c856440b4c573bf8594e4fb8860faf0ae 100644 (file)
@@ -116,6 +116,8 @@ class ResultRefNode(AtomicExprNode):
     def __init__(self, expression):
         self.pos = expression.pos
         self.expression = expression
+        if hasattr(expression, "type"):
+            self.type = expression.type
 
     def analyse_types(self, env):
         self.type = self.expression.type
@@ -132,6 +134,14 @@ class ResultRefNode(AtomicExprNode):
     def generate_disposal_code(self, code):
         pass
                 
+    def generate_assignment_code(self, rhs, code):
+        if self.type.is_pyobject:
+            rhs.make_owned_reference(code)
+            code.put_decref(self.result(), self.ctype())
+        code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
+        rhs.generate_post_assignment_code(code)
+        rhs.free_temps(code)
+
     def allocate_temps(self, env):
         pass
         
@@ -142,16 +152,39 @@ class ResultRefNode(AtomicExprNode):
         pass
 
 
-class EvalWithTempExprNode(ExprNodes.ExprNode):
+class LetNodeMixin:
+    def set_temp_expr(self, lazy_temp):
+        self.lazy_temp = lazy_temp
+        self.temp_expression = lazy_temp.expression
+
+    def setup_temp_expr(self, code):
+        self.temp_expression.generate_evaluation_code(code)
+        self.result_in_temp = self.temp_expression.result_in_temp()
+        self.temp_type = self.temp_expression.type
+        if self.result_in_temp:
+            self.temp = self.temp_expression.result()
+        else:
+            self.temp_expression.make_owned_reference(code)
+            self.temp = code.funcstate.allocate_temp(
+                self.temp_type, manage_ref=True)
+            code.putln("%s = %s;" % (self.temp, self.temp_expression.result()))
+        self.lazy_temp.result_code = self.temp
+
+    def teardown_temp_expr(self, code):
+       if not self.result_in_temp:
+            if self.temp_type.is_pyobject:
+                code.put_decref_clear(self.temp, self.temp_type)
+            code.funcstate.release_temp(self.temp)
+
+class EvalWithTempExprNode(ExprNodes.ExprNode, LetNodeMixin):
     # A wrapper around a subexpression that moves an expression into a
     # temp variable and provides it to the subexpression.
 
     subexprs = ['temp_expression', 'subexpression']
 
     def __init__(self, lazy_temp, subexpression):
+        self.set_temp_expr(lazy_temp)
         self.pos = subexpression.pos
-        self.lazy_temp = lazy_temp
-        self.temp_expression = lazy_temp.expression
         self.subexpression = subexpression
 
     def result(self):
@@ -163,19 +196,29 @@ class EvalWithTempExprNode(ExprNodes.ExprNode):
         self.type = self.subexpression.type
 
     def generate_evaluation_code(self, code):
-        self.temp_expression.generate_evaluation_code(code)
-        result_in_temp = self.temp_expression.result_in_temp()
-        temp_type = self.temp_expression.type
-        if result_in_temp:
-            temp = self.temp_expression.result()
-        else:
-            self.temp_expression.make_owned_reference(code)
-            temp = code.funcstate.allocate_temp(
-                temp_type, manage_ref=True)
-            code.putln("%s = %s;" % (temp, self.temp_expression.result()))
-        self.lazy_temp.result_code = temp
+        self.setup_temp_expr(code)
         self.subexpression.generate_evaluation_code(code)
-        if not result_in_temp:
-            if temp_type.is_pyobject:
-                code.put_decref_clear(temp, temp_type)
-            code.funcstate.release_temp(temp)
+        self.teardown_temp_expr(code)
+LetRefNode = ResultRefNode
+
+class LetNode(Nodes.StatNode, LetNodeMixin):
+    # Implements a local temporary variable scope. Imagine this
+    # syntax being present:
+    # let temp = VALUE:
+    #     BLOCK (can modify temp)
+    #     if temp is an object, decref
+    #
+    # To be used after analysis phase, does no analysis.
+
+    child_attrs = ['temp_expression', 'body']
+
+    def __init__(self, lazy_temp, body):
+        self.set_temp_expr(lazy_temp)
+        self.pos = body.pos
+        self.body = body
+
+    def generate_execution_code(self, code):
+        self.setup_temp_expr(code)
+        self.body.generate_execution_code(code)
+        self.teardown_temp_expr(code)