model: add MMethodDef::is_abstract
[nit.git] / src / model / model.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Object model of the Nit language
18 #
19 # This module define the entities of the Nit meta-model like modules,
20 # classes, types and properties
21 #
22 # It also provide an API to build and query models.
23 #
24 # All model classes starts with the M letter (MModule, MClass, etc.)
25 #
26 # TODO: better doc
27 #
28 # TODO: liearization, closures, extern stuff
29 # FIXME: better handling of the types
30 module model
31
32 import poset
33 import location
34 import model_base
35 private import more_collections
36
37 redef class Model
38 # All known classes
39 var mclasses: Array[MClass] = new Array[MClass]
40
41 # All known properties
42 var mproperties: Array[MProperty] = new Array[MProperty]
43
44 # Hierarchy of class definition.
45 #
46 # Each classdef is associated with its super-classdefs in regard to
47 # its module of definition.
48 var mclassdef_hierarchy: POSet[MClassDef] = new POSet[MClassDef]
49
50 # Class-type hierarchy restricted to the introduction.
51 #
52 # The idea is that what is true on introduction is always true whatever
53 # the module considered.
54 # Therefore, this hierarchy is used for a fast positive subtype check.
55 #
56 # This poset will evolve in a monotonous way:
57 # * Two non connected nodes will remain unconnected
58 # * New nodes can appear with new edges
59 private var intro_mtype_specialization_hierarchy: POSet[MClassType] = new POSet[MClassType]
60
61 # Global overlapped class-type hierarchy.
62 # The hierarchy when all modules are combined.
63 # Therefore, this hierarchy is used for a fast negative subtype check.
64 #
65 # This poset will evolve in an anarchic way. Loops can even be created.
66 #
67 # FIXME decide what to do on loops
68 private var full_mtype_specialization_hierarchy: POSet[MClassType] = new POSet[MClassType]
69
70 # Collections of classes grouped by their short name
71 private var mclasses_by_name: MultiHashMap[String, MClass] = new MultiHashMap[String, MClass]
72
73 # Return all class named `name'.
74 #
75 # If such a class does not exist, null is returned
76 # (instead of an empty array)
77 #
78 # Visibility or modules are not considered
79 fun get_mclasses_by_name(name: String): nullable Array[MClass]
80 do
81 if mclasses_by_name.has_key(name) then
82 return mclasses_by_name[name]
83 else
84 return null
85 end
86 end
87
88 # Collections of properties grouped by their short name
89 private var mproperties_by_name: MultiHashMap[String, MProperty] = new MultiHashMap[String, MProperty]
90
91 # Return all properties named `name'.
92 #
93 # If such a property does not exist, null is returned
94 # (instead of an empty array)
95 #
96 # Visibility or modules are not considered
97 fun get_mproperties_by_name(name: String): nullable Array[MProperty]
98 do
99 if not mproperties_by_name.has_key(name) then
100 return null
101 else
102 return mproperties_by_name[name]
103 end
104 end
105
106 # The only null type
107 var null_type: MNullType = new MNullType(self)
108 end
109
110 redef class MModule
111 # All the classes introduced in the module
112 var intro_mclasses: Array[MClass] = new Array[MClass]
113
114 # All the class definitions of the module
115 # (introduction and refinement)
116 var mclassdefs: Array[MClassDef] = new Array[MClassDef]
117
118 # Does the current module has a given class `mclass'?
119 # Return true if the mmodule introduces, refines or imports a class.
120 # Visibility is not considered.
121 fun has_mclass(mclass: MClass): Bool
122 do
123 return self.in_importation <= mclass.intro_mmodule
124 end
125
126 # Full hierarchy of introduced ans imported classes.
127 #
128 # Create a new hierarchy got by flattening the classes for the module
129 # and its imported modules.
130 # Visibility is not considered.
131 #
132 # Note: this function is expensive and is usually used for the main
133 # module of a program only. Do not use it to do you own subtype
134 # functions.
135 fun flatten_mclass_hierarchy: POSet[MClass]
136 do
137 var res = self.flatten_mclass_hierarchy_cache
138 if res != null then return res
139 res = new POSet[MClass]
140 for m in self.in_importation.greaters do
141 for cd in m.mclassdefs do
142 var c = cd.mclass
143 for s in cd.supertypes do
144 res.add_edge(c, s.mclass)
145 end
146 end
147 end
148 self.flatten_mclass_hierarchy_cache = res
149 return res
150 end
151
152 # Sort a given array of classes using the linerarization order of the module
153 # The most general is first, the most specific is last
154 fun linearize_mclasses(mclasses: Array[MClass])
155 do
156 self.flatten_mclass_hierarchy.sort(mclasses)
157 end
158
159 # Sort a given array of class definitions using the linerarization order of the module
160 # the refinement link is stronger than the specialisation link
161 # The most general is first, the most specific is last
162 fun linearize_mclassdefs(mclassdefs: Array[MClassDef])
163 do
164 var sorter = new MClassDefSorter(self)
165 sorter.sort(mclassdefs)
166 end
167
168 # Sort a given array of property definitions using the linerarization order of the module
169 # the refinement link is stronger than the specialisation link
170 # The most general is first, the most specific is last
171 fun linearize_mpropdefs(mpropdefs: Array[MPropDef])
172 do
173 var sorter = new MPropDefSorter(self)
174 sorter.sort(mpropdefs)
175 end
176
177 private var flatten_mclass_hierarchy_cache: nullable POSet[MClass] = null
178
179 # The primitive type Object, the root of the class hierarchy
180 fun object_type: MClassType
181 do
182 var res = self.object_type_cache
183 if res != null then return res
184 res = self.get_primitive_class("Object").mclass_type
185 self.object_type_cache = res
186 return res
187 end
188
189 private var object_type_cache: nullable MClassType
190
191 # The primitive type Bool
192 fun bool_type: MClassType
193 do
194 var res = self.bool_type_cache
195 if res != null then return res
196 res = self.get_primitive_class("Bool").mclass_type
197 self.bool_type_cache = res
198 return res
199 end
200
201 private var bool_type_cache: nullable MClassType
202
203 # The primitive type Sys, the main type of the program, if any
204 fun sys_type: nullable MClassType
205 do
206 var clas = self.model.get_mclasses_by_name("Sys")
207 if clas == null then return null
208 return get_primitive_class("Sys").mclass_type
209 end
210
211 # Force to get the primitive class named `name' or abort
212 fun get_primitive_class(name: String): MClass
213 do
214 var cla = self.model.get_mclasses_by_name(name)
215 if cla == null then
216 if name == "Bool" then
217 var c = new MClass(self, name, 0, enum_kind, public_visibility)
218 var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0), new Array[String])
219 return c
220 end
221 print("Fatal Error: no primitive class {name}")
222 exit(1)
223 end
224 assert cla.length == 1 else print cla.join(", ")
225 return cla.first
226 end
227
228 # Try to get the primitive method named `name' on the type `recv'
229 fun try_get_primitive_method(name: String, recv: MType): nullable MMethod
230 do
231 var props = self.model.get_mproperties_by_name(name)
232 if props == null then return null
233 var res: nullable MMethod = null
234 for mprop in props do
235 assert mprop isa MMethod
236 if not recv.has_mproperty(self, mprop) then continue
237 if res == null then
238 res = mprop
239 else
240 print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
241 abort
242 end
243 end
244 return res
245 end
246 end
247
248 private class MClassDefSorter
249 super AbstractSorter[MClassDef]
250 var mmodule: MModule
251 redef fun compare(a, b)
252 do
253 var ca = a.mclass
254 var cb = b.mclass
255 if ca != cb then return mmodule.flatten_mclass_hierarchy.compare(ca, cb)
256 return mmodule.model.mclassdef_hierarchy.compare(a, b)
257 end
258 end
259
260 private class MPropDefSorter
261 super AbstractSorter[MPropDef]
262 var mmodule: MModule
263 redef fun compare(pa, pb)
264 do
265 var a = pa.mclassdef
266 var b = pb.mclassdef
267 var ca = a.mclass
268 var cb = b.mclass
269 if ca != cb then return mmodule.flatten_mclass_hierarchy.compare(ca, cb)
270 return mmodule.model.mclassdef_hierarchy.compare(a, b)
271 end
272 end
273
274 # A named class
275 #
276 # MClass are global to the model; it means that a MClass is not bound to a
277 # specific `MModule`.
278 #
279 # This characteristic helps the reasoning about classes in a program since a
280 # single MClass object always denote the same class.
281 # However, because a MClass is global, it does not really have properties nor
282 # belong to a hierarchy since the property and the
283 # hierarchy of a class depends of a module.
284 class MClass
285 # The module that introduce the class
286 # While classes are not bound to a specific module,
287 # the introducing module is used for naming an visibility
288 var intro_mmodule: MModule
289
290 # The short name of the class
291 # In Nit, the name of a class cannot evolve in refinements
292 var name: String
293
294 # The canonical name of the class
295 # Example: "owner::module::MyClass"
296 fun full_name: String
297 do
298 return "{self.intro_mmodule.full_name}::{name}"
299 end
300
301 # The number of generic formal parameters
302 # 0 if the class is not generic
303 var arity: Int
304
305 # The kind of the class (interface, abstract class, etc.)
306 # In Nit, the kind of a class cannot evolve in refinements
307 var kind: MClassKind
308
309 # The visibility of the class
310 # In Nit, the visibility of a class cannot evolve in refinements
311 var visibility: MVisibility
312
313 init(intro_mmodule: MModule, name: String, arity: Int, kind: MClassKind, visibility: MVisibility)
314 do
315 self.intro_mmodule = intro_mmodule
316 self.name = name
317 self.arity = arity
318 self.kind = kind
319 self.visibility = visibility
320 intro_mmodule.intro_mclasses.add(self)
321 var model = intro_mmodule.model
322 model.mclasses_by_name.add_one(name, self)
323 model.mclasses.add(self)
324
325 # Create the formal parameter types
326 if arity > 0 then
327 var mparametertypes = new Array[MParameterType]
328 for i in [0..arity[ do
329 var mparametertype = new MParameterType(self, i)
330 mparametertypes.add(mparametertype)
331 end
332 var mclass_type = new MGenericType(self, mparametertypes)
333 self.mclass_type = mclass_type
334 self.get_mtype_cache.add(mclass_type)
335 else
336 self.mclass_type = new MClassType(self)
337 end
338 end
339
340 # All class definitions (introduction and refinements)
341 var mclassdefs: Array[MClassDef] = new Array[MClassDef]
342
343 # Alias for `name'
344 redef fun to_s do return self.name
345
346 # The definition that introduced the class
347 # Warning: the introduction is the first `MClassDef' object associated
348 # to self. If self is just created without having any associated
349 # definition, this method will abort
350 fun intro: MClassDef
351 do
352 assert has_a_first_definition: not mclassdefs.is_empty
353 return mclassdefs.first
354 end
355
356 # Return the class `self' in the class hierarchy of the module `mmodule'.
357 #
358 # SEE: MModule::flatten_mclass_hierarchy
359 # REQUIRE: mmodule.has_mclass(self)
360 fun in_hierarchy(mmodule: MModule): POSetElement[MClass]
361 do
362 return mmodule.flatten_mclass_hierarchy[self]
363 end
364
365 # The principal static type of the class.
366 #
367 # For non-generic class, mclass_type is the only MClassType based
368 # on self.
369 #
370 # For a generic class, the arguments are the formal parameters.
371 # i.e.: for the class `Array[E:Object]', the mtype is Array[E].
372 # If you want `Array[Object]' the see `MClassDef::bound_mtype'
373 #
374 # For generic classes, the mclass_type is also the way to get a formal
375 # generic parameter type.
376 #
377 # To get other types based on a generic class, see `get_mtype'.
378 #
379 # ENSURE: mclass_type.mclass == self
380 var mclass_type: MClassType
381
382 # Return a generic type based on the class
383 # Is the class is not generic, then the result is `mclass_type'
384 #
385 # REQUIRE: type_arguments.length == self.arity
386 fun get_mtype(mtype_arguments: Array[MType]): MClassType
387 do
388 assert mtype_arguments.length == self.arity
389 if self.arity == 0 then return self.mclass_type
390 for t in self.get_mtype_cache do
391 if t.arguments == mtype_arguments then
392 return t
393 end
394 end
395 var res = new MGenericType(self, mtype_arguments)
396 self.get_mtype_cache.add res
397 return res
398 end
399
400 private var get_mtype_cache: Array[MGenericType] = new Array[MGenericType]
401 end
402
403
404 # A definition (an introduction or a refinement) of a class in a module
405 #
406 # A MClassDef is associated with an explicit (or almost) definition of a
407 # class. Unlike MClass, a MClassDef is a local definition that belong to
408 # a specific module
409 class MClassDef
410 # The module where the definition is
411 var mmodule: MModule
412
413 # The associated MClass
414 var mclass: MClass
415
416 # The bounded type associated to the mclassdef
417 #
418 # For a non-generic class, `bound_mtype' and `mclass.mclass_type'
419 # are the same type.
420 #
421 # Example:
422 # For the classdef Array[E: Object], the bound_mtype is Array[Object].
423 # If you want Array[E], then see `mclass.mclass_type'
424 #
425 # ENSURE: bound_mtype.mclass = self.mclass
426 var bound_mtype: MClassType
427
428 # Name of each formal generic parameter (in order of declaration)
429 var parameter_names: Array[String]
430
431 # The origin of the definition
432 var location: Location
433
434 # Internal name combining the module and the class
435 # Example: "mymodule#MyClass"
436 redef var to_s: String
437
438 init(mmodule: MModule, bound_mtype: MClassType, location: Location, parameter_names: Array[String])
439 do
440 assert bound_mtype.mclass.arity == parameter_names.length
441 self.bound_mtype = bound_mtype
442 self.mmodule = mmodule
443 self.mclass = bound_mtype.mclass
444 self.location = location
445 mmodule.mclassdefs.add(self)
446 mclass.mclassdefs.add(self)
447 self.parameter_names = parameter_names
448 self.to_s = "{mmodule}#{mclass}"
449 end
450
451 # All declared super-types
452 # FIXME: quite ugly but not better idea yet
453 var supertypes: Array[MClassType] = new Array[MClassType]
454
455 # Register some super-types for the class (ie "super SomeType")
456 #
457 # The hierarchy must not already be set
458 # REQUIRE: self.in_hierarchy == null
459 fun set_supertypes(supertypes: Array[MClassType])
460 do
461 assert unique_invocation: self.in_hierarchy == null
462 var mmodule = self.mmodule
463 var model = mmodule.model
464 var mtype = self.bound_mtype
465
466 for supertype in supertypes do
467 self.supertypes.add(supertype)
468
469 # Register in full_type_specialization_hierarchy
470 model.full_mtype_specialization_hierarchy.add_edge(mtype, supertype)
471 # Register in intro_type_specialization_hierarchy
472 if mclass.intro_mmodule == mmodule and supertype.mclass.intro_mmodule == mmodule then
473 model.intro_mtype_specialization_hierarchy.add_edge(mtype, supertype)
474 end
475 end
476
477 end
478
479 # Collect the super-types (set by set_supertypes) to build the hierarchy
480 #
481 # This function can only invoked once by class
482 # REQUIRE: self.in_hierarchy == null
483 # ENSURE: self.in_hierarchy != null
484 fun add_in_hierarchy
485 do
486 assert unique_invocation: self.in_hierarchy == null
487 var model = mmodule.model
488 var res = model.mclassdef_hierarchy.add_node(self)
489 self.in_hierarchy = res
490 var mtype = self.bound_mtype
491
492 # Here we need to connect the mclassdef to its pairs in the mclassdef_hierarchy
493 # The simpliest way is to attach it to collect_mclassdefs
494 for mclassdef in mtype.collect_mclassdefs(mmodule) do
495 res.poset.add_edge(self, mclassdef)
496 end
497 end
498
499 # The view of the class definition in `mclassdef_hierarchy'
500 var in_hierarchy: nullable POSetElement[MClassDef] = null
501
502 # Is the definition the one that introduced `mclass`?
503 fun is_intro: Bool do return mclass.intro == self
504
505 # All properties introduced by the classdef
506 var intro_mproperties: Array[MProperty] = new Array[MProperty]
507
508 # All property definitions in the class (introductions and redefinitions)
509 var mpropdefs: Array[MPropDef] = new Array[MPropDef]
510 end
511
512 # A global static type
513 #
514 # MType are global to the model; it means that a MType is not bound to a
515 # specific `MModule`.
516 # This characteristic helps the reasoning about static types in a program
517 # since a single MType object always denote the same type.
518 #
519 # However, because a MType is global, it does not really have properties
520 # nor have subtypes to a hierarchy since the property and the class hierarchy
521 # depends of a module.
522 # Moreover, virtual types an formal generic parameter types also depends on
523 # a receiver to have sense.
524 #
525 # Therefore, most method of the types require a module and an anchor.
526 # The module is used to know what are the classes and the specialization
527 # links.
528 # The anchor is used to know what is the bound of the virtual types and formal
529 # generic parameter types.
530 #
531 # MType are not directly usable to get properties. See the `anchor_to' method
532 # and the `MClassType' class.
533 #
534 # FIXME: the order of the parameters is not the best. We mus pick on from:
535 # * foo(mmodule, anchor, othertype)
536 # * foo(othertype, anchor, mmodule)
537 # * foo(anchor, mmodule, othertype)
538 # * foo(othertype, mmodule, anchor)
539 abstract class MType
540
541 # The model of the type
542 fun model: Model is abstract
543
544 # Return true if `self' is an subtype of `sup'.
545 # The typing is done using the standard typing policy of Nit.
546 #
547 # REQUIRE: anchor == null implies not self.need_anchor and not sup.need_anchor
548 # REQUIRE: anchor != null implies self.can_resolve_for(anchor, null, mmodule) and sup.can_resolve_for(anchor, null, mmodule)
549 fun is_subtype(mmodule: MModule, anchor: nullable MClassType, sup: MType): Bool
550 do
551 var sub = self
552 if sub == sup then return true
553 if anchor == null then
554 assert not sub.need_anchor
555 assert not sup.need_anchor
556 else
557 assert sub.can_resolve_for(anchor, null, mmodule)
558 assert sup.can_resolve_for(anchor, null, mmodule)
559 end
560
561 # First, resolve the formal types to a common version in the receiver
562 # The trick here is that fixed formal type will be associed to the bound
563 # And unfixed formal types will be associed to a canonical formal type.
564 if sub isa MParameterType or sub isa MVirtualType then
565 assert anchor != null
566 sub = sub.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, false)
567 end
568 if sup isa MParameterType or sup isa MVirtualType then
569 assert anchor != null
570 sup = sup.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, false)
571 end
572
573 # Does `sup` accept null or not?
574 # Discard the nullable marker if it exists
575 var sup_accept_null = false
576 if sup isa MNullableType then
577 sup_accept_null = true
578 sup = sup.mtype
579 else if sup isa MNullType then
580 sup_accept_null = true
581 end
582
583 # Can `sub` provide null or not?
584 # Thus we can match with `sup_accept_null`
585 # Also discard the nullable marker if it exists
586 if sub isa MNullableType then
587 if not sup_accept_null then return false
588 sub = sub.mtype
589 else if sub isa MNullType then
590 return sup_accept_null
591 end
592 # Now the case of direct null and nullable is over.
593
594 # A unfixed formal type can only accept itself
595 if sup isa MParameterType or sup isa MVirtualType then
596 return sub == sup
597 end
598
599 # If `sub` is a formal type, then it is accepted if its bound is accepted
600 if sub isa MParameterType or sub isa MVirtualType then
601 assert anchor != null
602 sub = sub.anchor_to(mmodule, anchor)
603
604 # Manage the second layer of null/nullable
605 if sub isa MNullableType then
606 if not sup_accept_null then return false
607 sub = sub.mtype
608 else if sub isa MNullType then
609 return sup_accept_null
610 end
611 end
612
613 assert sub isa MClassType # It is the only remaining type
614
615 if sup isa MNullType then
616 # `sup` accepts only null
617 return false
618 end
619
620 assert sup isa MClassType # It is the only remaining type
621
622 # Now both are MClassType, we need to dig
623
624 if sub == sup then return true
625
626 if anchor == null then anchor = sub # UGLY: any anchor will work
627 var resolved_sub = sub.anchor_to(mmodule, anchor)
628 var res = resolved_sub.collect_mclasses(mmodule).has(sup.mclass)
629 if res == false then return false
630 if not sup isa MGenericType then return true
631 var sub2 = sub.supertype_to(mmodule, anchor, sup.mclass)
632 assert sub2.mclass == sup.mclass
633 for i in [0..sup.mclass.arity[ do
634 var sub_arg = sub2.arguments[i]
635 var sup_arg = sup.arguments[i]
636 res = sub_arg.is_subtype(mmodule, anchor, sup_arg)
637 if res == false then return false
638 end
639 return true
640 end
641
642 # The base class type on which self is based
643 #
644 # This base type is used to get property (an internally to perform
645 # unsafe type comparison).
646 #
647 # Beware: some types (like null) are not based on a class thus this
648 # method will crash
649 #
650 # Basically, this function transform the virtual types and parameter
651 # types to their bounds.
652 #
653 # Example
654 # class G[T: A]
655 # type U: X
656 # end
657 # class H
658 # super G[C]
659 # redef type U: Y
660 # end
661 # Map[T,U] anchor_to H #-> Map[C,Y]
662 #
663 # Explanation of the example:
664 # In H, T is set to C, because "H super G[C]", and U is bound to Y,
665 # because "redef type U: Y". Therefore, Map[T, U] is bound to
666 # Map[C, Y]
667 #
668 # ENSURE: not self.need_anchor implies return == self
669 # ENSURE: not return.need_anchor
670 fun anchor_to(mmodule: MModule, anchor: MClassType): MType
671 do
672 if not need_anchor then return self
673 assert not anchor.need_anchor
674 # Just resolve to the anchor and clear all the virtual types
675 var res = self.resolve_for(anchor, null, mmodule, true)
676 assert not res.need_anchor
677 return res
678 end
679
680 # Does `self' contain a virtual type or a formal generic parameter type?
681 # In order to remove those types, you usually want to use `anchor_to'.
682 fun need_anchor: Bool do return true
683
684 # Return the supertype when adapted to a class.
685 #
686 # In Nit, for each super-class of a type, there is a equivalent super-type.
687 #
688 # Example:
689 # class G[T, U]
690 # class H[V] super G[V, Bool]
691 # H[Int] supertype_to G #-> G[Int, Bool]
692 #
693 # REQUIRE: `super_mclass' is a super-class of `self'
694 # REQUIRE: self.need_anchor implies anchor != null and self.can_resolve_for(anchor, null, mmodule)
695 # ENSURE: return.mclass = mclass
696 fun supertype_to(mmodule: MModule, anchor: nullable MClassType, super_mclass: MClass): MClassType
697 do
698 if super_mclass.arity == 0 then return super_mclass.mclass_type
699 if self isa MClassType and self.mclass == super_mclass then return self
700 var resolved_self
701 if self.need_anchor then
702 assert anchor != null
703 resolved_self = self.anchor_to(mmodule, anchor)
704 else
705 resolved_self = self
706 end
707 var supertypes = resolved_self.collect_mtypes(mmodule)
708 for supertype in supertypes do
709 if supertype.mclass == super_mclass then
710 # FIXME: Here, we stop on the first goal. Should we check others and detect inconsistencies?
711 return supertype.resolve_for(self, anchor, mmodule, false)
712 end
713 end
714 abort
715 end
716
717 # Replace formals generic types in self with resolved values in `mtype'
718 # If `cleanup_virtual' is true, then virtual types are also replaced
719 # with their bounds
720 #
721 # This function returns self if `need_anchor' is false.
722 #
723 # ## Example 1
724 #
725 # class G[E]
726 # class H[F] super G[F]
727 # class X[Z]
728 #
729 # Array[E].resolve_for(H[Int]) #-> Array[Int]
730 # Array[E].resolve_for(G[Z], X[Int]) #-> Array[Z]
731 #
732 # Explanation of the example:
733 # * Array[E].need_anchor is true because there is a formal generic
734 # parameter type E
735 # * E makes sense for H[Int] because E is a formal parameter of G
736 # and H specialize G
737 # * Since "H[F] super G[F]", E is in fact F for H
738 # * More specifically, in H[Int], E is Int
739 # * So, in H[Int], Array[E] is Array[Int]
740 #
741 # This function is mainly used to inherit a signature.
742 # Because, unlike `anchor_to', we do not want a full resolution of
743 # a type but only an adapted version of it.
744 #
745 # ## Example 2
746 #
747 # class A[E]
748 # foo(e:E):E
749 # end
750 # class B super A[Int] end
751 #
752 # The signature on foo is (e: E): E
753 # If we resolve the signature for B, we get (e:Int):Int
754 #
755 # ## Example 3
756 #
757 # class A[E]
758 # fun foo(e:E) is abstract
759 # end
760 # class B[F]
761 # var a: A[Array[F]]
762 # fun bar do a.foo(x) # <- x is here
763 # end
764 #
765 # The first question is: is foo available on `a`?
766 #
767 # The static type of a is `A[Array[F]]`, that is an open type.
768 # in order to find a method `foo`, whe must look at a resolved type.
769 #
770 # A[Array[F]].anchor_to(B[nullable Object]) #-> A[Array[nullable Object]]
771 #
772 # the method `foo` exists in `A[Array[nullable Object]]`, therefore `foo` exists for `a`.
773 #
774 # The next question is: what is the accepted types for `x'?
775 #
776 # the signature of `foo` is `foo(e:E)`, thus we must resolve the type E
777 #
778 # E.resolve_for(A[Array[F]],B[nullable Object]) #-> Array[F]
779 #
780 # The resolution can be done because `E` make sense for the class A (see `can_resolve_for`)
781 #
782 # TODO: Explain the cleanup_virtual
783 #
784 # FIXME: the parameter `cleanup_virtual' is just a bad idea, but having
785 # two function instead of one seems also to be a bad idea.
786 #
787 # REQUIRE: can_resolve_for(mtype, anchor, mmodule)
788 # ENSURE: not self.need_anchor implies return == self
789 fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MType is abstract
790
791 # Can the type be resolved?
792 #
793 # In order to resolve open types, the formal types must make sence.
794 #
795 # ## Example
796 #
797 # class A[E]
798 # end
799 # class B[F]
800 # end
801 #
802 # E.can_resolve_for(A[Int]) #-> true, E make sense in A
803 # E.can_resolve_for(B[Int]) #-> false, E does not make sense in B
804 # B[E].can_resolve_for(A[F], B[Object]) #-> true,
805 # B[E] is a red hearing only the E is important,
806 # E make sense in A
807 #
808 # REQUIRE: anchor != null implies not anchor.need_anchor
809 # REQUIRE: mtype.need_anchor implies anchor != null and mtype.can_resolve_for(anchor, null, mmodule)
810 # ENSURE: not self.need_anchor implies return == true
811 fun can_resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule): Bool is abstract
812
813 # Return the nullable version of the type
814 # If the type is already nullable then self is returned
815 fun as_nullable: MType
816 do
817 var res = self.as_nullable_cache
818 if res != null then return res
819 res = new MNullableType(self)
820 self.as_nullable_cache = res
821 return res
822 end
823
824 private var as_nullable_cache: nullable MType = null
825
826
827 # The deph of the type seen as a tree.
828 #
829 # A -> 1
830 # G[A] -> 2
831 # H[A, B] -> 2
832 # H[G[A], B] -> 3
833 #
834 # Formal types have a depth of 1.
835 fun depth: Int
836 do
837 return 1
838 end
839
840 # The length of the type seen as a tree.
841 #
842 # A -> 1
843 # G[A] -> 2
844 # H[A, B] -> 3
845 # H[G[A], B] -> 4
846 #
847 # Formal types have a length of 1.
848 fun length: Int
849 do
850 return 1
851 end
852
853 # Compute all the classdefs inherited/imported.
854 # The returned set contains:
855 # * the class definitions from `mmodule` and its imported modules
856 # * the class definitions of this type and its super-types
857 #
858 # This function is used mainly internally.
859 #
860 # REQUIRE: not self.need_anchor
861 fun collect_mclassdefs(mmodule: MModule): Set[MClassDef] is abstract
862
863 # Compute all the super-classes.
864 # This function is used mainly internally.
865 #
866 # REQUIRE: not self.need_anchor
867 fun collect_mclasses(mmodule: MModule): Set[MClass] is abstract
868
869 # Compute all the declared super-types.
870 # Super-types are returned as declared in the classdefs (verbatim).
871 # This function is used mainly internally.
872 #
873 # REQUIRE: not self.need_anchor
874 fun collect_mtypes(mmodule: MModule): Set[MClassType] is abstract
875
876 # Is the property in self for a given module
877 # This method does not filter visibility or whatever
878 #
879 # REQUIRE: not self.need_anchor
880 fun has_mproperty(mmodule: MModule, mproperty: MProperty): Bool
881 do
882 assert not self.need_anchor
883 return self.collect_mclassdefs(mmodule).has(mproperty.intro_mclassdef)
884 end
885 end
886
887 # A type based on a class.
888 #
889 # MClassType have properties (see `has_property').
890 class MClassType
891 super MType
892
893 # The associated class
894 var mclass: MClass
895
896 redef fun model do return self.mclass.intro_mmodule.model
897
898 private init(mclass: MClass)
899 do
900 self.mclass = mclass
901 end
902
903 # The formal arguments of the type
904 # ENSURE: return.length == self.mclass.arity
905 var arguments: Array[MType] = new Array[MType]
906
907 redef fun to_s do return mclass.to_s
908
909 redef fun need_anchor do return false
910
911 redef fun anchor_to(mmodule: MModule, anchor: MClassType): MClassType
912 do
913 return super.as(MClassType)
914 end
915
916 redef fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MClassType do return self
917
918 redef fun can_resolve_for(mtype, anchor, mmodule) do return true
919
920 redef fun collect_mclassdefs(mmodule)
921 do
922 assert not self.need_anchor
923 var cache = self.collect_mclassdefs_cache
924 if not cache.has_key(mmodule) then
925 self.collect_things(mmodule)
926 end
927 return cache[mmodule]
928 end
929
930 redef fun collect_mclasses(mmodule)
931 do
932 assert not self.need_anchor
933 var cache = self.collect_mclasses_cache
934 if not cache.has_key(mmodule) then
935 self.collect_things(mmodule)
936 end
937 return cache[mmodule]
938 end
939
940 redef fun collect_mtypes(mmodule)
941 do
942 assert not self.need_anchor
943 var cache = self.collect_mtypes_cache
944 if not cache.has_key(mmodule) then
945 self.collect_things(mmodule)
946 end
947 return cache[mmodule]
948 end
949
950 # common implementation for `collect_mclassdefs', `collect_mclasses', and `collect_mtypes'.
951 private fun collect_things(mmodule: MModule)
952 do
953 var res = new HashSet[MClassDef]
954 var seen = new HashSet[MClass]
955 var types = new HashSet[MClassType]
956 seen.add(self.mclass)
957 var todo = [self.mclass]
958 while not todo.is_empty do
959 var mclass = todo.pop
960 #print "process {mclass}"
961 for mclassdef in mclass.mclassdefs do
962 if not mmodule.in_importation <= mclassdef.mmodule then continue
963 #print " process {mclassdef}"
964 res.add(mclassdef)
965 for supertype in mclassdef.supertypes do
966 types.add(supertype)
967 var superclass = supertype.mclass
968 if seen.has(superclass) then continue
969 #print " add {superclass}"
970 seen.add(superclass)
971 todo.add(superclass)
972 end
973 end
974 end
975 collect_mclassdefs_cache[mmodule] = res
976 collect_mclasses_cache[mmodule] = seen
977 collect_mtypes_cache[mmodule] = types
978 end
979
980 private var collect_mclassdefs_cache: HashMap[MModule, Set[MClassDef]] = new HashMap[MModule, Set[MClassDef]]
981 private var collect_mclasses_cache: HashMap[MModule, Set[MClass]] = new HashMap[MModule, Set[MClass]]
982 private var collect_mtypes_cache: HashMap[MModule, Set[MClassType]] = new HashMap[MModule, Set[MClassType]]
983
984 end
985
986 # A type based on a generic class.
987 # A generic type a just a class with additional formal generic arguments.
988 class MGenericType
989 super MClassType
990
991 private init(mclass: MClass, arguments: Array[MType])
992 do
993 super(mclass)
994 assert self.mclass.arity == arguments.length
995 self.arguments = arguments
996
997 self.need_anchor = false
998 for t in arguments do
999 if t.need_anchor then
1000 self.need_anchor = true
1001 break
1002 end
1003 end
1004
1005 self.to_s = "{mclass}[{arguments.join(", ")}]"
1006 end
1007
1008 # Recursively print the type of the arguments within brackets.
1009 # Example: "Map[String, List[Int]]"
1010 redef var to_s: String
1011
1012 redef var need_anchor: Bool
1013
1014 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1015 do
1016 if not need_anchor then return self
1017 assert can_resolve_for(mtype, anchor, mmodule)
1018 var types = new Array[MType]
1019 for t in arguments do
1020 types.add(t.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
1021 end
1022 return mclass.get_mtype(types)
1023 end
1024
1025 redef fun can_resolve_for(mtype, anchor, mmodule)
1026 do
1027 if not need_anchor then return true
1028 for t in arguments do
1029 if not t.can_resolve_for(mtype, anchor, mmodule) then return false
1030 end
1031 return true
1032 end
1033
1034
1035 redef fun depth
1036 do
1037 var dmax = 0
1038 for a in self.arguments do
1039 var d = a.depth
1040 if d > dmax then dmax = d
1041 end
1042 return dmax + 1
1043 end
1044
1045 redef fun length
1046 do
1047 var res = 1
1048 for a in self.arguments do
1049 res += a.length
1050 end
1051 return res
1052 end
1053 end
1054
1055 # A virtual formal type.
1056 class MVirtualType
1057 super MType
1058
1059 # The property associated with the type.
1060 # Its the definitions of this property that determine the bound or the virtual type.
1061 var mproperty: MProperty
1062
1063 redef fun model do return self.mproperty.intro_mclassdef.mmodule.model
1064
1065 # Lookup the bound for a given resolved_receiver
1066 # The result may be a other virtual type (or a parameter type)
1067 #
1068 # The result is returned exactly as declared in the "type" property (verbatim).
1069 #
1070 # In case of conflict, the method aborts.
1071 fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
1072 do
1073 assert not resolved_receiver.need_anchor
1074 var props = self.mproperty.lookup_definitions(mmodule, resolved_receiver)
1075 if props.is_empty then
1076 abort
1077 else if props.length == 1 then
1078 return props.first.as(MVirtualTypeDef).bound.as(not null)
1079 end
1080 var types = new ArraySet[MType]
1081 for p in props do
1082 types.add(p.as(MVirtualTypeDef).bound.as(not null))
1083 end
1084 if types.length == 1 then
1085 return types.first
1086 end
1087 abort
1088 end
1089
1090 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1091 do
1092 assert can_resolve_for(mtype, anchor, mmodule)
1093 # self is a virtual type declared (or inherited) in mtype
1094 # The point of the function it to get the bound of the virtual type that make sense for mtype
1095 # But because mtype is maybe a virtual/formal type, we need to get a real receiver first
1096 #print "{class_name}: {self}/{mtype}/{anchor}?"
1097 var resolved_reciever
1098 if mtype.need_anchor then
1099 assert anchor != null
1100 resolved_reciever = mtype.resolve_for(anchor, null, mmodule, true)
1101 else
1102 resolved_reciever = mtype
1103 end
1104 # Now, we can get the bound
1105 var verbatim_bound = lookup_bound(mmodule, resolved_reciever)
1106 # The bound is exactly as declared in the "type" property, so we must resolve it again
1107 var res = verbatim_bound.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1108 #print "{class_name}: {self}/{mtype}/{anchor} -> {self}/{resolved_reciever}/{anchor} -> {verbatim_bound}/{mtype}/{anchor} -> {res}"
1109
1110 # What to return here? There is a bunch a special cases:
1111 # If 'cleanup_virtual' we must return the resolved type, since we cannot return self
1112 if cleanup_virtual then return res
1113 # If the reciever is a intern class, then the virtual type cannot be redefined since there is no possible subclass. self is just fixed. so simply return the resolution
1114 if resolved_reciever isa MNullableType then resolved_reciever = resolved_reciever.mtype
1115 if resolved_reciever.as(MClassType).mclass.kind == enum_kind then return res
1116 # If the resolved type isa MVirtualType, it means that self was bound to it, and cannot be unbound. self is just fixed. so return the resolution.
1117 if res isa MVirtualType then return res
1118 # It the resolved type isa intern class, then there is no possible valid redefinition is any potentiel subclass. self is just fixed. so simply return the resolution
1119 if res isa MClassType and res.mclass.kind == enum_kind then return res
1120 # TODO: Add 'fixed' virtual type in the specification.
1121 # TODO: What if bound to a MParameterType?
1122 # Note that Nullable types can always be redefined by the non nullable version, so there is no specific case on it.
1123
1124 # If anything apply, then `self' cannot be resolved, so return self
1125 return self
1126 end
1127
1128 redef fun can_resolve_for(mtype, anchor, mmodule)
1129 do
1130 if mtype.need_anchor then
1131 assert anchor != null
1132 mtype = mtype.anchor_to(mmodule, anchor)
1133 end
1134 return mtype.has_mproperty(mmodule, mproperty)
1135 end
1136
1137 redef fun to_s do return self.mproperty.to_s
1138
1139 init(mproperty: MProperty)
1140 do
1141 self.mproperty = mproperty
1142 end
1143 end
1144
1145 # The type associated the a formal parameter generic type of a class
1146 #
1147 # Each parameter type is associated to a specific class.
1148 # It's mean that all refinements of a same class "share" the parameter type,
1149 # but that a generic subclass has its on parameter types.
1150 #
1151 # However, in the sense of the meta-model, the a parameter type of a class is
1152 # a valid types in a subclass. The "in the sense of the meta-model" is
1153 # important because, in the Nit language, the programmer cannot refers
1154 # directly to the parameter types of the super-classes.
1155 #
1156 # Example:
1157 # class A[E]
1158 # fun e: E is abstract
1159 # end
1160 # class B[F]
1161 # super A[Array[F]]
1162 # end
1163 # In the class definition B[F], `F' is a valid type but `E' is not.
1164 # However, `self.e' is a valid method call, and the signature of `e' is
1165 # declared `e: E'.
1166 #
1167 # Note that parameter types are shared among class refinements.
1168 # Therefore parameter only have an internal name (see `to_s' for details).
1169 # TODO: Add a 'name_for' to get better messages.
1170 class MParameterType
1171 super MType
1172
1173 # The generic class where the parameter belong
1174 var mclass: MClass
1175
1176 redef fun model do return self.mclass.intro_mmodule.model
1177
1178 # The position of the parameter (0 for the first parameter)
1179 # FIXME: is `position' a better name?
1180 var rank: Int
1181
1182 # Internal name of the parameter type
1183 # Names of parameter types changes in each class definition
1184 # Therefore, this method return an internal name.
1185 # Example: return "G#1" for the second parameter of the class G
1186 # FIXME: add a way to get the real name in a classdef
1187 redef fun to_s do return "{mclass}#{rank}"
1188
1189 # Resolve the bound for a given resolved_receiver
1190 # The result may be a other virtual type (or a parameter type)
1191 fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
1192 do
1193 assert not resolved_receiver.need_anchor
1194 var goalclass = self.mclass
1195 var supertypes = resolved_receiver.collect_mtypes(mmodule)
1196 for t in supertypes do
1197 if t.mclass == goalclass then
1198 # Yeah! c specialize goalclass with a "super `t'". So the question is what is the argument of f
1199 # FIXME: Here, we stop on the first goal. Should we check others and detect inconsistencies?
1200 var res = t.arguments[self.rank]
1201 return res
1202 end
1203 end
1204 abort
1205 end
1206
1207 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1208 do
1209 assert can_resolve_for(mtype, anchor, mmodule)
1210 #print "{class_name}: {self}/{mtype}/{anchor}?"
1211
1212 if mtype isa MGenericType and mtype.mclass == self.mclass then
1213 return mtype.arguments[self.rank]
1214 end
1215
1216 # self is a parameter type of mtype (or of a super-class of mtype)
1217 # The point of the function it to get the bound of the virtual type that make sense for mtype
1218 # But because mtype is maybe a virtual/formal type, we need to get a real receiver first
1219 # FIXME: What happend here is far from clear. Thus this part must be validated and clarified
1220 var resolved_receiver
1221 if mtype.need_anchor then
1222 assert anchor != null
1223 resolved_receiver = mtype.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, true)
1224 else
1225 resolved_receiver = mtype
1226 end
1227 if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
1228 if resolved_receiver isa MParameterType then
1229 assert resolved_receiver.mclass == anchor.mclass
1230 resolved_receiver = anchor.arguments[resolved_receiver.rank]
1231 if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
1232 end
1233 assert resolved_receiver isa MClassType
1234
1235 # Eh! The parameter is in the current class.
1236 # So we return the corresponding argument, no mater what!
1237 if resolved_receiver.mclass == self.mclass then
1238 var res = resolved_receiver.arguments[self.rank]
1239 #print "{class_name}: {self}/{mtype}/{anchor} -> direct {res}"
1240 return res
1241 end
1242
1243 if resolved_receiver.need_anchor then
1244 assert anchor != null
1245 resolved_receiver = resolved_receiver.resolve_for(anchor, null, mmodule, false)
1246 end
1247 # Now, we can get the bound
1248 var verbatim_bound = lookup_bound(mmodule, resolved_receiver)
1249 # The bound is exactly as declared in the "type" property, so we must resolve it again
1250 var res = verbatim_bound.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1251
1252 #print "{class_name}: {self}/{mtype}/{anchor} -> indirect {res}"
1253
1254 return res
1255 end
1256
1257 redef fun can_resolve_for(mtype, anchor, mmodule)
1258 do
1259 if mtype.need_anchor then
1260 assert anchor != null
1261 mtype = mtype.anchor_to(mmodule, anchor)
1262 end
1263 return mtype.collect_mclassdefs(mmodule).has(mclass.intro)
1264 end
1265
1266 init(mclass: MClass, rank: Int)
1267 do
1268 self.mclass = mclass
1269 self.rank = rank
1270 end
1271 end
1272
1273 # A type prefixed with "nullable"
1274 class MNullableType
1275 super MType
1276
1277 # The base type of the nullable type
1278 var mtype: MType
1279
1280 redef fun model do return self.mtype.model
1281
1282 init(mtype: MType)
1283 do
1284 self.mtype = mtype
1285 self.to_s = "nullable {mtype}"
1286 end
1287
1288 redef var to_s: String
1289
1290 redef fun need_anchor do return mtype.need_anchor
1291 redef fun as_nullable do return self
1292 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1293 do
1294 var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1295 return res.as_nullable
1296 end
1297
1298 redef fun can_resolve_for(mtype, anchor, mmodule)
1299 do
1300 return self.mtype.can_resolve_for(mtype, anchor, mmodule)
1301 end
1302
1303 redef fun depth do return self.mtype.depth
1304
1305 redef fun length do return self.mtype.length
1306
1307 redef fun collect_mclassdefs(mmodule)
1308 do
1309 assert not self.need_anchor
1310 return self.mtype.collect_mclassdefs(mmodule)
1311 end
1312
1313 redef fun collect_mclasses(mmodule)
1314 do
1315 assert not self.need_anchor
1316 return self.mtype.collect_mclasses(mmodule)
1317 end
1318
1319 redef fun collect_mtypes(mmodule)
1320 do
1321 assert not self.need_anchor
1322 return self.mtype.collect_mtypes(mmodule)
1323 end
1324 end
1325
1326 # The type of the only value null
1327 #
1328 # The is only one null type per model, see `MModel::null_type'.
1329 class MNullType
1330 super MType
1331 redef var model: Model
1332 protected init(model: Model)
1333 do
1334 self.model = model
1335 end
1336 redef fun to_s do return "null"
1337 redef fun as_nullable do return self
1338 redef fun need_anchor do return false
1339 redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
1340 redef fun can_resolve_for(mtype, anchor, mmodule) do return true
1341
1342 redef fun collect_mclassdefs(mmodule) do return new HashSet[MClassDef]
1343
1344 redef fun collect_mclasses(mmodule) do return new HashSet[MClass]
1345
1346 redef fun collect_mtypes(mmodule) do return new HashSet[MClassType]
1347 end
1348
1349 # A signature of a method (or a closure)
1350 class MSignature
1351 super MType
1352
1353 # The each parameter (in order)
1354 var mparameters: Array[MParameter]
1355
1356 var mclosures = new Array[MParameter]
1357
1358 # The return type (null for a procedure)
1359 var return_mtype: nullable MType
1360
1361 redef fun depth
1362 do
1363 var dmax = 0
1364 var t = self.return_mtype
1365 if t != null then dmax = t.depth
1366 for p in mparameters do
1367 var d = p.mtype.depth
1368 if d > dmax then dmax = d
1369 end
1370 for p in mclosures do
1371 var d = p.mtype.depth
1372 if d > dmax then dmax = d
1373 end
1374 return dmax + 1
1375 end
1376
1377 redef fun length
1378 do
1379 var res = 1
1380 var t = self.return_mtype
1381 if t != null then res += t.length
1382 for p in mparameters do
1383 res += p.mtype.length
1384 end
1385 for p in mclosures do
1386 res += p.mtype.length
1387 end
1388 return res
1389 end
1390
1391 # REQUIRE: 1 <= mparameters.count p -> p.is_vararg
1392 init(mparameters: Array[MParameter], return_mtype: nullable MType)
1393 do
1394 var vararg_rank = -1
1395 for i in [0..mparameters.length[ do
1396 var parameter = mparameters[i]
1397 if parameter.is_vararg then
1398 assert vararg_rank == -1
1399 vararg_rank = i
1400 end
1401 end
1402 self.mparameters = mparameters
1403 self.return_mtype = return_mtype
1404 self.vararg_rank = vararg_rank
1405 end
1406
1407 # The rank of the ellipsis (...) for vararg (starting from 0).
1408 # value is -1 if there is no vararg.
1409 # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
1410 var vararg_rank: Int
1411
1412 # The number or parameters
1413 fun arity: Int do return mparameters.length
1414
1415 redef fun to_s
1416 do
1417 var b = new Buffer
1418 if not mparameters.is_empty then
1419 b.append("(")
1420 for i in [0..mparameters.length[ do
1421 var mparameter = mparameters[i]
1422 if i > 0 then b.append(", ")
1423 b.append(mparameter.name)
1424 b.append(": ")
1425 b.append(mparameter.mtype.to_s)
1426 if mparameter.is_vararg then
1427 b.append("...")
1428 end
1429 end
1430 b.append(")")
1431 end
1432 var ret = self.return_mtype
1433 if ret != null then
1434 b.append(": ")
1435 b.append(ret.to_s)
1436 end
1437 return b.to_s
1438 end
1439
1440 redef fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MSignature
1441 do
1442 var params = new Array[MParameter]
1443 for p in self.mparameters do
1444 params.add(p.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
1445 end
1446 var ret = self.return_mtype
1447 if ret != null then
1448 ret = ret.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1449 end
1450 var res = new MSignature(params, ret)
1451 for p in self.mclosures do
1452 res.mclosures.add(p.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
1453 end
1454 return res
1455 end
1456 end
1457
1458 # A parameter in a signature
1459 class MParameter
1460 # The name of the parameter
1461 var name: String
1462
1463 # The static type of the parameter
1464 var mtype: MType
1465
1466 # Is the parameter a vararg?
1467 var is_vararg: Bool
1468
1469 fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MParameter
1470 do
1471 if not self.mtype.need_anchor then return self
1472 var newtype = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
1473 var res = new MParameter(self.name, newtype, self.is_vararg)
1474 return res
1475 end
1476 end
1477
1478 # A service (global property) that generalize method, attribute, etc.
1479 #
1480 # MProperty are global to the model; it means that a MProperty is not bound
1481 # to a specific `MModule` nor a specific `MClass`.
1482 #
1483 # A MProperty gather definitions (see `mpropdefs') ; one for the introduction
1484 # and the other in subclasses and in refinements.
1485 #
1486 # A MProperty is used to denotes services in polymorphic way (ie. independent
1487 # of any dynamic type).
1488 # For instance, a call site "x.foo" is associated to a MProperty.
1489 abstract class MProperty
1490 # The associated MPropDef subclass.
1491 # The two specialization hierarchy are symmetric.
1492 type MPROPDEF: MPropDef
1493
1494 # The classdef that introduce the property
1495 # While a property is not bound to a specific module, or class,
1496 # the introducing mclassdef is used for naming and visibility
1497 var intro_mclassdef: MClassDef
1498
1499 # The (short) name of the property
1500 var name: String
1501
1502 # The canonical name of the property
1503 # Example: "owner::my_module::MyClass::my_method"
1504 fun full_name: String
1505 do
1506 return "{self.intro_mclassdef.mmodule.full_name}::{self.intro_mclassdef.mclass.name}::{name}"
1507 end
1508
1509 # The visibility of the property
1510 var visibility: MVisibility
1511
1512 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1513 do
1514 self.intro_mclassdef = intro_mclassdef
1515 self.name = name
1516 self.visibility = visibility
1517 intro_mclassdef.intro_mproperties.add(self)
1518 var model = intro_mclassdef.mmodule.model
1519 model.mproperties_by_name.add_one(name, self)
1520 model.mproperties.add(self)
1521 end
1522
1523 # All definitions of the property.
1524 # The first is the introduction,
1525 # The other are redefinitions (in refinements and in subclasses)
1526 var mpropdefs: Array[MPROPDEF] = new Array[MPROPDEF]
1527
1528 # The definition that introduced the property
1529 # Warning: the introduction is the first `MPropDef' object
1530 # associated to self. If self is just created without having any
1531 # associated definition, this method will abort
1532 fun intro: MPROPDEF do return mpropdefs.first
1533
1534 # Alias for `name'
1535 redef fun to_s do return name
1536
1537 # Return the most specific property definitions defined or inherited by a type.
1538 # The selection knows that refinement is stronger than specialization;
1539 # however, in case of conflict more than one property are returned.
1540 # If mtype does not know mproperty then an empty array is returned.
1541 #
1542 # If you want the really most specific property, then look at `lookup_first_definition`
1543 fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
1544 do
1545 assert not mtype.need_anchor
1546 if mtype isa MNullableType then mtype = mtype.mtype
1547
1548 var cache = self.lookup_definitions_cache[mmodule, mtype]
1549 if cache != null then return cache
1550
1551 #print "select prop {mproperty} for {mtype} in {self}"
1552 # First, select all candidates
1553 var candidates = new Array[MPROPDEF]
1554 for mpropdef in self.mpropdefs do
1555 # If the definition is not imported by the module, then skip
1556 if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
1557 # If the definition is not inherited by the type, then skip
1558 if not mtype.is_subtype(mmodule, null, mpropdef.mclassdef.bound_mtype) then continue
1559 # Else, we keep it
1560 candidates.add(mpropdef)
1561 end
1562 # Fast track for only one candidate
1563 if candidates.length <= 1 then
1564 self.lookup_definitions_cache[mmodule, mtype] = candidates
1565 return candidates
1566 end
1567
1568 # Second, filter the most specific ones
1569 var res = new Array[MPROPDEF]
1570 for pd1 in candidates do
1571 var cd1 = pd1.mclassdef
1572 var c1 = cd1.mclass
1573 var keep = true
1574 for pd2 in candidates do
1575 if pd2 == pd1 then continue # do not compare with self!
1576 var cd2 = pd2.mclassdef
1577 var c2 = cd2.mclass
1578 if c2.mclass_type == c1.mclass_type then
1579 if cd2.mmodule.in_importation <= cd1.mmodule then
1580 # cd2 refines cd1; therefore we skip pd1
1581 keep = false
1582 break
1583 end
1584 else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
1585 # cd2 < cd1; therefore we skip pd1
1586 keep = false
1587 break
1588 end
1589 end
1590 if keep then
1591 res.add(pd1)
1592 end
1593 end
1594 if res.is_empty then
1595 print "All lost! {candidates.join(", ")}"
1596 # FIXME: should be abort!
1597 end
1598 self.lookup_definitions_cache[mmodule, mtype] = res
1599 return res
1600 end
1601
1602 private var lookup_definitions_cache: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
1603
1604 # Return the most specific property definitions inherited by a type.
1605 # The selection knows that refinement is stronger than specialization;
1606 # however, in case of conflict more than one property are returned.
1607 # If mtype does not know mproperty then an empty array is returned.
1608 #
1609 # If you want the really most specific property, then look at `lookup_next_definition`
1610 #
1611 # FIXME: Move to MPropDef?
1612 fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPropDef]
1613 do
1614 assert not mtype.need_anchor
1615 if mtype isa MNullableType then mtype = mtype.mtype
1616
1617 # First, select all candidates
1618 var candidates = new Array[MPropDef]
1619 for mpropdef in self.mpropdefs do
1620 # If the definition is not imported by the module, then skip
1621 if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
1622 # If the definition is not inherited by the type, then skip
1623 if not mtype.is_subtype(mmodule, null, mpropdef.mclassdef.bound_mtype) then continue
1624 # If the definition is defined by the type, then skip (we want the super, so e skip the current)
1625 if mtype == mpropdef.mclassdef.bound_mtype and mmodule == mpropdef.mclassdef.mmodule then continue
1626 # Else, we keep it
1627 candidates.add(mpropdef)
1628 end
1629 # Fast track for only one candidate
1630 if candidates.length <= 1 then return candidates
1631
1632 # Second, filter the most specific ones
1633 var res = new Array[MPropDef]
1634 for pd1 in candidates do
1635 var cd1 = pd1.mclassdef
1636 var c1 = cd1.mclass
1637 var keep = true
1638 for pd2 in candidates do
1639 if pd2 == pd1 then continue # do not compare with self!
1640 var cd2 = pd2.mclassdef
1641 var c2 = cd2.mclass
1642 if c2.mclass_type == c1.mclass_type then
1643 if cd2.mmodule.in_importation <= cd1.mmodule then
1644 # cd2 refines cd1; therefore we skip pd1
1645 keep = false
1646 break
1647 end
1648 else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
1649 # cd2 < cd1; therefore we skip pd1
1650 keep = false
1651 break
1652 end
1653 end
1654 if keep then
1655 res.add(pd1)
1656 end
1657 end
1658 if res.is_empty then
1659 print "All lost! {candidates.join(", ")}"
1660 # FIXME: should be abort!
1661 end
1662 return res
1663 end
1664
1665 # Return the most specific definition in the linearization of `mtype`.
1666 #
1667 # If you want to know the next properties in the linearization,
1668 # look at `MPropDef::lookup_next_definition`.
1669 #
1670 # FIXME: the linearisation is still unspecified
1671 #
1672 # REQUIRE: not mtype.need_anchor
1673 # REQUIRE: mtype.has_mproperty(mmodule, self)
1674 fun lookup_first_definition(mmodule: MModule, mtype: MType): MPROPDEF
1675 do
1676 return lookup_all_definitions(mmodule, mtype).first
1677 end
1678
1679 # Return all definitions in a linearisation order
1680 # Most speficic first, most general last
1681 fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
1682 do
1683 assert not mtype.need_anchor
1684 if mtype isa MNullableType then mtype = mtype.mtype
1685
1686 var cache = self.lookup_all_definitions_cache[mmodule, mtype]
1687 if cache != null then return cache
1688
1689 #print "select prop {mproperty} for {mtype} in {self}"
1690 # First, select all candidates
1691 var candidates = new Array[MPROPDEF]
1692 for mpropdef in self.mpropdefs do
1693 # If the definition is not imported by the module, then skip
1694 if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
1695 # If the definition is not inherited by the type, then skip
1696 if not mtype.is_subtype(mmodule, null, mpropdef.mclassdef.bound_mtype) then continue
1697 # Else, we keep it
1698 candidates.add(mpropdef)
1699 end
1700 # Fast track for only one candidate
1701 if candidates.length <= 1 then
1702 self.lookup_all_definitions_cache[mmodule, mtype] = candidates
1703 return candidates
1704 end
1705
1706 mmodule.linearize_mpropdefs(candidates)
1707 candidates = candidates.reversed
1708 self.lookup_all_definitions_cache[mmodule, mtype] = candidates
1709 return candidates
1710 end
1711
1712 private var lookup_all_definitions_cache: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
1713 end
1714
1715 # A global method
1716 class MMethod
1717 super MProperty
1718
1719 redef type MPROPDEF: MMethodDef
1720
1721 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1722 do
1723 super
1724 end
1725
1726 # Is the property a constructor?
1727 # Warning, this property can be inherited by subclasses with or without being a constructor
1728 # therefore, you should use `is_init_for' the verify if the property is a legal constructor for a given class
1729 var is_init: Bool writable = false
1730
1731 # The the property a 'new' contructor?
1732 var is_new: Bool writable = false
1733
1734 # Is the property a legal constructor for a given class?
1735 # As usual, visibility is not considered.
1736 # FIXME not implemented
1737 fun is_init_for(mclass: MClass): Bool
1738 do
1739 return self.is_init
1740 end
1741 end
1742
1743 # A global attribute
1744 class MAttribute
1745 super MProperty
1746
1747 redef type MPROPDEF: MAttributeDef
1748
1749 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1750 do
1751 super
1752 end
1753 end
1754
1755 # A global virtual type
1756 class MVirtualTypeProp
1757 super MProperty
1758
1759 redef type MPROPDEF: MVirtualTypeDef
1760
1761 init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1762 do
1763 super
1764 end
1765
1766 # The formal type associated to the virtual type property
1767 var mvirtualtype: MVirtualType = new MVirtualType(self)
1768 end
1769
1770 # A definition of a property (local property)
1771 #
1772 # Unlike MProperty, a MPropDef is a local definition that belong to a
1773 # specific class definition (which belong to a specific module)
1774 abstract class MPropDef
1775
1776 # The associated MProperty subclass.
1777 # the two specialization hierarchy are symmetric
1778 type MPROPERTY: MProperty
1779
1780 # Self class
1781 type MPROPDEF: MPropDef
1782
1783 # The origin of the definition
1784 var location: Location
1785
1786 # The class definition where the property definition is
1787 var mclassdef: MClassDef
1788
1789 # The associated global property
1790 var mproperty: MPROPERTY
1791
1792 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1793 do
1794 self.mclassdef = mclassdef
1795 self.mproperty = mproperty
1796 self.location = location
1797 mclassdef.mpropdefs.add(self)
1798 mproperty.mpropdefs.add(self)
1799 self.to_s = "{mclassdef}#{mproperty}"
1800 end
1801
1802 # Internal name combining the module, the class and the property
1803 # Example: "mymodule#MyClass#mymethod"
1804 redef var to_s: String
1805
1806 # Is self the definition that introduce the property?
1807 fun is_intro: Bool do return mproperty.intro == self
1808
1809 # Return the next definition in linearization of `mtype`.
1810 #
1811 # This method is used to determine what method is called by a super.
1812 #
1813 # REQUIRE: not mtype.need_anchor
1814 fun lookup_next_definition(mmodule: MModule, mtype: MType): MPROPDEF
1815 do
1816 assert not mtype.need_anchor
1817
1818 var mpropdefs = self.mproperty.lookup_all_definitions(mmodule, mtype)
1819 var i = mpropdefs.iterator
1820 while i.is_ok and i.item != self do i.next
1821 assert has_property: i.is_ok
1822 i.next
1823 assert has_next_property: i.is_ok
1824 return i.item
1825 end
1826 end
1827
1828 # A local definition of a method
1829 class MMethodDef
1830 super MPropDef
1831
1832 redef type MPROPERTY: MMethod
1833 redef type MPROPDEF: MMethodDef
1834
1835 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1836 do
1837 super
1838 end
1839
1840 # The signature attached to the property definition
1841 var msignature: nullable MSignature writable = null
1842
1843 # The the method definition abstract?
1844 var is_abstract: Bool writable = false
1845 end
1846
1847 # A local definition of an attribute
1848 class MAttributeDef
1849 super MPropDef
1850
1851 redef type MPROPERTY: MAttribute
1852 redef type MPROPDEF: MAttributeDef
1853
1854 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1855 do
1856 super
1857 end
1858
1859 # The static type of the attribute
1860 var static_mtype: nullable MType writable = null
1861 end
1862
1863 # A local definition of a virtual type
1864 class MVirtualTypeDef
1865 super MPropDef
1866
1867 redef type MPROPERTY: MVirtualTypeProp
1868 redef type MPROPDEF: MVirtualTypeDef
1869
1870 init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
1871 do
1872 super
1873 end
1874
1875 # The bound of the virtual type
1876 var bound: nullable MType writable = null
1877 end
1878
1879 # A kind of class.
1880 #
1881 # * abstract_kind
1882 # * concrete_kind
1883 # * interface_kind
1884 # * enum_kind
1885 # * extern_kind
1886 #
1887 # Note this class is basically an enum.
1888 # FIXME: use a real enum once user-defined enums are available
1889 class MClassKind
1890 redef var to_s: String
1891
1892 # Is a constructor required?
1893 var need_init: Bool
1894 private init(s: String, need_init: Bool)
1895 do
1896 self.to_s = s
1897 self.need_init = need_init
1898 end
1899 end
1900
1901 fun abstract_kind: MClassKind do return once new MClassKind("abstract class", true)
1902 fun concrete_kind: MClassKind do return once new MClassKind("class", true)
1903 fun interface_kind: MClassKind do return once new MClassKind("interface", false)
1904 fun enum_kind: MClassKind do return once new MClassKind("enum", false)
1905 fun extern_kind: MClassKind do return once new MClassKind("extern", false)