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
da0490ef
Commit
da0490ef
authored
Jan 19, 2021
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Introduce 'frozen' and 'read' keywords
parent
0bb6f98b
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
121 additions
and
84 deletions
+121
-84
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+8
-9
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+1
-1
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+6
-7
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+15
-3
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+22
-11
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+68
-52
tests/errors/cypclass_lock_errors.pyx
tests/errors/cypclass_lock_errors.pyx
+1
-1
No files found.
Cython/Compiler/ExprNodes.py
View file @
da0490ef
...
...
@@ -11399,16 +11399,15 @@ class ConsumeNode(ExprNode):
error
(
self
.
pos
,
"Can only consume cypclass (not '%s')"
%
operand_type
)
self
.
type
=
PyrexTypes
.
error_type
return
self
if
operand_type
.
is_qualified_cyp_class
:
self
.
generate_runtime_check
=
operand_type
.
qualifier
not
in
(
'iso'
,
'iso~'
)
self
.
check_refcount_only
=
operand_type
.
qualifier
in
(
'active'
,
'lock'
,
'locked'
)
if
operand_type
.
qualifier
==
'iso~'
:
self
.
type
=
operand_type
else
:
self
.
type
=
PyrexTypes
.
cyp_class_qualified_type
(
operand_type
.
qual_base_type
,
'iso~'
)
if
operand_type
.
qualifier
==
'frozen'
:
error
(
self
.
pos
,
"Cannot consume '%s'"
%
operand_type
)
self
.
type
=
PyrexTypes
.
error_type
return
self
self
.
generate_runtime_check
=
operand_type
.
qualifier
not
in
(
'iso'
,
'iso~'
)
self
.
check_refcount_only
=
operand_type
.
qualifier
in
(
'active'
,
'lock'
,
'locked'
)
if
operand_type
.
qualifier
==
'iso~'
:
self
.
type
=
operand_type
else
:
self
.
generate_runtime_check
=
True
self
.
check_refcount_only
=
False
self
.
type
=
PyrexTypes
.
cyp_class_qualified_type
(
operand_type
,
'iso~'
)
solid_operand
=
self
.
operand
while
isinstance
(
solid_operand
,
TypecastNode
)
and
not
solid_operand
.
is_temp
:
...
...
Cython/Compiler/ModuleNode.py
View file @
da0490ef
...
...
@@ -981,7 +981,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for
e
in
scope
.
entries
.
values
():
if
e
.
is_type
or
e
.
name
==
"this"
:
continue
elif
e
.
type
.
is_cyp_class
and
not
e
.
type
.
is_qualified_cyp_class
:
elif
e
.
type
.
is_cyp_class
and
e
.
type
.
qualifier
in
(
'read'
,
None
)
:
check_cypclass_attrs
.
append
(
e
)
elif
e
.
type
.
is_template_typename
:
check_template_attrs
.
append
(
e
)
...
...
Cython/Compiler/Nodes.py
View file @
da0490ef
...
...
@@ -680,13 +680,12 @@ class CFuncDeclaratorNode(CDeclaratorNode):
type
=
env
.
parent_type
elif
i
==
0
and
env
.
is_cyp_class_scope
and
'staticmethod'
not
in
env
.
directives
and
self
.
declared_name
()
!=
"alloc"
:
if
self
.
declared_name
()
!=
"__new__"
:
# Accept 'f(<qualifier> self, ...) syntax'
unqualified_type
=
type
if
type
.
is_qualified_cyp_class
:
self
.
self_qualifier
=
type
.
qualifier
unqualified_type
=
type
.
qual_base_type
# check that the type of self is correct:
if
not
unqualified_type
.
same_as
(
env
.
parent_type
):
# Check that the type of self is correct. Accept 'f(<qualifier> self, ...) syntax.
if
type
.
is_cyp_class
and
env
.
parent_type
.
same_as
(
type
.
qual_base_type
or
type
):
qualifier
=
self
.
self_qualifier
=
type
.
qualifier
if
return_type
.
is_qualified_cyp_class
and
return_type
.
qualifier
==
'self->'
and
qualifier
==
'read'
:
type
=
PyrexTypes
.
cyp_class_qualified_type
(
type
,
'self->'
)
else
:
error
(
self
.
pos
,
"Wrong type for self argument - expected %s, got %s"
%
(
env
.
parent_type
,
type
))
# skip 'self' argument from the list of actual arguments
# to comply with C++ implicit 'this' argument passing.
...
...
Cython/Compiler/Parsing.py
View file @
da0490ef
...
...
@@ -2513,6 +2513,19 @@ def p_c_complex_base_type(s, templates = None):
return
type_node
def
p_cypclass_qualifier
(
s
):
qualifier
=
None
if
s
.
sy
==
'IDENT'
:
if
s
.
systring
in
(
'active'
,
'iso'
,
'lock'
,
'locked'
,
'read'
,
'frozen'
):
qualifier
=
s
.
systring
s
.
next
()
elif
s
.
systring
==
'self'
and
s
.
peek
()[
0
]
==
'->'
:
qualifier
=
'self->'
s
.
next
()
s
.
next
()
return
qualifier
def
p_c_simple_base_type
(
s
,
self_flag
,
nonempty
,
templates
=
None
):
#print "p_c_simple_base_type: self_flag =", self_flag, nonempty
is_basic
=
0
...
...
@@ -2545,9 +2558,8 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
base_type
=
base_type
,
is_const
=
is_const
,
is_volatile
=
is_volatile
)
# Handle cypclass qualifiers
if
s
.
sy
==
'IDENT'
and
s
.
systring
in
(
'active'
,
'iso'
,
'lock'
,
'locked'
):
qualifier
=
s
.
systring
s
.
next
()
qualifier
=
p_cypclass_qualifier
(
s
)
if
qualifier
:
base_type
=
p_c_base_type
(
s
,
self_flag
=
self_flag
,
nonempty
=
nonempty
,
templates
=
templates
)
return
Nodes
.
QualifiedCypclassNode
(
pos
,
base_type
=
base_type
,
qualifier
=
qualifier
)
...
...
Cython/Compiler/PyrexTypes.py
View file @
da0490ef
...
...
@@ -4767,7 +4767,10 @@ class QualifiedCypclassType(BaseType):
'iso->'
:
(
'iso~'
,),
'lock'
:
(
'lock'
,
'locked'
,
'iso~'
),
'locked'
:
(
'locked'
,
'iso~'
),
'lock->'
:
(
'iso~'
,),
'frozen'
:
(
'frozen'
,
'iso~'
),
'read'
:
(
'read'
,
'frozen'
,
'self->'
,
None
,
'iso~'
),
'iso->read'
:
(
'iso~'
,),
'self->'
:
(
'self->'
,
'iso~'
),
}
def
__new__
(
cls
,
base_type
,
qualifier
):
...
...
@@ -5799,17 +5802,25 @@ def qualified_method_type(base_type, const, volatile):
else
:
return
QualifiedMethodType
(
base_type
,
const
,
volatile
)
def
viewpoint_adaptation
(
base_type
,
qualifier
=
'iso->'
):
qualifier_adaptation
=
{
'iso'
:
{
None
:
'iso->'
,
'read'
:
'iso->read'
},
'read'
:
{
None
:
'read'
,
'iso'
:
'iso->read'
},
'frozen'
:
{
None
:
'frozen'
,
'read'
:
'frozen'
,
'iso'
:
'frozen'
},
'iso->read'
:
{
None
:
'iso->read'
,
'read'
:
'iso->read'
,
'iso'
:
'iso->read'
},
'self->'
:
{
None
:
'self->'
,
'iso'
:
'iso->read'
},
}
def
viewpoint_adaptation
(
field_type
,
origin
=
'iso'
):
# Perform viewpoint adaptation for cypclass types.
if
base_type
.
is_qualified
_cyp_class
:
return
base
_type
if
base_type
.
is_cyp_class
:
if
qualifier
.
startswith
(
'iso'
):
qualifier
=
'iso->'
elif
qualifier
.
startswith
(
'lock'
):
qualifier
=
'lock->'
return
QualifiedCypclassType
(
base_type
,
qualifier
)
return
base_type
if
not
field_type
.
is
_cyp_class
:
return
field
_type
if
origin
!=
'iso->read'
and
origin
.
startswith
(
'iso'
)
or
origin
.
startswith
(
'lock'
)
:
origin
=
'iso'
field
=
field_type
.
qualifier
qualifier
=
qualifier_adaptation
[
origin
].
get
(
field
,
field
)
if
qualifier
==
field
:
return
field_type
return
QualifiedCypclassType
(
field_type
,
qualifier
)
def
same_type
(
type1
,
type2
):
return
type1
.
same_as
(
type2
)
...
...
Cython/Compiler/Symtab.py
View file @
da0490ef
...
...
@@ -3164,9 +3164,21 @@ class CppClassScope(Scope):
def
lookup_here
(
self
,
name
):
entry
=
super
(
CppClassScope
,
self
).
lookup_here
(
self
.
adapt_name_lookup
(
name
))
if
entry
and
self
.
is_cyp_class_scope
and
entry
.
is_cfunction
and
entry
.
type
.
self_qualifier
:
# Cannot access self-qualified methods from unqualified cypclass.
return
None
if
entry
and
self
.
is_cyp_class_scope
and
entry
.
is_cfunction
:
if
entry
.
type
.
self_qualifier
not
in
(
'read'
,
None
):
# Cannot access self-qualified methods from unqualified cypclass except for 'read'.
return
None
elif
any
(
e
.
type
.
return_type
.
is_cyp_class
and
e
.
type
.
return_type
.
qualifier
==
'self->'
for
e
in
entry
.
all_alternatives
()):
alternatives
=
[]
for
e
in
entry
.
all_alternatives
():
e
=
copy
.
copy
(
e
)
if
e
.
type
.
return_type
.
is_cyp_class
and
e
.
type
.
return_type
.
qualifier
==
'self->'
:
method_type
=
copy
.
copy
(
e
.
type
)
method_type
.
return_type
=
method_type
.
return_type
.
qual_base_type
e
.
type
=
method_type
e
.
overloaded_alternatives
=
alternatives
alternatives
.
append
(
e
)
return
alternatives
[
0
]
return
entry
def
lookup_here_unfiltered
(
self
,
name
):
...
...
@@ -3280,18 +3292,11 @@ class CConstOrVolatileScope(Scope):
return
entry
class
QualifiedCypclassScope
(
Scope
):
qualifier
=
'qual'
class
BaseAdapterScope
(
Scope
):
def
__init__
(
self
,
base_type_scope
,
qualifier
=
None
):
qualifier
=
qualifier
or
self
.
qualifier
Scope
.
__init__
(
self
,
'%s_'
%
qualifier
+
base_type_scope
.
name
,
base_type_scope
.
outer_scope
,
base_type_scope
.
parent_scope
)
self
.
base_type_scope
=
base_type_scope
self
.
qualifier
=
qualifier
def
__init__
(
self
,
base_scope
,
name
):
Scope
.
__init__
(
self
,
name
,
base_scope
.
outer_scope
,
base_scope
.
parent_scope
)
self
.
base_scope
=
base_scope
self
.
cached_qualified_entries
=
{}
def
lookup_here
(
self
,
name
):
...
...
@@ -3303,7 +3308,7 @@ class QualifiedCypclassScope(Scope):
return
entry
def
resolve
(
self
,
name
):
base_entry
=
self
.
base_
type_
scope
.
lookup_here_unfiltered
(
name
)
base_entry
=
self
.
base_scope
.
lookup_here_unfiltered
(
name
)
if
base_entry
is
None
:
return
None
alternatives
=
[]
...
...
@@ -3321,65 +3326,76 @@ class QualifiedCypclassScope(Scope):
return
None
def
qualified_cypclass_scope
(
base_
type_
scope
,
qualifier
):
def
qualified_cypclass_scope
(
base_scope
,
qualifier
):
if
qualifier
==
'active'
:
return
ActiveCypclassScope
(
base_type_scope
)
elif
qualifier
.
startswith
(
'iso'
):
return
IsoCypclassScope
(
base_type_scope
,
qualifier
)
elif
qualifier
.
startswith
(
'lock'
):
return
IsoCypclassScope
(
base_type_scope
,
qualifier
)
return
ActiveCypclassScope
(
base_scope
)
else
:
return
QualifiedCypclassScope
(
base_
type_
scope
,
qualifier
)
return
QualifiedCypclassScope
(
base_scope
,
qualifier
)
class
ActiveCypclassScope
(
QualifiedCypclass
Scope
):
class
ActiveCypclassScope
(
BaseAdapter
Scope
):
qualifier
=
'active'
def
__init__
(
self
,
base_scope
):
name
=
'active_%s'
%
base_scope
.
name
BaseAdapterScope
.
__init__
(
self
,
base_scope
,
name
)
def
adapt
(
self
,
base_entry
):
if
base_entry
.
is_cfunction
and
base_entry
.
type
.
self_qualifier
==
'active'
:
return
base_entry
return
base_entry
.
active_entry
class
IsoCypclassScope
(
QualifiedCypclassScope
):
qualifier
=
'iso'
def
adapt_arg_type
(
self
,
arg
):
arg
=
copy
.
copy
(
arg
)
arg
.
type
=
viewpoint_adaptation
(
arg
.
type
,
self
.
qualifier
)
return
arg
class
QualifiedCypclassScope
(
BaseAdapterScope
):
def
adapt_method_entry
(
self
,
base_entry
):
base_type
=
base_entry
.
type
if
base_type
.
self_qualifier
:
if
self
.
qualifier
in
PyrexTypes
.
QualifiedCypclassType
.
assignable_to
[
base_type
.
self_qualifier
]:
return
base_entry
elif
base_type
.
self_qualifier
==
'locked'
and
self
.
qualifier
==
'lock'
:
return
base_entry
else
:
return
None
iso_method_type
=
copy
.
copy
(
base_type
)
return_type
=
viewpoint_adaptation
(
base_type
.
return_type
,
self
.
qualifier
)
iso_method_type
.
return_type
=
return_type
iso_method_type
.
args
=
[
self
.
adapt_arg_type
(
arg
)
for
arg
in
base_type
.
args
]
entry
=
copy
.
copy
(
base_entry
)
entry
.
type
=
iso_method_type
return
entry
def
__init__
(
self
,
base_scope
,
qualifier
):
name
=
'%s_%s'
%
(
qualifier
,
base_scope
.
name
)
BaseAdapterScope
.
__init__
(
self
,
base_scope
,
name
)
self
.
qualifier
=
qualifier
def
adapt
(
self
,
base_entry
):
if
base_entry
.
is_type
:
return
base_entry
if
base_entry
.
is_cfunction
:
return
self
.
adapt_method
_entry
(
base_entry
)
return
self
.
adapt_method
(
base_entry
)
else
:
base_entry_type
=
base_entry
.
type
adapted_type
=
viewpoint_adaptation
(
base_entry_type
,
self
.
qualifier
)
if
adapted_type
is
base_entry_type
:
adapted_type
=
viewpoint_adaptation
(
base_entry
.
type
,
self
.
qualifier
)
if
self
.
qualifier
.
endswith
(
'read'
)
or
self
.
qualifier
==
'frozen'
:
adapted_type
=
PyrexTypes
.
c_const_or_volatile_type
(
adapted_type
,
True
,
False
)
elif
adapted_type
is
base_entry
.
type
:
return
base_entry
else
:
entry
=
copy
.
copy
(
base_entry
)
entry
.
type
=
adapted_type
return
entry
def
adapt_method
(
self
,
base_entry
):
base_type
=
base_entry
.
type
return_type
=
base_type
.
return_type
if
return_type
.
is_cyp_class
and
return_type
.
qualifier
==
'self->'
:
if
self
.
qualifier
in
(
'read'
,
'iso->read'
,
'frozen'
):
method_type
=
copy
.
copy
(
base_type
)
method_type
.
return_type
=
PyrexTypes
.
cyp_class_qualified_type
(
return_type
,
self
.
qualifier
)
entry
=
copy
.
copy
(
base_entry
)
entry
.
type
=
adapte
d_type
entry
.
type
=
metho
d_type
return
entry
elif
self
.
qualifier
in
PyrexTypes
.
QualifiedCypclassType
.
assignable_to
[
base_type
.
self_qualifier
]:
return
base_entry
elif
self
.
qualifier
==
'lock'
and
base_type
.
self_qualifier
==
'locked'
:
return
base_entry
elif
self
.
qualifier
.
startswith
(
'iso'
)
or
self
.
qualifier
.
startswith
(
'lock'
):
if
self
.
qualifier
!=
'iso->read'
or
base_type
.
self_qualifier
==
'read'
:
iso_method_type
=
copy
.
copy
(
base_type
)
iso_method_type
.
return_type
=
viewpoint_adaptation
(
return_type
,
self
.
qualifier
)
iso_method_type
.
args
=
[
self
.
adapt_arg
(
arg
)
for
arg
in
base_type
.
args
]
entry
=
copy
.
copy
(
base_entry
)
entry
.
type
=
iso_method_type
return
entry
return
None
def
adapt_arg
(
self
,
arg
):
arg
=
copy
.
copy
(
arg
)
arg
.
type
=
viewpoint_adaptation
(
arg
.
type
,
self
.
qualifier
)
return
arg
class
TemplateScope
(
Scope
):
...
...
tests/errors/cypclass_lock_errors.pyx
View file @
da0490ef
...
...
@@ -106,7 +106,7 @@ _ERRORS = u'''
33:15: Cannot assign type 'lock A' to 'locked A'
36:12: Cannot assign type 'lock A' to 'A'
40:14: Cannot assign type 'A' to 'lock A'
56:9: Cannot assign type 'A' to '
lock
-> A'
56:9: Cannot assign type 'A' to '
iso
-> A'
77:20: Cannot cast 'lock A' to 'iso A'
80:15: Cannot cast 'lock A' to 'active A'
83:15: Cannot cast 'lock A' to 'locked A'
...
...
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