Commit 8418439d authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Buffers: Inplace operators working

This time hopefully without breaking other inplace operators.
parent c462cf06
...@@ -1534,30 +1534,34 @@ class IndexNode(ExprNode): ...@@ -1534,30 +1534,34 @@ class IndexNode(ExprNode):
value_code, value_code,
self.index_unsigned_parameter(), self.index_unsigned_parameter(),
code.error_goto(self.pos))) code.error_goto(self.pos)))
def generate_buffer_setitem_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:
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): def generate_assignment_code(self, rhs, code):
self.generate_subexpr_evaluation_code(code) self.generate_subexpr_evaluation_code(code)
if self.is_buffer_access: if self.is_buffer_access:
ptrexpr = self.buffer_lookup_code(code) self.generate_buffer_setitem_code(rhs, 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))
elif self.type.is_pyobject: elif self.type.is_pyobject:
self.generate_setitem_code(rhs.py_result(), code) self.generate_setitem_code(rhs.py_result(), code)
else: else:
...@@ -3946,6 +3950,7 @@ class CoercionNode(ExprNode): ...@@ -3946,6 +3950,7 @@ class CoercionNode(ExprNode):
def __init__(self, arg): def __init__(self, arg):
self.pos = arg.pos self.pos = arg.pos
self.arg = arg self.arg = arg
self.options = arg.options
if debug_coercion: if debug_coercion:
print("%s Coercing %s" % (self, self.arg)) print("%s Coercing %s" % (self, self.arg))
......
...@@ -71,10 +71,12 @@ class Node(object): ...@@ -71,10 +71,12 @@ class Node(object):
# pos (string, int, int) Source file position # pos (string, int, int) Source file position
# is_name boolean Is a NameNode # is_name boolean Is a NameNode
# is_literal boolean Is a ConstNode # is_literal boolean Is a ConstNode
# options dict Compiler directives in effect for this node
is_name = 0 is_name = 0
is_literal = 0 is_literal = 0
temps = None temps = None
options = None
# All descandants should set child_attrs to a list of the attributes # All descandants should set child_attrs to a list of the attributes
# containing nodes considered "children" in the tree. Each such attribute # containing nodes considered "children" in the tree. Each such attribute
...@@ -2517,12 +2519,13 @@ class InPlaceAssignmentNode(AssignmentNode): ...@@ -2517,12 +2519,13 @@ class InPlaceAssignmentNode(AssignmentNode):
def generate_execution_code(self, code): def generate_execution_code(self, code):
self.rhs.generate_evaluation_code(code) self.rhs.generate_evaluation_code(code)
self.dup.generate_subexpr_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 == "**": if self.operator == "**":
extra = ", Py_None" extra = ", Py_None"
else: else:
extra = "" extra = ""
if self.lhs.type.is_pyobject: if self.lhs.type.is_pyobject:
self.dup.generate_result_code(code)
code.putln( code.putln(
"%s = %s(%s, %s%s); %s" % ( "%s = %s(%s, %s%s); %s" % (
self.result.result_code, self.result.result_code,
...@@ -2545,7 +2548,12 @@ class InPlaceAssignmentNode(AssignmentNode): ...@@ -2545,7 +2548,12 @@ class InPlaceAssignmentNode(AssignmentNode):
else: else:
error(self.pos, "No C inplace power operator") error(self.pos, "No C inplace power operator")
# have to do assignment directly to avoid side-effects # 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_setitem_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) self.rhs.generate_disposal_code(code)
if self.dup.is_temp: if self.dup.is_temp:
self.dup.generate_subexpr_disposal_code(code) self.dup.generate_subexpr_disposal_code(code)
...@@ -2558,12 +2566,14 @@ class InPlaceAssignmentNode(AssignmentNode): ...@@ -2558,12 +2566,14 @@ class InPlaceAssignmentNode(AssignmentNode):
target_lhs = ExprNodes.NameNode(self.dup.pos, target_lhs = ExprNodes.NameNode(self.dup.pos,
name = self.dup.name, name = self.dup.name,
is_temp = self.dup.is_temp, is_temp = self.dup.is_temp,
entry = self.dup.entry) entry = self.dup.entry,
options = self.dup.options)
elif isinstance(self.lhs, ExprNodes.AttributeNode): elif isinstance(self.lhs, ExprNodes.AttributeNode):
target_lhs = ExprNodes.AttributeNode(self.dup.pos, target_lhs = ExprNodes.AttributeNode(self.dup.pos,
obj = ExprNodes.CloneNode(self.lhs.obj), obj = ExprNodes.CloneNode(self.lhs.obj),
attribute = self.dup.attribute, attribute = self.dup.attribute,
is_temp = self.dup.is_temp) is_temp = self.dup.is_temp,
options = self.dup.options)
elif isinstance(self.lhs, ExprNodes.IndexNode): elif isinstance(self.lhs, ExprNodes.IndexNode):
if self.lhs.index: if self.lhs.index:
index = ExprNodes.CloneNode(self.lhs.index) index = ExprNodes.CloneNode(self.lhs.index)
...@@ -2577,7 +2587,8 @@ class InPlaceAssignmentNode(AssignmentNode): ...@@ -2577,7 +2587,8 @@ class InPlaceAssignmentNode(AssignmentNode):
base = ExprNodes.CloneNode(self.dup.base), base = ExprNodes.CloneNode(self.dup.base),
index = index, index = index,
indices = indices, indices = indices,
is_temp = self.dup.is_temp) is_temp = self.dup.is_temp,
options = self.dup.options)
self.lhs = target_lhs self.lhs = target_lhs
return self.dup return self.dup
......
...@@ -596,12 +596,23 @@ TODO ...@@ -596,12 +596,23 @@ TODO
uc[0] = <int>3.14 uc[0] = <int>3.14
print uc[0] print uc[0]
cdef char* ch = "asfd"
cdef object[object] objbuf
objbuf[3] = ch
# #
# Testing that accessing data using various types of buffer access # Testing that accessing data using various types of buffer access
# all works. # all works.
# #
def printbuf_int(object[int] buf, shape):
# Utility func
cdef int i
for i in range(shape[0]):
print buf[i],
print 'END'
@testcase @testcase
def printbuf_int_2d(o, shape): def printbuf_int_2d(o, shape):
...@@ -654,6 +665,24 @@ def printbuf_float(o, shape): ...@@ -654,6 +665,24 @@ def printbuf_float(o, shape):
print "END" print "END"
#
# Test assignments
#
@testcase
def inplace_operators(object[int] buf):
"""
>>> buf = IntMockBuffer(None, [2, 2])
>>> inplace_operators(buf)
>>> printbuf_int(buf, (2,))
0 3 END
"""
cdef int j = 0
buf[1] += 1
buf[j] *= 2
buf[0] -= 4
# #
# Typedefs # Typedefs
# #
......
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