Skip to content

Commit

Permalink
Fixes CodeWriter for cdef functions aka. CFuncDefNode.
Browse files Browse the repository at this point in the history
Signed-off-by: Tao He <linzhu.ht@alibaba-inc.com>
  • Loading branch information
sighingnow committed Jun 23, 2020
1 parent 8f53112 commit f4fff96
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 7 deletions.
77 changes: 70 additions & 7 deletions Cython/CodeWriter.py
@@ -1,7 +1,6 @@
"""
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).
"""
Expand All @@ -10,6 +9,7 @@

from .Compiler.Visitor import TreeVisitor
from .Compiler.ExprNodes import *
from .Compiler.Nodes import CNameDeclaratorNode


class LinesResult(object):
Expand Down Expand Up @@ -80,6 +80,9 @@ def comma_separated_list(self, items, output_rhs=False):
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_Node(self, node):
raise AssertionError("Node not handled by serializer: %r" % node)
Expand Down Expand Up @@ -133,7 +136,8 @@ def visit_CSimpleBaseTypeNode(self, node):
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'(')
Expand Down Expand Up @@ -245,10 +249,43 @@ def visit_FuncDefNode(self, node):
self.visit(node.body)
self.dedent()

def visit_CFuncDefNode(self, node):
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' ')
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.indent()
self.visit(node.body)
self.dedent()

def visit_CArgDeclNode(self, node):
if node.base_type.name is not None:
self.visit(node.base_type)
self.put(u" ")
# a special case: if `node.declarator` is a `CNameDeclaratorNode`,
# its "name" might be empty string, for example, for `cdef f(x)`.
if not isinstance(node.declarator, CNameDeclaratorNode) or \
node.declarator.name:
self.put(u" ")
self.visit(node.declarator)
if node.default is not None:
self.put(u" = ")
Expand Down Expand Up @@ -359,6 +396,25 @@ def visit_IfStatNode(self, node):
self.visit(node.else_clause)
self.dedent()

def visit_WhileStatNode(self, node):
self.startline(u"while ")
self.visit(node.condition)
self.endline(u":")
self.indent()
self.visit(node.body)
self.dedent()
if node.else_clause is not None:
self.line("else:")
self.indent()
self.visit(node.else_clause)
self.dedent()

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...

Expand Down Expand Up @@ -480,12 +536,18 @@ def comma_separated_list(self, items):
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"...")

Expand Down Expand Up @@ -756,12 +818,13 @@ def __call__(self, node):
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' ')
Expand Down
23 changes: 23 additions & 0 deletions Cython/Tests/TestCodeWriter.py
Expand Up @@ -21,6 +21,7 @@ def test_print(self):
self.t(u"""
print(x + y ** 2)
print(x, y, z)
print(x + y, x + y * z, x * (y + z))
""")

def test_if(self):
Expand All @@ -46,6 +47,20 @@ def f(x = 34, y = 54, z):
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")

Expand Down Expand Up @@ -75,6 +90,14 @@ def test_for_loop(self):
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")

Expand Down

0 comments on commit f4fff96

Please sign in to comment.