Simplify local property inheritance.
[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 # Number of parameters
86 meth arity: Int
87 do
88 assert _params != null
89 return _params.length
90 end
91
92 # Is self a valid subtype of an other signature
93 meth <(s: MMSignature): Bool
94 do
95 assert s != null
96 if self == s then
97 return true
98 end
99 assert _recv.module == s.recv.module
100 assert arity == s.arity
101 assert (_return_type == null) == (s.return_type == null)
102 if _return_type != null and not _return_type < s.return_type then
103 return false
104 end
105
106 for i in [0..arity[ do
107 if not s[i] < self[i] then
108 return false
109 end
110 end
111 return true
112 end
113
114 # The type of the i-th parameter
115 meth [](i: Int): MMType
116 do
117 assert _params.length > i
118 return _params[i]
119 end
120
121 redef meth to_s
122 do
123 var s: String
124 if _params != null and _params.length > 0 then
125 var tmp: String
126 var a = new Array[String].with_capacity(_params.length)
127 for i in [0.._params.length[ do
128 #var pn = _params_name[i]
129 var p = _params[i]
130 #a.add("{pn}: {p}")
131 a.add(p.to_s)
132 end
133 s = "({a.join(",")})"
134 else
135 s = ""
136 end
137 if _return_type != null then
138 s.append(": {_return_type}")
139 end
140 return s
141 end
142
143 # Adapt the signature to a different receiver
144 meth adaptation_to(r: MMType): MMSignature
145 do
146 if _recv == r then
147 return self
148 end
149 var mod = r.module
150 var p = _params
151 if p != null then
152 p = new Array[MMType]
153 for i in _params do
154 p.add(i.for_module(mod).adapt_to(r))
155 end
156 end
157 var rv = _return_type
158 if rv != null then
159 rv = rv.for_module(mod).adapt_to(r)
160 end
161 return new MMSignature(p,rv,r)
162 end
163
164 init(params: Array[MMType], return_type: MMType, r: MMType)
165 do
166 assert params != null
167 _params = params
168 _return_type = return_type
169 _recv = r
170 end
171 end
172
173 # Inheritance relation between two types
174 abstract class MMAncestor
175 # The inherited type
176 readable writable attr _stype: MMType
177
178 # The inheriter (heir) type
179 readable writable attr _inheriter: MMType
180
181 meth is_reffinement: Bool do
182 return stype.module != stype.module
183 end
184
185 meth is_specialisation: Bool do
186 return stype.local_class.global != inheriter.local_class.global
187 end
188
189 # The inherited class
190 meth local_class: MMLocalClass is abstract
191
192 redef meth to_s
193 do
194 if stype == null then
195 return local_class.to_s
196 else
197 return stype.to_s
198 end
199 end
200 end
201
202 # A static type
203 # Note that static type a related to a specific module
204 abstract class MMType
205 # The module where self makes sence
206 meth module: MMModule is abstract
207
208 # The local class that self direclty or indirectly refers to
209 meth local_class: MMLocalClass is abstract
210
211 # Is self a valid subtype of t
212 meth <(t : MMType): Bool is abstract
213
214 # Is self a valid supertype of t
215 # This method must be only called within definition of < if
216 # a double dispatch is needed
217 meth is_supertype(t: MMType): Bool is abstract
218
219 # Select a method from its name
220 meth select_method(name: Symbol): MMMethod
221 do
222 assert local_class != null
223 assert name != null
224 var res = select_property(local_class.method(name))
225 assert res isa MMMethod
226 return res
227 end
228
229 # Select an attribute from its name
230 meth select_attribute(name: Symbol): MMAttribute
231 do
232 assert name != null
233 assert local_class != null
234 var res = select_property(local_class.attribute(name))
235 assert res isa MMAttribute
236 return res
237 end
238
239 # Select a local property from its global property
240 meth select_property(t: MMGlobalProperty): MMLocalProperty is abstract
241
242 # Adapt self to another module
243 meth for_module(mod: MMModule): MMType is abstract
244
245 # Get the type adapted to another receiver type
246 # Useful for formal types
247 meth adapt_to(recv: MMType): MMType is abstract
248
249 # Adapt self to another local class context
250 # Useful for genericity
251 meth upcast_for(c: MMLocalClass): MMType is abstract
252
253 # Return a type approximation if the reveiver is not self
254 # Useful for virtual types
255 meth not_for_self: MMType do return self
256 end
257
258 class MMTypeClass
259 special MMType
260 redef readable attr _local_class: MMLocalClass
261 redef meth module do return _local_class.module end
262 redef meth <(t) do return t != null and t.is_supertype(self)
263
264 redef meth to_s
265 do
266 return _local_class.to_s
267 end
268
269 redef meth upcast_for(c)
270 do
271 assert _local_class != null
272 assert c != null
273
274 var t: MMType = self
275 if _local_class != c then
276 t = _local_class.ancestor(c)
277 end
278 assert t != null
279 return t
280 end
281
282 init(c : MMLocalClass)
283 do
284 _local_class = c
285 end
286 end
287
288 class MMTypeSimpleClass
289 special MMTypeClass
290 redef meth is_supertype(t)
291 do
292 return t.local_class.cshe <= _local_class
293 end
294
295 redef meth select_property(g)
296 do
297 assert _local_class != null
298 if g == null then
299 return null
300 end
301 return _local_class[g]
302 end
303
304 redef meth for_module(mod)
305 do
306 var t: MMType = self
307 if module != mod then
308 t = _local_class.for_module(mod).get_type
309 end
310 assert t != null
311 return t
312 end
313
314 redef meth adapt_to(recv) do return self
315
316 redef init(c: MMLocalClass)
317 do
318 super(c)
319 end
320 end
321
322 # The type of null
323 class MMTypeNone
324 special MMType
325 redef readable attr _module: MMModule
326 redef meth <(t) do return true
327 redef meth is_supertype(t) do return false
328 redef meth local_class do abort
329 redef meth upcast_for(c) do return self
330
331 private init(m: MMModule) do _module = m
332 end
333
334 redef class MMModule
335 # The type of null
336 readable attr _type_none: MMTypeNone = new MMTypeNone(self)
337 end