Basic typing and compilation for default closures.
[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 # The closure parameters
86 readable attr _closures: Array[MMClosure] = new Array[MMClosure]
87
88 # Number of parameters
89 meth arity: Int
90 do
91 assert _params != null
92 return _params.length
93 end
94
95 # Is self a valid subtype of an other signature
96 meth <(s: MMSignature): Bool
97 do
98 assert s != null
99 if self == s then
100 return true
101 end
102 assert _recv.module == s.recv.module
103 if arity != s.arity or (_return_type == null) != (s.return_type == null) then return false
104 if _return_type != null and not _return_type < s.return_type then
105 return false
106 end
107
108 for i in [0..arity[ do
109 if not s[i] < self[i] then
110 return false
111 end
112 end
113 return true
114 end
115
116 # The type of the i-th parameter
117 meth [](i: Int): MMType
118 do
119 assert _params.length > i
120 return _params[i]
121 end
122
123 redef meth to_s
124 do
125 var s: String
126 if _params != null and _params.length > 0 then
127 var tmp: String
128 var a = new Array[String].with_capacity(_params.length)
129 for i in [0.._params.length[ do
130 #var pn = _params_name[i]
131 var p = _params[i]
132 #a.add("{pn}: {p}")
133 a.add(p.to_s)
134 end
135 s = "({a.join(",")})"
136 else
137 s = ""
138 end
139 if _return_type != null then
140 s.append(": {_return_type}")
141 end
142 return s
143 end
144
145 # Adapt the signature to a different receiver
146 meth adaptation_to(r: MMType): MMSignature
147 do
148 if _recv == r then
149 return self
150 end
151 var mod = r.module
152 var p = _params
153 if p != null then
154 p = new Array[MMType]
155 for i in _params do
156 p.add(i.for_module(mod).adapt_to(r))
157 end
158 end
159 var rv = _return_type
160 if rv != null then
161 rv = rv.for_module(mod).adapt_to(r)
162 end
163 var res = new MMSignature(p,rv,r)
164 for clos in _closures do
165 res.closures.add(clos.adaptation_to(r))
166 end
167 return res
168 end
169
170 attr _not_for_self_cache: MMSignature = null
171
172 # Return a type approximation if the reveiver is not self
173 # Useful for virtual types
174 meth not_for_self: MMSignature
175 do
176 var res = _not_for_self_cache
177 if res != null then return res
178
179 var need_for_self = false
180 var p = _params
181 if p != null then
182 p = new Array[MMType]
183 for i in _params do
184 var i2 = i.not_for_self
185 if i != i2 then need_for_self = true
186 p.add(i2)
187 end
188 end
189
190 var rv = _return_type
191 if rv != null then
192 rv = rv.not_for_self
193 if rv != _return_type then need_for_self = true
194 end
195
196 var clos = _closures
197 if clos != null then
198 clos = new Array[MMClosure]
199 for c in _closures do
200 var c2 = c.not_for_self
201 if c2 != c then need_for_self = true
202 clos.add(c2)
203 end
204 end
205
206 if need_for_self then
207 res = new MMSignature(p, rv, _recv)
208 res.closures.add_all(clos)
209 else
210 res = self
211 end
212
213 _not_for_self_cache = res
214 return res
215 end
216
217 init(params: Array[MMType], return_type: MMType, r: MMType)
218 do
219 assert params != null
220 _params = params
221 _return_type = return_type
222 _recv = r
223 end
224 end
225
226 # A closure in a signature
227 class MMClosure
228 # The signature of the closure
229 readable attr _signature: MMSignature
230
231 # Is the closure a brek one
232 # aka is defined with the break keyword thus does not return
233 readable attr _is_break: Bool
234
235 # Is the closure optional?
236 # ie is there a default definition
237 readable attr _is_optional: Bool
238
239 # Adapt the signature to a different receiver
240 meth adaptation_to(r: MMType): MMClosure
241 do
242 return new MMClosure(_signature.adaptation_to(r), _is_break, _is_optional)
243 end
244
245 init(s: MMSignature, is_break: Bool, is_optional: Bool)
246 do
247 _signature = s
248 _is_break = is_break
249 _is_optional = is_optional
250 end
251
252 meth not_for_self: MMClosure
253 do
254 var sig = _signature.not_for_self
255 if sig != _signature then
256 return new MMClosure(sig, _is_break, _is_optional)
257 else
258 return self
259 end
260 end
261 end
262
263 # Inheritance relation between two types
264 abstract class MMAncestor
265 # The inherited type
266 readable writable attr _stype: MMType = null
267
268 # The inheriter (heir) type
269 readable writable attr _inheriter: MMType = null
270
271 meth is_reffinement: Bool do
272 return stype.module != stype.module
273 end
274
275 meth is_specialisation: Bool do
276 return stype.local_class.global != inheriter.local_class.global
277 end
278
279 # The inherited class
280 meth local_class: MMLocalClass is abstract
281
282 redef meth to_s
283 do
284 if stype == null then
285 return local_class.to_s
286 else
287 return stype.to_s
288 end
289 end
290 end
291
292 # A static type
293 # Note that static type a related to a specific module
294 abstract class MMType
295 # The module where self makes sence
296 meth module: MMModule is abstract
297
298 # The local class that self direclty or indirectly refers to
299 meth local_class: MMLocalClass is abstract
300
301 # Is self a valid subtype of t
302 meth <(t : MMType): Bool is abstract
303
304 # Is self a valid supertype of t
305 # This method must be only called within definition of < if
306 # a double dispatch is needed
307 meth is_supertype(t: MMType): Bool is abstract
308
309 # Adapt self to another module
310 meth for_module(mod: MMModule): MMType is abstract
311
312 # Get the type adapted to another receiver type
313 # Useful for formal types
314 meth adapt_to(recv: MMType): MMType is abstract
315
316 # Adapt self to another local class context
317 # Useful for genericity
318 meth upcast_for(c: MMLocalClass): MMType is abstract
319
320 # Return a type approximation if the reveiver is not self
321 # Useful for virtual types
322 meth not_for_self: MMType do return self
323 end
324
325 class MMTypeClass
326 special MMType
327 redef readable attr _local_class: MMLocalClass
328 redef meth module do return _local_class.module end
329 redef meth <(t) do return t != null and t.is_supertype(self)
330
331 redef meth to_s
332 do
333 return _local_class.to_s
334 end
335
336 redef meth upcast_for(c)
337 do
338 assert _local_class != null
339 assert c != null
340
341 var t: MMType = self
342 if _local_class != c then
343 t = _local_class.ancestor(c)
344 end
345 assert t != null
346 return t
347 end
348
349 init(c : MMLocalClass)
350 do
351 _local_class = c
352 end
353 end
354
355 class MMTypeSimpleClass
356 special MMTypeClass
357 redef meth is_supertype(t)
358 do
359 return t.local_class.cshe <= _local_class
360 end
361
362 redef meth for_module(mod)
363 do
364 var t: MMType = self
365 if module != mod then
366 t = _local_class.for_module(mod).get_type
367 end
368 assert t != null
369 return t
370 end
371
372 redef meth adapt_to(recv) do return self
373
374 init(c: MMLocalClass)
375 do
376 super(c)
377 end
378 end
379
380 # The type of null
381 class MMTypeNone
382 special MMType
383 redef readable attr _module: MMModule
384 redef meth <(t) do return true
385 redef meth is_supertype(t) do return false
386 redef meth local_class do abort
387 redef meth upcast_for(c) do return self
388
389 private init(m: MMModule) do _module = m
390 end
391
392 redef class MMModule
393 # The type of null
394 readable attr _type_none: MMTypeNone = new MMTypeNone(self)
395 end