syntax: 'meth' -> 'fun', 'attr' -> 'var'
[nit.git] / src / metamodel / genericity.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 # Generic classes, generic types and generic formal parameters
19 package genericity
20
21 intrude import type_formal
22 intrude import inheritance
23
24 redef class MMLocalClass
25 # The pos-th formal type parameter
26 fun get_formal(pos: Int): MMTypeFormalParameter
27 do
28 return formals_types[pos]
29 end
30
31 # Register a new formal type
32 # Called in order during the building of the class
33 fun register_formal(f: MMTypeFormalParameter)
34 do
35 assert f.def_class == self
36 assert f.position == _formals_types.length
37 _formals_types.add(f)
38 end
39
40 # All the insanciated types of the class
41 var _types: Array[MMTypeGeneric] = new Array[MMTypeGeneric]
42
43 # Instanciate a type from the generic class
44 fun get_instantiate_type(t: Array[MMType]): MMType
45 do
46 for g in _types do
47 if g.params_equals(t) then return g
48 end
49 var g = new MMTypeGeneric(self, t)
50 _types.add(g)
51 return g
52 end
53
54 # The formal types of the class
55 var _formals_types: Array[MMTypeFormalParameter] = new Array[MMTypeFormalParameter]
56
57 # Return the definition formal types for the class
58 # Import them from the intro class if needed
59 private fun formals_types: Array[MMTypeFormalParameter]
60 do
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)
68 register_formal(ft)
69 end
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)
75 end
76 end
77 return _formals_types
78 end
79
80 redef fun get_type
81 do
82 if _base_type_cache == null and is_generic then
83 _base_type_cache = get_instantiate_type(formals_types)
84 return _base_type_cache.as(not null)
85 else
86 return super
87 end
88 end
89
90 # Is the class a generic one?
91 fun is_generic: Bool do return arity > 0
92 end
93
94 redef class MMType
95 # TODO: IS this useful?
96 fun is_generic: Bool is abstract
97 end
98
99 redef class MMTypeFormal
100 redef fun is_generic do return _bound.is_generic
101 end
102
103 redef class MMTypeSimpleClass
104 redef fun is_generic do return false
105 end
106
107 class MMTypeGeneric
108 special MMTypeClass
109 # Formal arguments
110 readable var _params: Array[MMType]
111
112 redef fun is_generic do return true
113
114 redef fun is_supertype(t)
115 do
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
120 end
121 end
122 return false
123 end
124
125 redef fun upcast_for(c)
126 do
127 var t = super
128 if t != self then
129 t = t.adapt_to(self)
130 end
131 return t
132 end
133
134 redef fun for_module(mod)
135 do
136 var t: MMType = self
137 if module != mod then
138 var parms = new Array[MMType]
139 for p in _params do
140 parms.add(p.for_module(mod))
141 end
142 var b = _local_class.for_module(mod)
143 t = b.get_instantiate_type(parms)
144 end
145 return t
146 end
147
148 redef fun adapt_to(r)
149 do
150 var rv = new Array[MMType]
151 for i in _params do
152 rv.add(i.adapt_to(r))
153 end
154 var l = _local_class.get_instantiate_type(rv)
155 return l
156 end
157
158 private fun params_equals(t: Array[MMType]): Bool
159 do
160 if t.length != _params.length then
161 return false
162 end
163 for i in [0..t.length[ do
164 if _params[i] != t[i] then
165 return false
166 end
167 end
168 return true
169 end
170
171 redef fun to_s
172 do
173 return "{super}[{_params.join(", ")}]"
174 end
175
176 # Is self a subtype of t?
177 # Require that t.local_class = self.local_class
178 private fun is_subtype(t: MMTypeGeneric) : Bool
179 do
180 for i in [0.._params.length[
181 do
182 if not t.params[i] < _params[i] then
183 return false
184 end
185 end
186 return true
187 end
188
189 init(c: MMLocalClass, p: Array[MMType])
190 do
191 super(c)
192 _params = p
193 end
194 end
195
196 class MMTypeFormalParameter
197 special MMTypeFormal
198 # The class where self is defined
199 readable var _def_class: MMLocalClass
200
201 # The position is self in def_class
202 readable var _position: Int
203
204 redef fun module do return _def_class.module
205
206 redef fun for_module(mod)
207 do
208 var t: MMType = self
209 if module != mod then
210 t = mod[_def_class.global].get_formal(position)
211 end
212 return t
213 end
214
215 redef fun upcast_for(c) do return _bound.upcast_for(c)
216
217 fun bound=(t: MMType)
218 do
219 assert _bound == null
220 _bound = t
221 end
222
223 redef fun adapt_to(r)
224 do
225 r = r.direct_type
226 var old_r = r.upcast_for(def_class)
227 #if not old_r isa MMTypeGeneric then
228 # print "adapt {self}'{def_class}'{self.module} to {r}'{r.module}"
229 # print " old_r = {old_r}'{old_r.module}"
230 #end
231 assert old_r isa MMTypeGeneric
232 var reduct = old_r.params[position]
233 return reduct
234 end
235
236 init with_bound(n: Symbol, p: Int, intro: MMLocalClass, b: MMType)
237 do
238 init(n,p,intro)
239 _bound = b
240 end
241
242 init(n: Symbol, p: Int, intro: MMLocalClass)
243 do
244 super(n, null)
245 _position = p
246 _def_class = intro
247 end
248 end
249
250 redef class MMTypeNone
251 redef fun is_generic do return false
252 redef fun for_module(mod) do return self
253 redef fun adapt_to(r) do return self
254 end