Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xavier Thompson
cython
Commits
9844c461
Commit
9844c461
authored
Aug 21, 2020
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up cypclass subscript operations analysis
parent
387799ab
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
72 additions
and
45 deletions
+72
-45
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+68
-45
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+4
-0
No files found.
Cython/Compiler/ExprNodes.py
View file @
9844c461
...
...
@@ -3812,7 +3812,7 @@ class IndexNode(_IndexingBaseNode):
elif
base_type
.
is_ptr
or
base_type
.
is_array
:
return
self
.
analyse_as_c_array
(
env
,
is_slice
)
elif
base_type
.
is_cyp_class
:
return
self
.
analyse_as_cyp
(
env
,
setting
,
deleting
)
return
self
.
analyse_as_cyp
_class
(
env
,
setting
,
deleting
)
elif
base_type
.
is_cpp_class
:
return
self
.
analyse_as_cpp
(
env
,
setting
)
elif
base_type
.
is_cfunction
:
...
...
@@ -3892,14 +3892,17 @@ class IndexNode(_IndexingBaseNode):
error
(
self
.
pos
,
"Invalid index type '%s'"
%
self
.
index
.
type
)
return
self
def
cpp_error
(
self
,
msg
):
error
(
self
.
pos
,
msg
)
self
.
type
=
PyrexTypes
.
error_type
self
.
result_code
=
"<error>"
return
self
def
analyse_as_cpp
(
self
,
env
,
setting
):
base_type
=
self
.
base
.
type
function
=
env
.
lookup_operator
(
"[]"
,
[
self
.
base
,
self
.
index
])
if
function
is
None
:
error
(
self
.
pos
,
"Indexing '%s' not supported for index type '%s'"
%
(
base_type
,
self
.
index
.
type
))
self
.
type
=
PyrexTypes
.
error_type
self
.
result_code
=
"<error>"
return
self
return
self
.
cpp_error
(
"Indexing '%s' not supported for index type '%s'"
%
(
base_type
,
self
.
index
.
type
))
func_type
=
function
.
type
if
func_type
.
is_ptr
:
func_type
=
func_type
.
base_type
...
...
@@ -3916,54 +3919,74 @@ class IndexNode(_IndexingBaseNode):
error
(
self
.
pos
,
"Can't set non-reference result '%s'"
%
self
.
type
)
return
self
def
analyse_as_cyp
(
self
,
env
,
setting
,
deleting
):
def
analyse_as_cyp
_class
(
self
,
env
,
setting
,
deleting
):
if
not
setting
:
return
self
.
analyse_as_cpp
(
env
,
setting
)
return
self
.
analyse_cyp_class_getitem
(
env
)
elif
not
deleting
:
return
self
.
analyse_cyp_class_setitem
(
env
)
else
:
return
self
.
analyse_
as_cyp_setitem_or_delitem
(
env
,
deleting
)
return
self
.
analyse_
cyp_class_delitem
(
env
)
def
analyse_cyp_
setitem_or_delitem_method
(
self
,
env
,
deleting
):
def
analyse_cyp_
class_getitem
(
self
,
env
):
base_type
=
self
.
base
.
type
function_name
=
"__delitem__"
if
deleting
else
"__setitem__"
function
=
base_type
.
scope
.
lookup_here
(
function_name
)
function
=
base_type
.
scope
.
lookup
(
"__getitem__"
)
if
function
is
None
:
action
=
"Deleting"
if
deleting
else
"Setting"
error
(
self
.
pos
,
"%s item '%s' not supported for index type '%s'"
%
(
action
,
base_type
,
self
.
index
.
type
))
return
None
if
len
(
function
.
all_alternatives
())
>
1
:
error
(
self
.
pos
,
"%s.%s has several alternatives"
%
(
function_name
,
base_type
))
return
None
return
self
.
cpp_error
(
"Cypclass %s does not support getting subscript item"
%
base_type
)
elif
len
(
function
.
all_alternatives
())
!=
1
:
return
self
.
cpp_error
(
"%s.__getitem__ must have only one signature"
%
base_type
)
func_type
=
function
.
type
expected_nargs
=
1
if
deleting
else
2
if
len
(
func_type
.
args
)
!=
expected_nargs
:
error
(
self
.
pos
,
"%s.%s takes wrong number of arguments"
%
(
function_name
,
base_type
))
return
None
return
func_type
if
len
(
func_type
.
args
)
!=
1
:
return
self
.
cpp_error
(
"%s.__getitem__ must take one argument"
%
base_type
)
def
analyse_as_cyp_setitem_or_delitem
(
self
,
env
,
deleting
):
self
.
exception_check
=
func_type
.
exception_check
self
.
exception_value
=
func_type
.
exception_value
if
self
.
exception_check
==
'+'
:
self
.
is_temp
=
True
if
self
.
exception_value
is
None
:
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CppExceptionConversion"
,
"CppSupport.cpp"
))
self
.
index
=
self
.
index
.
coerce_to
(
function
.
type
.
args
[
0
].
type
,
env
)
self
.
type
=
func_type
.
return_type
return
self
def
analyse_cyp_class_setitem
(
self
,
env
):
base_type
=
self
.
base
.
type
func_type
=
self
.
analyse_cyp_setitem_or_delitem_method
(
env
,
deleting
)
if
func_type
is
None
:
self
.
type
=
PyrexTypes
.
error_type
self
.
result_code
=
"<error>"
return
self
function
=
base_type
.
scope
.
lookup
(
"__setitem__"
)
if
function
is
None
:
return
self
.
cpp_error
(
"Cypclass %s does not support setting subscript item"
%
base_type
)
elif
len
(
function
.
all_alternatives
())
!=
1
:
return
self
.
cpp_error
(
"Cypclass method %s.__setitem__ must have only one signature"
%
base_type
)
func_type
=
function
.
type
if
len
(
func_type
.
args
)
!=
2
:
return
self
.
cpp_error
(
"Cypclass method %s.__setitem__ must take two arguments"
%
base_type
)
self
.
exception_check
=
func_type
.
exception_check
self
.
exception_value
=
func_type
.
exception_value
if
self
.
exception_check
==
'+'
and
self
.
exception_value
is
None
:
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CppExceptionConversion"
,
"CppSupport.cpp"
))
self
.
index
=
self
.
index
.
coerce_to
(
func_type
.
args
[
0
].
type
,
env
)
if
not
deleting
:
self
.
type
=
func_type
.
args
[
1
].
type
else
:
setitem_type
=
self
.
analyse_cyp_setitem_or_delitem_method
(
env
,
deleting
=
False
)
if
setitem_type
is
None
:
# Hack: we use the setitem method to find the contained type and error out if there isn't one.
# We need it to add elements anyway, but a better way to find the contained type would be good.
error
(
self
.
pos
,
"Deleting element from collection without a __setitem__ method"
)
self
.
type
=
PyrexTypes
.
error_type
self
.
result_code
=
"<error>"
return
self
self
.
type
=
setitem_type
.
args
[
1
].
type
self
.
index
=
self
.
index
.
coerce_to
(
function
.
type
.
args
[
0
].
type
,
env
)
self
.
type
=
func_type
.
args
[
1
].
type
return
self
def
analyse_cyp_class_delitem
(
self
,
env
):
base_type
=
self
.
base
.
type
function
=
base_type
.
scope
.
lookup
(
"__delitem__"
)
if
function
is
None
:
return
self
.
cpp_error
(
"Cypclass %s does not support deleting subscript item"
%
base_type
)
elif
len
(
function
.
all_alternatives
())
!=
1
:
return
self
.
cpp_error
(
"Cypclass method %s.__delitem__ must have only one signature"
%
base_type
)
func_type
=
function
.
type
if
len
(
func_type
.
args
)
!=
1
:
return
self
.
cpp_error
(
"Cypclass method %s.__delitem__ must take one argument"
%
base_type
)
self
.
exception_check
=
func_type
.
exception_check
self
.
exception_value
=
func_type
.
exception_value
if
self
.
exception_check
==
'+'
and
self
.
exception_value
is
None
:
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CppExceptionConversion"
,
"CppSupport.cpp"
))
self
.
index
=
self
.
index
.
coerce_to
(
function
.
type
.
args
[
0
].
type
,
env
)
self
.
type
=
func_type
.
return_type
return
self
def
analyse_as_c_function
(
self
,
env
):
...
...
@@ -4333,7 +4356,7 @@ class IndexNode(_IndexingBaseNode):
self
.
extra_index_params
(
code
)),
self
.
pos
))
def
generate_cyp_setitem_code
(
self
,
value_code
,
code
):
def
generate_cyp_
class_
setitem_code
(
self
,
value_code
,
code
):
function
=
self
.
base
.
type
.
scope
.
lookup_here
(
"__setitem__"
)
function_code
=
function
.
cname
setitem_code
=
"%s->%s(%s, %s);"
%
(
...
...
@@ -4356,7 +4379,7 @@ class IndexNode(_IndexingBaseNode):
if
self
.
type
.
is_pyobject
:
self
.
generate_setitem_code
(
rhs
.
py_result
(),
code
)
elif
self
.
base
.
type
.
is_cyp_class
:
self
.
generate_cyp_setitem_code
(
rhs
.
result
(),
code
)
self
.
generate_cyp_
class_
setitem_code
(
rhs
.
result
(),
code
)
elif
self
.
base
.
type
is
bytearray_type
:
value_code
=
self
.
_check_byte_value
(
code
,
rhs
)
self
.
generate_setitem_code
(
value_code
,
code
)
...
...
@@ -4420,7 +4443,7 @@ class IndexNode(_IndexingBaseNode):
value_code
=
'((unsigned char)%s)'
%
value_code
return
value_code
def
generate_cyp_delitem_code
(
self
,
code
):
def
generate_cyp_
class_
delitem_code
(
self
,
code
):
function
=
self
.
base
.
type
.
scope
.
lookup_here
(
"__delitem__"
)
function_code
=
function
.
cname
setitem_code
=
"%s->%s(%s);"
%
(
...
...
@@ -4438,7 +4461,7 @@ class IndexNode(_IndexingBaseNode):
def
generate_deletion_code
(
self
,
code
,
ignore_nonexisting
=
False
):
self
.
generate_subexpr_evaluation_code
(
code
)
if
self
.
base
.
type
.
is_cyp_class
:
self
.
generate_cyp_delitem_code
(
code
)
self
.
generate_cyp_
class_
delitem_code
(
code
)
else
:
#if self.type.is_pyobject:
if
self
.
index
.
type
.
is_int
:
...
...
Cython/Compiler/Nodes.py
View file @
9844c461
...
...
@@ -6458,6 +6458,10 @@ class DelStatNode(StatNode):
for
i
,
arg
in
enumerate
(
self
.
args
):
if
arg
.
is_subscript
:
arg
=
self
.
args
[
i
]
=
arg
.
analyse_del_expression
(
env
)
if
arg
.
base
.
type
.
is_cyp_class
:
# We don't need to know the type of base[index], we'll just call base.__delitem__(index).
self
.
cpp_check
(
env
)
return
self
else
:
arg
=
self
.
args
[
i
]
=
arg
.
analyse_target_expression
(
env
,
None
)
if
arg
.
type
.
is_pyobject
or
(
arg
.
is_name
and
arg
.
type
.
is_memoryviewslice
):
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment