skip_child_analysis = False
buffer_access = False
if self.base.type.is_buffer:
- assert isinstance(self.base, NameNode)
+ assert hasattr(self.base, "entry") # Must be a NameNode-like node
if isinstance(self.index, TupleNode):
indices = self.index.args
else:
if buffer_access:
self.indices = indices
- self.index = None
+ self.index = None # note that original is kept in _index, which is used for cloning
self.type = self.base.type.dtype
self.is_buffer_access = True
self.buffer_type = self.base.entry.type
def generate_subexpr_evaluation_code(self, code):
self.base.generate_evaluation_code(code)
- if self.index is not None:
- self.index.generate_evaluation_code(code)
- else:
+ if self.indices:
for i in self.indices:
i.generate_evaluation_code(code)
-
+ else:
+ self.index.generate_evaluation_code(code)
+
def generate_subexpr_disposal_code(self, code):
self.base.generate_disposal_code(code)
- if self.index is not None:
- self.index.generate_disposal_code(code)
- else:
+ if self.indices:
for i in self.indices:
i.generate_disposal_code(code)
+ else:
+ self.index.generate_disposal_code(code)
def generate_result_code(self, code):
if self.is_buffer_access:
value_code,
self.index_unsigned_parameter(),
code.error_goto(self.pos)))
-
+
+ def generate_buffer_assignment_code(self, rhs, code, op=""):
+ # Used from generate_assignment_code and InPlaceAssignmentNode
+ ptrexpr = self.buffer_lookup_code(code)
+ if self.buffer_type.dtype.is_pyobject:
+ # Must manage refcounts. Decref what is already there
+ # and incref what we put in.
+ ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
+ if rhs.is_temp: #TODO: REMOVE
+ rhs_code = code.funcstate.allocate_temp(rhs.type)
+ else:
+ rhs_code = rhs.result_code
+ code.putln("%s = %s;" % (ptr, ptrexpr))
+ code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
+ ptr, rhs_code
+ ))
+ code.putln("*%s %s= %s;" % (ptr, op, rhs_code))
+ if rhs.is_temp:
+ code.funcstate.release_temp(rhs_code)
+ code.funcstate.release_temp(ptr)
+ else:
+ # Simple case
+ code.putln("*%s %s= %s;" % (ptrexpr, op, rhs.result_code))
+
def generate_assignment_code(self, rhs, code):
self.generate_subexpr_evaluation_code(code)
if self.is_buffer_access:
- ptrexpr = self.buffer_lookup_code(code)
- if self.buffer_type.dtype.is_pyobject:
- # Must manage refcounts. Decref what is already there
- # and incref what we put in.
- ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type)
- if rhs.is_temp:
- rhs_code = code.funcstate.allocate_temp(rhs.type)
- else:
- rhs_code = rhs.result_code
- code.putln("%s = %s;" % (ptr, ptrexpr))
- code.putln("Py_DECREF(*%s); Py_INCREF(%s);" % (
- ptr, rhs_code
- ))
- code.putln("*%s = %s;" % (ptr, rhs_code))
- if rhs.is_temp:
- code.funcstate.release_temp(rhs_code)
- code.funcstate.release_temp(ptr)
- else:
- # Simple case
- code.putln("*%s = %s;" % (ptrexpr, rhs.result_code))
+ self.generate_buffer_assignment_code(rhs, code)
elif self.type.is_pyobject:
self.generate_setitem_code(rhs.py_result(), code)
else:
def __init__(self, arg):
self.pos = arg.pos
self.arg = arg
+ self.options = arg.options
if debug_coercion:
print("%s Coercing %s" % (self, self.arg))
# pos (string, int, int) Source file position
# is_name boolean Is a NameNode
# is_literal boolean Is a ConstNode
+ # options dict Compiler directives for this node
is_name = 0
is_literal = 0
temps = None
+ options = {}
# All descandants should set child_attrs to a list of the attributes
# containing nodes considered "children" in the tree. Each such attribute
def generate_execution_code(self, code):
self.rhs.generate_evaluation_code(code)
self.dup.generate_subexpr_evaluation_code(code)
- self.dup.generate_result_code(code)
+ # self.dup.generate_result_code is run only if it is not buffer access
if self.operator == "**":
extra = ", Py_None"
else:
extra = ""
if self.lhs.type.is_pyobject:
+ self.dup.generate_result_code(code)
code.putln(
"%s = %s(%s, %s%s); %s" % (
self.result.result_code,
else:
error(self.pos, "No C inplace power operator")
# have to do assignment directly to avoid side-effects
- code.putln("%s %s= %s;" % (self.lhs.result_code, c_op, self.rhs.result_code) )
+ import ExprNodes
+ if isinstance(self.lhs, ExprNodes.IndexNode) and self.lhs.is_buffer_access:
+ self.lhs.generate_buffer_assignment_code(self.rhs, code, c_op)
+ else:
+ self.dup.generate_result_code(code)
+ code.putln("%s %s= %s;" % (self.lhs.result_code, c_op, self.rhs.result_code) )
self.rhs.generate_disposal_code(code)
if self.dup.is_temp:
self.dup.generate_subexpr_disposal_code(code)
self.dup = self.lhs
self.dup.analyse_types(env)
if isinstance(self.lhs, ExprNodes.NameNode):
- target_lhs = ExprNodes.NameNode(self.dup.pos, name = self.dup.name, is_temp = self.dup.is_temp, entry = self.dup.entry)
+ target_lhs = ExprNodes.NameNode(self.dup.pos,
+ name = self.dup.name,
+ is_temp = self.dup.is_temp,
+ entry = self.dup.entry,
+ options = self.dup.options)
elif isinstance(self.lhs, ExprNodes.AttributeNode):
- target_lhs = ExprNodes.AttributeNode(self.dup.pos, obj = ExprNodes.CloneNode(self.lhs.obj), attribute = self.dup.attribute, is_temp = self.dup.is_temp)
+ target_lhs = ExprNodes.AttributeNode(self.dup.pos,
+ obj = ExprNodes.CloneNode(self.lhs.obj),
+ attribute = self.dup.attribute,
+ is_temp = self.dup.is_temp,
+ options = self.dup.options)
elif isinstance(self.lhs, ExprNodes.IndexNode):
- target_lhs = ExprNodes.IndexNode(self.dup.pos, base = ExprNodes.CloneNode(self.dup.base), index = ExprNodes.CloneNode(self.lhs.index), is_temp = self.dup.is_temp)
+ target_lhs = ExprNodes.IndexNode(self.dup.pos,
+ base = ExprNodes.CloneNode(self.dup.base),
+ index = ExprNodes.CloneNode(self.lhs._index),
+ is_temp = self.dup.is_temp,
+ options = self.dup.options)
self.lhs = target_lhs
return self.dup