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