3dd1184f68da188655104e6b293f3e991d878775
[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 class INew
239 special IAbsCall
240 # The type to instantiate
241 readable var _stype: MMType
242 init(t: MMType, p: MMMethod, a: Sequence[IRegister])
243 do
244 super(p, a)
245 _stype = t
246 end
247 end
248
249 # A static call to a specific method
250 class IStaticCall
251 special IAbsCall
252 init(p: MMMethod, a: Sequence[IRegister]) do super
253 end
254
255 # A closure call
256 # exprs are the arguments
257 class IClosCall
258 special ICodeN
259 # The called closure
260 readable var _closure_decl: IClosureDecl
261
262 # The !break sequence (if any)
263 readable writable var _break_seq: nullable ISeq = null
264
265 init(c: IClosureDecl, e: Sequence[IRegister])
266 do
267 super(e)
268 _closure_decl = c
269 end
270 end
271
272 # A native C code
273 # Mainly used to implements things that do not have a specific ICode yet
274 # expr are the arguments
275 class INative
276 special ICodeN
277 # The native C code
278 # Special character sequence '@@@' will be substitued in order with the arguments
279 readable var _code: String
280
281 init(c: String, e: nullable Sequence[IRegister])
282 do
283 super(e)
284 _code = c
285 end
286
287 redef readable writable var _is_pure: Bool = false
288 end
289
290 # A register assigment
291 # expr is the assigned value
292 # result is the register assigned
293 class IMove
294 special ICode1
295 init(r: IRegister, e: IRegister)
296 do
297 super(e)
298 _result = r
299 end
300
301 redef fun is_pure do return true
302 end
303
304 # An attribute read access
305 # expr is the reciever
306 class IAttrRead
307 special ICode1
308 # The accessed attribute
309 readable var _property: MMAttribute
310
311 init(p: MMAttribute, r: IRegister)
312 do
313 super(r)
314 _property = p
315 end
316
317 redef fun is_pure do return true
318 end
319
320 # An attribute assignment
321 # expr1 is the receiver, expr2 is the assigned value
322 class IAttrWrite
323 special ICode2
324 # The accessed attribute
325 readable var _property: MMAttribute
326
327 init(p: MMAttribute, r: IRegister, v: IRegister)
328 do
329 super(r, v)
330 _property = p
331 end
332 end
333
334
335 # An attribute is_set check
336 # expr is the reciever
337 class IAttrIsset
338 special ICode1
339 # The accessed attribute
340 readable var _property: MMAttribute
341
342 init(p: MMAttribute, r: IRegister)
343 do
344 super(r)
345 _property = p
346 end
347
348 redef fun is_pure do return true
349 end
350
351 # A type check
352 # expr is the expression checked
353 class ITypeCheck
354 special ICode1
355 # The static type checkes to
356 readable var _stype: MMType
357
358 init(e: IRegister, t: MMType)
359 do
360 super(e)
361 _stype = t
362 end
363
364 redef fun is_pure do return true
365 end
366
367 # The 'is' operator
368 # expr1 and expr2 are both operands
369 class IIs
370 special ICode2
371 init(e1, e2: IRegister)
372 do
373 super
374 end
375
376 redef fun is_pure do return true
377 end
378
379 # The unary 'not' operation
380 # expr is the operand
381 class INot
382 special ICode1
383 init(e: IRegister)
384 do
385 super
386 end
387
388 redef fun is_pure do return true
389 end
390
391 # Evaluate body once them return the same value again and again
392 # if result is not null, then it must also be assigned in the body
393 class IOnce
394 special ICode0
395 readable var _body: ISeq = new ISeq
396 init do end
397 end
398
399 # Is a closure given as a parameter?
400 class IHasClos
401 special ICode0
402 # The called closure
403 readable var _closure_decl: IClosureDecl
404
405 init(c: IClosureDecl)
406 do
407 _closure_decl = c
408 end
409
410 redef fun is_pure do return true
411 end
412
413 #################################################
414
415 redef class MMAttribute
416 # The attached initialisation iroutine if any
417 # To call between the allocate-instance and the initialize-instance
418 fun iroutine: nullable IRoutine is abstract
419 end
420
421 redef class MMMethod
422 # The attached body iroutine if any
423 fun iroutine: nullable IRoutine is abstract
424 end