Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / cython / src / Cython / CodeWriter.py
1 """
2 Serializes a Cython code tree to Cython code. This is primarily useful for
3 debugging and testing purposes.
4
5 The output is in a strict format, no whitespace or comments from the input
6 is preserved (and it could not be as it is not present in the code tree).
7 """
8
9 from Cython.Compiler.Visitor import TreeVisitor
10 from Cython.Compiler.ExprNodes import *
11
12 class LinesResult(object):
13     def __init__(self):
14         self.lines = []
15         self.s = u""
16
17     def put(self, s):
18         self.s += s
19
20     def newline(self):
21         self.lines.append(self.s)
22         self.s = u""
23
24     def putline(self, s):
25         self.put(s)
26         self.newline()
27
28 class DeclarationWriter(TreeVisitor):
29
30     indent_string = u"    "
31
32     def __init__(self, result = None):
33         super(DeclarationWriter, self).__init__()
34         if result is None:
35             result = LinesResult()
36         self.result = result
37         self.numindents = 0
38         self.tempnames = {}
39         self.tempblockindex = 0
40
41     def write(self, tree):
42         self.visit(tree)
43         return self.result
44
45     def indent(self):
46         self.numindents += 1
47
48     def dedent(self):
49         self.numindents -= 1
50
51     def startline(self, s = u""):
52         self.result.put(self.indent_string * self.numindents + s)
53
54     def put(self, s):
55         self.result.put(s)
56
57     def putline(self, s):
58         self.result.putline(self.indent_string * self.numindents + s)
59
60     def endline(self, s = u""):
61         self.result.putline(s)
62
63     def line(self, s):
64         self.startline(s)
65         self.endline()
66
67     def comma_separated_list(self, items, output_rhs=False):
68         if len(items) > 0:
69             for item in items[:-1]:
70                 self.visit(item)
71                 if output_rhs and item.default is not None:
72                     self.put(u" = ")
73                     self.visit(item.default)
74                 self.put(u", ")
75             self.visit(items[-1])
76
77     def visit_Node(self, node):
78         raise AssertionError("Node not handled by serializer: %r" % node)
79
80     def visit_ModuleNode(self, node):
81         self.visitchildren(node)
82
83     def visit_StatListNode(self, node):
84         self.visitchildren(node)
85     
86     def visit_CDefExternNode(self, node):
87         if node.include_file is None:
88             file = u'*'
89         else:
90             file = u'"%s"' % node.include_file
91         self.putline(u"cdef extern from %s:" % file)
92         self.indent()
93         self.visit(node.body)
94         self.dedent()
95
96     def visit_CPtrDeclaratorNode(self, node):
97         self.put('*')
98         self.visit(node.base)
99
100     def visit_CReferenceDeclaratorNode(self, node):
101         self.put('&')
102         self.visit(node.base)
103
104     def visit_CArrayDeclaratorNode(self, node):
105         self.visit(node.base)
106         self.put(u'[')
107         if node.dimension is not None:
108             self.visit(node.dimension)
109         self.put(u']')
110
111     def visit_CArrayDeclaratorNode(self, node):
112         self.visit(node.base)
113         self.put(u'[')
114         if node.dimension is not None:
115             self.visit(node.dimension)
116         self.put(u']')
117
118     def visit_CFuncDeclaratorNode(self, node):
119         # TODO: except, gil, etc.
120         self.visit(node.base)
121         self.put(u'(')
122         self.comma_separated_list(node.args)
123         self.endline(u')')
124
125     def visit_CNameDeclaratorNode(self, node):
126         self.put(node.name)
127
128     def visit_CSimpleBaseTypeNode(self, node):
129         # See Parsing.p_sign_and_longness
130         if node.is_basic_c_type:
131             self.put(("unsigned ", "", "signed ")[node.signed])
132             if node.longness < 0:
133                 self.put("short " * -node.longness)
134             elif node.longness > 0:
135                 self.put("long " * node.longness)
136         self.put(node.name)
137
138     def visit_CComplexBaseTypeNode(self, node):
139         self.put(u'(')
140         self.visit(node.base_type)
141         self.visit(node.declarator)
142         self.put(u')')
143
144     def visit_CNestedBaseTypeNode(self, node):
145         self.visit(node.base_type)
146         self.put(u'.')
147         self.put(node.name)
148
149     def visit_TemplatedTypeNode(self, node):
150         self.visit(node.base_type_node)
151         self.put(u'[')
152         self.comma_separated_list(node.positional_args + node.keyword_args.key_value_pairs)
153         self.put(u']')
154
155     def visit_CVarDefNode(self, node):
156         self.startline(u"cdef ")
157         self.visit(node.base_type)
158         self.put(u" ")
159         self.comma_separated_list(node.declarators, output_rhs=True)
160         self.endline()
161
162     def visit_container_node(self, node, decl, extras, attributes):
163         # TODO: visibility
164         self.startline(decl)
165         if node.name:
166             self.put(u' ')
167             self.put(node.name)
168             if node.cname is not None:
169                 self.put(u' "%s"' % node.cname)
170         if extras:
171             self.put(extras)
172         self.endline(':')
173         self.indent()
174         if not attributes:
175             self.putline('pass')
176         else:
177             for attribute in attributes:
178                 self.visit(attribute)
179         self.dedent()
180
181     def visit_CStructOrUnionDefNode(self, node):
182         if node.typedef_flag:
183             decl = u'ctypedef '
184         else:
185             decl = u'cdef '
186         if node.visibility == 'public':
187             decl += u'public '
188         if node.packed:
189             decl += u'packed '
190         decl += node.kind
191         self.visit_container_node(node, decl, None, node.attributes)
192
193     def visit_CppClassNode(self, node):
194         extras = ""
195         if node.templates:
196             extras = u"[%s]" % ", ".join(node.templates)
197         if node.base_classes:
198             extras += "(%s)" % ", ".join(node.base_classes)
199         self.visit_container_node(node, u"cdef cppclass", extras, node.attributes)
200
201     def visit_CEnumDefNode(self, node):
202         self.visit_container_node(node, u"cdef enum", None, node.items)
203
204     def visit_CEnumDefItemNode(self, node):
205         self.startline(node.name)
206         if node.cname:
207             self.put(u' "%s"' % node.cname)
208         if node.value:
209             self.put(u" = ")
210             self.visit(node.value)
211         self.endline()
212
213     def visit_CClassDefNode(self, node):
214         assert not node.module_name
215         if node.decorators:
216             for decorator in node.decorators:
217                 self.visit(decorator)
218         self.startline(u"cdef class ")
219         self.put(node.class_name)
220         if node.base_class_name:
221             self.put(u"(")
222             if node.base_class_module:
223                 self.put(node.base_class_module)
224                 self.put(u".")
225             self.put(node.base_class_name)
226             self.put(u")")
227         self.endline(u":")
228         self.indent()
229         self.visit(node.body)
230         self.dedent()
231
232     def visit_CTypeDefNode(self, node):
233         self.startline(u"ctypedef ")
234         self.visit(node.base_type)
235         self.put(u" ")
236         self.visit(node.declarator)
237         self.endline()
238
239     def visit_FuncDefNode(self, node):
240         self.startline(u"def %s(" % node.name)
241         self.comma_separated_list(node.args)
242         self.endline(u"):")
243         self.indent()
244         self.visit(node.body)
245         self.dedent()
246
247     def visit_CArgDeclNode(self, node):
248         if node.base_type.name is not None:
249             self.visit(node.base_type)
250             self.put(u" ")
251         self.visit(node.declarator)
252         if node.default is not None:
253             self.put(u" = ")
254             self.visit(node.default)
255
256     def visit_CImportStatNode(self, node):
257         self.startline(u"cimport ")
258         self.put(node.module_name)
259         if node.as_name:
260             self.put(u" as ")
261             self.put(node.as_name)
262         self.endline()
263
264     def visit_FromCImportStatNode(self, node):
265         self.startline(u"from ")
266         self.put(node.module_name)
267         self.put(u" cimport ")
268         first = True
269         for pos, name, as_name, kind in node.imported_names:
270             assert kind is None
271             if first:
272                 first = False
273             else:
274                 self.put(u", ")
275             self.put(name)
276             if as_name:
277                 self.put(u" as ")
278                 self.put(as_name)
279         self.endline()
280
281     def visit_NameNode(self, node):
282         self.put(node.name)
283
284     def visit_IntNode(self, node):
285         self.put(node.value)
286
287     def visit_NoneNode(self, node):
288         self.put(u"None")
289
290     def visit_NotNode(self, node):
291         self.put(u"(not ")
292         self.visit(node.operand)
293         self.put(u")")
294
295     def visit_DecoratorNode(self, node):
296         self.startline("@")
297         self.visit(node.decorator)
298         self.endline()
299
300     def visit_BinopNode(self, node):
301         self.visit(node.operand1)
302         self.put(u" %s " % node.operator)
303         self.visit(node.operand2)
304
305     def visit_AttributeNode(self, node):
306         self.visit(node.obj)
307         self.put(u".%s" % node.attribute)
308
309     def visit_BoolNode(self, node):
310         self.put(str(node.value))
311
312     # FIXME: represent string nodes correctly
313     def visit_StringNode(self, node):
314         value = node.value
315         if value.encoding is not None:
316             value = value.encode(value.encoding)
317         self.put(repr(value))
318
319     def visit_PassStatNode(self, node):
320         self.startline(u"pass")
321         self.endline()
322
323 class CodeWriter(DeclarationWriter):
324
325     def visit_SingleAssignmentNode(self, node):
326         self.startline()
327         self.visit(node.lhs)
328         self.put(u" = ")
329         self.visit(node.rhs)
330         self.endline()
331
332     def visit_CascadedAssignmentNode(self, node):
333         self.startline()
334         for lhs in node.lhs_list:
335             self.visit(lhs)
336             self.put(u" = ")
337         self.visit(node.rhs)
338         self.endline()
339
340     def visit_PrintStatNode(self, node):
341         self.startline(u"print ")
342         self.comma_separated_list(node.arg_tuple.args)
343         if not node.append_newline:
344             self.put(u",")
345         self.endline()
346
347     def visit_ForInStatNode(self, node):
348         self.startline(u"for ")
349         self.visit(node.target)
350         self.put(u" in ")
351         self.visit(node.iterator.sequence)
352         self.endline(u":")
353         self.indent()
354         self.visit(node.body)
355         self.dedent()
356         if node.else_clause is not None:
357             self.line(u"else:")
358             self.indent()
359             self.visit(node.else_clause)
360             self.dedent()
361
362     def visit_IfStatNode(self, node):
363         # The IfClauseNode is handled directly without a seperate match
364         # for clariy.
365         self.startline(u"if ")
366         self.visit(node.if_clauses[0].condition)
367         self.endline(":")
368         self.indent()
369         self.visit(node.if_clauses[0].body)
370         self.dedent()
371         for clause in node.if_clauses[1:]:
372             self.startline("elif ")
373             self.visit(clause.condition)
374             self.endline(":")
375             self.indent()
376             self.visit(clause.body)
377             self.dedent()
378         if node.else_clause is not None:
379             self.line("else:")
380             self.indent()
381             self.visit(node.else_clause)
382             self.dedent()
383
384     def visit_SequenceNode(self, node):
385         self.comma_separated_list(node.args) # Might need to discover whether we need () around tuples...hmm...
386
387     def visit_SimpleCallNode(self, node):
388         self.visit(node.function)
389         self.put(u"(")
390         self.comma_separated_list(node.args)
391         self.put(")")
392
393     def visit_GeneralCallNode(self, node):
394         self.visit(node.function)
395         self.put(u"(")
396         posarg = node.positional_args
397         if isinstance(posarg, AsTupleNode):
398             self.visit(posarg.arg)
399         else:
400             self.comma_separated_list(posarg)
401         if node.keyword_args is not None or node.starstar_arg is not None:
402             raise Exception("Not implemented yet")
403         self.put(u")")
404
405     def visit_ExprStatNode(self, node):
406         self.startline()
407         self.visit(node.expr)
408         self.endline()
409
410     def visit_InPlaceAssignmentNode(self, node):
411         self.startline()
412         self.visit(node.lhs)
413         self.put(u" %s= " % node.operator)
414         self.visit(node.rhs)
415         self.endline()
416
417     def visit_WithStatNode(self, node):
418         self.startline()
419         self.put(u"with ")
420         self.visit(node.manager)
421         if node.target is not None:
422             self.put(u" as ")
423             self.visit(node.target)
424         self.endline(u":")
425         self.indent()
426         self.visit(node.body)
427         self.dedent()
428
429     def visit_TryFinallyStatNode(self, node):
430         self.line(u"try:")
431         self.indent()
432         self.visit(node.body)
433         self.dedent()
434         self.line(u"finally:")
435         self.indent()
436         self.visit(node.finally_clause)
437         self.dedent()
438
439     def visit_TryExceptStatNode(self, node):
440         self.line(u"try:")
441         self.indent()
442         self.visit(node.body)
443         self.dedent()
444         for x in node.except_clauses:
445             self.visit(x)
446         if node.else_clause is not None:
447             self.visit(node.else_clause)
448
449     def visit_ExceptClauseNode(self, node):
450         self.startline(u"except")
451         if node.pattern is not None:
452             self.put(u" ")
453             self.visit(node.pattern)
454         if node.target is not None:
455             self.put(u", ")
456             self.visit(node.target)
457         self.endline(":")
458         self.indent()
459         self.visit(node.body)
460         self.dedent()
461
462     def visit_ReturnStatNode(self, node):
463         self.startline("return ")
464         self.visit(node.value)
465         self.endline()
466
467     def visit_ReraiseStatNode(self, node):
468         self.line("raise")
469
470     def visit_ImportNode(self, node):
471         self.put(u"(import %s)" % node.module_name.value)
472
473     def visit_TempsBlockNode(self, node):
474         """
475         Temporaries are output like $1_1', where the first number is
476         an index of the TempsBlockNode and the second number is an index
477         of the temporary which that block allocates.
478         """
479         idx = 0
480         for handle in node.temps:
481             self.tempnames[handle] = "$%d_%d" % (self.tempblockindex, idx)
482             idx += 1
483         self.tempblockindex += 1
484         self.visit(node.body)
485
486     def visit_TempRefNode(self, node):
487         self.put(self.tempnames[node.handle])
488
489
490 class PxdWriter(DeclarationWriter):
491     def __call__(self, node):
492         print u'\n'.join(self.write(node).lines)
493         return node
494
495     def visit_CFuncDefNode(self, node):
496         if 'inline' in node.modifiers:
497             return
498         if node.overridable:
499             self.startline(u'cpdef ')
500         else:
501             self.startline(u'cdef ')
502         if node.visibility != 'private':
503             self.put(node.visibility)
504             self.put(u' ')
505         if node.api:
506             self.put(u'api ')
507         self.visit(node.declarator)
508     
509     def visit_StatNode(self, node):
510         pass
511
512