X-Git-Url: http://nitlanguage.org diff --git a/src/model/model.nit b/src/model/model.nit index 0d8d6ad..21b182e 100644 --- a/src/model/model.nit +++ b/src/model/model.nit @@ -103,6 +103,9 @@ redef class Model # The only null type var null_type = new MNullType(self) + # The only bottom type + var bottom_type: MBottomType = null_type.as_notnull + # Build an ordered tree with from `concerns` fun concerns_tree(mconcerns: Collection[MConcern]): ConcernsTree do var seen = new HashSet[MConcern] @@ -151,6 +154,14 @@ redef class MModule # (introduction and refinement) var mclassdefs = new Array[MClassDef] + private var mclassdef_sorter: MClassDefSorter is lazy do + return new MClassDefSorter(self) + end + + private var mpropdef_sorter: MPropDefSorter is lazy do + return new MPropDefSorter(self) + end + # Does the current module has a given class `mclass`? # Return true if the mmodule introduces, refines or imports a class. # Visibility is not considered. @@ -166,7 +177,7 @@ redef class MModule # Visibility is not considered. # # Note: this function is expensive and is usually used for the main - # module of a program only. Do not use it to do you own subtype + # module of a program only. Do not use it to do your own subtype # functions. fun flatten_mclass_hierarchy: POSet[MClass] do @@ -198,8 +209,7 @@ redef class MModule # The most general is first, the most specific is last fun linearize_mclassdefs(mclassdefs: Array[MClassDef]) do - var sorter = new MClassDefSorter(self) - sorter.sort(mclassdefs) + mclassdef_sorter.sort(mclassdefs) end # Sort a given array of property definitions using the linearization order of the module @@ -207,8 +217,7 @@ redef class MModule # The most general is first, the most specific is last fun linearize_mpropdefs(mpropdefs: Array[MPropDef]) do - var sorter = new MPropDefSorter(self) - sorter.sort(mpropdefs) + mpropdef_sorter.sort(mpropdefs) end private var flatten_mclass_hierarchy_cache: nullable POSet[MClass] = null @@ -352,21 +361,19 @@ private class MPropDefSorter super Comparator redef type COMPARED: MPropDef var mmodule: MModule + redef fun compare(pa, pb) do var a = pa.mclassdef var b = pb.mclassdef - var ca = a.mclass - var cb = b.mclass - if ca != cb then return mmodule.flatten_mclass_hierarchy.compare(ca, cb) - return mmodule.model.mclassdef_hierarchy.compare(a, b) + return mmodule.mclassdef_sorter.compare(a, b) end end # A named class # -# `MClass` are global to the model; it means that a `MClass` is not bound to a -# specific `MModule`. +# `MClass`es are global to the model; it means that a `MClass` is not bound +# to a specific `MModule`. # # This characteristic helps the reasoning about classes in a program since a # single `MClass` object always denote the same class. @@ -470,11 +477,13 @@ class MClass end # The kind of the class (interface, abstract class, etc.) - # In Nit, the kind of a class cannot evolve in refinements + # + # In Nit, the kind of a class cannot evolve in refinements. var kind: MClassKind # The visibility of the class - # In Nit, the visibility of a class cannot evolve in refinements + # + # In Nit, the visibility of a class cannot evolve in refinements. redef var visibility init @@ -498,12 +507,12 @@ class MClass # Warning: such a definition may not exist in the early life of the object. # In this case, the method will abort. # - # Use `try_intro` instead + # Use `try_intro` instead. var intro: MClassDef is noinit - # The definition that introduces the class or null if not yet known. + # The definition that introduces the class or `null` if not yet known. # - # See `intro` + # SEE: `intro` fun try_intro: nullable MClassDef do if isset _intro then return _intro else return null end @@ -566,7 +575,12 @@ class MClass # Is `self` and abstract class? var is_abstract: Bool is lazy do return kind == abstract_kind - redef fun mdoc_or_fallback do return intro.mdoc_or_fallback + redef fun mdoc_or_fallback + do + # Don’t use `intro.mdoc_or_fallback` because it would create an infinite + # recursion. + return intro.mdoc + end end @@ -725,6 +739,8 @@ class MClassDef # All property introductions and redefinitions (not inheritance) in `self` by its associated property. var mpropdefs_by_property = new HashMap[MProperty, MPropDef] + + redef fun mdoc_or_fallback do return mdoc or else mclass.mdoc_or_fallback end # A global static type @@ -901,12 +917,13 @@ abstract class MType # because "redef type U: Y". Therefore, Map[T, U] is bound to # Map[B, Y] # + # REQUIRE: `self.need_anchor implies anchor != null` # ENSURE: `not self.need_anchor implies result == self` # ENSURE: `not result.need_anchor` - fun anchor_to(mmodule: MModule, anchor: MClassType): MType + fun anchor_to(mmodule: MModule, anchor: nullable MClassType): MType do if not need_anchor then return self - assert not anchor.need_anchor + assert anchor != null and not anchor.need_anchor # Just resolve to the anchor and clear all the virtual types var res = self.resolve_for(anchor, null, mmodule, true) assert not res.need_anchor @@ -1136,6 +1153,7 @@ abstract class MType # * H[G[A], B] -> 3 # # Formal types have a depth of 1. + # Only `MClassType` and `MFormalType` nodes are counted. fun depth: Int do return 1 @@ -1149,6 +1167,7 @@ abstract class MType # * H[G[A], B] -> 4 # # Formal types have a length of 1. + # Only `MClassType` and `MFormalType` nodes are counted. fun length: Int do return 1 @@ -1215,7 +1234,7 @@ class MClassType redef fun need_anchor do return false - redef fun anchor_to(mmodule: MModule, anchor: MClassType): MClassType + redef fun anchor_to(mmodule, anchor): MClassType do return super.as(MClassType) end @@ -1295,6 +1314,7 @@ class MClassType private var collect_mclasses_cache = new HashMap[MModule, Set[MClass]] private var collect_mtypes_cache = new HashMap[MModule, Set[MClassType]] + redef fun mdoc_or_fallback do return mclass.mdoc_or_fallback end # A type based on a generic class. @@ -1458,8 +1478,8 @@ class MVirtualType # A VT is fixed when: # * the VT is (re-)defined with the annotation `is fixed` - # * the VT is (indirectly) bound to an enum class (see `enum_kind`) since there is no subtype possible - # * the receiver is an enum class since there is no subtype possible + # * the receiver is an enum class since there is no subtype that can + # redefine this virtual type redef fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType do assert not resolved_receiver.need_anchor @@ -1473,13 +1493,10 @@ class MVirtualType # Recursively lookup the fixed result res = res.lookup_fixed(mmodule, resolved_receiver) - # 1. For a fixed VT, return the resolved bound + # For a fixed VT, return the resolved bound if prop.is_fixed then return res - # 2. For a enum boud, return the bound - if res isa MClassType and res.mclass.kind == enum_kind then return res - - # 3. for a enum receiver return the bound + # For a enum receiver return the bound if resolved_receiver.mclass.kind == enum_kind then return res return self @@ -1525,6 +1542,8 @@ class MVirtualType redef fun full_name do return self.mproperty.full_name redef fun c_name do return self.mproperty.c_name + + redef fun mdoc_or_fallback do return mproperty.mdoc_or_fallback end # The type associated to a formal parameter generic type of a class @@ -1598,9 +1617,7 @@ class MParameterType end # A PT is fixed when: - # * Its bound is a enum class (see `enum_kind`). - # The PT is just useless, but it is still a case. - # * More usually, the `resolved_receiver` is a subclass of `self.mclass`, + # * The `resolved_receiver` is a subclass of `self.mclass`, # so it is necessarily fixed in a `super` clause, either with a normal type # or with another PT. # See `resolve_for` for examples about related issues. @@ -1619,13 +1636,7 @@ class MParameterType #print "{class_name}: {self}/{mtype}/{anchor}?" if mtype isa MGenericType and mtype.mclass == self.mclass then - var res = mtype.arguments[self.rank] - if anchor != null and res.need_anchor then - # Maybe the result can be resolved more if are bound to a final class - var r2 = res.anchor_to(mmodule, anchor) - if r2 isa MClassType and r2.mclass.kind == enum_kind then return r2 - end - return res + return mtype.arguments[self.rank] end # self is a parameter type of mtype (or of a super-class of mtype) @@ -1809,7 +1820,7 @@ class MNullType redef fun c_name do return "null" redef fun as_nullable do return self - redef var as_notnull = new MBottomType(model) is lazy + redef var as_notnull: MBottomType = new MBottomType(model) is lazy redef fun need_anchor do return false redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self redef fun can_resolve_for(mtype, anchor, mmodule) do return true @@ -2049,7 +2060,12 @@ abstract class MProperty redef var location - redef fun mdoc_or_fallback do return intro.mdoc_or_fallback + redef fun mdoc_or_fallback + do + # Don’t use `intro.mdoc_or_fallback` because it would create an infinite + # recursion. + return intro.mdoc + end # The canonical name of the property. # @@ -2471,6 +2487,8 @@ abstract class MPropDef assert has_next_property: i.is_ok return i.item end + + redef fun mdoc_or_fallback do return mdoc or else mproperty.mdoc_or_fallback end # A local definition of a method @@ -2559,7 +2577,7 @@ class MClassKind # TODO: private init because enumeration. - # Can a class of kind `self` specializes a class of kine `other`? + # Can a class of kind `self` specializes a class of kind `other`? fun can_specialize(other: MClassKind): Bool do if other == interface_kind then return true # everybody can specialize interfaces