metamodel: rename 'universal' to 'enum'
[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 super(e)
336 _method = m
337 end
338
339 redef readable writable var _is_pure: Bool = false
340 end
341
342 # A literal Int value
343 class IIntValue
344 super ICode0
345 # The value
346 readable var _value: String
347
348 init(v: String) do _value = v
349
350 redef fun is_pure do return true
351 end
352
353 # A literal Bool value
354 class IBoolValue
355 super ICode0
356 # The value
357 readable var _value: Bool
358
359 init(v: Bool) do _value = v
360
361 redef fun is_pure do return true
362 end
363
364 # A literal NativeString value
365 class IStringValue
366 super ICode0
367 # The value
368 readable var _value: String
369
370 init(v: String) do _value = v
371
372 redef fun is_pure do return true
373 end
374
375 # A literal Float value
376 class IFloatValue
377 super ICode0
378 # The value
379 readable var _value: String
380
381 init(v: String) do _value = v
382
383 redef fun is_pure do return true
384 end
385
386 # A literal Char value
387 class ICharValue
388 super ICode0
389 # The value
390 readable var _value: String
391
392 init(v: String) do _value = v
393
394 redef fun is_pure do return true
395 end
396
397 # A register assigment
398 # expr is the assigned value
399 # result is the register assigned
400 class IMove
401 super ICode1
402 init(r: IRegister, e: IRegister)
403 do
404 super(e)
405 _result = r
406 end
407
408 redef fun is_pure do return true
409 end
410
411 # An attribute read access
412 # expr is the reciever
413 class IAttrRead
414 super ICode1
415 # The accessed attribute
416 readable var _property: MMAttribute
417
418 init(p: MMAttribute, r: IRegister)
419 do
420 super(r)
421 _property = p
422 end
423
424 redef fun is_pure do return true
425 end
426
427 # An attribute assignment
428 # expr1 is the receiver, expr2 is the assigned value
429 class IAttrWrite
430 super ICode2
431 # The accessed attribute
432 readable var _property: MMAttribute
433
434 init(p: MMAttribute, r: IRegister, v: IRegister)
435 do
436 super(r, v)
437 _property = p
438 end
439 end
440
441
442 # An attribute is_set check
443 # expr is the reciever
444 class IAttrIsset
445 super ICode1
446 # The accessed attribute
447 readable var _property: MMAttribute
448
449 init(p: MMAttribute, r: IRegister)
450 do
451 super(r)
452 _property = p
453 end
454
455 redef fun is_pure do return true
456 end
457
458 # A type check
459 # expr is the expression checked
460 class ITypeCheck
461 super ICode1
462 # The static type checkes to
463 readable var _stype: MMType
464
465 init(e: IRegister, t: MMType)
466 do
467 super(e)
468 _stype = t
469 end
470
471 redef fun is_pure do return true
472 end
473
474 # The 'is' operator
475 # expr1 and expr2 are both operands
476 class IIs
477 super ICode2
478 init(e1, e2: IRegister)
479 do
480 super
481 end
482
483 redef fun is_pure do return true
484 end
485
486 # The unary 'not' operation
487 # expr is the operand
488 class INot
489 super ICode1
490 init(e: IRegister)
491 do
492 super
493 end
494
495 redef fun is_pure do return true
496 end
497
498 # Evaluate body once them return the same value again and again
499 # if result is not null, then it must also be assigned in the body
500 class IOnce
501 super ICode0
502 readable var _body: ISeq = new ISeq
503 init do end
504 end
505
506 # Is a closure given as a parameter?
507 class IHasClos
508 super ICode0
509 # The called closure
510 readable var _closure_decl: IClosureDecl
511
512 init(c: IClosureDecl)
513 do
514 _closure_decl = c
515 end
516
517 redef fun is_pure do return true
518 end
519
520 #################################################
521
522 redef class MMAttribute
523 # The attached initialisation iroutine if any
524 # To call between the allocate-instance and the initialize-instance
525 fun iroutine: nullable IRoutine is abstract
526 end
527
528 redef class MMMethod
529 # The attached body iroutine if any
530 fun iroutine: nullable IRoutine is abstract
531 end