Merge branch 'fix-vt' into wip
[nit.git] / src / icode / icode_base.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 # Base classes for Nit intermediate code representation
18 package icode_base
19
20 import metamodel
21 import mmloader
22
23 ## UTILITY CLASSES ##
24
25 # Register store local variable and intermediate results
26 class IRegister
27 # The static type
28 readable var _stype: MMType
29 init(s: MMType)
30 do
31 _stype = s
32 end
33 end
34
35 # A mark used to associate IEscapes to ISeqs
36 class IEscapeMark
37 end
38
39 # A Closure declaration
40 class IClosureDecl
41 # The associated closure definition
42 readable var _closure: MMClosure
43
44 # The default implementation
45 readable writable var _default: nullable IRoutine
46
47 init(c: MMClosure) do _closure = c
48 end
49
50 # A routine is a sequence of icodes with entry iregisters (params) and an exit iregister (result)
51 class IRoutine
52 # The parameters of the routine
53 readable var _params: Sequence[IRegister]
54
55 # The closure declared
56 readable writable var _closure_decls: nullable Sequence[IClosureDecl] = null
57
58 # The local variables (excluding params and result)
59 readable var _registers: Set[IRegister] = new HashSet[IRegister]
60
61 # The result of the routine
62 readable var _result: nullable IRegister
63
64 # The local escapes marks of the routine
65 readable var _escape_marks: Set[IEscapeMark] = new HashSet[IEscapeMark]
66
67 # The sequence of icode
68 readable var _body: ISeq = new ISeq
69
70 # The location of the iroutine (if any)
71 readable writable var _location: nullable Location = null
72
73 init(p: Sequence[IRegister], r: nullable IRegister)
74 do
75 _params = p.to_a
76 _result = r
77 end
78 end
79
80 # A closure definition in a iroutine body
81 class IClosureDef
82 super IRoutine
83 init(p: Array[IRegister], r: nullable IRegister)
84 do
85 super(p, r)
86 end
87 end
88
89 ## INTERMEDIATE CODE ##
90
91 # The root of the intermediate code representation
92 abstract class ICode
93 # The number of registers used by the icode
94 fun arity: Int is abstract
95
96 # The result of the icode (if any)
97 readable writable var _result: nullable IRegister = null
98
99 # The location of the icode (if any)
100 readable writable var _location: nullable Location = null
101
102 # Is the icode side effect free?
103 fun is_pure: Bool do return false
104 end
105
106 # An icode that uses no registers (no args)
107 abstract class ICode0
108 super ICode
109 redef fun arity do return 0
110 end
111
112 # An icode that uses a single register (1 arg)
113 abstract class ICode1
114 super ICode
115 redef fun arity do return 1
116
117 # The single argument
118 readable var _expr: IRegister
119
120 init(e: IRegister) do _expr = e
121 end
122
123 # An icode that uses two single registers (2 args)
124 abstract class ICode2
125 super ICode
126 redef fun arity do return 2
127
128 # The first argument
129 readable var _expr1: IRegister
130
131 # The second argument
132 readable var _expr2: IRegister
133
134 init(e1, e2: IRegister)
135 do
136 _expr1 = e1
137 _expr2 = e2
138 end
139 end
140
141 # An icode that uses a variable number of registers (n args) and a variable number of closure definitions
142 abstract class ICodeN
143 super ICode
144 redef fun arity do return _exprs.length
145
146 # All arguments
147 readable var _exprs: Sequence[IRegister]
148
149 # All closure definition
150 readable writable var _closure_defs: nullable Sequence[nullable IClosureDef]
151
152 init(e: nullable Sequence[IRegister])
153 do
154 if e == null then
155 _exprs = new Array[IRegister]
156 else
157 _exprs = e
158 end
159 end
160 end
161
162 #################################################
163
164 # A linear sequence of ICode
165 class ISeq
166 super ICode0
167 # The sequence of icode
168 readable var _icodes: List[ICode] = new List[ICode]
169
170 # The associated iescape_mark (if any)
171 readable writable var _iescape_mark: nullable IEscapeMark
172
173 init do end
174 end
175
176 # An infinite loop of ICode
177 # Use IEscape to exit
178 class ILoop
179 super ISeq
180 init do end
181 end
182
183 # A Condidianal if-then-else statement
184 # expr is the condition
185 class IIf
186 super ICode1
187 # The 'then' sequence of icode
188 readable var _then_seq: ISeq = new ISeq
189 # The 'else' sequence of icode
190 readable var _else_seq: ISeq = new ISeq
191 init(e: IRegister) do super
192 end
193
194 # Escape to to end of a parent sequence
195 class IEscape
196 super ICode0
197 # The seqeuence to escape
198 # The control flow continues at the next icode after the associated sequence
199 readable var _iescape_mark: IEscapeMark
200 init(mark: IEscapeMark) do _iescape_mark = mark
201 end
202
203 # An abort statement
204 class IAbort
205 super ICode0
206 # The reason the abort occured
207 # tests.first is the format
208 readable var _texts: Array[String]
209 # The module that has the abort
210 readable var _module_location: MMModule
211 init(t: Array[String], ml: MMModule)
212 do
213 _texts = t
214 _module_location = ml
215 end
216 end
217
218 #################################################
219
220 # The root of all method invocations
221 abstract class IAbsCall
222 super ICodeN
223 # The called method
224 readable var _property: MMMethod
225
226 init(p: MMMethod, e: Sequence[IRegister])
227 do
228 super(e)
229 _property = p
230 end
231 end
232
233 # A simple procedure or function call
234 # exprs.first is the reciever, other are arguments
235 class ICall
236 super IAbsCall
237 init(p, e) do super
238 end
239
240 # A super method call
241 # exprs.first is the reciever, other are arguments
242 class ISuper
243 super IAbsCall
244 init(p, e) do super
245 end
246
247 # An instantiation
248 # no reciever, all exprs are arguments
249 # Will call in order:
250 # - IAllocateInstance
251 # - IInitAttributes
252 # - IStaticCall -> target Initializer
253 # - ICheckInstance
254 class INew
255 super IAbsCall
256 # The type to instantiate
257 readable var _stype: MMType
258 init(t: MMType, p: MMMethod, a: Sequence[IRegister])
259 do
260 super(p, a)
261 _stype = t
262 end
263 end
264
265 # An allocation of a new object
266 # No receivers, returns a new object of type 't'
267 # Will allocate memory and ensure dynamic type and object identity
268 class IAllocateInstance
269 super ICode0
270 # The type to allocate
271 readable var _stype: MMType
272 init(t: MMType)
273 do
274 _stype = t
275 end
276 end
277
278 # A static call to a specific method
279 class IStaticCall
280 super IAbsCall
281 init(p: MMMethod, a: Sequence[IRegister]) do super
282 end
283
284 # A validation of a newly constructed instance
285 class ICheckInstance
286 super ICode1
287 # The type to allocate
288 readable var _stype: MMType
289 init(t: MMType, e: IRegister)
290 do
291 super(e)
292 _stype = t
293 end
294 end
295
296 # Initialisation of default attributes of a new instance
297 class IInitAttributes
298 super ICode1
299 # The type to initialize
300 readable var _stype: MMType
301 init(t: MMType, e: IRegister)
302 do
303 super(e)
304 _stype = t
305 end
306 end
307
308 # A closure call
309 # exprs are the arguments
310 class IClosCall
311 super ICodeN
312 # The called closure
313 readable var _closure_decl: IClosureDecl
314
315 # The !break sequence (if any)
316 readable writable var _break_seq: nullable ISeq = null
317
318 init(c: IClosureDecl, e: Sequence[IRegister])
319 do
320 super(e)
321 _closure_decl = c
322 end
323 end
324
325 # A native inlined call
326 # Native are associated to local properties to distinguish them
327 # expr are the arguments
328 class INative
329 super ICodeN
330 # The associated local property
331 readable var _method: MMMethod
332
333 init(m: MMMethod, e: nullable Sequence[IRegister])
334 do
335 # Checks that arguments contains at least one IRegister element
336 assert e.length == m.signature.arity + 1
337
338 super(e)
339 _method = m
340 end
341
342 redef readable writable var _is_pure: Bool = false
343 end
344
345 # A literal Int value
346 class IIntValue
347 super ICode0
348 # The value
349 readable var _value: String
350
351 init(v: String) do _value = v
352
353 redef fun is_pure do return true
354 end
355
356 # A literal Bool value
357 class IBoolValue
358 super ICode0
359 # The value
360 readable var _value: Bool
361
362 init(v: Bool) do _value = v
363
364 redef fun is_pure do return true
365 end
366
367 # A literal NativeString value
368 class IStringValue
369 super ICode0
370 # The value
371 readable var _value: String
372
373 init(v: String) do _value = v
374
375 redef fun is_pure do return true
376 end
377
378 # A literal Float value
379 class IFloatValue
380 super ICode0
381 # The value
382 readable var _value: String
383
384 init(v: String) do _value = v
385
386 redef fun is_pure do return true
387 end
388
389 # A literal Char value
390 class ICharValue
391 super ICode0
392 # The value
393 readable var _value: String
394
395 init(v: String) do _value = v
396
397 redef fun is_pure do return true
398 end
399
400 # A register assigment
401 # expr is the assigned value
402 # result is the register assigned
403 class IMove
404 super ICode1
405 init(r: IRegister, e: IRegister)
406 do
407 super(e)
408 _result = r
409 end
410
411 redef fun is_pure do return true
412 end
413
414 # An attribute read access
415 # expr is the reciever
416 class IAttrRead
417 super ICode1
418 # The accessed attribute
419 readable var _property: MMAttribute
420
421 init(p: MMAttribute, r: IRegister)
422 do
423 super(r)
424 _property = p
425 end
426
427 redef fun is_pure do return true
428 end
429
430 # An attribute assignment
431 # expr1 is the receiver, expr2 is the assigned value
432 class IAttrWrite
433 super ICode2
434 # The accessed attribute
435 readable var _property: MMAttribute
436
437 init(p: MMAttribute, r: IRegister, v: IRegister)
438 do
439 super(r, v)
440 _property = p
441 end
442 end
443
444
445 # An attribute is_set check
446 # expr is the reciever
447 class IAttrIsset
448 super ICode1
449 # The accessed attribute
450 readable var _property: MMAttribute
451
452 init(p: MMAttribute, r: IRegister)
453 do
454 super(r)
455 _property = p
456 end
457
458 redef fun is_pure do return true
459 end
460
461 # A type check
462 # expr1 is the type reciever (self)
463 # expr2 is the expression checked
464 class ITypeCheck
465 super ICode2
466 # The static type checkes to
467 readable var _stype: MMType
468
469 init(e1, e2: IRegister, t: MMType)
470 do
471 super(e1, e2)
472 _stype = t
473 end
474
475 redef fun is_pure do return true
476 end
477
478 # The 'is' operator
479 # expr1 and expr2 are both operands
480 class IIs
481 super ICode2
482 init(e1, e2: IRegister)
483 do
484 super
485 end
486
487 redef fun is_pure do return true
488 end
489
490 # The unary 'not' operation
491 # expr is the operand
492 class INot
493 super ICode1
494 init(e: IRegister)
495 do
496 super
497 end
498
499 redef fun is_pure do return true
500 end
501
502 # Evaluate body once them return the same value again and again
503 # if result is not null, then it must also be assigned in the body
504 class IOnce
505 super ICode0
506 readable var _body: ISeq = new ISeq
507 init do end
508 end
509
510 # Is a closure given as a parameter?
511 class IHasClos
512 super ICode0
513 # The called closure
514 readable var _closure_decl: IClosureDecl
515
516 init(c: IClosureDecl)
517 do
518 _closure_decl = c
519 end
520
521 redef fun is_pure do return true
522 end
523
524 #################################################
525
526 redef class MMAttribute
527 # The attached initialisation iroutine if any
528 # To call between the allocate-instance and the initialize-instance
529 fun iroutine: nullable IRoutine is abstract
530 end
531
532 redef class MMMethod
533 # The attached body iroutine if any
534 fun iroutine: nullable IRoutine is abstract
535 end