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): ...@@ -148,12 +148,11 @@ class IterationTransform(Visitor.VisitorTransform):
# nothing we can do here, I guess # nothing we can do here, I guess
return node return node
temp = UtilNodes.TempHandle(counter_type) temp = UtilNodes.LetRefNode(ExprNodes.IntNode(enumerate_function.pos, value='0',
init_val = ExprNodes.IntNode(enumerate_function.pos, value='0', type=counter_type))
type=counter_type)
inc_expression = ExprNodes.AddNode( inc_expression = ExprNodes.AddNode(
enumerate_function.pos, enumerate_function.pos,
operand1 = temp.ref(enumerate_target.pos), operand1 = temp,
operand2 = ExprNodes.IntNode(node.pos, value='1', operand2 = ExprNodes.IntNode(node.pos, value='1',
type=counter_type), type=counter_type),
operator = '+', operator = '+',
...@@ -165,10 +164,10 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -165,10 +164,10 @@ class IterationTransform(Visitor.VisitorTransform):
Nodes.SingleAssignmentNode( Nodes.SingleAssignmentNode(
pos = enumerate_target.pos, pos = enumerate_target.pos,
lhs = enumerate_target, lhs = enumerate_target,
rhs = temp.ref(enumerate_target.pos)), rhs = temp),
Nodes.SingleAssignmentNode( Nodes.SingleAssignmentNode(
pos = enumerate_target.pos, pos = enumerate_target.pos,
lhs = temp.ref(enumerate_target.pos), lhs = temp,
rhs = inc_expression) rhs = inc_expression)
] ]
...@@ -184,22 +183,7 @@ class IterationTransform(Visitor.VisitorTransform): ...@@ -184,22 +183,7 @@ class IterationTransform(Visitor.VisitorTransform):
node.iterator.sequence = enumerate_function.arg_tuple.args[0] node.iterator.sequence = enumerate_function.arg_tuple.args[0]
# recurse into loop to check for further optimisations # recurse into loop to check for further optimisations
node = self._optimise_for_loop(node) return UtilNodes.LetNode(temp, 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
))
def _transform_range_iteration(self, node, range_function): def _transform_range_iteration(self, node, range_function):
args = range_function.arg_tuple.args args = range_function.arg_tuple.args
......
...@@ -116,6 +116,8 @@ class ResultRefNode(AtomicExprNode): ...@@ -116,6 +116,8 @@ class ResultRefNode(AtomicExprNode):
def __init__(self, expression): def __init__(self, expression):
self.pos = expression.pos self.pos = expression.pos
self.expression = expression self.expression = expression
if hasattr(expression, "type"):
self.type = expression.type
def analyse_types(self, env): def analyse_types(self, env):
self.type = self.expression.type self.type = self.expression.type
...@@ -132,6 +134,14 @@ class ResultRefNode(AtomicExprNode): ...@@ -132,6 +134,14 @@ class ResultRefNode(AtomicExprNode):
def generate_disposal_code(self, code): def generate_disposal_code(self, code):
pass 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): def allocate_temps(self, env):
pass pass
...@@ -142,16 +152,39 @@ class ResultRefNode(AtomicExprNode): ...@@ -142,16 +152,39 @@ class ResultRefNode(AtomicExprNode):
pass 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 # A wrapper around a subexpression that moves an expression into a
# temp variable and provides it to the subexpression. # temp variable and provides it to the subexpression.
subexprs = ['temp_expression', 'subexpression'] subexprs = ['temp_expression', 'subexpression']
def __init__(self, lazy_temp, subexpression): def __init__(self, lazy_temp, subexpression):
self.set_temp_expr(lazy_temp)
self.pos = subexpression.pos self.pos = subexpression.pos
self.lazy_temp = lazy_temp
self.temp_expression = lazy_temp.expression
self.subexpression = subexpression self.subexpression = subexpression
def result(self): def result(self):
...@@ -163,19 +196,29 @@ class EvalWithTempExprNode(ExprNodes.ExprNode): ...@@ -163,19 +196,29 @@ class EvalWithTempExprNode(ExprNodes.ExprNode):
self.type = self.subexpression.type self.type = self.subexpression.type
def generate_evaluation_code(self, code): def generate_evaluation_code(self, code):
self.temp_expression.generate_evaluation_code(code) self.setup_temp_expr(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.subexpression.generate_evaluation_code(code) self.subexpression.generate_evaluation_code(code)
if not result_in_temp: self.teardown_temp_expr(code)
if temp_type.is_pyobject:
code.put_decref_clear(temp, temp_type) LetRefNode = ResultRefNode
code.funcstate.release_temp(temp)
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