icode: add IStaticCall
[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 return "ABORT (\"{texts.join("\", \"")}\")"
258 end
259 end
260
261 redef class ICall
262 redef fun dump_intern(icd)
263 do
264 return "CALL {property.full_name}({icd.register_all(exprs)})"
265 end
266 end
267
268 redef class IStaticCall
269 redef fun dump_intern(icd)
270 do
271 return "STATIC_CALL {property.full_name}({icd.register_all(exprs)})"
272 end
273 end
274
275 redef class IClosCall
276 redef fun dump_intern(icd)
277 do
278 return "CLOS_CALL {icd.closdecl(closure_decl)}({icd.register_all(exprs)})"
279 end
280 end
281
282 redef class IAttrRead
283 redef fun dump_intern(icd)
284 do
285 return "ATTR_READ {property.full_name}({icd.register(expr)})"
286 end
287 end
288
289 redef class IAttrWrite
290 redef fun dump_intern(icd)
291 do
292 return "ATTR_WRITE {property.full_name}({icd.register(expr1)}) := {icd.register(expr2)}"
293 end
294 end
295
296 redef class IAttrIsset
297 redef fun dump_intern(icd)
298 do
299 return "ATTR_ISSET {property.full_name}({icd.register(expr)})"
300 end
301 end
302
303 redef class ITypeCheck
304 redef fun dump_intern(icd)
305 do
306 return "CHECKTYPE {icd.register(expr)} isa {stype}"
307 end
308 end
309
310 redef class INative
311 redef fun dump_intern(icd)
312 do
313 if exprs.is_empty then
314 return "NATIVE \"{code}\""
315 else
316 return "NATIVE \"{code}\"({icd.register_all(exprs)})"
317 end
318 end
319 end
320
321 redef class IMove
322 redef fun dump_intern(icd)
323 do
324 return "{icd.register(expr)}"
325 end
326 end
327
328 redef class IIs
329 redef fun dump_intern(icd)
330 do
331 return "{icd.register(expr1)} is {icd.register(expr2)}"
332 end
333 end
334
335 redef class INot
336 redef fun dump_intern(icd)
337 do
338 return "NOT {icd.register(expr)}"
339 end
340 end
341
342 redef class IOnce
343 redef fun dump(icd)
344 do
345 icd.write "{icd.register(result.as(not null))} := ONCE \{"
346 icd.indent
347 body.dump(icd)
348 icd.unindent
349 icd.write "}"
350 end
351 end
352
353 redef class IHasClos
354 redef fun dump_intern(icd)
355 do
356 return "HASCLOS {icd.closdecl(closure_decl)}"
357 end
358 end