diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2020-04-18 22:36:27 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-18 22:36:27 +0200 |
commit | 8abcb26f075a7985a71a37f9320252019ef4bfe7 (patch) | |
tree | 6203b5fae2c6af9bbf7bb18dbcc92e1cc80d23a7 | |
parent | bfc4c3fab90d90b09ccd55b0f038a528619f15e3 (diff) | |
download | cython-8abcb26f075a7985a71a37f9320252019ef4bfe7.tar.gz |
Make CodeWriter inherit from ExpressionWriter in order to support all kinds of expressions without duplicating code. (GH-3528)
-rw-r--r-- | Cython/CodeWriter.py | 139 | ||||
-rw-r--r-- | Cython/Compiler/AutoDocTransforms.py | 3 | ||||
-rw-r--r-- | Cython/Tests/TestCodeWriter.py | 9 |
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") |