lib: rename IndexedCollection to Sequence
[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 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: Sequence[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
92 # Is the icode side effect free?
93 fun is_pure: Bool do return false
94 end
95
96 # An icode that uses no registers (no args)
97 abstract class ICode0
98 special ICode
99 redef fun arity do return 0
100 end
101
102 # An icode that uses a single register (1 arg)
103 abstract class ICode1
104 special ICode
105 redef fun arity do return 1
106
107 # The single argument
108 readable var _expr: IRegister
109
110 init(e: IRegister) do _expr = e
111 end
112
113 # An icode that uses two single registers (2 args)
114 abstract class ICode2
115 special ICode
116 redef fun arity do return 2
117
118 # The first argument
119 readable var _expr1: IRegister
120
121 # The second argument
122 readable var _expr2: IRegister
123
124 init(e1, e2: IRegister)
125 do
126 _expr1 = e1
127 _expr2 = e2
128 end
129 end
130
131 # An icode that uses a variable number of registers (n args) and a variable number of closure definitions
132 abstract class ICodeN
133 special ICode
134 redef fun arity do return _exprs.length
135
136 # All arguments
137 readable var _exprs: Sequence[IRegister]
138
139 # All closure definition
140 readable writable var _closure_defs: nullable Sequence[nullable IClosureDef]
141
142 init(e: nullable Sequence[IRegister])
143 do
144 if e == null then
145 _exprs = new Array[IRegister]
146 else
147 _exprs = e
148 end
149 end
150 end
151
152 #################################################
153
154 # A linear sequence of ICode
155 class ISeq
156 special ICode0
157 # The sequence of icode
158 readable var _icodes: List[ICode] = new List[ICode]
159 init do end
160 end
161
162 # An infinite loop of ICode
163 # Use IEscape to exit
164 class ILoop
165 special ISeq
166 init do end
167 end
168
169 # A Condidianal if-then-else statement
170 # expr is the condition
171 class IIf
172 special ICode1
173 # The 'then' sequence of icode
174 readable var _then_seq: ISeq = new ISeq
175 # The 'else' sequence of icode
176 readable var _else_seq: ISeq = new ISeq
177 init(e: IRegister) do super
178 end
179
180 # Escape to to end of a parent sequence
181 class IEscape
182 special ICode0
183 # The seqeuence to escape
184 # The control flow continues at the next icode after the sequence
185 readable var _seq: ISeq
186 init(seq: ISeq) do _seq = seq
187 end
188
189 # An abort statement
190 class IAbort
191 special ICode0
192 # The reason the abort occured
193 # tests.first is the format
194 readable var _texts: Array[String]
195 # The local property that has the abort (if any)
196 readable var _property_location: nullable MMLocalProperty
197 # The module that has the abort
198 readable var _module_location: MMModule
199 init(t: Array[String], pl: nullable MMLocalProperty, ml: MMModule)
200 do
201 _texts = t
202 _property_location = pl
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