Commit 8f716f15 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Start replacing TempBlockNode with LetNode/EvalWithTempExprNode

parent 3b0a3e59
......@@ -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
......
......@@ -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)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment