1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2004-2008 Jean Privat <jean@pryen.org>
4 # Copyright 2006-2008 Floréal Morandat <morandat@lirmm.fr>
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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.
18 # Static types and property signatures
21 intrude import abstractmetamodel
23 redef class MMLocalClass
24 # Cached result of get_type
25 attr _base_type_cache
: MMType
27 # Return the type of self for this class
30 if _base_type_cache
== null then _base_type_cache
= new MMTypeSimpleClass(self)
31 return _base_type_cache
34 # Register a new ancestor
35 protected meth add_ancestor
(a
: MMAncestor)
37 assert not _ancestors
.has_key
(a
.local_class
)
38 assert a
.local_class
!= self
39 _ancestors
[a
.local_class
] = a
42 # Array of ancestor that associate each superclass with the corresponding ancestor
43 readable attr _ancestors
: Map[MMLocalClass, MMAncestor]
45 # The ancestor type for a given superclass
46 meth ancestor
(c
: MMLocalClass): MMType
48 return _ancestors
[c
].stype
52 redef class MMLocalProperty
53 # The signature of the property (where it is declared)
54 readable writable attr _signature
: MMSignature
56 attr _signatures_cache
: HashMap[MMType, MMSignature] = new HashMap[MMType, MMSignature]
58 # Return the adapted signature of self for a receiver of type t
59 meth signature_for
(t
: MMType): MMSignature do
60 if t
== local_class
.get_type
then return signature
62 if _signatures_cache
.has_key
(t
) then return _signatures_cache
[t
]
64 var res
= signature
.adaptation_to
(t
)
65 _signatures_cache
[t
] = res
70 # Signature for local properties
72 # The type of the reveiver
73 readable attr _recv
: MMType
76 attr _params
: Array[MMType]
79 readable attr _return_type
: MMType
81 # The closure parameters
82 readable attr _closures
: Array[MMClosure] = new Array[MMClosure]
84 # Number of parameters
87 assert _params
!= null
91 # Is self a valid subtype of an other signature
92 meth
<(s
: MMSignature): Bool
98 assert _recv
.module == s
.recv
.module
99 if arity
!= s
.arity
or (_return_type
== null) != (s
.return_type
== null) then return false
100 if _return_type
!= null and not _return_type
< s
.return_type
then
104 for i
in [0..arity
[ do
105 if not s
[i
] < self[i
] then
110 if closures
.length
!= s
.closures
.length
then return false
111 for i
in [0..closures
.length
[ do
112 if not s
.closures
[i
] < closures
[i
] then return false
117 # The type of the i-th parameter
118 meth
[](i
: Int): MMType
120 assert _params
.length
> i
127 if _params
!= null and _params
.length
> 0 then
129 var a
= new Array[String].with_capacity
(_params
.length
)
130 for i
in [0.._params
.length
[ do
131 #var pn = _params_name[i]
136 s
.append
("({a.join(",")})")
138 if _return_type
!= null then
139 s
.append
(": {_return_type}")
144 # Adapt the signature to a different receiver
145 meth adaptation_to
(r
: MMType): MMSignature
153 p
= new Array[MMType]
155 p
.add
(i
.for_module
(mod
).adapt_to
(r
))
158 var rv
= _return_type
160 rv
= rv
.for_module
(mod
).adapt_to
(r
)
162 var res
= new MMSignature(p
,rv
,r
)
163 for clos
in _closures
do
164 res
.closures
.add
(clos
.adaptation_to
(r
))
169 attr _not_for_self_cache
: MMSignature = null
171 # Return a type approximation if the reveiver is not self
172 # Useful for virtual types
173 meth not_for_self
: MMSignature
175 var res
= _not_for_self_cache
176 if res
!= null then return res
178 var need_for_self
= false
181 p
= new Array[MMType]
183 var i2
= i
.not_for_self
184 if i
!= i2
then need_for_self
= true
189 var rv
= _return_type
192 if rv
!= _return_type
then need_for_self
= true
197 clos
= new Array[MMClosure]
198 for c
in _closures
do
199 var c2
= c
.not_for_self
200 if c2
!= c
then need_for_self
= true
205 if need_for_self
then
206 res
= new MMSignature(p
, rv
, _recv
)
207 res
.closures
.add_all
(clos
)
212 _not_for_self_cache
= res
216 init(params
: Array[MMType], return_type
: MMType, r
: MMType)
218 assert params
!= null
220 _return_type
= return_type
225 # A closure in a signature
227 # The signature of the closure
228 readable attr _signature
: MMSignature
230 # Is the closure a brek one
231 # aka is defined with the break keyword thus does not return
232 readable attr _is_break
: Bool
234 # Is the closure optional?
235 # ie is there a default definition
236 readable attr _is_optional
: Bool
238 # Adapt the signature to a different receiver
239 meth adaptation_to
(r
: MMType): MMClosure
241 return new MMClosure(_signature
.adaptation_to
(r
), _is_break
, _is_optional
)
244 init(s
: MMSignature, is_break
: Bool, is_optional
: Bool)
248 _is_optional
= is_optional
251 meth not_for_self
: MMClosure
253 var sig
= _signature
.not_for_self
254 if sig
!= _signature
then
255 return new MMClosure(sig
, _is_break
, _is_optional
)
261 meth
<(c
: MMClosure): Bool
263 if c
.is_optional
and not is_optional
then return false
264 if not c
.is_break
and is_break
then return false
265 return c
.signature
< signature
269 # Inheritance relation between two types
270 abstract class MMAncestor
272 readable writable attr _stype
: MMType = null
274 # The inheriter (heir) type
275 readable writable attr _inheriter
: MMType = null
277 meth is_reffinement
: Bool do
278 return stype
.module != stype
.module
281 meth is_specialisation
: Bool do
282 return stype
.local_class
.global
!= inheriter
.local_class
.global
285 # The inherited class
286 meth local_class
: MMLocalClass is abstract
290 if stype
== null then
291 return local_class
.to_s
299 # Note that static type a related to a specific module
300 abstract class MMType
301 # The module where self makes sence
302 meth
module: MMModule is abstract
304 # The local class that self direclty or indirectly refers to
305 meth local_class
: MMLocalClass is abstract
307 # Is the type a valid one
308 # For instance, circular dependency on formal types is invalid
309 meth is_valid
: Bool do return true
311 # Is self a valid subtype of t
312 meth
<(t
: MMType): Bool is abstract
314 # Is self a valid supertype of t
315 # This method must be only called within definition of < if
316 # a double dispatch is needed
317 meth is_supertype
(t
: MMType): Bool is abstract
319 # Adapt self to another module
320 meth for_module
(mod
: MMModule): MMType is abstract
322 # Get the type adapted to another receiver type
323 # Useful for formal types
324 meth adapt_to
(recv
: MMType): MMType is abstract
326 # Adapt self to another local class context
327 # Useful for genericity
328 # 'c' Must be a super-class of self
331 # class B[F] special A[F]
332 # class C[G] special B[String]
333 # class D special C[Float]
334 # 'A[Int]'.upcast_for('A') -> 'A[Int]'
335 # 'A[Int]'.upcast_for('B') -> abort
336 # 'B[Int]'.upcast_for('B') -> 'B[Int]'
337 # 'B[Int]'.upcast_for('A') -> 'A[Int]'
338 # 'B[Int]'.upcast_for('C') -> abort
339 # 'C[Int]'.upcast_for('C') -> 'C[Int]'
340 # 'C[Int]'.upcast_for('B') -> 'B[String]'
341 # 'C[Int]'.upcast_for('A') -> 'A[String]'
342 # 'D'.upcast_for('D') -> 'D'
343 # 'D'.upcast_for('C') -> 'C[Float]'
344 # 'D'.upcast_for('B') -> 'C[String]'
345 # 'D'.upcast_for('A') -> 'A[String]'
346 meth upcast_for
(c
: MMLocalClass): MMType is abstract
348 # Return a type approximation if the reveiver is not self
349 # Useful for virtual types
350 meth not_for_self
: MMType do return self
352 # The nullable version of self (if needed)
353 attr _as_nullable_cache
: MMType = null
355 # IS the type can accept null?
356 meth is_nullable
: Bool do return false
358 # Return the nullable version of the type
359 # Noop if already nullable
360 meth as_nullable
: MMType do
361 var cache
= _as_nullable_cache
362 if cache
!= null then return cache
363 var res
= new MMNullableType(self)
364 _as_nullable_cache
= res
368 # Return the not null version of the type
369 # Noop if already not null
370 meth as_notnull
: MMType do return self
375 attr _base_type
: MMType
376 redef meth is_nullable
: Bool do return true
377 redef meth as_notnull
do return _base_type
378 redef meth as_nullable
do return self
379 init(t
: MMType) do _base_type
= t
381 redef meth
module do return _base_type
.module
383 redef meth local_class
do return _base_type
.local_class
387 return t
isa MMNullableType and _base_type
< t
.as_notnull
392 return "nullable {_base_type}"
395 redef meth is_supertype
(t
)
397 return _base_type
.is_supertype
(t
)
400 redef meth for_module
(mod
)
402 return _base_type
.for_module
(mod
).as_nullable
405 redef meth adapt_to
(recv
)
407 return _base_type
.adapt_to
(recv
).as_nullable
410 redef meth upcast_for
(c
)
412 return _base_type
.upcast_for
(c
)
415 redef meth not_for_self
417 return _base_type
.not_for_self
.as_nullable
423 redef readable attr _local_class
: MMLocalClass
424 redef meth
module do return _local_class
.module end
425 redef meth
<(t
) do return t
!= null and t
.is_supertype
(self)
429 return _local_class
.to_s
432 redef meth upcast_for
(c
)
434 assert _local_class
!= null
438 if _local_class
!= c
then
439 t
= _local_class
.ancestor
(c
)
445 init(c
: MMLocalClass)
451 class MMTypeSimpleClass
453 redef meth is_supertype
(t
)
455 return t
.local_class
.cshe
<= _local_class
458 redef meth for_module
(mod
)
461 if module != mod
then
462 t
= _local_class
.for_module
(mod
).get_type
468 redef meth adapt_to
(recv
) do return self
470 init(c
: MMLocalClass)
479 redef readable attr _module
: MMModule
480 redef meth is_nullable
: Bool do return true
481 redef meth
<(t
) do return t
isa MMTypeNone or t
isa MMNullableType
482 redef meth to_s
do return "null"
483 redef meth is_supertype
(t
) do return false
484 redef meth local_class
do abort
485 redef meth upcast_for
(c
) do abort
486 redef meth as_nullable
do return self
487 redef meth as_notnull
do abort
489 private init(m
: MMModule) do _module
= m
494 readable attr _type_none
: MMTypeNone = new MMTypeNone(self)