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