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