From 8f716f150f1e118124f13dfe6bfebcaacde35056 Mon Sep 17 00:00:00 2001 From: Dag Sverre Seljebotn Date: Tue, 19 May 2009 22:01:32 +0200 Subject: [PATCH] Start replacing TempBlockNode with LetNode/EvalWithTempExprNode --- Cython/Compiler/Optimize.py | 28 +++---------- Cython/Compiler/UtilNodes.py | 79 ++++++++++++++++++++++++++++-------- 2 files changed, 67 insertions(+), 40 deletions(-) diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py index ea1c6b28..884a215b 100644 --- a/Cython/Compiler/Optimize.py +++ b/Cython/Compiler/Optimize.py @@ -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 diff --git a/Cython/Compiler/UtilNodes.py b/Cython/Compiler/UtilNodes.py index 091a8f54..79d4b78c 100644 --- a/Cython/Compiler/UtilNodes.py +++ b/Cython/Compiler/UtilNodes.py @@ -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) -- 2.26.2