astprinter: update code
[nit.git] / src / astprinter.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # print AST in an human form
18 module astprinter
19
20 import semantize
21 intrude import parser
22 private import literal
23
24 private class ASTPrinterVisitor
25 super Visitor
26 redef fun visit(node)
27 do
28 node.accept_printer(self)
29 end
30
31 var out = new List[String]
32 var indent_level = 0
33
34 var has_eol = true
35
36 fun eol
37 do
38 if has_eol then return
39 out.add("\n")
40 for x in [0..indent_level[ do out.add("\t")
41 has_eol = true
42 end
43
44 var last_current: nullable ANode = null
45
46 fun write(s: String)
47 do
48 if last_current != current_node then
49 last_current = current_node
50 var l = current_node._location
51 if l != null then
52 eol
53 out.add(s)
54 out.add("\t# {l.colored_line("0;32").split_with('\n').first}")
55 has_eol = false
56 eol
57 return
58 end
59 end
60 out.add(s)
61 has_eol = false
62 end
63
64 fun indent do indent_level += 1
65 fun unindent do indent_level -= 1
66 end
67
68 redef class ANode
69 # print the tree (using the semantic information) on screen
70 # This method is used to debug AST transformations
71 fun print_tree
72 do
73 var v = new ASTPrinterVisitor
74 v.enter_visit(self)
75 v.eol
76 for s in v.out do
77 printn s
78 end
79 end
80
81 private fun accept_printer(v: ASTPrinterVisitor)
82 do
83 v.eol
84 v.write("({inspect}")
85 v.indent
86 visit_all(v)
87 v.write(")")
88 v.unindent
89 end
90 end
91
92 redef class ABlockExpr
93 redef fun accept_printer(v)
94 do
95 for x in n_expr do
96 v.enter_visit(x)
97 v.eol
98 end
99 end
100 end
101
102 redef class AIntExpr
103 redef fun accept_printer(v)
104 do
105 v.write(value.to_s)
106 end
107 end
108
109 redef class ANewExpr
110 redef fun accept_printer(v)
111 do
112 v.write("new {mtype.as(not null)}.{callsite.mproperty}")
113 if not n_args.n_exprs.is_empty then
114 v.write("(")
115 v.indent
116 var is_first = true
117 for a in n_args.n_exprs do
118 if is_first then is_first = false else v.write(",")
119 v.enter_visit(a)
120 end
121 v.unindent
122 v.write(")")
123 end
124 end
125 end
126
127 redef class ASendExpr
128 redef fun accept_printer(v)
129 do
130 v.enter_visit(n_expr)
131 v.write(".{callsite.mproperty.name}")
132 if not raw_arguments.is_empty then
133 v.write("(")
134 v.indent
135 var is_first = true
136 for a in raw_arguments do
137 if is_first then is_first = false else v.write(",")
138 v.enter_visit(a)
139 end
140 v.unindent
141 v.write(")")
142 end
143 end
144 end
145
146 redef class AVarExpr
147 redef fun accept_printer(v)
148 do
149 var name = variable.name
150 if name == "" then name = "t{variable.object_id}"
151 v.write(name)
152 end
153 end
154
155 redef class AVarAssignExpr
156 redef fun accept_printer(v)
157 do
158 var name = variable.name
159 if name == "" then name = "t{variable.object_id}"
160 v.write("{name} = ")
161 v.indent
162 v.enter_visit(n_value)
163 v.unindent
164 end
165 end