# 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 = '+',
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)
]
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
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
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
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):
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)