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