metamodel: new MMType::is_valid method
[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 attr _base_type_cache: MMType
26
27 # Return the type of self for this class
28 meth get_type: MMType
29 do
30 if _base_type_cache == null then _base_type_cache = new MMTypeSimpleClass(self)
31 return _base_type_cache
32 end
33
34 # Register a new ancestor
35 protected meth 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 attr _ancestors: Map[MMLocalClass, MMAncestor]
44
45 # The ancestor type for a given superclass
46 meth ancestor(c: MMLocalClass): MMType
47 do
48 assert _ancestors != null
49 if _ancestors.has_key(c) then
50 return _ancestors[c].stype
51 end
52 return null
53 end
54 end
55
56 redef class MMLocalProperty
57 # The signature of the property (where it is declared)
58 readable writable attr _signature: MMSignature
59
60 attr _signatures_cache: HashMap[MMType, MMSignature] = new HashMap[MMType, MMSignature]
61
62 # Return the adapted signature of self for a receiver of type t
63 meth signature_for(t: MMType): MMSignature do
64 if t == local_class.get_type then return signature
65
66 if _signatures_cache.has_key(t) then return _signatures_cache[t]
67
68 var res = signature.adaptation_to(t)
69 _signatures_cache[t] = res
70 return res
71 end
72 end
73
74 # Signature for local properties
75 class MMSignature
76 # The type of the reveiver
77 readable attr _recv: MMType
78
79 # The parameter types
80 attr _params: Array[MMType]
81
82 # The return type
83 readable attr _return_type: MMType
84
85 # The closure parameters
86 readable attr _closures: Array[MMClosure] = new Array[MMClosure]
87
88 # Number of parameters
89 meth arity: Int
90 do
91 assert _params != null
92 return _params.length
93 end
94
95 # Is self a valid subtype of an other signature
96 meth <(s: MMSignature): Bool
97 do
98 assert s != null
99 if self == s then
100 return true
101 end
102 assert _recv.module == s.recv.module
103 if arity != s.arity or (_return_type == null) != (s.return_type == null) then return false
104 if _return_type != null and not _return_type < s.return_type then
105 return false
106 end
107
108 for i in [0..arity[ do
109 if not s[i] < self[i] then
110 return false
111 end
112 end
113
114 if closures.length != s.closures.length then return false
115 for i in [0..closures.length[ do
116 if not s.closures[i] < closures[i] then return false
117 end
118 return true
119 end
120
121 # The type of the i-th parameter
122 meth [](i: Int): MMType
123 do
124 assert _params.length > i
125 return _params[i]
126 end
127
128 redef meth to_s
129 do
130 var s = new Buffer
131 if _params != null and _params.length > 0 then
132 var tmp: String
133 var a = new Array[String].with_capacity(_params.length)
134 for i in [0.._params.length[ do
135 #var pn = _params_name[i]
136 var p = _params[i]
137 #a.add("{pn}: {p}")
138 a.add(p.to_s)
139 end
140 s.append("({a.join(",")})")
141 end
142 if _return_type != null then
143 s.append(": {_return_type}")
144 end
145 return s.to_s
146 end
147
148 # Adapt the signature to a different receiver
149 meth adaptation_to(r: MMType): MMSignature
150 do
151 if _recv == r then
152 return self
153 end
154 var mod = r.module
155 var p = _params
156 if p != null then
157 p = new Array[MMType]
158 for i in _params do
159 p.add(i.for_module(mod).adapt_to(r))
160 end
161 end
162 var rv = _return_type
163 if rv != null then
164 rv = rv.for_module(mod).adapt_to(r)
165 end
166 var res = new MMSignature(p,rv,r)
167 for clos in _closures do
168 res.closures.add(clos.adaptation_to(r))
169 end
170 return res
171 end
172
173 attr _not_for_self_cache: MMSignature = null
174
175 # Return a type approximation if the reveiver is not self
176 # Useful for virtual types
177 meth not_for_self: MMSignature
178 do
179 var res = _not_for_self_cache
180 if res != null then return res
181
182 var need_for_self = false
183 var p = _params
184 if p != null then
185 p = new Array[MMType]
186 for i in _params do
187 var i2 = i.not_for_self
188 if i != i2 then need_for_self = true
189 p.add(i2)
190 end
191 end
192
193 var rv = _return_type
194 if rv != null then
195 rv = rv.not_for_self
196 if rv != _return_type then need_for_self = true
197 end
198
199 var clos = _closures
200 if clos != null then
201 clos = new Array[MMClosure]
202 for c in _closures do
203 var c2 = c.not_for_self
204 if c2 != c then need_for_self = true
205 clos.add(c2)
206 end
207 end
208
209 if need_for_self then
210 res = new MMSignature(p, rv, _recv)
211 res.closures.add_all(clos)
212 else
213 res = self
214 end
215
216 _not_for_self_cache = res
217 return res
218 end
219
220 init(params: Array[MMType], return_type: MMType, r: MMType)
221 do
222 assert params != null
223 _params = params
224 _return_type = return_type
225 _recv = r
226 end
227 end
228
229 # A closure in a signature
230 class MMClosure
231 # The signature of the closure
232 readable attr _signature: MMSignature
233
234 # Is the closure a brek one
235 # aka is defined with the break keyword thus does not return
236 readable attr _is_break: Bool
237
238 # Is the closure optional?
239 # ie is there a default definition
240 readable attr _is_optional: Bool
241
242 # Adapt the signature to a different receiver
243 meth adaptation_to(r: MMType): MMClosure
244 do
245 return new MMClosure(_signature.adaptation_to(r), _is_break, _is_optional)
246 end
247
248 init(s: MMSignature, is_break: Bool, is_optional: Bool)
249 do
250 _signature = s
251 _is_break = is_break
252 _is_optional = is_optional
253 end
254
255 meth not_for_self: MMClosure
256 do
257 var sig = _signature.not_for_self
258 if sig != _signature then
259 return new MMClosure(sig, _is_break, _is_optional)
260 else
261 return self
262 end
263 end
264
265 meth <(c: MMClosure): Bool
266 do
267 if c.is_optional and not is_optional then return false
268 if not c.is_break and is_break then return false
269 return c.signature < signature
270 end
271 end
272
273 # Inheritance relation between two types
274 abstract class MMAncestor
275 # The inherited type
276 readable writable attr _stype: MMType = null
277
278 # The inheriter (heir) type
279 readable writable attr _inheriter: MMType = null
280
281 meth is_reffinement: Bool do
282 return stype.module != stype.module
283 end
284
285 meth is_specialisation: Bool do
286 return stype.local_class.global != inheriter.local_class.global
287 end
288
289 # The inherited class
290 meth local_class: MMLocalClass is abstract
291
292 redef meth to_s
293 do
294 if stype == null then
295 return local_class.to_s
296 else
297 return stype.to_s
298 end
299 end
300 end
301
302 # A static type
303 # Note that static type a related to a specific module
304 abstract class MMType
305 # The module where self makes sence
306 meth module: MMModule is abstract
307
308 # The local class that self direclty or indirectly refers to
309 meth local_class: MMLocalClass is abstract
310
311 # Is the type a valid one
312 # For instance, circular dependency on formal types is invalid
313 meth is_valid: Bool do return true
314
315 # Is self a valid subtype of t
316 meth <(t : MMType): Bool is abstract
317
318 # Is self a valid supertype of t
319 # This method must be only called within definition of < if
320 # a double dispatch is needed
321 meth is_supertype(t: MMType): Bool is abstract
322
323 # Adapt self to another module
324 meth for_module(mod: MMModule): MMType is abstract
325
326 # Get the type adapted to another receiver type
327 # Useful for formal types
328 meth adapt_to(recv: MMType): MMType is abstract
329
330 # Adapt self to another local class context
331 # Useful for genericity
332 # 'c' Must be a super-class of self
333 # Example:
334 # class A[E]
335 # class B[F] special A[F]
336 # class C[G] special B[String]
337 # class D special C[Float]
338 # 'A[Int]'.upcast_for('A') -> 'A[Int]'
339 # 'A[Int]'.upcast_for('B') -> abort
340 # 'B[Int]'.upcast_for('B') -> 'B[Int]'
341 # 'B[Int]'.upcast_for('A') -> 'A[Int]'
342 # 'B[Int]'.upcast_for('C') -> abort
343 # 'C[Int]'.upcast_for('C') -> 'C[Int]'
344 # 'C[Int]'.upcast_for('B') -> 'B[String]'
345 # 'C[Int]'.upcast_for('A') -> 'A[String]'
346 # 'D'.upcast_for('D') -> 'D'
347 # 'D'.upcast_for('C') -> 'C[Float]'
348 # 'D'.upcast_for('B') -> 'C[String]'
349 # 'D'.upcast_for('A') -> 'A[String]'
350 meth upcast_for(c: MMLocalClass): MMType is abstract
351
352 # Return a type approximation if the reveiver is not self
353 # Useful for virtual types
354 meth not_for_self: MMType do return self
355 end
356
357 class MMTypeClass
358 special MMType
359 redef readable attr _local_class: MMLocalClass
360 redef meth module do return _local_class.module end
361 redef meth <(t) do return t != null and t.is_supertype(self)
362
363 redef meth to_s
364 do
365 return _local_class.to_s
366 end
367
368 redef meth upcast_for(c)
369 do
370 assert _local_class != null
371 assert c != null
372
373 var t: MMType = self
374 if _local_class != c then
375 t = _local_class.ancestor(c)
376 end
377 assert t != null
378 return t
379 end
380
381 init(c : MMLocalClass)
382 do
383 _local_class = c
384 end
385 end
386
387 class MMTypeSimpleClass
388 special MMTypeClass
389 redef meth is_supertype(t)
390 do
391 return t.local_class.cshe <= _local_class
392 end
393
394 redef meth for_module(mod)
395 do
396 var t: MMType = self
397 if module != mod then
398 t = _local_class.for_module(mod).get_type
399 end
400 assert t != null
401 return t
402 end
403
404 redef meth adapt_to(recv) do return self
405
406 init(c: MMLocalClass)
407 do
408 super(c)
409 end
410 end
411
412 # The type of null
413 class MMTypeNone
414 special MMType
415 redef readable attr _module: MMModule
416 redef meth <(t) do return true
417 redef meth to_s do return "null"
418 redef meth is_supertype(t) do return false
419 redef meth local_class do abort
420 redef meth upcast_for(c) do abort
421
422 private init(m: MMModule) do _module = m
423 end
424
425 redef class MMModule
426 # The type of null
427 readable attr _type_none: MMTypeNone = new MMTypeNone(self)
428 end