From 0cda22c4e17a7f26a658ebeeed15dcd23f368598 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 13 Nov 2008 23:17:51 +0100 Subject: [PATCH] allow slice assignments for arrays --- Cython/Compiler/ExprNodes.py | 50 ++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index 86bdec15..44c7120f 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -1779,19 +1779,29 @@ class SliceIndexNode(ExprNode): self.start.analyse_types(env) if self.stop: self.stop.analyse_types(env) - self.base = self.base.coerce_to_pyobject(env) + if self.base.type.is_array or self.base.type.is_ptr: + # we need a ptr type here instead of an array type, as + # array types can result in invalid type casts in the C + # code + self.type = PyrexTypes.CPtrType(self.base.type.base_type) + else: + self.base = self.base.coerce_to_pyobject(env) + self.type = py_object_type c_int = PyrexTypes.c_py_ssize_t_type if self.start: self.start = self.start.coerce_to(c_int, env) if self.stop: self.stop = self.stop.coerce_to(c_int, env) - self.type = py_object_type self.gil_check(env) self.is_temp = 1 gil_message = "Slicing Python object" def generate_result_code(self, code): + if not self.type.is_pyobject: + error(self.pos, + "Slicing is not currently supported for '%s'." % self.type) + return code.putln( "%s = PySequence_GetSlice(%s, %s, %s); %s" % ( self.result(), @@ -1802,16 +1812,38 @@ class SliceIndexNode(ExprNode): def generate_assignment_code(self, rhs, code): self.generate_subexpr_evaluation_code(code) - code.put_error_if_neg(self.pos, - "PySequence_SetSlice(%s, %s, %s, %s)" % ( - self.base.py_result(), - self.start_code(), - self.stop_code(), - rhs.result())) + if self.type.is_pyobject: + code.put_error_if_neg(self.pos, + "PySequence_SetSlice(%s, %s, %s, %s)" % ( + self.base.py_result(), + self.start_code(), + self.stop_code(), + rhs.result())) + else: + if rhs.type.is_array: + # FIXME: we should check both array sizes here + array_length = rhs.type.size + else: + array_length = self.base.type.size + start_offset = '' + if self.start: + start_offset = self.start_code() + if start_offset == '0': + start_offset = '' + else: + start_offset += '+' + for i in range(array_length): + code.putln("%s[%s%s] = %s[%d];" % ( + self.base.result(), start_offset, i, + rhs.result(), i)) self.generate_subexpr_disposal_code(code) rhs.generate_disposal_code(code) def generate_deletion_code(self, code): + if not self.type.is_pyobject: + error(self.pos, + "Deleting slices is only supported for Python types, not '%s'." % self.type) + return self.generate_subexpr_evaluation_code(code) code.put_error_if_neg(self.pos, "PySequence_DelSlice(%s, %s, %s)" % ( @@ -1829,6 +1861,8 @@ class SliceIndexNode(ExprNode): def stop_code(self): if self.stop: return self.stop.result() + elif self.base.type.is_array: + return self.base.type.size else: return "PY_SSIZE_T_MAX" -- 2.26.2