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
95 # TODO: IS this useful?
96 meth is_generic
: Bool is abstract
99 redef class MMTypeFormal
100 redef meth is_generic
do return _bound
.is_generic
103 redef class MMTypeSimpleClass
104 redef meth is_generic
do return false
110 readable attr _params
: Array[MMType]
112 redef meth is_generic
do return true
114 redef meth is_supertype
(t
)
116 if t
.local_class
.cshe
<= _local_class
then
117 var u
= t
.upcast_for
(_local_class
)
118 if u
isa MMTypeGeneric then
119 return is_subtype
(u
) # and u.is_subtype(self) # Strong typing is too strong
125 redef meth upcast_for
(c
)
134 redef meth for_module
(mod
)
137 if module != mod
then
138 var parms
= new Array[MMType]
140 parms
.add
(p
.for_module
(mod
))
142 var b
= _local_class
.for_module
(mod
)
143 t
= b
.get_instantiate_type
(parms
)
149 redef meth adapt_to
(r
)
151 var rv
= new Array[MMType]
153 rv
.add
(i
.adapt_to
(r
))
155 var l
= _local_class
.get_instantiate_type
(rv
)
159 private meth params_equals
(t
: Array[MMType]): Bool
161 if t
.length
!= _params
.length
then
164 for i
in [0..t
.length
[ do
165 assert _params
[i
] != null
167 if _params
[i
] != t
[i
] then
176 return "{super}[{_params.join(", ")}]"
179 # Is self a subtype of t?
180 # Require that t.local_class = self.local_class
181 private meth is_subtype
(t
: MMTypeGeneric) : Bool
183 for i
in [0.._params
.length
[
185 if not t
.params
[i
] < _params
[i
] then
192 init(c
: MMLocalClass, p
: Array[MMType])
199 class MMTypeFormalParameter
201 # The class where self is defined
202 readable attr _def_class
: MMLocalClass
204 # The position is self in def_class
205 readable attr _position
: Int
207 redef meth
module do return _def_class
.module
209 redef meth for_module
(mod
)
212 if module != mod
then
213 t
= mod
[_def_class
.global
].get_formal
(position
)
219 redef meth upcast_for
(c
) do return _bound
.upcast_for
(c
)
221 meth bound
=(t
: MMType)
223 assert _bound
== null
227 redef meth adapt_to
(r
)
230 var old_r
= r
.upcast_for
(def_class
)
231 #if not old_r isa MMTypeGeneric then
232 # print "adapt {self}'{def_class}'{self.module} to {r}'{r.module}"
233 # print " old_r = {old_r}'{old_r.module}"
235 assert old_r
isa MMTypeGeneric
236 var reduct
= old_r
.params
[position
]
237 assert reduct
!= null
241 init with_bound
(n
: Symbol, p
: Int, intro
: MMLocalClass, b
: MMType)
247 init(n
: Symbol, p
: Int, intro
: MMLocalClass)
256 redef class MMTypeNone
257 redef meth is_generic
do return false
258 redef meth for_module
(mod
) do return self
259 redef meth adapt_to
(r
) do return self