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