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