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>")
cdef extern from *:
int __Pyx_GetBuffer(object, Py_buffer *, int)
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):
......@@ -389,9 +394,13 @@ cdef object init_memviewslice_from_memview(
if has_suboffsets:
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.data = <char *>pybuf.buf
memviewslice.data = <char *>pybuf.buf
""" % Options.buffer_max_dims, name="foobar", prefix="__pyx_viewaxis_")
cyarray_prefix = u'__pyx_cythonarray_'
......
......@@ -585,11 +585,15 @@ class ExprNode(Node):
dst_type = dst_type.ref_base_type
if dst_type.is_memoryview:
import MemoryView
if not src.type.is_memoryview:
src = CoerceToMemViewNode(src, dst_type, env)
# src = AcquireBufferFromNode(src, env)
# src = CheckMemoryViewFormatNode(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 dst_type is bytes_type and src.type.is_int:
src = CoerceIntToBytesNode(src, env)
......@@ -1653,7 +1657,7 @@ class NameNode(AtomicExprNode):
if self.type.is_memoryview:
self.generate_acquire_memoryview(rhs, code)
if self.type.is_buffer:
elif self.type.is_buffer:
# Generate code for doing the buffer release/acquisition.
# This might raise an exception in which case the assignment (done
# below) will not happen.
......@@ -1687,9 +1691,8 @@ class NameNode(AtomicExprNode):
code.put_decref(self.result(), self.ctype())
if is_external_ref:
code.put_giveref(rhs.py_result())
code.putln('%s = %s;' % (self.result(),
rhs.result_as(self.ctype())))
if not self.type.is_memoryview:
code.putln('%s = %s;' % (self.result(), rhs.result_as(self.ctype())))
if debug_disposal_code:
print("NameNode.generate_assignment_code:")
print("...generating post-assignment code for %s" % rhs)
......@@ -1698,9 +1701,10 @@ class NameNode(AtomicExprNode):
def generate_acquire_memoryview(self, rhs, code):
import MemoryView
MemoryView.put_assign_to_memview(self.result(), rhs.result(), self.entry,
is_initialized=not self.lhs_of_first_assignment,
MemoryView.put_assign_to_memview(self.result(), rhs.result(), self.type,
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):
# rhstmp is only used in case the rhs is a complicated expression leading to
......@@ -3940,6 +3944,13 @@ class AttributeNode(ExprNode):
code.put_giveref(rhs.py_result())
code.put_gotref(select_code)
code.put_decref(select_code, self.ctype())
elif self.type.is_memoryview:
import MemoryView
MemoryView.put_assign_to_memview(select_code, rhs.result(), self.type,
pos=self.pos, code=code)
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,
......@@ -7583,27 +7594,35 @@ class CoerceToMemViewNode(CoercionNode):
def __init__(self, arg, dst_type, env):
assert dst_type.is_memoryview
assert not arg.type.is_memoryview
CoercionNode.__init__(self, arg)
self.type = dst_type
self.is_temp = 1
self.env = env
self.is_temp = 1
def generate_result_code(self, code):
import MemoryView
memviewobj = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
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)
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)
for idx, cspec in enumerate(specs_code):
code.putln("%s[%d] = %s;" % (spec_int_arr, idx, cspec))
itemsize = self.type.dtype.sign_and_name()
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(spec_int_arr)
code.putln('/* @@@ */')
class CastNode(CoercionNode):
# Wrap a node in a C type cast.
......
......@@ -5,6 +5,7 @@ import Options
import CythonScope
from Code import UtilityCode
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."
STOP_ERR = "Axis specification only allowed in the 'stop' slot."
......@@ -64,9 +65,24 @@ _typename_to_format = {
def format_from_type(base_type):
return _typename_to_format[base_type.sign_and_name()]
def put_assign_to_memview(lhs_cname, rhs_cname, buf_entry,
is_initialized, pos, code):
pass
def put_init_entry(mv_cname, code):
code.putln("%s.data = NULL;" % mv_cname)
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):
is_c_contig, is_f_contig = is_cf_contig(specs)
......@@ -101,6 +117,36 @@ def use_memview_cwrap(env):
import CythonScope
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):
'''
......
......@@ -1185,10 +1185,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type = scope.parent_type
base_type = type.base_type
py_attrs = []
memview_attrs = []
for entry in scope.var_entries:
if entry.type.is_pyobject:
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(
"static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {"
......@@ -1231,6 +1234,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("p->%s = 0;" % entry.cname)
else:
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__")
if entry and entry.is_special:
if entry.trivial_signature:
......@@ -2134,8 +2141,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# variables to None.
for entry in env.var_entries:
if entry.visibility != 'extern':
if entry.type.is_pyobject and entry.used:
code.put_init_var_to_py_none(entry, nanny=False)
if entry.used:
entry.type.global_init_code(entry, code)
def generate_c_variable_export_code(self, env, code):
# Generate code to create PyCFunction wrappers for exported C functions.
......
......@@ -1261,7 +1261,7 @@ class FuncDefNode(StatNode, BlockNode):
self.body.generate_execution_code(code)
def generate_function_definitions(self, env, code):
import Buffer
import Buffer, MemoryView
lenv = self.local_scope
if lenv.is_closure_scope and not lenv.is_passthrough:
......@@ -1428,6 +1428,10 @@ class FuncDefNode(StatNode, BlockNode):
for entry in lenv.var_entries + lenv.arg_entries:
if entry.type.is_buffer and entry.buffer_aux.buflocal_nd_var.used:
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
self.generate_argument_type_tests(code)
# ----- Acquire buffer arguments
......
......@@ -170,6 +170,10 @@ class PyrexType(BaseType):
# type information of the struct.
return 1
def global_init_code(self, entry, code):
# abstract
raise NotImplementedError()
def public_decl(base_code, dll_linkage):
if dll_linkage:
......@@ -362,11 +366,16 @@ class MemoryViewType(PyrexType):
assert not pyrex
assert not dll_linkage
import MemoryView
if not for_display:
self.env.use_utility_code(MemoryView.memviewslice_declare_code)
return self.base_declaration_code(
MemoryView.memviewslice_cname,
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):
#
# Delegates most attribute
......@@ -447,6 +456,12 @@ class PyObjectType(PyrexType):
else:
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):
# objstruct_cname string Name of PyObject struct
......@@ -2547,8 +2562,8 @@ c_pyx_buffer_ptr_type = CPtrType(c_pyx_buffer_type)
c_pyx_buffer_nd_type = CStructOrUnionType("__Pyx_LocalBuf_ND", "struct",
None, 1, "__Pyx_LocalBuf_ND")
cython_memoryview_type = CStructOrUnionType("__pyx_obj_memoryview", "struct",
None, 1, "__pyx_obj_memoryview")
cython_memoryview_type = CPtrType(CStructOrUnionType("__pyx_obj_memoryview", "struct",
None, 0, "__pyx_obj_memoryview"))
error_type = ErrorType()
......
......@@ -12,7 +12,6 @@ def f():
cdef memoryview mv = memoryview(arr, PyBUF_C_CONTIGUOUS)
def g():
# 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')
......@@ -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')
def call():
global global_mv
global_mv = array((3,3), itemsize=sizeof(float), format='f')
cdg()
f = Foo()
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