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