From de6dcfaead79758c10ed42db53b4a09ff6f7d063 Mon Sep 17 00:00:00 2001 From: Dag Sverre Seljebotn Date: Fri, 15 Aug 2008 18:11:40 +0200 Subject: [PATCH] Backed out changeset c59d0e5d0bdf -- it broke C array inplace operations --- Cython/Compiler/ExprNodes.py | 65 +++++++++++++++++------------------- Cython/Compiler/Nodes.py | 30 +++-------------- tests/run/bufaccess.pyx | 29 ---------------- 3 files changed, 35 insertions(+), 89 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 9ec23bcd..a1b7982e 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -1379,7 +1379,7 @@ class IndexNode(ExprNode): skip_child_analysis = False buffer_access = False if self.base.type.is_buffer: - assert hasattr(self.base, "entry") # Must be a NameNode-like node + assert isinstance(self.base, NameNode) if isinstance(self.index, TupleNode): indices = self.index.args else: @@ -1394,7 +1394,7 @@ class IndexNode(ExprNode): if buffer_access: self.indices = indices - self.index = None # note that original is kept in _index, which is used for cloning + self.index = None self.type = self.base.type.dtype self.is_buffer_access = True self.buffer_type = self.base.entry.type @@ -1469,19 +1469,19 @@ class IndexNode(ExprNode): def generate_subexpr_evaluation_code(self, code): self.base.generate_evaluation_code(code) - if self.indices: + if self.index is not None: + self.index.generate_evaluation_code(code) + else: 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.indices: + if self.index is not None: + self.index.generate_disposal_code(code) + else: 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: @@ -1525,34 +1525,30 @@ class IndexNode(ExprNode): 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: - self.generate_buffer_assignment_code(rhs, code) + 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)) elif self.type.is_pyobject: self.generate_setitem_code(rhs.py_result(), code) else: @@ -3941,7 +3937,6 @@ class CoercionNode(ExprNode): 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)) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index df2ac65e..f10d278d 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -71,12 +71,10 @@ class Node(object): # 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 @@ -2519,13 +2517,12 @@ class InPlaceAssignmentNode(AssignmentNode): def generate_execution_code(self, code): self.rhs.generate_evaluation_code(code) self.dup.generate_subexpr_evaluation_code(code) - # self.dup.generate_result_code is run only if it is not buffer access + self.dup.generate_result_code(code) 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, @@ -2548,12 +2545,7 @@ class InPlaceAssignmentNode(AssignmentNode): else: error(self.pos, "No C inplace power operator") # have to do assignment directly to avoid side-effects - 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) ) + 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) @@ -2563,23 +2555,11 @@ class InPlaceAssignmentNode(AssignmentNode): 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, - options = self.dup.options) + target_lhs = ExprNodes.NameNode(self.dup.pos, name = self.dup.name, is_temp = self.dup.is_temp, entry = self.dup.entry) 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, - options = self.dup.options) + target_lhs = ExprNodes.AttributeNode(self.dup.pos, obj = ExprNodes.CloneNode(self.lhs.obj), attribute = self.dup.attribute, is_temp = self.dup.is_temp) 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, - options = self.dup.options) + 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) self.lhs = target_lhs return self.dup diff --git a/tests/run/bufaccess.pyx b/tests/run/bufaccess.pyx index 5d7d32e1..a4ad192c 100644 --- a/tests/run/bufaccess.pyx +++ b/tests/run/bufaccess.pyx @@ -596,23 +596,12 @@ TODO uc[0] = 3.14 print uc[0] - cdef char* ch = "asfd" - cdef object[object] objbuf - objbuf[3] = ch - # # Testing that accessing data using various types of buffer access # 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 def printbuf_int_2d(o, shape): @@ -665,24 +654,6 @@ def printbuf_float(o, shape): 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 # -- 2.26.2