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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
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):
...
@@ -3812,7 +3812,7 @@ class IndexNode(_IndexingBaseNode):
elif
base_type
.
is_ptr
or
base_type
.
is_array
:
elif
base_type
.
is_ptr
or
base_type
.
is_array
:
return
self
.
analyse_as_c_array
(
env
,
is_slice
)
return
self
.
analyse_as_c_array
(
env
,
is_slice
)
elif
base_type
.
is_cyp_class
:
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
:
elif
base_type
.
is_cpp_class
:
return
self
.
analyse_as_cpp
(
env
,
setting
)
return
self
.
analyse_as_cpp
(
env
,
setting
)
elif
base_type
.
is_cfunction
:
elif
base_type
.
is_cfunction
:
...
@@ -3892,14 +3892,17 @@ class IndexNode(_IndexingBaseNode):
...
@@ -3892,14 +3892,17 @@ class IndexNode(_IndexingBaseNode):
error
(
self
.
pos
,
"Invalid index type '%s'"
%
self
.
index
.
type
)
error
(
self
.
pos
,
"Invalid index type '%s'"
%
self
.
index
.
type
)
return
self
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
):
def
analyse_as_cpp
(
self
,
env
,
setting
):
base_type
=
self
.
base
.
type
base_type
=
self
.
base
.
type
function
=
env
.
lookup_operator
(
"[]"
,
[
self
.
base
,
self
.
index
])
function
=
env
.
lookup_operator
(
"[]"
,
[
self
.
base
,
self
.
index
])
if
function
is
None
:
if
function
is
None
:
error
(
self
.
pos
,
"Indexing '%s' not supported for index type '%s'"
%
(
base_type
,
self
.
index
.
type
))
return
self
.
cpp_error
(
"Indexing '%s' not supported for index type '%s'"
%
(
base_type
,
self
.
index
.
type
))
self
.
type
=
PyrexTypes
.
error_type
self
.
result_code
=
"<error>"
return
self
func_type
=
function
.
type
func_type
=
function
.
type
if
func_type
.
is_ptr
:
if
func_type
.
is_ptr
:
func_type
=
func_type
.
base_type
func_type
=
func_type
.
base_type
...
@@ -3916,54 +3919,74 @@ class IndexNode(_IndexingBaseNode):
...
@@ -3916,54 +3919,74 @@ class IndexNode(_IndexingBaseNode):
error
(
self
.
pos
,
"Can't set non-reference result '%s'"
%
self
.
type
)
error
(
self
.
pos
,
"Can't set non-reference result '%s'"
%
self
.
type
)
return
self
return
self
def
analyse_as_cyp
(
self
,
env
,
setting
,
deleting
):
def
analyse_as_cyp
_class
(
self
,
env
,
setting
,
deleting
):
if
not
setting
:
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
:
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
base_type
=
self
.
base
.
type
function_name
=
"__delitem__"
if
deleting
else
"__setitem__"
function
=
base_type
.
scope
.
lookup
(
"__getitem__"
)
function
=
base_type
.
scope
.
lookup_here
(
function_name
)
if
function
is
None
:
if
function
is
None
:
action
=
"Deleting"
if
deleting
else
"Setting"
return
self
.
cpp_error
(
"Cypclass %s does not support getting subscript item"
%
base_type
)
error
(
self
.
pos
,
"%s item '%s' not supported for index type '%s'"
%
(
action
,
base_type
,
self
.
index
.
type
))
elif
len
(
function
.
all_alternatives
())
!=
1
:
return
None
return
self
.
cpp_error
(
"%s.__getitem__ must have only one signature"
%
base_type
)
if
len
(
function
.
all_alternatives
())
>
1
:
error
(
self
.
pos
,
"%s.%s has several alternatives"
%
(
function_name
,
base_type
))
return
None
func_type
=
function
.
type
func_type
=
function
.
type
expected_nargs
=
1
if
deleting
else
2
if
len
(
func_type
.
args
)
!=
1
:
if
len
(
func_type
.
args
)
!=
expected_nargs
:
return
self
.
cpp_error
(
"%s.__getitem__ must take one argument"
%
base_type
)
error
(
self
.
pos
,
"%s.%s takes wrong number of arguments"
%
(
function_name
,
base_type
))
return
None
return
func_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
base_type
=
self
.
base
.
type
func_type
=
self
.
analyse_cyp_setitem_or_delitem_method
(
env
,
deleting
)
function
=
base_type
.
scope
.
lookup
(
"__setitem__"
)
if
func_type
is
None
:
if
function
is
None
:
self
.
type
=
PyrexTypes
.
error_type
return
self
.
cpp_error
(
"Cypclass %s does not support setting subscript item"
%
base_type
)
self
.
result_code
=
"<error>"
elif
len
(
function
.
all_alternatives
())
!=
1
:
return
self
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_check
=
func_type
.
exception_check
self
.
exception_value
=
func_type
.
exception_value
self
.
exception_value
=
func_type
.
exception_value
if
self
.
exception_check
==
'+'
and
self
.
exception_value
is
None
:
if
self
.
exception_check
==
'+'
and
self
.
exception_value
is
None
:
env
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CppExceptionConversion"
,
"CppSupport.cpp"
))
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
.
index
=
self
.
index
.
coerce_to
(
function
.
type
.
args
[
0
].
type
,
env
)
self
.
type
=
func_type
.
args
[
1
].
type
self
.
type
=
func_type
.
args
[
1
].
type
else
:
return
self
setitem_type
=
self
.
analyse_cyp_setitem_or_delitem_method
(
env
,
deleting
=
False
)
if
setitem_type
is
None
:
def
analyse_cyp_class_delitem
(
self
,
env
):
# Hack: we use the setitem method to find the contained type and error out if there isn't one.
base_type
=
self
.
base
.
type
# We need it to add elements anyway, but a better way to find the contained type would be good.
function
=
base_type
.
scope
.
lookup
(
"__delitem__"
)
error
(
self
.
pos
,
"Deleting element from collection without a __setitem__ method"
)
if
function
is
None
:
self
.
type
=
PyrexTypes
.
error_type
return
self
.
cpp_error
(
"Cypclass %s does not support deleting subscript item"
%
base_type
)
self
.
result_code
=
"<error>"
elif
len
(
function
.
all_alternatives
())
!=
1
:
return
self
return
self
.
cpp_error
(
"Cypclass method %s.__delitem__ must have only one signature"
%
base_type
)
self
.
type
=
setitem_type
.
args
[
1
].
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
return
self
def
analyse_as_c_function
(
self
,
env
):
def
analyse_as_c_function
(
self
,
env
):
...
@@ -4333,7 +4356,7 @@ class IndexNode(_IndexingBaseNode):
...
@@ -4333,7 +4356,7 @@ class IndexNode(_IndexingBaseNode):
self
.
extra_index_params
(
code
)),
self
.
extra_index_params
(
code
)),
self
.
pos
))
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
=
self
.
base
.
type
.
scope
.
lookup_here
(
"__setitem__"
)
function_code
=
function
.
cname
function_code
=
function
.
cname
setitem_code
=
"%s->%s(%s, %s);"
%
(
setitem_code
=
"%s->%s(%s, %s);"
%
(
...
@@ -4356,7 +4379,7 @@ class IndexNode(_IndexingBaseNode):
...
@@ -4356,7 +4379,7 @@ class IndexNode(_IndexingBaseNode):
if
self
.
type
.
is_pyobject
:
if
self
.
type
.
is_pyobject
:
self
.
generate_setitem_code
(
rhs
.
py_result
(),
code
)
self
.
generate_setitem_code
(
rhs
.
py_result
(),
code
)
elif
self
.
base
.
type
.
is_cyp_class
:
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
:
elif
self
.
base
.
type
is
bytearray_type
:
value_code
=
self
.
_check_byte_value
(
code
,
rhs
)
value_code
=
self
.
_check_byte_value
(
code
,
rhs
)
self
.
generate_setitem_code
(
value_code
,
code
)
self
.
generate_setitem_code
(
value_code
,
code
)
...
@@ -4420,7 +4443,7 @@ class IndexNode(_IndexingBaseNode):
...
@@ -4420,7 +4443,7 @@ class IndexNode(_IndexingBaseNode):
value_code
=
'((unsigned char)%s)'
%
value_code
value_code
=
'((unsigned char)%s)'
%
value_code
return
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
=
self
.
base
.
type
.
scope
.
lookup_here
(
"__delitem__"
)
function_code
=
function
.
cname
function_code
=
function
.
cname
setitem_code
=
"%s->%s(%s);"
%
(
setitem_code
=
"%s->%s(%s);"
%
(
...
@@ -4438,7 +4461,7 @@ class IndexNode(_IndexingBaseNode):
...
@@ -4438,7 +4461,7 @@ class IndexNode(_IndexingBaseNode):
def
generate_deletion_code
(
self
,
code
,
ignore_nonexisting
=
False
):
def
generate_deletion_code
(
self
,
code
,
ignore_nonexisting
=
False
):
self
.
generate_subexpr_evaluation_code
(
code
)
self
.
generate_subexpr_evaluation_code
(
code
)
if
self
.
base
.
type
.
is_cyp_class
:
if
self
.
base
.
type
.
is_cyp_class
:
self
.
generate_cyp_delitem_code
(
code
)
self
.
generate_cyp_
class_
delitem_code
(
code
)
else
:
else
:
#if self.type.is_pyobject:
#if self.type.is_pyobject:
if
self
.
index
.
type
.
is_int
:
if
self
.
index
.
type
.
is_int
:
...
...
Cython/Compiler/Nodes.py
View file @
9844c461
...
@@ -6458,6 +6458,10 @@ class DelStatNode(StatNode):
...
@@ -6458,6 +6458,10 @@ class DelStatNode(StatNode):
for
i
,
arg
in
enumerate
(
self
.
args
):
for
i
,
arg
in
enumerate
(
self
.
args
):
if
arg
.
is_subscript
:
if
arg
.
is_subscript
:
arg
=
self
.
args
[
i
]
=
arg
.
analyse_del_expression
(
env
)
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
:
else
:
arg
=
self
.
args
[
i
]
=
arg
.
analyse_target_expression
(
env
,
None
)
arg
=
self
.
args
[
i
]
=
arg
.
analyse_target_expression
(
env
,
None
)
if
arg
.
type
.
is_pyobject
or
(
arg
.
is_name
and
arg
.
type
.
is_memoryviewslice
):
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