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