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
ccd17d53
Commit
ccd17d53
authored
Jul 03, 2020
by
Tao He
Committed by
GitHub
Jul 02, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve syntax feature support of Cython CodeWriter (GH-3514)
parent
75f4aff7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
112 additions
and
53 deletions
+112
-53
Cython/CodeWriter.py
Cython/CodeWriter.py
+89
-53
Cython/Tests/TestCodeWriter.py
Cython/Tests/TestCodeWriter.py
+23
-0
No files found.
Cython/CodeWriter.py
View file @
ccd17d53
"""
Serializes a Cython code tree to Cython code. This is primarily useful for
debugging and testing purposes.
The output is in a strict format, no whitespace or comments from the input
is preserved (and it could not be as it is not present in the code tree).
"""
...
...
@@ -10,6 +9,7 @@ from __future__ import absolute_import, print_function
from
.Compiler.Visitor
import
TreeVisitor
from
.Compiler.ExprNodes
import
*
from
.Compiler.Nodes
import
CNameDeclaratorNode
,
CSimpleBaseTypeNode
class
LinesResult
(
object
):
...
...
@@ -80,6 +80,14 @@ class DeclarationWriter(TreeVisitor):
self
.
visit
(
item
.
default
)
self
.
put
(
u", "
)
self
.
visit
(
items
[
-
1
])
if
output_rhs
and
items
[
-
1
].
default
is
not
None
:
self
.
put
(
u" = "
)
self
.
visit
(
items
[
-
1
].
default
)
def
_visit_indented
(
self
,
node
):
self
.
indent
()
self
.
visit
(
node
)
self
.
dedent
()
def
visit_Node
(
self
,
node
):
raise
AssertionError
(
"Node not handled by serializer: %r"
%
node
)
...
...
@@ -96,9 +104,7 @@ class DeclarationWriter(TreeVisitor):
else
:
file
=
u'"%s"'
%
node
.
include_file
self
.
putline
(
u"cdef extern from %s:"
%
file
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
def
visit_CPtrDeclaratorNode
(
self
,
node
):
self
.
put
(
'*'
)
...
...
@@ -133,13 +139,12 @@ class DeclarationWriter(TreeVisitor):
self
.
put
(
"short "
*
-
node
.
longness
)
elif
node
.
longness
>
0
:
self
.
put
(
"long "
*
node
.
longness
)
self
.
put
(
node
.
name
)
if
node
.
name
is
not
None
:
self
.
put
(
node
.
name
)
def
visit_CComplexBaseTypeNode
(
self
,
node
):
self
.
put
(
u'('
)
self
.
visit
(
node
.
base_type
)
self
.
visit
(
node
.
declarator
)
self
.
put
(
u')'
)
def
visit_CNestedBaseTypeNode
(
self
,
node
):
self
.
visit
(
node
.
base_type
)
...
...
@@ -159,7 +164,7 @@ class DeclarationWriter(TreeVisitor):
self
.
comma_separated_list
(
node
.
declarators
,
output_rhs
=
True
)
self
.
endline
()
def
visit_container_node
(
self
,
node
,
decl
,
extras
,
attributes
):
def
_
visit_container_node
(
self
,
node
,
decl
,
extras
,
attributes
):
# TODO: visibility
self
.
startline
(
decl
)
if
node
.
name
:
...
...
@@ -188,7 +193,7 @@ class DeclarationWriter(TreeVisitor):
if
node
.
packed
:
decl
+=
u'packed '
decl
+=
node
.
kind
self
.
visit_container_node
(
node
,
decl
,
None
,
node
.
attributes
)
self
.
_
visit_container_node
(
node
,
decl
,
None
,
node
.
attributes
)
def
visit_CppClassNode
(
self
,
node
):
extras
=
""
...
...
@@ -196,10 +201,10 @@ class DeclarationWriter(TreeVisitor):
extras
=
u"[%s]"
%
", "
.
join
(
node
.
templates
)
if
node
.
base_classes
:
extras
+=
"(%s)"
%
", "
.
join
(
node
.
base_classes
)
self
.
visit_container_node
(
node
,
u"cdef cppclass"
,
extras
,
node
.
attributes
)
self
.
_
visit_container_node
(
node
,
u"cdef cppclass"
,
extras
,
node
.
attributes
)
def
visit_CEnumDefNode
(
self
,
node
):
self
.
visit_container_node
(
node
,
u"cdef enum"
,
None
,
node
.
items
)
self
.
_
visit_container_node
(
node
,
u"cdef enum"
,
None
,
node
.
items
)
def
visit_CEnumDefItemNode
(
self
,
node
):
self
.
startline
(
node
.
name
)
...
...
@@ -225,9 +230,7 @@ class DeclarationWriter(TreeVisitor):
self
.
put
(
node
.
base_class_name
)
self
.
put
(
u")"
)
self
.
endline
(
u":"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
def
visit_CTypeDefNode
(
self
,
node
):
self
.
startline
(
u"ctypedef "
)
...
...
@@ -241,14 +244,45 @@ class DeclarationWriter(TreeVisitor):
self
.
startline
(
u"def %s("
%
node
.
name
)
self
.
comma_separated_list
(
node
.
args
)
self
.
endline
(
u"):"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
def
visit_CFuncDefNode
(
self
,
node
):
self
.
startline
(
u'cpdef '
if
node
.
overridable
else
u'cdef '
)
if
node
.
modifiers
:
self
.
put
(
' '
.
join
(
node
.
modifiers
))
self
.
put
(
' '
)
if
node
.
visibility
!=
'private'
:
self
.
put
(
node
.
visibility
)
self
.
put
(
u' '
)
if
node
.
api
:
self
.
put
(
u'api '
)
if
node
.
base_type
:
self
.
visit
(
node
.
base_type
)
if
node
.
base_type
.
name
is
not
None
:
self
.
put
(
u' '
)
# visit the CFuncDeclaratorNode, but put a `:` at the end of line
self
.
visit
(
node
.
declarator
.
base
)
self
.
put
(
u'('
)
self
.
comma_separated_list
(
node
.
declarator
.
args
)
self
.
endline
(
u'):'
)
self
.
_visit_indented
(
node
.
body
)
def
visit_CArgDeclNode
(
self
,
node
):
if
node
.
base_type
.
name
is
not
None
:
# For "CSimpleBaseTypeNode", the variable type may have been parsed as type.
# For other node types, the "name" is always None.
if
not
isinstance
(
node
.
base_type
,
CSimpleBaseTypeNode
)
or
\
node
.
base_type
.
name
is
not
None
:
self
.
visit
(
node
.
base_type
)
self
.
put
(
u" "
)
# If we printed something for "node.base_type", we may need to print an extra ' '.
#
# Special case: if "node.declarator" is a "CNameDeclaratorNode",
# its "name" might be an empty string, for example, for "cdef f(x)".
if
node
.
declarator
.
declared_name
():
self
.
put
(
u" "
)
self
.
visit
(
node
.
declarator
)
if
node
.
default
is
not
None
:
self
.
put
(
u" = "
)
...
...
@@ -328,14 +362,10 @@ class StatementWriter(DeclarationWriter):
self
.
put
(
u" in "
)
self
.
visit
(
node
.
iterator
.
sequence
)
self
.
endline
(
u":"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
if
node
.
else_clause
is
not
None
:
self
.
line
(
u"else:"
)
self
.
indent
()
self
.
visit
(
node
.
else_clause
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
else_clause
)
def
visit_IfStatNode
(
self
,
node
):
# The IfClauseNode is handled directly without a separate match
...
...
@@ -343,21 +373,30 @@ class StatementWriter(DeclarationWriter):
self
.
startline
(
u"if "
)
self
.
visit
(
node
.
if_clauses
[
0
].
condition
)
self
.
endline
(
":"
)
self
.
indent
()
self
.
visit
(
node
.
if_clauses
[
0
].
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
if_clauses
[
0
].
body
)
for
clause
in
node
.
if_clauses
[
1
:]:
self
.
startline
(
"elif "
)
self
.
visit
(
clause
.
condition
)
self
.
endline
(
":"
)
self
.
indent
()
self
.
visit
(
clause
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
clause
.
body
)
if
node
.
else_clause
is
not
None
:
self
.
line
(
"else:"
)
self
.
indent
()
self
.
visit
(
node
.
else_clause
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
else_clause
)
def
visit_WhileStatNode
(
self
,
node
):
self
.
startline
(
u"while "
)
self
.
visit
(
node
.
condition
)
self
.
endline
(
u":"
)
self
.
_visit_indented
(
node
.
body
)
if
node
.
else_clause
is
not
None
:
self
.
line
(
"else:"
)
self
.
_visit_indented
(
node
.
else_clause
)
def
visit_ContinueStatNode
(
self
,
node
):
self
.
line
(
u"continue"
)
def
visit_BreakStatNode
(
self
,
node
):
self
.
line
(
u"break"
)
def
visit_SequenceNode
(
self
,
node
):
self
.
comma_separated_list
(
node
.
args
)
# Might need to discover whether we need () around tuples...hmm...
...
...
@@ -382,25 +421,17 @@ class StatementWriter(DeclarationWriter):
self
.
put
(
u" as "
)
self
.
visit
(
node
.
target
)
self
.
endline
(
u":"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
def
visit_TryFinallyStatNode
(
self
,
node
):
self
.
line
(
u"try:"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
self
.
line
(
u"finally:"
)
self
.
indent
()
self
.
visit
(
node
.
finally_clause
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
finally_clause
)
def
visit_TryExceptStatNode
(
self
,
node
):
self
.
line
(
u"try:"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
for
x
in
node
.
except_clauses
:
self
.
visit
(
x
)
if
node
.
else_clause
is
not
None
:
...
...
@@ -415,9 +446,7 @@ class StatementWriter(DeclarationWriter):
self
.
put
(
u", "
)
self
.
visit
(
node
.
target
)
self
.
endline
(
":"
)
self
.
indent
()
self
.
visit
(
node
.
body
)
self
.
dedent
()
self
.
_visit_indented
(
node
.
body
)
def
visit_ReturnStatNode
(
self
,
node
):
self
.
startline
(
"return "
)
...
...
@@ -480,12 +509,18 @@ class ExpressionWriter(TreeVisitor):
def
visit_Node
(
self
,
node
):
raise
AssertionError
(
"Node not handled by serializer: %r"
%
node
)
def
visit_NameNode
(
self
,
node
):
self
.
put
(
node
.
name
)
def
visit_IntNode
(
self
,
node
):
self
.
put
(
node
.
value
)
def
visit_FloatNode
(
self
,
node
):
self
.
put
(
node
.
value
)
def
visit_NoneNode
(
self
,
node
):
self
.
put
(
u"None"
)
def
visit_NameNode
(
self
,
node
):
self
.
put
(
node
.
name
)
def
visit_EllipsisNode
(
self
,
node
):
self
.
put
(
u"..."
)
...
...
@@ -756,12 +791,13 @@ class PxdWriter(DeclarationWriter, ExpressionWriter):
return
node
def
visit_CFuncDefNode
(
self
,
node
):
if
'inline'
in
node
.
modifiers
:
return
if
node
.
overridable
:
self
.
startline
(
u'cpdef '
)
else
:
self
.
startline
(
u'cdef '
)
if
node
.
modifiers
:
self
.
put
(
' '
.
join
(
node
.
modifiers
))
self
.
put
(
' '
)
if
node
.
visibility
!=
'private'
:
self
.
put
(
node
.
visibility
)
self
.
put
(
u' '
)
...
...
Cython/Tests/TestCodeWriter.py
View file @
ccd17d53
...
...
@@ -21,6 +21,7 @@ class TestCodeWriter(CythonTest):
self
.
t
(
u"""
print(x + y ** 2)
print(x, y, z)
print(x + y, x + y * z, x * (y + z))
"""
)
def
test_if
(
self
):
...
...
@@ -46,6 +47,20 @@ class TestCodeWriter(CythonTest):
pass
"""
)
def
test_cdef
(
self
):
self
.
t
(
u"""
cdef f(x, y, z):
pass
cdef public void (x = 34, y = 54, z):
pass
cdef f(int *x, void *y, Value *z):
pass
cdef f(int **x, void **y, Value **z):
pass
cdef inline f(int &x, Value &z):
pass
"""
)
def
test_longness_and_signedness
(
self
):
self
.
t
(
u"def f(unsigned long long long long long int y):
\
n
pass"
)
...
...
@@ -75,6 +90,14 @@ class TestCodeWriter(CythonTest):
print(43)
"""
)
def
test_while_loop
(
self
):
self
.
t
(
u"""
while True:
while True:
while True:
continue
"""
)
def
test_inplace_assignment
(
self
):
self
.
t
(
u"x += 43"
)
...
...
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