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