summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2020-04-18 17:10:25 +0200
committerStefan Behnel <stefan_ml@behnel.de>2020-04-18 17:22:11 +0200
commitfdfd96d1b6e29dec0faa849321765c96fe39bb93 (patch)
treec22b1c194ea6152771fdd4ef37746fb1448b9033
parent1c8d21e19fbf469f770423fa8664f19a67a59ab2 (diff)
downloadcython-full_code_writer.tar.gz
Make CodeWriter inherit from ExpressionWriter in order to support all kinds of expressions without duplicating code.full_code_writer
-rw-r--r--Cython/CodeWriter.py139
-rw-r--r--Cython/Compiler/AutoDocTransforms.py3
-rw-r--r--Cython/Tests/TestCodeWriter.py9
3 files changed, 63 insertions, 88 deletions
diff --git a/Cython/CodeWriter.py b/Cython/CodeWriter.py
index 2e4646a65..ec37c5bb4 100644
--- a/Cython/CodeWriter.py
+++ b/Cython/CodeWriter.py
@@ -28,7 +28,11 @@ class LinesResult(object):
self.put(s)
self.newline()
+
class DeclarationWriter(TreeVisitor):
+ """
+ A Cython code writer that is limited to declarations nodes.
+ """
indent_string = u" "
@@ -111,13 +115,6 @@ class DeclarationWriter(TreeVisitor):
self.visit(node.dimension)
self.put(u']')
- def visit_CArrayDeclaratorNode(self, node):
- self.visit(node.base)
- self.put(u'[')
- if node.dimension is not None:
- self.visit(node.dimension)
- self.put(u']')
-
def visit_CFuncDeclaratorNode(self, node):
# TODO: except, gil, etc.
self.visit(node.base)
@@ -240,6 +237,7 @@ class DeclarationWriter(TreeVisitor):
self.endline()
def visit_FuncDefNode(self, node):
+ # TODO: support cdef + cpdef functions
self.startline(u"def %s(" % node.name)
self.comma_separated_list(node.args)
self.endline(u"):")
@@ -284,46 +282,20 @@ class DeclarationWriter(TreeVisitor):
def visit_NameNode(self, node):
self.put(node.name)
- def visit_IntNode(self, node):
- self.put(node.value)
-
- def visit_NoneNode(self, node):
- self.put(u"None")
-
- def visit_NotNode(self, node):
- self.put(u"(not ")
- self.visit(node.operand)
- self.put(u")")
-
def visit_DecoratorNode(self, node):
self.startline("@")
self.visit(node.decorator)
self.endline()
- def visit_BinopNode(self, node):
- self.visit(node.operand1)
- self.put(u" %s " % node.operator)
- self.visit(node.operand2)
-
- def visit_AttributeNode(self, node):
- self.visit(node.obj)
- self.put(u".%s" % node.attribute)
-
- def visit_BoolNode(self, node):
- self.put(str(node.value))
-
- # FIXME: represent string nodes correctly
- def visit_StringNode(self, node):
- value = node.value
- if value.encoding is not None:
- value = value.encode(value.encoding)
- self.put(repr(value))
-
def visit_PassStatNode(self, node):
self.startline(u"pass")
self.endline()
-class CodeWriter(DeclarationWriter):
+
+class StatementWriter(DeclarationWriter):
+ """
+ A Cython code writer for most language statement features.
+ """
def visit_SingleAssignmentNode(self, node):
self.startline()
@@ -349,7 +321,10 @@ class CodeWriter(DeclarationWriter):
def visit_ForInStatNode(self, node):
self.startline(u"for ")
- self.visit(node.target)
+ if node.target.is_sequence_constructor:
+ self.comma_separated_list(node.target.args)
+ else:
+ self.visit(node.target)
self.put(u" in ")
self.visit(node.iterator.sequence)
self.endline(u":")
@@ -387,32 +362,6 @@ class CodeWriter(DeclarationWriter):
def visit_SequenceNode(self, node):
self.comma_separated_list(node.args) # Might need to discover whether we need () around tuples...hmm...
- def visit_SimpleCallNode(self, node):
- self.visit(node.function)
- self.put(u"(")
- self.comma_separated_list(node.args)
- self.put(")")
-
- def visit_GeneralCallNode(self, node):
- self.visit(node.function)
- self.put(u"(")
- posarg = node.positional_args
- if isinstance(posarg, AsTupleNode):
- self.visit(posarg.arg)
- else:
- self.comma_separated_list(posarg.args) # TupleNode.args
- if node.keyword_args:
- if isinstance(node.keyword_args, DictNode):
- for i, (name, value) in enumerate(node.keyword_args.key_value_pairs):
- if i > 0:
- self.put(', ')
- self.visit(name)
- self.put('=')
- self.visit(value)
- else:
- raise Exception("Not implemented yet")
- self.put(u")")
-
def visit_ExprStatNode(self, node):
self.startline()
self.visit(node.expr)
@@ -498,30 +447,10 @@ class CodeWriter(DeclarationWriter):
self.put(self.tempnames[node.handle])
-class PxdWriter(DeclarationWriter):
- def __call__(self, node):
- print(u'\n'.join(self.write(node).lines))
- 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.visibility != 'private':
- self.put(node.visibility)
- self.put(u' ')
- if node.api:
- self.put(u'api ')
- self.visit(node.declarator)
-
- def visit_StatNode(self, node):
- pass
-
-
class ExpressionWriter(TreeVisitor):
+ """
+ A Cython code writer that is intentionally limited to expressions.
+ """
def __init__(self, result=None):
super(ExpressionWriter, self).__init__()
@@ -814,3 +743,37 @@ class ExpressionWriter(TreeVisitor):
# type(body) is Nodes.ExprStatNode
body = body.expr.arg
self.emit_comprehension(body, target, sequence, condition, u"()")
+
+
+class PxdWriter(DeclarationWriter, ExpressionWriter):
+ """
+ A Cython code writer for everything supported in pxd files.
+ (currently unused)
+ """
+
+ def __call__(self, node):
+ print(u'\n'.join(self.write(node).lines))
+ 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.visibility != 'private':
+ self.put(node.visibility)
+ self.put(u' ')
+ if node.api:
+ self.put(u'api ')
+ self.visit(node.declarator)
+
+ def visit_StatNode(self, node):
+ pass
+
+
+class CodeWriter(StatementWriter, ExpressionWriter):
+ """
+ A complete Cython code writer.
+ """
diff --git a/Cython/Compiler/AutoDocTransforms.py b/Cython/Compiler/AutoDocTransforms.py
index 9b8f2000b..a5648f49e 100644
--- a/Cython/Compiler/AutoDocTransforms.py
+++ b/Cython/Compiler/AutoDocTransforms.py
@@ -9,6 +9,9 @@ from .Errors import warning
class AnnotationWriter(ExpressionWriter):
+ """
+ A Cython code writer for Python expressions in argument/variable annotations.
+ """
def __init__(self, description=None):
"""description is optional. If specified it is used in
warning messages for the nodes that don't convert to string properly.
diff --git a/Cython/Tests/TestCodeWriter.py b/Cython/Tests/TestCodeWriter.py
index 2f9ee6179..c8bddd0bf 100644
--- a/Cython/Tests/TestCodeWriter.py
+++ b/Cython/Tests/TestCodeWriter.py
@@ -68,10 +68,19 @@ class TestCodeWriter(CythonTest):
else:
print(43)
""")
+ self.t(u"""
+ for abc in (1, 2, 3):
+ print(x, y, z)
+ else:
+ print(43)
+ """)
def test_inplace_assignment(self):
self.t(u"x += 43")
+ def test_cascaded_assignment(self):
+ self.t(u"x = y = z = abc = 43")
+
def test_attribute(self):
self.t(u"a.x")