Commit 64f6b025 authored by Mark Florisson's avatar Mark Florisson

Convert memoryviewslice SliceNodes to IndexNodes

parent 0b1b3f00
......@@ -2392,7 +2392,7 @@ class IndexNode(ExprNode):
def analyse_target_types(self, env):
self.analyse_base_and_index_types(env, setting = 1)
def analyse_base_and_index_types(self, env, getting = 0, setting = 0):
def analyse_base_and_index_types(self, env, getting = 0, setting = 0, analyse_base = True):
# Note: This might be cleaned up by having IndexNode
# parsed in a saner way and only construct the tuple if
# needed.
......@@ -2409,7 +2409,9 @@ class IndexNode(ExprNode):
# integer indexing
self.memslice_index = False
if analyse_base:
self.base.analyse_types(env)
if self.base.type.is_error:
# Do not visit child tree if base is undeclared to avoid confusing
# error messages
......@@ -2417,12 +2419,15 @@ class IndexNode(ExprNode):
return
is_slice = isinstance(self.index, SliceNode)
# Potentially overflowing index value.
if not is_slice and isinstance(self.index, IntNode) and Utils.long_literal(self.index.value):
self.index = self.index.coerce_to_pyobject(env)
is_memslice = self.base.type.is_memoryviewslice
# Handle the case where base is a literal char* (and we expect a string, not an int)
if isinstance(self.base, BytesNode) or is_slice:
if not is_memslice and (isinstance(self.base, BytesNode) or is_slice):
if self.base.type.is_string or not (self.base.type.is_ptr or self.base.type.is_array):
self.base = self.base.coerce_to_pyobject(env)
......@@ -2430,8 +2435,6 @@ class IndexNode(ExprNode):
buffer_access = False
memoryviewslice_access = False
is_memslice = self.base.type.is_memoryviewslice
if self.indices:
indices = self.indices
elif isinstance(self.index, TupleNode):
......@@ -2909,8 +2912,6 @@ class IndexNode(ExprNode):
have_gil = not self.in_nogil_context
buffer_entry.generate_buffer_slice_code(code,
self.original_indices,
self.base.type,
self.type,
self.result(),
have_gil=have_gil)
......@@ -2965,13 +2966,33 @@ class SliceIndexNode(ExprNode):
pass
def analyse_target_types(self, env):
self.analyse_types(env)
self.analyse_types(env, getting=False)
# when assigning, we must accept any Python type
if self.type.is_pyobject:
self.type = py_object_type
def analyse_types(self, env):
def analyse_types(self, env, getting=True):
self.base.analyse_types(env)
if self.base.type.is_memoryviewslice:
# Gross hack here! But we do not know the type until this point,
# and we cannot create and return a new node. So we change the
# type...
none_node = NoneNode(self.pos)
index = SliceNode(self.pos,
start=self.start or none_node,
stop=self.stop or none_node,
step=none_node)
del self.start
del self.stop
self.index = index
self.__class__ = IndexNode
self.analyse_base_and_index_types(env,
getting=getting,
setting=not getting,
analyse_base=False)
return
if self.start:
self.start.analyse_types(env)
if self.stop:
......
......@@ -230,7 +230,16 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
return bufp
def generate_buffer_slice_code(self, code, indices, type, dst_type, dst, have_gil):
def generate_buffer_slice_code(self, code, indices, dst, have_gil):
"""
Slice a memoryviewslice.
indices - list of index nodes. If not a SliceNode, then it must be
coercible to Py_ssize_t
Simply call __pyx_memoryview_slice_memviewslice with the right
arguments.
"""
slicefunc = "__pyx_memoryview_slice_memviewslice"
new_ndim = 0
cname = self.cname
......
......@@ -1400,3 +1400,21 @@ def test_nogil():
cdef_nogil(_a)
cdef int[:, :] a = _a
print a[2, 7]
@testcase
def test_convert_slicenode_to_indexnode():
"""
When indexing with a[i:j] a SliceNode gets created instead of an IndexNode, which
forces coercion to object and back. This would not only be inefficient, but it would
also not compile in nogil mode. So instead we mutate it into an IndexNode.
>>> test_convert_slicenode_to_indexnode()
acquired A
2
released A
"""
cdef int[:] a = IntMockBuffer("A", range(10), shape=(10,))
with nogil:
a = a[2:4]
print a[0]
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