pass
-class TempNode(ExprNode):
- # Node created during analyse_types phase
- # of some nodes to hold a temporary value.
+class TempNode(NewTempExprNode):
+ # Node created during analyse_types phase
+ # of some nodes to hold a temporary value.
+ #
+ # Note: One must call "allocate" and "release" on
+ # the node during code generation to get/release the temp.
+ # This is because the temp result is often used outside of
+ # the regular cycle.
subexprs = []
def generate_result_code(self, code):
pass
+ def allocate(self, code):
+ self.temp_cname = code.funcstate.allocate_temp(self.type, manage_ref=True)
+
+ def release(self, code):
+ code.funcstate.release_temp(self.temp_cname)
+ self.temp_cname = None
+
+ def result(self):
+ try:
+ return self.temp_cname
+ except:
+ assert False, "Remember to call allocate/release on TempNode"
+ raise
+
+ # Do not participate in normal temp alloc/dealloc:
+ def allocate_temp_result(self, code):
+ pass
+
+ def release_temp_result(self, code):
+ pass
class PyTempNode(TempNode):
# TempNode holding a Python value.
rhs.py_result(),
len(self.args)))
code.putln("PyObject* tuple = %s;" % rhs.py_result())
+ for item in self.unpacked_items:
+ item.allocate(code)
for i in range(len(self.args)):
item = self.unpacked_items[i]
code.put(
rhs.py_result(), len(self.args)))
code.putln(code.error_goto(self.pos))
else:
+ self.iterator.allocate(code)
code.putln(
"%s = PyObject_GetIter(%s); %s" % (
self.iterator.result(),
print("...generating disposal code for %s" % self.iterator)
self.iterator.generate_disposal_code(code)
self.iterator.free_temps(code)
+ self.iterator.release(code)
for i in range(len(self.args)):
self.args[i].generate_assignment_code(
self.coerced_unpacked_items[i], code)
code.putln("}")
+ for item in self.unpacked_items:
+ item.release(code)
rhs.free_temps(code)
def annotate(self, code):
code.putln("else {")
else:
code.putln("else if (unlikely(Py_TYPE(%s)->tp_dictoffset != 0)) {" % self_arg)
+ self.func_node.allocate(code)
err = code.error_goto_if_null(self.func_node.result(), self.pos)
# need to get attribute manually--scope would return cdef method
code.putln("%s = PyObject_GetAttr(%s, %s); %s" % (
code.putln('}')
code.put_decref_clear(self.func_node.result(), PyrexTypes.py_object_type)
code.putln("}")
+ self.func_node.release(code)
class ClassDefNode(StatNode, BlockNode):
pass
elif self.rhs.type.is_pyobject:
self.rhs = self.rhs.coerce_to(self.lhs.type, env)
if self.lhs.type.is_pyobject:
- self.result_value = ExprNodes.PyTempNode(self.pos, env).coerce_to(self.lhs.type, env)
- self.result_value.allocate_temps(env)
+ self.result_value_temp = ExprNodes.PyTempNode(self.pos, env)
+ self.result_value = self.result_value_temp.coerce_to(self.lhs.type, env)
+ self.result_value.allocate_temps(env)
# if use_temp:
# self.rhs = self.rhs.coerce_to_temp(env)
self.rhs.allocate_temps(env)
if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
error(self.pos, "In-place operators not allowed on object buffers in this release.")
self.dup.generate_result_code(code)
+ self.result_value_temp.allocate(code)
code.putln(
"%s = %s(%s, %s%s); %s" % (
self.result_value.result(),
self.dup.generate_disposal_code(code)
self.dup.free_temps(code)
self.lhs.generate_assignment_code(self.result_value, code)
+ self.result_value_temp.release(code)
else:
c_op = self.operator
if c_op == "//":
self.step.generate_evaluation_code(code)
step = self.step.result()
incop = "%s=%s" % (incop[0], step)
+ import ExprNodes
+ if isinstance(self.loopvar_node, ExprNodes.TempNode):
+ self.loopvar_node.allocate(code)
+ if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
+ self.py_loopvar_node.allocate(code)
if from_range:
loopvar_name = code.funcstate.allocate_temp(self.target.type, False)
else:
self.bound1.free_temps(code)
self.bound2.generate_disposal_code(code)
self.bound2.free_temps(code)
+ if isinstance(self.loopvar_node, ExprNodes.TempNode):
+ self.loopvar_node.release(code)
+ if isinstance(self.py_loopvar_node, ExprNodes.TempNode):
+ self.py_loopvar_node.release(code)
if self.step is not None:
self.step.generate_disposal_code(code)
self.step.free_temps(code)
Naming.import_star,
self.module.py_result(),
code.error_goto(self.pos)))
+ self.item.allocate(code)
for name, target, coerced_item in self.interned_items:
cname = code.intern_identifier(name)
code.putln(
target.generate_assignment_code(coerced_item, code)
if self.item.result() != coerced_item.result():
code.put_decref_clear(self.item.result(), self.item.type)
+ self.item.release(code)
self.module.generate_disposal_code(code)
self.module.free_temps(code)