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