Merge -dagss and -devel
[cython.git] / Cython / CodeWriter.py
1 from Cython.Compiler.Visitor import TreeVisitor
2 from Cython.Compiler.Nodes import *
3
4 """
5 Serializes a Cython code tree to Cython code. This is primarily useful for
6 debugging and testing purposes.
7
8 The output is in a strict format, no whitespace or comments from the input
9 is preserved (and it could not be as it is not present in the code tree).
10 """
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 CodeWriter(TreeVisitor):
29
30     indent_string = u"    "
31     
32     def __init__(self, result = None):
33         super(CodeWriter, self).__init__()
34         if result is None:
35             result = LinesResult()
36         self.result = result
37         self.numindents = 0
38     
39     def write(self, tree):
40         self.visit(tree)
41     
42     def indent(self):
43         self.numindents += 1
44     
45     def dedent(self):
46         self.numindents -= 1
47     
48     def startline(self, s = u""):
49         self.result.put(self.indent_string * self.numindents + s)
50     
51     def put(self, s):
52         self.result.put(s)
53     
54     def endline(self, s = u""):
55         self.result.putline(s)
56
57     def line(self, s):
58         self.startline(s)
59         self.endline()
60     
61     def comma_seperated_list(self, items, output_rhs=False):
62         if len(items) > 0:
63             for item in items[:-1]:
64                 self.visit(item)
65                 if output_rhs and item.rhs is not None:
66                     self.put(u" = ")
67                     self.visit(item.rhs)
68                 self.put(u", ")
69             self.visit(items[-1])
70     
71     def visit_Node(self, node):
72         raise AssertionError("Node not handled by serializer: %r" % node)
73     
74     def visit_ModuleNode(self, node):
75         self.visitchildren(node)
76     
77     def visit_StatListNode(self, node):
78         self.visitchildren(node)
79
80     def visit_FuncDefNode(self, node):
81         self.startline(u"def %s(" % node.name)
82         self.comma_seperated_list(node.args)
83         self.endline(u"):")
84         self.indent()
85         self.visit(node.body)
86         self.dedent()
87     
88     def visit_CArgDeclNode(self, node):
89         if node.base_type.name is not None:
90             self.visit(node.base_type)
91             self.put(u" ")
92         self.visit(node.declarator)
93         if node.default is not None:
94             self.put(u" = ")
95             self.visit(node.default)
96     
97     def visit_CNameDeclaratorNode(self, node):
98         self.put(node.name)
99     
100     def visit_CSimpleBaseTypeNode(self, node):
101         # See Parsing.p_sign_and_longness
102         if node.is_basic_c_type:
103             self.put(("unsigned ", "", "signed ")[node.signed])
104             if node.longness < 0:
105                 self.put("short " * -node.longness)
106             elif node.longness > 0:
107                 self.put("long " * node.longness)
108             
109         self.put(node.name)
110     
111     def visit_SingleAssignmentNode(self, node):
112         self.startline()
113         self.visit(node.lhs)
114         self.put(u" = ")
115         self.visit(node.rhs)
116         self.endline()
117     
118     def visit_NameNode(self, node):
119         self.put(node.name)
120     
121     def visit_IntNode(self, node):
122         self.put(node.value)
123         
124     def visit_IfStatNode(self, node):
125         # The IfClauseNode is handled directly without a seperate match
126         # for clariy.
127         self.startline(u"if ")
128         self.visit(node.if_clauses[0].condition)
129         self.endline(":")
130         self.indent()
131         self.visit(node.if_clauses[0].body)
132         self.dedent()
133         for clause in node.if_clauses[1:]:
134             self.startline("elif ")
135             self.visit(clause.condition)
136             self.endline(":")
137             self.indent()
138             self.visit(clause.body)
139             self.dedent()
140         if node.else_clause is not None:
141             self.line("else:")
142             self.indent()
143             self.visit(node.else_clause)
144             self.dedent()
145
146     def visit_PassStatNode(self, node):
147         self.startline(u"pass")
148         self.endline()
149     
150     def visit_PrintStatNode(self, node):
151         self.startline(u"print ")
152         self.comma_seperated_list(node.arg_tuple.args)
153         if not node.append_newline:
154             self.put(u",")
155         self.endline()
156
157     def visit_BinopNode(self, node):
158         self.visit(node.operand1)
159         self.put(u" %s " % node.operator)
160         self.visit(node.operand2)
161     
162     def visit_CVarDefNode(self, node):
163         self.startline(u"cdef ")
164         self.visit(node.base_type)
165         self.put(u" ")
166         self.comma_seperated_list(node.declarators, output_rhs=True)
167         self.endline()
168
169     def visit_ForInStatNode(self, node):
170         self.startline(u"for ")
171         self.visit(node.target)
172         self.put(u" in ")
173         self.visit(node.iterator.sequence)
174         self.endline(u":")
175         self.indent()
176         self.visit(node.body)
177         self.dedent()
178         if node.else_clause is not None:
179             self.line(u"else:")
180             self.indent()
181             self.visit(node.else_clause)
182             self.dedent()
183
184     def visit_SequenceNode(self, node):
185         self.comma_seperated_list(node.args) # Might need to discover whether we need () around tuples...hmm...
186     
187     def visit_SimpleCallNode(self, node):
188         self.put(node.function.name + u"(")
189         self.comma_seperated_list(node.args)
190         self.put(")")
191
192     def visit_ExprStatNode(self, node):
193         self.startline()
194         self.visit(node.expr)
195         self.endline()
196     
197     def visit_InPlaceAssignmentNode(self, node):
198         self.startline()
199         self.visit(node.lhs)
200         self.put(" %s= " % node.operator)
201         self.visit(node.rhs)
202         self.endline()
203     
204     
205