model: introduce MFormalType as a superclass of MVirtualType and MParameterType
[nit.git] / src / model / model.nit
index d27c429..a5aeb76 100644 (file)
@@ -195,31 +195,40 @@ redef class MModule
        private var flatten_mclass_hierarchy_cache: nullable POSet[MClass] = null
 
        # The primitive type `Object`, the root of the class hierarchy
-       fun object_type: MClassType
-       do
-               var res = self.object_type_cache
-               if res != null then return res
-               res = self.get_primitive_class("Object").mclass_type
-               self.object_type_cache = res
-               return res
-       end
-
-       private var object_type_cache: nullable MClassType
+       var object_type: MClassType = self.get_primitive_class("Object").mclass_type is lazy
 
        # The type `Pointer`, super class to all extern classes
        var pointer_type: MClassType = self.get_primitive_class("Pointer").mclass_type is lazy
 
        # The primitive type `Bool`
-       fun bool_type: MClassType
-       do
-               var res = self.bool_type_cache
-               if res != null then return res
-               res = self.get_primitive_class("Bool").mclass_type
-               self.bool_type_cache = res
-               return res
-       end
+       var bool_type: MClassType = self.get_primitive_class("Bool").mclass_type is lazy
+
+       # The primitive type `Int`
+       var int_type: MClassType = self.get_primitive_class("Int").mclass_type is lazy
+
+       # The primitive type `Char`
+       var char_type: MClassType = self.get_primitive_class("Char").mclass_type is lazy
+
+       # The primitive type `Float`
+       var float_type: MClassType = self.get_primitive_class("Float").mclass_type is lazy
+
+       # 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
+
+       # A primitive type of `Array`
+       fun array_type(elt_type: MType): MClassType do return array_class.get_mtype([elt_type])
 
-       private var bool_type_cache: nullable MClassType
+       # The primitive class `Array`
+       var array_class: MClass = self.get_primitive_class("Array") is lazy
+
+       # A primitive type of `NativeArray`
+       fun native_array_type(elt_type: MType): MClassType do return native_array_class.get_mtype([elt_type])
+
+       # The primitive class `NativeArray`
+       var native_array_class: MClass = self.get_primitive_class("NativeArray") is lazy
 
        # The primitive type `Sys`, the main type of the program, if any
        fun sys_type: nullable MClassType
@@ -468,6 +477,9 @@ class MClass
        end
 
        private var get_mtype_cache = new HashMap[Array[MType], MGenericType]
+
+       # Is there a `new` factory to allow the pseudo instantiation?
+       var has_new_factory = false is writable
 end
 
 
@@ -1191,7 +1203,7 @@ class MGenericType
                for t in arguments do
                        args.add t.full_name
                end
-               return "{mclass.full_name}[{args.join(", ")}]}"
+               return "{mclass.full_name}[{args.join(", ")}]"
        end
 
        redef var c_name is lazy do
@@ -1247,9 +1259,17 @@ class MGenericType
        end
 end
 
+# A formal type (either virtual of parametric).
+#
+# The main issue with formal types is that they offer very little information on their own
+# and need a context (anchor and mmodule) to be useful.
+abstract class MFormalType
+       super MType
+end
+
 # A virtual formal type.
 class MVirtualType
-       super MType
+       super MFormalType
 
        # The property associated with the type.
        # Its the definitions of this property that determine the bound or the virtual type.
@@ -1377,7 +1397,7 @@ end
 # Note that parameter types are shared among class refinements.
 # Therefore parameter only have an internal name (see `to_s` for details).
 class MParameterType
-       super MType
+       super MFormalType
 
        # The generic class where the parameter belong
        var mclass: MClass
@@ -1757,6 +1777,9 @@ abstract class MProperty
        # The visibility of the property
        var visibility: MVisibility
 
+       # Is the property usable as an initializer?
+       var is_autoinit = false is writable
+
        init
        do
                intro_mclassdef.intro_mproperties.add(self)
@@ -1787,6 +1810,9 @@ abstract class MProperty
        # If mtype does not know mproperty then an empty array is returned.
        #
        # If you want the really most specific property, then look at `lookup_first_definition`
+       #
+       # REQUIRE: `not mtype.need_anchor` to simplify the API (no `anchor` parameter)
+       # ENSURE: `not mtype.has_mproperty(mmodule, self) == result.is_empty`
        fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
@@ -1825,7 +1851,8 @@ abstract class MProperty
        #
        # If you want the really most specific property, then look at `lookup_next_definition`
        #
-       # FIXME: Move to `MPropDef`?
+       # REQUIRE: `not mtype.need_anchor` to simplify the API (no `anchor` parameter)
+       # ENSURE: `not mtype.has_mproperty(mmodule, self) implies result.is_empty`
        fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
@@ -1893,7 +1920,7 @@ abstract class MProperty
        #
        # FIXME: the linearization is still unspecified
        #
-       # REQUIRE: `not mtype.need_anchor`
+       # REQUIRE: `not mtype.need_anchor` to simplify the API (no `anchor` parameter)
        # REQUIRE: `mtype.has_mproperty(mmodule, self)`
        fun lookup_first_definition(mmodule: MModule, mtype: MType): MPROPDEF
        do
@@ -1902,6 +1929,9 @@ abstract class MProperty
 
        # Return all definitions in a linearization order
        # Most specific first, most general last
+       #
+       # REQUIRE: `not mtype.need_anchor` to simplify the API (no `anchor` parameter)
+       # REQUIRE: `mtype.has_mproperty(mmodule, self)`
        fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                mtype = mtype.as_notnullable