Commit bf083b70 authored by Kurt Smith's avatar Kurt Smith Committed by Mark Florisson

memoryviewslice declaration and assignments work.

parent 9b3555dc
...@@ -257,6 +257,11 @@ cdef full = Enum("<full axis access mode>") ...@@ -257,6 +257,11 @@ cdef full = Enum("<full axis access mode>")
cdef extern from *: cdef extern from *:
int __Pyx_GetBuffer(object, Py_buffer *, int) int __Pyx_GetBuffer(object, Py_buffer *, int)
void __Pyx_ReleaseBuffer(Py_buffer *) void __Pyx_ReleaseBuffer(Py_buffer *)
void __Pyx_XDECREF(object)
void __Pyx_DECREF(object)
void __Pyx_GIVEREF(object)
void __Pyx_INCREF(object)
void __Pyx_GOTREF(object)
cdef class memoryview(object): cdef class memoryview(object):
...@@ -389,9 +394,13 @@ cdef object init_memviewslice_from_memview( ...@@ -389,9 +394,13 @@ cdef object init_memviewslice_from_memview(
if has_suboffsets: if has_suboffsets:
memviewslice.diminfo[i].suboffsets = pybuf.suboffsets[i] memviewslice.diminfo[i].suboffsets = pybuf.suboffsets[i]
__Pyx_INCREF(<object>memview)
__Pyx_GIVEREF(<object>memview)
__Pyx_GOTREF(<object>memviewslice.memview)
__Pyx_DECREF(<object>memviewslice.memview)
memviewslice.memview = <__pyx_obj_memoryview*>memview memviewslice.memview = <__pyx_obj_memoryview*>memview
memviewslice.data = <char *>pybuf.buf
memviewslice.data = <char *>pybuf.buf
""" % Options.buffer_max_dims, name="foobar", prefix="__pyx_viewaxis_") """ % Options.buffer_max_dims, name="foobar", prefix="__pyx_viewaxis_")
cyarray_prefix = u'__pyx_cythonarray_' cyarray_prefix = u'__pyx_cythonarray_'
......
...@@ -585,11 +585,15 @@ class ExprNode(Node): ...@@ -585,11 +585,15 @@ class ExprNode(Node):
dst_type = dst_type.ref_base_type dst_type = dst_type.ref_base_type
if dst_type.is_memoryview: if dst_type.is_memoryview:
src = CoerceToMemViewNode(src, dst_type, env) import MemoryView
# src = AcquireBufferFromNode(src, env) if not src.type.is_memoryview:
# src = CheckMemoryViewFormatNode(src, dst_type, env) src = CoerceToMemViewNode(src, dst_type, env)
elif not MemoryView.src_conforms_to_dst(src.type, dst_type):
error(self.pos, "Memoryview '%s' not conformable to memoryview '%s'." %
(src.type, dst_type))
if dst_type.is_pyobject:
elif dst_type.is_pyobject:
if not src.type.is_pyobject: if not src.type.is_pyobject:
if dst_type is bytes_type and src.type.is_int: if dst_type is bytes_type and src.type.is_int:
src = CoerceIntToBytesNode(src, env) src = CoerceIntToBytesNode(src, env)
...@@ -1653,7 +1657,7 @@ class NameNode(AtomicExprNode): ...@@ -1653,7 +1657,7 @@ class NameNode(AtomicExprNode):
if self.type.is_memoryview: if self.type.is_memoryview:
self.generate_acquire_memoryview(rhs, code) self.generate_acquire_memoryview(rhs, code)
if self.type.is_buffer: elif self.type.is_buffer:
# Generate code for doing the buffer release/acquisition. # Generate code for doing the buffer release/acquisition.
# This might raise an exception in which case the assignment (done # This might raise an exception in which case the assignment (done
# below) will not happen. # below) will not happen.
...@@ -1687,9 +1691,8 @@ class NameNode(AtomicExprNode): ...@@ -1687,9 +1691,8 @@ class NameNode(AtomicExprNode):
code.put_decref(self.result(), self.ctype()) code.put_decref(self.result(), self.ctype())
if is_external_ref: if is_external_ref:
code.put_giveref(rhs.py_result()) code.put_giveref(rhs.py_result())
if not self.type.is_memoryview:
code.putln('%s = %s;' % (self.result(), code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
rhs.result_as(self.ctype())))
if debug_disposal_code: if debug_disposal_code:
print("NameNode.generate_assignment_code:") print("NameNode.generate_assignment_code:")
print("...generating post-assignment code for %s" % rhs) print("...generating post-assignment code for %s" % rhs)
...@@ -1698,9 +1701,10 @@ class NameNode(AtomicExprNode): ...@@ -1698,9 +1701,10 @@ class NameNode(AtomicExprNode):
def generate_acquire_memoryview(self, rhs, code): def generate_acquire_memoryview(self, rhs, code):
import MemoryView import MemoryView
MemoryView.put_assign_to_memview(self.result(), rhs.result(), self.entry, MemoryView.put_assign_to_memview(self.result(), rhs.result(), self.type,
is_initialized=not self.lhs_of_first_assignment,
pos=self.pos, code=code) pos=self.pos, code=code)
if rhs.is_temp:
code.put_xdecref_clear("%s.memview" % rhs.result(), py_object_type)
def generate_acquire_buffer(self, rhs, code): def generate_acquire_buffer(self, rhs, code):
# rhstmp is only used in case the rhs is a complicated expression leading to # rhstmp is only used in case the rhs is a complicated expression leading to
...@@ -3940,11 +3944,18 @@ class AttributeNode(ExprNode): ...@@ -3940,11 +3944,18 @@ class AttributeNode(ExprNode):
code.put_giveref(rhs.py_result()) code.put_giveref(rhs.py_result())
code.put_gotref(select_code) code.put_gotref(select_code)
code.put_decref(select_code, self.ctype()) code.put_decref(select_code, self.ctype())
code.putln( elif self.type.is_memoryview:
"%s = %s;" % ( import MemoryView
select_code, MemoryView.put_assign_to_memview(select_code, rhs.result(), self.type,
rhs.result_as(self.ctype()))) pos=self.pos, code=code)
#rhs.result())) if rhs.is_temp:
code.put_xdecref_clear("%s.memview" % rhs.result(), py_object_type)
if not self.type.is_memoryview:
code.putln(
"%s = %s;" % (
select_code,
rhs.result_as(self.ctype())))
#rhs.result()))
rhs.generate_post_assignment_code(code) rhs.generate_post_assignment_code(code)
rhs.free_temps(code) rhs.free_temps(code)
self.obj.generate_disposal_code(code) self.obj.generate_disposal_code(code)
...@@ -7583,27 +7594,35 @@ class CoerceToMemViewNode(CoercionNode): ...@@ -7583,27 +7594,35 @@ class CoerceToMemViewNode(CoercionNode):
def __init__(self, arg, dst_type, env): def __init__(self, arg, dst_type, env):
assert dst_type.is_memoryview assert dst_type.is_memoryview
assert not arg.type.is_memoryview
CoercionNode.__init__(self, arg) CoercionNode.__init__(self, arg)
self.type = dst_type self.type = dst_type
self.is_temp = 1
self.env = env self.env = env
self.is_temp = 1
def generate_result_code(self, code): def generate_result_code(self, code):
import MemoryView import MemoryView
memviewobj = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True) memviewobj = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
buf_flag = MemoryView.get_buf_flag(self.type.axes) buf_flag = MemoryView.get_buf_flag(self.type.axes)
code.putln("%s = (PyObject *)__pyx_viewaxis_memoryview_cwrapper(%s, %s);" % (memviewobj, self.arg.result(), buf_flag)) code.putln("%s = (PyObject *)"
"__pyx_viewaxis_memoryview_cwrapper(%s, %s);" %\
(memviewobj, self.arg.result(), buf_flag))
ndim = len(self.type.axes) ndim = len(self.type.axes)
spec_int_arr = code.funcstate.allocate_temp(PyrexTypes.c_array_type(PyrexTypes.c_int_type, ndim),manage_ref=True) spec_int_arr = code.funcstate.allocate_temp(
PyrexTypes.c_array_type(PyrexTypes.c_int_type, ndim),
manage_ref=False)
specs_code = MemoryView.specs_to_code(self.type.axes) specs_code = MemoryView.specs_to_code(self.type.axes)
for idx, cspec in enumerate(specs_code): for idx, cspec in enumerate(specs_code):
code.putln("%s[%d] = %s;" % (spec_int_arr, idx, cspec)) code.putln("%s[%d] = %s;" % (spec_int_arr, idx, cspec))
itemsize = self.type.dtype.sign_and_name() itemsize = self.type.dtype.sign_and_name()
format = MemoryView.format_from_type(self.type.dtype) format = MemoryView.format_from_type(self.type.dtype)
code.putln("__pyx_viewaxis_init_memviewslice_from_memview((struct __pyx_obj_memoryview *)%s, %s, %d, sizeof(%s), \"%s\", &%s);" % (memviewobj, spec_int_arr, ndim, itemsize, format, self.result())) MemoryView.put_init_entry(self.result(), code)
code.putln("__pyx_viewaxis_init_memviewslice_from_memview"
"((struct __pyx_obj_memoryview *)%s, %s, %d, sizeof(%s), \"%s\", &%s);" %\
(memviewobj, spec_int_arr, ndim, itemsize, format, self.result()))
code.put_gotref("%s.memview" % self.result())
code.funcstate.release_temp(memviewobj) code.funcstate.release_temp(memviewobj)
code.funcstate.release_temp(spec_int_arr) code.funcstate.release_temp(spec_int_arr)
code.putln('/* @@@ */')
class CastNode(CoercionNode): class CastNode(CoercionNode):
# Wrap a node in a C type cast. # Wrap a node in a C type cast.
......
...@@ -5,6 +5,7 @@ import Options ...@@ -5,6 +5,7 @@ import Options
import CythonScope import CythonScope
from Code import UtilityCode from Code import UtilityCode
from UtilityCode import CythonUtilityCode from UtilityCode import CythonUtilityCode
from PyrexTypes import py_object_type, cython_memoryview_type
START_ERR = "there must be nothing or the value 0 (zero) in the start slot." START_ERR = "there must be nothing or the value 0 (zero) in the start slot."
STOP_ERR = "Axis specification only allowed in the 'stop' slot." STOP_ERR = "Axis specification only allowed in the 'stop' slot."
...@@ -64,9 +65,24 @@ _typename_to_format = { ...@@ -64,9 +65,24 @@ _typename_to_format = {
def format_from_type(base_type): def format_from_type(base_type):
return _typename_to_format[base_type.sign_and_name()] return _typename_to_format[base_type.sign_and_name()]
def put_assign_to_memview(lhs_cname, rhs_cname, buf_entry, def put_init_entry(mv_cname, code):
is_initialized, pos, code): code.putln("%s.data = NULL;" % mv_cname)
pass code.put_init_to_py_none("%s.memview" % mv_cname, cython_memoryview_type)
code.put_giveref("%s.memview" % mv_cname)
def put_assign_to_memview(lhs_cname, rhs_cname, memviewtype, pos, code):
# XXX: add error checks!
code.put_giveref("%s.memview" % (rhs_cname))
code.put_incref("%s.memview" % (rhs_cname), py_object_type)
code.put_gotref("%s.memview" % (lhs_cname))
code.put_xdecref("%s.memview" % (lhs_cname), py_object_type)
code.putln("%s.memview = %s.memview;" % (lhs_cname, rhs_cname))
code.putln("%s.data = %s.data;" % (lhs_cname, rhs_cname))
ndim = len(memviewtype.axes)
for i in range(ndim):
code.putln("%s.diminfo[%d] = %s.diminfo[%d];" % (lhs_cname, i, rhs_cname, i))
def get_buf_flag(specs): def get_buf_flag(specs):
is_c_contig, is_f_contig = is_cf_contig(specs) is_c_contig, is_f_contig = is_cf_contig(specs)
...@@ -101,6 +117,36 @@ def use_memview_cwrap(env): ...@@ -101,6 +117,36 @@ def use_memview_cwrap(env):
import CythonScope import CythonScope
mv_cwrap_entry = use_cython_util_code(env, CythonScope.memview_cwrap_name) mv_cwrap_entry = use_cython_util_code(env, CythonScope.memview_cwrap_name)
def src_conforms_to_dst(src, dst):
'''
returns True if src conforms to dst, False otherwise.
If conformable, the types are the same, the ndims are equal, and each axis spec is conformable.
Any packing/access spec is conformable to itself.
'contig' and 'follow' are conformable to 'strided'.
'direct' and 'ptr' are conformable to 'full'.
Any other combo is not conformable.
'''
if src.dtype != dst.dtype:
return False
if len(src.axes) != len(dst.axes):
return False
for src_spec, dst_spec in zip(src.axes, dst.axes):
src_access, src_packing = src_spec
dst_access, dst_packing = dst_spec
if src_access != dst_access and dst_access != 'strided':
return False
if src_packing != dst_packing and dst_packing != 'full':
return False
return True
def get_axes_specs(env, axes): def get_axes_specs(env, axes):
''' '''
......
...@@ -1185,10 +1185,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1185,10 +1185,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type = scope.parent_type type = scope.parent_type
base_type = type.base_type base_type = type.base_type
py_attrs = [] py_attrs = []
memview_attrs = []
for entry in scope.var_entries: for entry in scope.var_entries:
if entry.type.is_pyobject: if entry.type.is_pyobject:
py_attrs.append(entry) py_attrs.append(entry)
need_self_cast = type.vtabslot_cname or py_attrs elif entry.type.is_memoryview:
memview_attrs.append(entry)
need_self_cast = type.vtabslot_cname or py_attrs or memview_attrs
code.putln("") code.putln("")
code.putln( code.putln(
"static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {" "static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {"
...@@ -1231,6 +1234,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1231,6 +1234,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("p->%s = 0;" % entry.cname) code.putln("p->%s = 0;" % entry.cname)
else: else:
code.put_init_var_to_py_none(entry, "p->%s", nanny=False) code.put_init_var_to_py_none(entry, "p->%s", nanny=False)
for entry in memview_attrs:
code.putln("p->%s.data = NULL;" % entry.cname)
code.put_init_to_py_none("p->%s.memview" % entry.cname,
PyrexTypes.cython_memoryview_type, nanny=False)
entry = scope.lookup_here("__new__") entry = scope.lookup_here("__new__")
if entry and entry.is_special: if entry and entry.is_special:
if entry.trivial_signature: if entry.trivial_signature:
...@@ -2134,8 +2141,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2134,8 +2141,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# variables to None. # variables to None.
for entry in env.var_entries: for entry in env.var_entries:
if entry.visibility != 'extern': if entry.visibility != 'extern':
if entry.type.is_pyobject and entry.used: if entry.used:
code.put_init_var_to_py_none(entry, nanny=False) entry.type.global_init_code(entry, code)
def generate_c_variable_export_code(self, env, code): def generate_c_variable_export_code(self, env, code):
# Generate code to create PyCFunction wrappers for exported C functions. # Generate code to create PyCFunction wrappers for exported C functions.
......
...@@ -1261,7 +1261,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1261,7 +1261,7 @@ class FuncDefNode(StatNode, BlockNode):
self.body.generate_execution_code(code) self.body.generate_execution_code(code)
def generate_function_definitions(self, env, code): def generate_function_definitions(self, env, code):
import Buffer import Buffer, MemoryView
lenv = self.local_scope lenv = self.local_scope
if lenv.is_closure_scope and not lenv.is_passthrough: if lenv.is_closure_scope and not lenv.is_passthrough:
...@@ -1428,6 +1428,10 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1428,6 +1428,10 @@ class FuncDefNode(StatNode, BlockNode):
for entry in lenv.var_entries + lenv.arg_entries: for entry in lenv.var_entries + lenv.arg_entries:
if entry.type.is_buffer and entry.buffer_aux.buflocal_nd_var.used: if entry.type.is_buffer and entry.buffer_aux.buflocal_nd_var.used:
Buffer.put_init_vars(entry, code) Buffer.put_init_vars(entry, code)
# ----- Initialise local memoryviews
for entry in lenv.var_entries + lenv.arg_entries:
if entry.type.is_memoryview:
MemoryView.put_init_entry(entry.cname, code)
# ----- Check and convert arguments # ----- Check and convert arguments
self.generate_argument_type_tests(code) self.generate_argument_type_tests(code)
# ----- Acquire buffer arguments # ----- Acquire buffer arguments
......
...@@ -170,6 +170,10 @@ class PyrexType(BaseType): ...@@ -170,6 +170,10 @@ class PyrexType(BaseType):
# type information of the struct. # type information of the struct.
return 1 return 1
def global_init_code(self, entry, code):
# abstract
raise NotImplementedError()
def public_decl(base_code, dll_linkage): def public_decl(base_code, dll_linkage):
if dll_linkage: if dll_linkage:
...@@ -362,11 +366,16 @@ class MemoryViewType(PyrexType): ...@@ -362,11 +366,16 @@ class MemoryViewType(PyrexType):
assert not pyrex assert not pyrex
assert not dll_linkage assert not dll_linkage
import MemoryView import MemoryView
self.env.use_utility_code(MemoryView.memviewslice_declare_code) if not for_display:
self.env.use_utility_code(MemoryView.memviewslice_declare_code)
return self.base_declaration_code( return self.base_declaration_code(
MemoryView.memviewslice_cname, MemoryView.memviewslice_cname,
entity_code) entity_code)
def global_init_code(self, entry, code):
code.putln("%s.data = NULL;" % entry.cname)
code.put_init_to_py_none("%s.memview" % entry.cname, cython_memoryview_type, nanny=False)
class BufferType(BaseType): class BufferType(BaseType):
# #
# Delegates most attribute # Delegates most attribute
...@@ -447,6 +456,12 @@ class PyObjectType(PyrexType): ...@@ -447,6 +456,12 @@ class PyObjectType(PyrexType):
else: else:
return cname return cname
def invalid_value(self):
return "1"
def global_init_code(self, entry, code):
code.put_init_var_to_py_none(entry, nanny=False)
class BuiltinObjectType(PyObjectType): class BuiltinObjectType(PyObjectType):
# objstruct_cname string Name of PyObject struct # objstruct_cname string Name of PyObject struct
...@@ -2547,8 +2562,8 @@ c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type) ...@@ -2547,8 +2562,8 @@ c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type)
c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct", c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct",
None, 1, "__Pyx_LocalBuf_ND") None, 1, "__Pyx_LocalBuf_ND")
cython_memoryview_type = CStructOrUnionType("__pyx_obj_memoryview", "struct", cython_memoryview_type = CPtrType(CStructOrUnionType("__pyx_obj_memoryview", "struct",
None, 1, "__pyx_obj_memoryview") None, 0, "__pyx_obj_memoryview"))
error_type = ErrorType() error_type = ErrorType()
......
...@@ -12,7 +12,6 @@ def f(): ...@@ -12,7 +12,6 @@ def f():
cdef memoryview mv = memoryview(arr, PyBUF_C_CONTIGUOUS) cdef memoryview mv = memoryview(arr, PyBUF_C_CONTIGUOUS)
def g(): def g():
# cdef int[::1] mview = array((10,), itemsize=sizeof(int), format='i')
cdef int[::1] mview = array((10,), itemsize=sizeof(int), format='i') cdef int[::1] mview = array((10,), itemsize=sizeof(int), format='i')
mview = array((10,), itemsize=sizeof(int), format='i') mview = array((10,), itemsize=sizeof(int), format='i')
...@@ -36,6 +35,8 @@ cdef float[:,::1] global_mv = array((10,10), itemsize=sizeof(float), format='f') ...@@ -36,6 +35,8 @@ cdef float[:,::1] global_mv = array((10,10), itemsize=sizeof(float), format='f')
global_mv = array((10,10), itemsize=sizeof(float), format='f') global_mv = array((10,10), itemsize=sizeof(float), format='f')
def call(): def call():
global global_mv
global_mv = array((3,3), itemsize=sizeof(float), format='f')
cdg() cdg()
f = Foo() f = Foo()
pf = pyfoo() pf = pyfoo()
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