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
034a53fd
Commit
034a53fd
authored
Jun 10, 2020
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Compute the MRO for each cycplass
parent
631d465b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
84 additions
and
0 deletions
+84
-0
Cython/Compiler/ParseTreeTransforms.py
Cython/Compiler/ParseTreeTransforms.py
+7
-0
Cython/Compiler/Pipeline.py
Cython/Compiler/Pipeline.py
+2
-0
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+75
-0
No files found.
Cython/Compiler/ParseTreeTransforms.py
View file @
034a53fd
...
...
@@ -2198,6 +2198,13 @@ if VALUE is not None:
return
property
class
ComputeMROTransform
(
CythonTransform
):
def
visit_CppClassNode
(
self
,
node
):
if
node
.
cypclass
:
node
.
entry
.
type
.
compute_mro
()
return
node
class
CalculateQualifiedNamesTransform
(
EnvTransform
):
"""
Calculate and store the '__qualname__' and the global
...
...
Cython/Compiler/Pipeline.py
View file @
034a53fd
...
...
@@ -143,6 +143,7 @@ def create_pipeline(context, mode, exclude_classes=()):
from
.Visitor
import
PrintTree
from
.ParseTreeTransforms
import
WithTransform
,
NormalizeTree
,
PostParse
,
PxdPostParse
from
.ParseTreeTransforms
import
ForwardDeclareTypes
,
InjectGilHandling
,
AnalyseDeclarationsTransform
from
.ParseTreeTransforms
import
ComputeMROTransform
from
.ParseTreeTransforms
import
AnalyseExpressionsTransform
,
FindInvalidUseOfFusedTypes
from
.ParseTreeTransforms
import
CreateClosureClasses
,
MarkClosureVisitor
,
DecoratorTransform
from
.ParseTreeTransforms
import
TrackNumpyAttributes
,
InterpretCompilerDirectives
,
TransformBuiltinMethods
...
...
@@ -197,6 +198,7 @@ def create_pipeline(context, mode, exclude_classes=()):
ForwardDeclareTypes
(
context
),
InjectGilHandling
(),
AnalyseDeclarationsTransform
(
context
),
ComputeMROTransform
(
context
),
AutoTestDictTransform
(
context
),
EmbedSignature
(
context
),
EarlyReplaceBuiltinCalls
(
context
),
## Necessary?
...
...
Cython/Compiler/PyrexTypes.py
View file @
034a53fd
...
...
@@ -4109,9 +4109,63 @@ class CppScopedEnumType(CType):
env
.
use_utility_code
(
rst
)
# Merge procedure for the C3 linearisation used to produce the MRO
#
# sources:
# - https://www.python.org/download/releases/2.3/mro/
# - https://mail.python.org/pipermail/python-dev/2002-October/029176.html
# - https://github.com/mikeboers/C3Linearize/blob/master/c3linearize.py
#
def
mro_C3_merge
(
sequences
):
# make copies of the input lists to avoid side effect mutations
sequences
=
[
list
(
s
)
for
s
in
sequences
]
result
=
[]
while
True
:
# remove empty sequences from consideration
sequences
=
[
s
for
s
in
sequences
if
s
]
# the result is fully computed when there are no more sequences to examine
if
not
sequences
:
return
result
# find the first good head: a head of one of the sequences that is not in any tail
for
sequence
in
sequences
:
head
=
sequence
[
0
]
if
not
any
(
head
in
s
[
1
:]
for
s
in
sequences
):
break
else
:
error
(
None
,
"Inconsistent inheritance hierarchy for %s"
%
self
.
name
)
# make the head that was found the next element in the linearisation
result
.
append
(
head
)
# remove that head from consideration
for
seq
in
sequences
:
if
seq
[
0
]
==
head
:
del
seq
[
0
]
# Compute MRO for generic classes with minimal assumptions
#
# One assumption only:
# - if a class has bases, they are held in 'base_classes' attribute
#
def
compute_mro_generic
(
cls
):
print
(
"GENERIC C3 !!"
)
if
not
hasattr
(
cls
,
"base_classes"
)
or
cls
.
base_classes
is
None
:
return
[
cls
]
inputs
=
[[
cls
]]
for
base
in
cls
.
base_classes
:
inputs
.
append
(
compute_mro_generic
(
base
))
inputs
.
append
(
cls
.
base_classes
)
return
mro_C3_merge
(
inputs
)
class
CypClassType
(
CppClassType
):
# lock_mode string (tri-state: "nolock"/"checklock"/"autolock")
# mro [CppClassType] or None The Method Resolution Order of this cypclass according to Python
is_cyp_class
=
1
...
...
@@ -4119,6 +4173,27 @@ class CypClassType(CppClassType):
CppClassType
.
__init__
(
self
,
name
,
scope
,
cname
,
base_classes
,
templates
,
template_type
,
nogil
)
self
.
lock_mode
=
lock_mode
if
lock_mode
else
"autolock"
self
.
activable
=
activable
self
.
mro
=
None
# compute the MRO for this cypclass
# the mro is also computed for bases when needed
# based on https://mail.python.org/pipermail/python-dev/2002-October/029176.html
def
compute_mro
(
self
):
if
self
.
mro
is
not
None
:
return
self
.
mro
if
self
.
base_classes
is
None
:
self
.
mro
=
[
self
]
return
self
.
mro
inputs
=
[[
self
]]
for
base
in
self
.
base_classes
:
if
base
.
is_cyp_class
:
base_mro
=
base
.
compute_mro
()
else
:
base_mro
=
compute_mro_generic
(
base
)
inputs
.
append
(
base_mro
)
inputs
.
append
(
self
.
base_classes
)
self
.
mro
=
mro_C3_merge
(
inputs
)
return
self
.
mro
def
empty_declaration_code
(
self
):
if
self
.
_empty_declaration
is
None
:
...
...
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