sdl2: intro minimal bindings to SDL2 mixer
[nit.git] / src / model / model.nit
index 5301e50..8fb09ee 100644 (file)
@@ -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.
@@ -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
@@ -252,8 +261,8 @@ redef class MModule
        # The primitive type `String`
        var string_type: MClassType = self.get_primitive_class("String").mclass_type is lazy
 
-       # The primitive type `NativeString`
-       var native_string_type: MClassType = self.get_primitive_class("NativeString").mclass_type is lazy
+       # The primitive type `CString`
+       var c_string_type: MClassType = self.get_primitive_class("CString").mclass_type is lazy
 
        # A primitive type of `Array`
        fun array_type(elt_type: MType): MClassType do return array_class.get_mtype([elt_type])
@@ -352,14 +361,12 @@ 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
 
@@ -566,7 +573,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
 
 
@@ -603,7 +615,7 @@ class MClassDef
        # ENSURE: `bound_mtype.mclass == self.mclass`
        var bound_mtype: MClassType
 
-       redef var location: Location
+       redef var location
 
        redef fun visibility do return mclass.visibility
 
@@ -725,6 +737,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
@@ -898,15 +912,16 @@ abstract class MType
        #
        # Explanation of the example:
        # In H, T is set to B, because "H super G[B]", and U is bound to Y,
-        # because "redef type U: Y". Therefore, Map[T, U] is bound to
+       # 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
@@ -1058,8 +1073,17 @@ abstract class MType
        #
        # `MErrorType` are used in result with conflict or inconsistencies.
        #
+       # See `is_legal_in` to check conformity with generic bounds.
        fun is_ok: Bool do return true
 
+       # Is the type legal in a given `mmodule` (with an optional `anchor`)?
+       #
+       # A type is valid if:
+       #
+       # * it does not contain a `MErrorType` (see `is_ok`).
+       # * its generic formal arguments are within their bounds.
+       fun is_legal_in(mmodule: MModule, anchor: nullable MClassType): Bool do return is_ok
+
        # Can the type be resolved?
        #
        # In order to resolve open types, the formal types must make sence.
@@ -1127,6 +1151,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
@@ -1140,6 +1165,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
@@ -1206,7 +1232,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
@@ -1286,6 +1312,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.
@@ -1364,6 +1391,18 @@ class MGenericType
                return super
        end
 
+       redef fun is_legal_in(mmodule, anchor)
+       do
+               var mtype
+               if need_anchor then
+                       assert anchor != null
+                       mtype = anchor_to(mmodule, anchor)
+               else
+                       mtype = self
+               end
+               if not mtype.is_ok then return false
+               return mtype.is_subtype(mmodule, null, mtype.mclass.intro.bound_mtype)
+       end
 
        redef fun depth
        do
@@ -1407,8 +1446,10 @@ class MVirtualType
 
        redef fun model do return self.mproperty.intro_mclassdef.mmodule.model
 
-       redef fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
+       redef fun lookup_bound(mmodule, resolved_receiver)
        do
+               # There is two possible invalid cases: the vt does not exists in resolved_receiver or the bound is broken
+               if not resolved_receiver.has_mproperty(mmodule, mproperty) then return new MErrorType(model)
                return lookup_single_definition(mmodule, resolved_receiver).bound or else new MErrorType(model)
        end
 
@@ -1502,6 +1543,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
@@ -1570,7 +1613,8 @@ class MParameterType
                                return res
                        end
                end
-               abort
+               # Cannot found `self` in `resolved_receiver`
+               return new MErrorType(model)
        end
 
        # A PT is fixed when:
@@ -1685,6 +1729,8 @@ abstract class MProxyType
 
        redef fun is_ok do return mtype.is_ok
 
+       redef fun is_legal_in(mmodule, anchor) do return mtype.is_legal_in(mmodule, anchor)
+
        redef fun lookup_fixed(mmodule, resolved_receiver)
        do
                var t = mtype.lookup_fixed(mmodule, resolved_receiver)
@@ -1783,7 +1829,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
@@ -2023,7 +2069,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.
        #
@@ -2445,6 +2496,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