355481602c1ed8573c55d7fa2c9218d9f96120d6
[nit.git] / src / analysis / icode_dump.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2009 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 # Output the intermediate code unded a textual representation
18 package icode_dump
19
20 import icode
21 import allocate_iregister_slots
22
23 redef class IRoutine
24 # Output the intermediate code representation of the iroutine
25 fun dump(icd: ICodeDumper)
26 do
27 if not params.is_empty then
28 var a = new Array[String]
29 for p in params do
30 a.add(icd.register(p))
31 end
32 icd.write "Parameters: {a.join(", ")}"
33 end
34 var r = result
35 if r != null then
36 icd.write "Result: {icd.register(r)}"
37 end
38 var closdecls = closure_decls
39 if closdecls != null then
40 for c in closdecls do
41 c.dump(icd)
42 end
43 end
44 body.dump(icd)
45 end
46 end
47
48 redef class IClosureDecl
49 # Output the intermediate code representation of the iclosuredecl
50 fun dump(icd: ICodeDumper)
51 do
52 icd.write "Closure: {icd.closdecl(self)}"
53 if default != null then
54 icd.indent
55 default.dump(icd)
56 icd.unindent
57 end
58 end
59 end
60
61 class ICodeDumper
62 var _ids: HashMap[Object, String] = new HashMap[Object, String]
63 var _last_value: Int = 0
64
65 # Return the name of e
66 # If e is unknown, a new name is gived
67 fun register(e: IRegister): String
68 do
69 if _ids.has_key(e) then
70 return _ids[e]
71 else
72 var i = e.slot_index
73 if i == null then
74 _last_value += 1
75 var s = "r{_last_value}"
76 _ids[e] = s
77 return s
78 else
79 _last_value += 1
80 var s = "REG{i}(r{_last_value})"
81 _ids[e] = s
82 return s
83 end
84 end
85 end
86
87 # Returns the names of es (separated with comma)
88 fun register_all(es: nullable Collection[IRegister]): String
89 do
90 if es == null then return ""
91 var a = new Array[String]
92 for e in es do
93 a.add(register(e))
94 end
95 return a.join(", ")
96 end
97
98 var _last_clos: Int = 0
99
100 # Return the name of e
101 # If e is unknown, a new name is gived
102 fun closdecl(e: IClosureDecl): String
103 do
104 if _ids.has_key(e) then
105 return _ids[e]
106 else
107 _last_clos += 1
108 var s = "clos{_last_clos}"
109 _ids[e] = s
110 return s
111 end
112 end
113
114 var _last_label: Int = 0
115 # Return the name of e
116 # If e is unknown, a new name is gived
117 fun lab(e: ISeq): String
118 do
119 if _ids.has_key(e) then
120 return _ids[e]
121 else
122 _last_label += 1
123 var s = "[l{_last_label}]"
124 _ids[e] = s
125 return s
126 end
127 end
128
129 var _last_line: Int = 0
130 # Return the line index of e
131 fun line(e: ICode): String
132 do
133 if _ids.has_key(e) then
134 return _ids[e]
135 else
136 _last_line += 1
137 var s = "{_last_line}"
138 _ids[e] = s
139 return s
140 end
141 end
142
143 # Is the label e known? (because we goto to it)
144 fun has_lab(e: ISeq): Bool
145 do
146 return _ids.has_key(e)
147 end
148
149 # Output something
150 fun write(s: String)
151 do
152 for i in [0.._indent_level[ do
153 printn " "
154 end
155 print s
156 end
157
158 var _indent_level: Int = 0
159
160 # Indent the next writes
161 fun indent do _indent_level += 1
162
163 # Outdent the next writes
164 fun unindent do _indent_level -= 1
165 end
166
167 redef class ICode
168 # Output the intermediate code representation
169 fun dump(icd: ICodeDumper)
170 do
171 var result = result
172 var s = ""
173 var l = location
174 if l != null then
175 s = " ... {l}"
176 end
177 if result == null then
178 icd.write "{icd.line(self)}: {dump_intern(icd)}{s}"
179 else
180 icd.write "{icd.line(self)}: {icd.register(result)} := {dump_intern(icd)}{s}"
181 end
182 end
183
184 # Output the intermediate code representation (inner method)
185 fun dump_intern(icd: ICodeDumper): String do return "???"
186 end
187
188 redef class ICodeN
189 redef fun dump(icd: ICodeDumper)
190 do
191 super
192 var closure_defs = closure_defs
193 if closure_defs != null then
194 for clos in closure_defs do
195 if clos == null then
196 icd.write "CLOSURE = NULL"
197 else
198 icd.write "CLOSURE"
199 icd.indent
200 clos.dump(icd)
201 icd.unindent
202 end
203 end
204 end
205 end
206 end
207
208 redef class ISeq
209 redef fun dump(icd)
210 do
211 for ic in icodes do
212 ic.dump(icd)
213 end
214 if icd.has_lab(self) then icd.write("{icd.lab(self)}:")
215 end
216 end
217
218 redef class IIf
219 redef fun dump(icd)
220 do
221 icd.write "IF({icd.register(expr)}) \{"
222 icd.indent
223 then_seq.dump(icd)
224 icd.unindent
225 icd.write "} ELSE \{"
226 icd.indent
227 else_seq.dump(icd)
228 icd.unindent
229 icd.write "}"
230 end
231 end
232
233 redef class ILoop
234 redef fun dump(icd)
235 do
236 icd.write "LOOP \{"
237 icd.indent
238 for ic in icodes do
239 ic.dump(icd)
240 end
241 icd.unindent
242 icd.write "}"
243 if icd.has_lab(self) then icd.write("{icd.lab(self)}:")
244 end
245 end
246
247 redef class IEscape
248 redef fun dump_intern(icd)
249 do
250 return "ESCAPE {icd.lab(seq)}"
251 end
252 end
253
254 redef class IAbort
255 redef fun dump_intern(icd)
256 do
257 var pl = property_location
258 if pl != null then
259 return "ABORT (\"{texts.join("\", \"")}\") in {pl.full_name}"
260 else
261 return "ABORT (\"{texts.join("\", \"")}\")"
262 end
263 end
264 end
265
266 redef class ICall
267 redef fun dump_intern(icd)
268 do
269 return "CALL {property.full_name}({icd.register_all(exprs)})"
270 end
271 end
272
273 redef class IClosCall
274 redef fun dump_intern(icd)
275 do
276 return "CLOS_CALL {icd.closdecl(closure_decl)}({icd.register_all(exprs)})"
277 end
278 end
279
280 redef class IAttrRead
281 redef fun dump_intern(icd)
282 do
283 return "ATTR_READ {property.full_name}({icd.register(expr)})"
284 end
285 end
286
287 redef class IAttrWrite
288 redef fun dump_intern(icd)
289 do
290 return "ATTR_WRITE {property.full_name}({icd.register(expr1)}) := {icd.register(expr2)}"
291 end
292 end
293
294 redef class IAttrIsset
295 redef fun dump_intern(icd)
296 do
297 return "ATTR_ISSET {property.full_name}({icd.register(expr)})"
298 end
299 end
300
301 redef class ITypeCheck
302 redef fun dump_intern(icd)
303 do
304 return "CHECKTYPE {icd.register(expr)} isa {stype}"
305 end
306 end
307
308 redef class INative
309 redef fun dump_intern(icd)
310 do
311 if exprs.is_empty then
312 return "NATIVE \"{code}\""
313 else
314 return "NATIVE \"{code}\"({icd.register_all(exprs)})"
315 end
316 end
317 end
318
319 redef class IMove
320 redef fun dump_intern(icd)
321 do
322 return "{icd.register(expr)}"
323 end
324 end
325
326 redef class IIs
327 redef fun dump_intern(icd)
328 do
329 return "{icd.register(expr1)} is {icd.register(expr2)}"
330 end
331 end
332
333 redef class INot
334 redef fun dump_intern(icd)
335 do
336 return "NOT {icd.register(expr)}"
337 end
338 end
339
340 redef class IOnce
341 redef fun dump(icd)
342 do
343 icd.write "{icd.register(result.as(not null))} := ONCE \{"
344 icd.indent
345 body.dump(icd)
346 icd.unindent
347 icd.write "}"
348 end
349 end
350
351 redef class IHasClos
352 redef fun dump_intern(icd)
353 do
354 return "HASCLOS {icd.closdecl(closure_decl)}"
355 end
356 end