new modules astbuilder, astvalidation, astprinter, and transform
[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 typing
21 import phase
22 intrude import parser
23 import literal
24
25 private class ASTPrinterVisitor
26 super Visitor
27 redef fun visit(node)
28 do
29 node.accept_printer(self)
30 end
31
32 var out = new List[String]
33 var indent_level = 0
34
35 var has_eol = true
36
37 fun eol
38 do
39 if has_eol then return
40 out.add("\n")
41 for x in [0..indent_level[ do out.add("\t")
42 has_eol = true
43 end
44
45 var last_current: nullable ANode
46
47 fun write(s: String)
48 do
49 if last_current != current_node then
50 last_current = current_node
51 var l = current_node._location
52 if l != null then
53 eol
54 out.add(s)
55 out.add("\t# {l.colored_line("0;32").split_with('\n').first}")
56 has_eol = false
57 eol
58 return
59 end
60 end
61 out.add(s)
62 has_eol = false
63 end
64
65 fun indent do indent_level += 1
66 fun unindent do indent_level -= 1
67 end
68
69 redef class ANode
70 # print the tree (using the semantic information) on screen
71 # This method is used to debug AST transformations
72 fun print_tree
73 do
74 var v = new ASTPrinterVisitor
75 v.enter_visit(self)
76 v.eol
77 for s in v.out do
78 printn s
79 end
80 end
81
82 private fun accept_printer(v: ASTPrinterVisitor)
83 do
84 v.eol
85 v.write("({inspect}")
86 v.indent
87 visit_all(v)
88 v.write(")")
89 v.unindent
90 end
91 end
92
93 redef class ABlockExpr
94 redef fun accept_printer(v)
95 do
96 for x in n_expr do
97 v.enter_visit(x)
98 v.eol
99 end
100 end
101 end
102
103 redef class AIntExpr
104 redef fun accept_printer(v)
105 do
106 v.write(value.to_s)
107 end
108 end
109
110 redef class ANewExpr
111 redef fun accept_printer(v)
112 do
113 v.write("new {mtype.as(not null)}.{mproperty.as(not null)}")
114 if not n_args.n_exprs.is_empty then
115 v.write("(")
116 v.indent
117 var is_first = true
118 for a in n_args.n_exprs do
119 if is_first then is_first = false else v.write(",")
120 v.enter_visit(a)
121 end
122 v.unindent
123 v.write(")")
124 end
125 end
126 end
127
128 redef class ASendExpr
129 redef fun accept_printer(v)
130 do
131 v.enter_visit(n_expr)
132 v.write(".{mproperty.name}")
133 if not raw_arguments.is_empty then
134 v.write("(")
135 v.indent
136 var is_first = true
137 for a in raw_arguments.as(not null) do
138 if is_first then is_first = false else v.write(",")
139 v.enter_visit(a)
140 end
141 v.unindent
142 v.write(")")
143 end
144 end
145 end
146
147 redef class AVarExpr
148 redef fun accept_printer(v)
149 do
150 var name = variable.name
151 if name == "" then name = "t{variable.object_id}"
152 v.write(name)
153 end
154 end
155
156 redef class AVarAssignExpr
157 redef fun accept_printer(v)
158 do
159 var name = variable.name
160 if name == "" then name = "t{variable.object_id}"
161 v.write("{name} = ")
162 v.indent
163 v.enter_visit(n_value)
164 v.unindent
165 end
166 end