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