1 from Cython.Compiler.Visitor import TreeVisitor, get_temp_name_handle_desc
2 from Cython.Compiler.Nodes import *
3 from Cython.Compiler.ExprNodes import *
6 Serializes a Cython code tree to Cython code. This is primarily useful for
7 debugging and testing purposes.
9 The output is in a strict format, no whitespace or comments from the input
10 is preserved (and it could not be as it is not present in the code tree).
13 class LinesResult(object):
22 self.lines.append(self.s)
29 class CodeWriter(TreeVisitor):
33 def __init__(self, result = None):
34 super(CodeWriter, self).__init__()
36 result = LinesResult()
41 def write(self, tree):
50 def startline(self, s = u""):
51 self.result.put(self.indent_string * self.numindents + s)
56 def endline(self, s = u""):
57 self.result.putline(s)
63 def putname(self, name):
64 tmpdesc = get_temp_name_handle_desc(name)
65 if tmpdesc is not None:
66 name = self.tempnames.setdefault(tmpdesc, u"$" +tmpdesc)
69 def comma_seperated_list(self, items, output_rhs=False):
71 for item in items[:-1]:
73 if output_rhs and item.default is not None:
75 self.visit(item.default)
79 def visit_Node(self, node):
80 raise AssertionError("Node not handled by serializer: %r" % node)
82 def visit_ModuleNode(self, node):
83 self.visitchildren(node)
85 def visit_StatListNode(self, node):
86 self.visitchildren(node)
88 def visit_FuncDefNode(self, node):
89 self.startline(u"def %s(" % node.name)
90 self.comma_seperated_list(node.args)
96 def visit_CArgDeclNode(self, node):
97 if node.base_type.name is not None:
98 self.visit(node.base_type)
100 self.visit(node.declarator)
101 if node.default is not None:
103 self.visit(node.default)
105 def visit_CNameDeclaratorNode(self, node):
108 def visit_CSimpleBaseTypeNode(self, node):
109 # See Parsing.p_sign_and_longness
110 if node.is_basic_c_type:
111 self.put(("unsigned ", "", "signed ")[node.signed])
112 if node.longness < 0:
113 self.put("short " * -node.longness)
114 elif node.longness > 0:
115 self.put("long " * node.longness)
119 def visit_SingleAssignmentNode(self, node):
126 def visit_CascadedAssignmentNode(self, node):
128 for lhs in node.lhs_list:
134 def visit_NameNode(self, node):
135 self.putname(node.name)
137 def visit_IntNode(self, node):
140 def visit_StringNode(self, node):
142 if value.encoding is not None:
143 value = value.encode(value.encoding)
144 self.put(repr(value))
146 def visit_IfStatNode(self, node):
147 # The IfClauseNode is handled directly without a seperate match
149 self.startline(u"if ")
150 self.visit(node.if_clauses[0].condition)
153 self.visit(node.if_clauses[0].body)
155 for clause in node.if_clauses[1:]:
156 self.startline("elif ")
157 self.visit(clause.condition)
160 self.visit(clause.body)
162 if node.else_clause is not None:
165 self.visit(node.else_clause)
168 def visit_PassStatNode(self, node):
169 self.startline(u"pass")
172 def visit_PrintStatNode(self, node):
173 self.startline(u"print ")
174 self.comma_seperated_list(node.arg_tuple.args)
175 if not node.append_newline:
179 def visit_BinopNode(self, node):
180 self.visit(node.operand1)
181 self.put(u" %s " % node.operator)
182 self.visit(node.operand2)
184 def visit_CVarDefNode(self, node):
185 self.startline(u"cdef ")
186 self.visit(node.base_type)
188 self.comma_seperated_list(node.declarators, output_rhs=True)
191 def visit_ForInStatNode(self, node):
192 self.startline(u"for ")
193 self.visit(node.target)
195 self.visit(node.iterator.sequence)
198 self.visit(node.body)
200 if node.else_clause is not None:
203 self.visit(node.else_clause)
206 def visit_SequenceNode(self, node):
207 self.comma_seperated_list(node.args) # Might need to discover whether we need () around tuples...hmm...
209 def visit_SimpleCallNode(self, node):
210 self.visit(node.function)
212 self.comma_seperated_list(node.args)
215 def visit_GeneralCallNode(self, node):
216 self.visit(node.function)
218 posarg = node.positional_args
219 if isinstance(posarg, AsTupleNode):
220 self.visit(posarg.arg)
222 self.comma_seperated_list(posarg)
223 if node.keyword_args is not None or node.starstar_arg is not None:
224 raise Exception("Not implemented yet")
227 def visit_ExprStatNode(self, node):
229 self.visit(node.expr)
232 def visit_InPlaceAssignmentNode(self, node):
235 self.put(u" %s= " % node.operator)
239 def visit_WithStatNode(self, node):
242 self.visit(node.manager)
243 if node.target is not None:
245 self.visit(node.target)
248 self.visit(node.body)
251 def visit_AttributeNode(self, node):
253 self.put(u".%s" % node.attribute)
255 def visit_BoolNode(self, node):
256 self.put(str(node.value))
258 def visit_TryFinallyStatNode(self, node):
261 self.visit(node.body)
263 self.line(u"finally:")
265 self.visit(node.finally_clause)
268 def visit_TryExceptStatNode(self, node):
271 self.visit(node.body)
273 for x in node.except_clauses:
275 if node.else_clause is not None:
276 self.visit(node.else_clause)
278 def visit_ExceptClauseNode(self, node):
279 self.startline(u"except")
280 if node.pattern is not None:
282 self.visit(node.pattern)
283 if node.target is not None:
285 self.visit(node.target)
288 self.visit(node.body)
291 def visit_ReturnStatNode(self, node):
292 self.startline("return ")
293 self.visit(node.value)
296 def visit_DecoratorNode(self, node):
298 self.visit(node.decorator)
301 def visit_ReraiseStatNode(self, node):
304 def visit_NoneNode(self, node):
307 def visit_ImportNode(self, node):
308 self.put(u"(import %s)" % node.module_name.value)
310 def visit_NotNode(self, node):
312 self.visit(node.operand)