icode: new IEscapeMark class to bind ISeq and IEscape
[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 ArraySet[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 ArraySet[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 special 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 special 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 special 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 special 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 special 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 special 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 special ISeq
180 init do end
181 end
182
183 # A Condidianal if-then-else statement
184 # expr is the condition
185 class IIf
186 special 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 special 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 special 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 special 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 special 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 special 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 special 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 special 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 special 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 special 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 special 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 special 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 C code
326 # Mainly used to implements things that do not have a specific ICode yet
327 # expr are the arguments
328 class INative
329 special ICodeN
330 # The native C code
331 # Special character sequence '@@@' will be substitued in order with the arguments
332 readable var _code: String
333
334 init(c: String, e: nullable Sequence[IRegister])
335 do
336 super(e)
337 _code = c
338 end
339
340 redef readable writable var _is_pure: Bool = false
341 end
342
343 # A register assigment
344 # expr is the assigned value
345 # result is the register assigned
346 class IMove
347 special ICode1
348 init(r: IRegister, e: IRegister)
349 do
350 super(e)
351 _result = r
352 end
353
354 redef fun is_pure do return true
355 end
356
357 # An attribute read access
358 # expr is the reciever
359 class IAttrRead
360 special ICode1
361 # The accessed attribute
362 readable var _property: MMAttribute
363
364 init(p: MMAttribute, r: IRegister)
365 do
366 super(r)
367 _property = p
368 end
369
370 redef fun is_pure do return true
371 end
372
373 # An attribute assignment
374 # expr1 is the receiver, expr2 is the assigned value
375 class IAttrWrite
376 special ICode2
377 # The accessed attribute
378 readable var _property: MMAttribute
379
380 init(p: MMAttribute, r: IRegister, v: IRegister)
381 do
382 super(r, v)
383 _property = p
384 end
385 end
386
387
388 # An attribute is_set check
389 # expr is the reciever
390 class IAttrIsset
391 special ICode1
392 # The accessed attribute
393 readable var _property: MMAttribute
394
395 init(p: MMAttribute, r: IRegister)
396 do
397 super(r)
398 _property = p
399 end
400
401 redef fun is_pure do return true
402 end
403
404 # A type check
405 # expr is the expression checked
406 class ITypeCheck
407 special ICode1
408 # The static type checkes to
409 readable var _stype: MMType
410
411 init(e: IRegister, t: MMType)
412 do
413 super(e)
414 _stype = t
415 end
416
417 redef fun is_pure do return true
418 end
419
420 # The 'is' operator
421 # expr1 and expr2 are both operands
422 class IIs
423 special ICode2
424 init(e1, e2: IRegister)
425 do
426 super
427 end
428
429 redef fun is_pure do return true
430 end
431
432 # The unary 'not' operation
433 # expr is the operand
434 class INot
435 special ICode1
436 init(e: IRegister)
437 do
438 super
439 end
440
441 redef fun is_pure do return true
442 end
443
444 # Evaluate body once them return the same value again and again
445 # if result is not null, then it must also be assigned in the body
446 class IOnce
447 special ICode0
448 readable var _body: ISeq = new ISeq
449 init do end
450 end
451
452 # Is a closure given as a parameter?
453 class IHasClos
454 special ICode0
455 # The called closure
456 readable var _closure_decl: IClosureDecl
457
458 init(c: IClosureDecl)
459 do
460 _closure_decl = c
461 end
462
463 redef fun is_pure do return true
464 end
465
466 #################################################
467
468 redef class MMAttribute
469 # The attached initialisation iroutine if any
470 # To call between the allocate-instance and the initialize-instance
471 fun iroutine: nullable IRoutine is abstract
472 end
473
474 redef class MMMethod
475 # The attached body iroutine if any
476 fun iroutine: nullable IRoutine is abstract
477 end