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 # Generic classes, generic types and generic formal parameters
21 intrude import type_formal
22 intrude import inheritance
24 redef class MMLocalClass
25 # The pos-th formal type parameter
26 meth get_formal
(pos
: Int): MMTypeFormalParameter
28 return formals_types
[pos
]
31 # Register a new formal type
32 # Called in order during the building of the class
33 meth register_formal
(f
: MMTypeFormalParameter)
35 assert f
.def_class
== self
36 assert f
.position
== _formals_types
.length
40 # All the insanciated types of the class
41 attr _types
: Array[MMTypeGeneric] = new Array[MMTypeGeneric]
43 # Instanciate a type from the generic class
44 meth get_instantiate_type
(t
: Array[MMType]): MMType
47 if g
.params_equals
(t
) then return g
49 var g
= new MMTypeGeneric(self, t
)
54 # The formal types of the class
55 attr _formals_types
: Array[MMTypeFormalParameter] = new Array[MMTypeFormalParameter]
57 # Return the definition formal types for the class
58 # Import them from the intro class if needed
59 private meth formals_types
: Array[MMTypeFormalParameter]
61 if _formals_types
.is_empty
then
62 assert not self isa MMConcreteClass
63 # Because of F-genericity, the import is done in two pass
64 # First, get the formal types untyped so that one can recurcively call formals_types
65 for i
in [0..arity
[ do
66 var oft
= global
.intro
.get_formal
(i
)
67 var ft
= new MMTypeFormalParameter(oft
.name
, i
, self)
70 # Second, assign the bound to the formal type
71 for i
in [0..arity
[ do
72 var oft
= global
.intro
.get_formal
(i
)
73 var ft
= _formals_types
[i
]
74 ft
.bound
= oft
.bound
.for_module
(module)
82 if _base_type_cache
== null and is_generic
then
83 _base_type_cache
= get_instantiate_type
(formals_types
)
84 return _base_type_cache
90 # Is the class a generic one?
91 meth is_generic
: Bool do return arity
> 0
94 redef class MMSignature
95 # Adapt the signature to a different receiver
96 meth adaptation_to
(r
: MMType): MMSignature
104 p
= new Array[MMType]
106 p
.add
(i
.for_module
(mod
).adapt_to
(r
))
109 var rv
= _return_type
111 rv
= rv
.for_module
(mod
).adapt_to
(r
)
113 return new MMSignature(p
,rv
,r
)
117 redef class MMLocalProperty
118 # The receiver type if the signature is unknown (aka lazily computed)
119 attr _recv_alone
: MMType
123 assert signature
!= null
124 return signature
.recv
127 meth recv
=(rec
: MMType)
130 # print("setting recv for {self} {rec} {_recv == null}")
131 assert _signature_cache
== null
137 var sig
= _signature_cache
141 if self isa MMConcreteProperty then
146 var impl
= _concrete_property
147 if sp
== null then # superprop ?
148 # print("building signature for {self}:{self.object_id} and type {_recv}")
149 _signature_cache
= impl
.signature
150 assert _signature_cache
!= null
152 # print("adapting signature for {self}:{self.object_id} and type {_recv}")
153 assert sp
.signature
!= null
154 assert _recv_alone
!= null
155 #_signature = sp.signature
156 _signature_cache
= sp
.signature
.adaptation_to
(_recv_alone
)
158 assert _signature_cache
!= null
159 # print("finally recv is {_recv} for {self}:{self.object_id} and sig is {_signature.recv}")
160 return _signature_cache
163 # Adapt the property to a different receiver
164 # TODO: Merge with inheritance stuff
165 meth adapt_property
(t
: MMType): MMLocalProperty
168 var recv
= local_class
.get_type
176 redef meth inherit_from
(s
, t
) # for the super bugs
184 # TODO: IS this useful?
185 meth is_generic
: Bool is abstract
188 redef class MMTypeFormal
189 redef meth is_generic
do return _bound
.is_generic
192 redef class MMTypeSimpleClass
193 redef meth is_generic
do return false
199 readable attr _params
: Array[MMType]
200 attr _props
: Map[MMGlobalProperty, MMLocalProperty] = new HashMap[MMGlobalProperty, MMLocalProperty]
202 redef meth is_generic
do return true
204 redef meth is_supertype
(t
)
206 if t
.local_class
.cshe
<= _local_class
then
207 var u
= t
.upcast_for
(_local_class
)
208 if u
isa MMTypeGeneric then
209 return is_subtype
(u
) # and u.is_subtype(self) # Strong typing is too strong
215 redef meth upcast_for
(c
)
224 redef meth for_module
(mod
)
227 if module != mod
then
228 var parms
= new Array[MMType]
230 parms
.add
(p
.for_module
(mod
))
232 var b
= _local_class
.for_module
(mod
)
233 t
= b
.get_instantiate_type
(parms
)
239 redef meth adapt_to
(r
)
241 var rv
= new Array[MMType]
243 rv
.add
(i
.adapt_to
(r
))
245 var l
= _local_class
.get_instantiate_type
(rv
)
249 private meth params_equals
(t
: Array[MMType]): Bool
251 if t
.length
!= _params
.length
then
254 for i
in [0..t
.length
[ do
255 assert _params
[i
] != null
257 if _params
[i
] != t
[i
] then
264 redef meth select_property
(g
)
269 if not _props
.has_key
(g
) then
270 assert _local_class
!= null
271 var p
= _local_class
[g
]
273 var p2
= p
.adapt_property
(self)
285 return "{super}[{_params.join(", ")}]"
288 # Is self a subtype of t?
289 # Require that t.local_class = self.local_class
290 private meth is_subtype
(t
: MMTypeGeneric) : Bool
292 for i
in [0.._params
.length
[
294 if not t
.params
[i
] < _params
[i
] then
301 init(c
: MMLocalClass, p
: Array[MMType])
308 class MMTypeFormalParameter
310 # The class where self is defined
311 readable attr _def_class
: MMLocalClass
313 # The position is self in def_class
314 readable attr _position
: Int
316 redef meth
module do return _def_class
.module
318 redef meth for_module
(mod
)
321 if module != mod
then
322 t
= mod
[_def_class
.global
].get_formal
(position
)
328 redef meth upcast_for
(c
) do return self
330 meth bound
=(t
: MMType)
332 assert _bound
== null
336 redef meth adapt_to
(r
)
338 var old_r
= r
.upcast_for
(def_class
)
339 #print "adapt {self} for ({old_r} -> {r})"
340 assert old_r
isa MMTypeGeneric
341 var reduct
= old_r
.params
[position
]
342 assert reduct
!= null
346 init with_bound
(n
: Symbol, p
: Int, intro
: MMLocalClass, b
: MMType)
352 init(n
: Symbol, p
: Int, intro
: MMLocalClass)
361 redef class MMTypeNone
362 redef meth is_generic
do return false
363 redef meth for_module
(mod
) do return self
364 redef meth adapt_to
(r
) do return self