metamodel: rename 'universal' to 'enum'
[nit.git] / src / metamodel / static_type.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2006-2008 Floréal Morandat <morandat@lirmm.fr>
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17
18 # Static types and property signatures
19 package static_type
20
21 intrude import abstractmetamodel
22
23 redef class MMLocalClass
24 # Cached result of get_type
25 var _base_type_cache: nullable MMType
26
27 # Return the type of self for this class
28 fun get_type: MMType
29 do
30 if _base_type_cache == null then _base_type_cache = new MMTypeSimpleClass(self)
31 return _base_type_cache.as(not null)
32 end
33
34 # Register a new ancestor
35 protected fun add_ancestor(a: MMAncestor)
36 do
37 assert not _ancestors.has_key(a.local_class)
38 assert a.local_class != self
39 _ancestors[a.local_class] = a
40 end
41
42 # Array of ancestor that associate each superclass with the corresponding ancestor
43 readable var _ancestors: nullable Map[MMLocalClass, MMAncestor]
44
45 # The ancestor type for a given superclass
46 fun ancestor(c: MMLocalClass): MMType
47 do
48 return _ancestors[c].stype
49 end
50 end
51
52 redef class MMLocalProperty
53 # The signature of the property (where it is declared)
54 readable writable var _signature: nullable MMSignature
55
56 var _signatures_cache: HashMap[MMType, MMSignature] = new HashMap[MMType, MMSignature]
57
58 # Return the adapted signature of self for a receiver of type t
59 fun signature_for(t: MMType): MMSignature do
60 if t == local_class.get_type then return signature.as(not null)
61
62 if _signatures_cache.has_key(t) then return _signatures_cache[t]
63
64 var res = signature.adaptation_to(t)
65 _signatures_cache[t] = res
66 return res
67 end
68 end
69
70 # Signature for local properties
71 class MMSignature
72 # The type of the reveiver
73 readable var _recv: MMType
74
75 # The parameter types
76 var _params: Array[MMType]
77
78 # The return type
79 readable var _return_type: nullable MMType
80
81 # The closure parameters
82 readable var _closures: Array[MMClosure] = new Array[MMClosure]
83
84 # Return the closure named 'name'. Null if no such a closure exists.
85 fun closure_named(name: Symbol): nullable MMClosure
86 do
87 for c in _closures do
88 if c.name == name then return c
89 end
90 return null
91 end
92
93 # Number of parameters
94 fun arity: Int
95 do
96 return _params.length
97 end
98
99 # Is self a valid subtype of an other signature
100 fun <(s: MMSignature): Bool
101 do
102 if self == s then
103 return true
104 end
105 assert _recv.mmmodule == s.recv.mmmodule
106 var rt = _return_type
107 var srt = s.return_type
108 if arity != s.arity or (rt == null) != (srt == null) then return false
109 if rt != null and not rt < srt.as(not null) then
110 return false
111 end
112
113 for i in [0..arity[ do
114 if not s[i] < self[i] then
115 return false
116 end
117 end
118
119 if closures.length != s.closures.length then return false
120 for i in [0..closures.length[ do
121 if not s.closures[i] < closures[i] then return false
122 end
123 return true
124 end
125
126 # The type of the i-th parameter
127 fun [](i: Int): MMType
128 do
129 assert _params.length > i
130 return _params[i]
131 end
132
133 redef fun to_s
134 do
135 var s = new Buffer
136 if _params.length > 0 then
137 var tmp: String
138 var a = new Array[String].with_capacity(_params.length)
139 for i in [0.._params.length[ do
140 #var pn = _params_name[i]
141 var p = _params[i]
142 #a.add("{pn}: {p}")
143 a.add(p.to_s)
144 end
145 s.append("({a.join(",")})")
146 end
147 var rt = _return_type
148 if rt != null then s.append(": {rt}")
149 return s.to_s
150 end
151
152 # Adapt the signature to a different receiver
153 fun adaptation_to(r: MMType): MMSignature
154 do
155 if _recv == r then
156 return self
157 end
158 var mod = r.mmmodule
159 var p = new Array[MMType]
160 for i in _params do
161 p.add(i.for_module(mod).adapt_to(r))
162 end
163 var rv = _return_type
164 if rv != null then
165 rv = rv.for_module(mod).adapt_to(r)
166 end
167 var res = new MMSignature(p,rv,r)
168 for clos in _closures do
169 res.closures.add(clos.adaptation_to(r))
170 end
171 return res
172 end
173
174 var _not_for_self_cache: nullable MMSignature = null
175
176 # Return a type approximation if the reveiver is not self
177 # Useful for virtual types
178 fun not_for_self: MMSignature
179 do
180 if _not_for_self_cache != null then return _not_for_self_cache.as(not null)
181
182 var need_for_self = false
183 var p = new Array[MMType]
184 for i in _params do
185 var i2 = i.not_for_self
186 if i != i2 then need_for_self = true
187 p.add(i2)
188 end
189
190 var rv = _return_type
191 if rv != null then
192 rv = rv.not_for_self
193 if rv != _return_type then need_for_self = true
194 end
195
196 var clos = new Array[MMClosure]
197 for c in _closures do
198 var c2 = c.not_for_self
199 if c2 != c then need_for_self = true
200 clos.add(c2)
201 end
202
203 var res: MMSignature
204 if need_for_self then
205 res = new MMSignature(p, rv, _recv)
206 res.closures.add_all(clos)
207 else
208 res = self
209 end
210
211 _not_for_self_cache = res
212 return res
213 end
214
215 init(params: Array[MMType], return_type: nullable MMType, r: MMType)
216 do
217 _params = params
218 _return_type = return_type
219 _recv = r
220 end
221 end
222
223 # A closure in a signature
224 class MMClosure
225 # The name of the closure (without the !)
226 readable var _name: Symbol
227
228 # The signature of the closure
229 readable var _signature: MMSignature
230
231 # Is the closure a brek one
232 # aka is defined with the break keyword thus does not return
233 readable var _is_break: Bool
234
235 # Is the closure optional?
236 # ie is there a default definition
237 readable var _is_optional: Bool
238
239 # Adapt the signature to a different receiver
240 fun adaptation_to(r: MMType): MMClosure
241 do
242 return new MMClosure(_name, _signature.adaptation_to(r), _is_break, _is_optional)
243 end
244
245 init(name: Symbol, s: MMSignature, is_break: Bool, is_optional: Bool)
246 do
247 _name = name
248 _signature = s
249 _is_break = is_break
250 _is_optional = is_optional
251 end
252
253 fun not_for_self: MMClosure
254 do
255 var sig = _signature.not_for_self
256 if sig != _signature then
257 return new MMClosure(_name, sig, _is_break, _is_optional)
258 else
259 return self
260 end
261 end
262
263 fun <(c: MMClosure): Bool
264 do
265 if c.is_optional and not is_optional then return false
266 if not c.is_break and is_break then return false
267 return c.signature < signature
268 end
269 end
270
271 # Inheritance relation between two types
272 abstract class MMAncestor
273 # The inherited type
274 writable var _stype: nullable MMType = null
275
276 # The inherited type
277 fun stype: MMType do return _stype.as(not null)
278
279 # The inheriter (heir) type
280 writable var _inheriter: nullable MMType = null
281
282 # The inheriter (heir) type
283 fun inheriter: MMType do return _inheriter.as(not null)
284
285 fun is_reffinement: Bool do
286 return stype.mmmodule != stype.mmmodule
287 end
288
289 fun is_specialisation: Bool do
290 return stype.local_class.global != inheriter.local_class.global
291 end
292
293 # The inherited class
294 fun local_class: MMLocalClass is abstract
295
296 redef fun to_s
297 do
298 if _stype == null then
299 return local_class.to_s
300 else
301 return stype.to_s
302 end
303 end
304 end
305
306 # A static type
307 # Note that static type a related to a specific module
308 abstract class MMType
309 # The module where self makes sence
310 fun mmmodule: MMModule is abstract
311
312 # The local class that self direclty or indirectly refers to
313 fun local_class: MMLocalClass is abstract
314
315 # Is the type a valid one
316 # For instance, circular dependency on formal types is invalid
317 fun is_valid: Bool do return true
318
319 # Is self a valid subtype of t
320 fun <(t : MMType): Bool is abstract
321
322 # Is self a valid supertype of t
323 # This method must be only called within definition of < if
324 # a double dispatch is needed
325 fun is_supertype(t: MMType): Bool is abstract
326
327 # Adapt self to another module
328 fun for_module(mod: MMModule): MMType is abstract
329
330 # Get the type adapted to another receiver type
331 # Useful for formal types
332 fun adapt_to(recv: MMType): MMType is abstract
333
334 # Adapt self to another local class context
335 # Useful for genericity
336 # 'c' Must be a super-class of self
337 # Example:
338 # class A[E]
339 # class B[F] special A[F]
340 # class C[G] special B[String]
341 # class D special C[Float]
342 # 'A[Int]'.upcast_for('A') -> 'A[Int]'
343 # 'A[Int]'.upcast_for('B') -> abort
344 # 'B[Int]'.upcast_for('B') -> 'B[Int]'
345 # 'B[Int]'.upcast_for('A') -> 'A[Int]'
346 # 'B[Int]'.upcast_for('C') -> abort
347 # 'C[Int]'.upcast_for('C') -> 'C[Int]'
348 # 'C[Int]'.upcast_for('B') -> 'B[String]'
349 # 'C[Int]'.upcast_for('A') -> 'A[String]'
350 # 'D'.upcast_for('D') -> 'D'
351 # 'D'.upcast_for('C') -> 'C[Float]'
352 # 'D'.upcast_for('B') -> 'C[String]'
353 # 'D'.upcast_for('A') -> 'A[String]'
354 fun upcast_for(c: MMLocalClass): MMType is abstract
355
356 # Return a type approximation if the reveiver is not self
357 # Useful for virtual types
358 fun not_for_self: MMType do return self
359
360 # The nullable version of self (if needed)
361 var _as_nullable_cache: nullable MMType = null
362
363 # IS the type can accept null?
364 fun is_nullable: Bool do return false
365
366 # Return the nullable version of the type
367 # Noop if already nullable
368 fun as_nullable: MMType do
369 var cache = _as_nullable_cache
370 if cache != null then return cache
371 var res = new MMNullableType(self)
372 _as_nullable_cache = res
373 return res
374 end
375
376 # Return the not null version of the type
377 # Noop if already not null
378 fun as_notnull: MMType do return self
379 end
380
381 class MMNullableType
382 super MMType
383 var _base_type: MMType
384 redef fun is_valid do return _base_type.is_valid
385 redef fun is_nullable: Bool do return true
386 redef fun as_notnull do return _base_type
387 redef fun as_nullable do return self
388 init(t: MMType) do _base_type = t
389
390 redef fun mmmodule do return _base_type.mmmodule
391
392 redef fun local_class do return _base_type.local_class
393
394 redef fun <(t)
395 do
396 return t isa MMNullableType and _base_type < t.as_notnull
397 end
398
399 redef fun to_s
400 do
401 return "nullable {_base_type}"
402 end
403
404 redef fun is_supertype(t)
405 do
406 return _base_type.is_supertype(t)
407 end
408
409 redef fun for_module(mod)
410 do
411 return _base_type.for_module(mod).as_nullable
412 end
413
414 redef fun adapt_to(recv)
415 do
416 return _base_type.adapt_to(recv).as_nullable
417 end
418
419 redef fun upcast_for(c)
420 do
421 return _base_type.upcast_for(c)
422 end
423
424 redef fun not_for_self
425 do
426 return _base_type.not_for_self.as_nullable
427 end
428 end
429
430 class MMTypeClass
431 super MMType
432 redef readable var _local_class: MMLocalClass
433 redef fun mmmodule do return _local_class.mmmodule end
434 redef fun <(t) do return t.is_supertype(self)
435
436 redef fun to_s
437 do
438 return _local_class.to_s
439 end
440
441 redef fun upcast_for(c)
442 do
443 var t: MMType = self
444 if _local_class != c then
445 t = _local_class.ancestor(c)
446 end
447 return t
448 end
449
450 init(c : MMLocalClass)
451 do
452 _local_class = c
453 end
454 end
455
456 class MMTypeSimpleClass
457 super MMTypeClass
458 redef fun is_supertype(t)
459 do
460 return t.local_class.cshe <= _local_class
461 end
462
463 redef fun for_module(mod)
464 do
465 var t: MMType = self
466 if mmmodule != mod then
467 t = _local_class.for_module(mod).get_type
468 end
469 return t
470 end
471
472 redef fun adapt_to(recv) do return self
473
474 init(c: MMLocalClass)
475 do
476 super(c)
477 end
478 end
479
480 # The type of null
481 class MMTypeNone
482 super MMType
483 redef readable var _mmmodule: MMModule
484 redef fun is_nullable: Bool do return true
485 redef fun <(t) do return t isa MMTypeNone or t isa MMNullableType
486 redef fun to_s do return "null"
487 redef fun is_supertype(t) do return false
488 redef fun local_class do abort
489 redef fun upcast_for(c) do abort
490 redef fun as_nullable do return self
491 redef fun as_notnull do abort
492
493 private init(m: MMModule) do _mmmodule = m
494 end
495
496 redef class MMModule
497 # The type of null
498 readable var _type_none: MMTypeNone = new MMTypeNone(self)
499
500 # The type of bool
501 fun type_bool: MMType
502 do
503 return class_by_name(once ("Bool".to_symbol)).get_type
504 end
505 end