src: update most tools to new constructors
[nit.git] / src / model / model.nit
index 11bdce3..f5582d8 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# Object model of the Nit language
+# Classes, types and properties
 #
-# This module define the entities of the Nit meta-model like modules,
-# classes, types and properties
+# All three concepts are defined in this same module because these are strongly connected:
+# * types are based on classes
+# * classes contains properties
+# * some properties are types (virtual types)
 #
-# It also provide an API to build and query models.
-#
-# All model classes starts with the M letter (`MModule`, `MClass`, etc.)
-#
-# TODO: better doc
-#
-# TODO: liearization, closures, extern stuff
+# TODO: liearization, extern stuff
 # FIXME: better handling of the types
 module model
 
-import poset
-import location
-import model_base
+import mmodule
+import mdoc
+import ordered_tree
 private import more_collections
 
 redef class Model
        # All known classes
-       var mclasses: Array[MClass] = new Array[MClass]
+       var mclasses = new Array[MClass]
 
        # All known properties
-       var mproperties: Array[MProperty] = new Array[MProperty]
+       var mproperties = new Array[MProperty]
 
        # Hierarchy of class definition.
        #
        # Each classdef is associated with its super-classdefs in regard to
        # its module of definition.
-       var mclassdef_hierarchy: POSet[MClassDef] = new POSet[MClassDef]
+       var mclassdef_hierarchy = new POSet[MClassDef]
 
        # Class-type hierarchy restricted to the introduction.
        #
@@ -56,7 +52,7 @@ redef class Model
        # This poset will evolve in a monotonous way:
        # * Two non connected nodes will remain unconnected
        # * New nodes can appear with new edges
-       private var intro_mtype_specialization_hierarchy: POSet[MClassType] = new POSet[MClassType]
+       private var intro_mtype_specialization_hierarchy = new POSet[MClassType]
 
        # Global overlapped class-type hierarchy.
        # The hierarchy when all modules are combined.
@@ -65,10 +61,10 @@ redef class Model
        # This poset will evolve in an anarchic way. Loops can even be created.
        #
        # FIXME decide what to do on loops
-       private var full_mtype_specialization_hierarchy: POSet[MClassType] = new POSet[MClassType]
+       private var full_mtype_specialization_hierarchy = new POSet[MClassType]
 
        # Collections of classes grouped by their short name
-       private var mclasses_by_name: MultiHashMap[String, MClass] = new MultiHashMap[String, MClass]
+       private var mclasses_by_name = new MultiHashMap[String, MClass]
 
        # Return all class named `name`.
        #
@@ -86,7 +82,7 @@ redef class Model
        end
 
        # Collections of properties grouped by their short name
-       private var mproperties_by_name: MultiHashMap[String, MProperty] = new MultiHashMap[String, MProperty]
+       private var mproperties_by_name = new MultiHashMap[String, MProperty]
 
        # Return all properties named `name`.
        #
@@ -104,16 +100,45 @@ redef class Model
        end
 
        # The only null type
-       var null_type: MNullType = new MNullType(self)
+       var null_type = new MNullType(self)
+
+       # Build an ordered tree with from `concerns`
+       fun concerns_tree(mconcerns: Collection[MConcern]): ConcernsTree do
+               var seen = new HashSet[MConcern]
+               var res = new ConcernsTree
+
+               var todo = new Array[MConcern]
+               todo.add_all mconcerns
+
+               while not todo.is_empty do
+                       var c = todo.pop
+                       if seen.has(c) then continue
+                       var pc = c.parent_concern
+                       if pc == null then
+                               res.add(null, c)
+                       else
+                               res.add(pc, c)
+                               todo.add(pc)
+                       end
+                       seen.add(c)
+               end
+
+               return res
+       end
+end
+
+# An OrderedTree that can be easily refined for display purposes
+class ConcernsTree
+       super OrderedTree[MConcern]
 end
 
 redef class MModule
        # All the classes introduced in the module
-       var intro_mclasses: Array[MClass] = new Array[MClass]
+       var intro_mclasses = new Array[MClass]
 
        # All the class definitions of the module
        # (introduction and refinement)
-       var mclassdefs: Array[MClassDef] = new Array[MClassDef]
+       var mclassdefs = new Array[MClassDef]
 
        # Does the current module has a given class `mclass`?
        # Return true if the mmodule introduces, refines or imports a class.
@@ -150,14 +175,14 @@ redef class MModule
                return res
        end
 
-       # Sort a given array of classes using the linerarization order of the module
+       # Sort a given array of classes using the linearization order of the module
        # The most general is first, the most specific is last
        fun linearize_mclasses(mclasses: Array[MClass])
        do
                self.flatten_mclass_hierarchy.sort(mclasses)
        end
 
-       # Sort a given array of class definitions using the linerarization order of the module
+       # Sort a given array of class definitions using the linearization order of the module
        # the refinement link is stronger than the specialisation link
        # The most general is first, the most specific is last
        fun linearize_mclassdefs(mclassdefs: Array[MClassDef])
@@ -166,7 +191,7 @@ redef class MModule
                sorter.sort(mclassdefs)
        end
 
-       # Sort a given array of property definitions using the linerarization order of the module
+       # Sort a given array of property definitions using the linearization order of the module
        # the refinement link is stronger than the specialisation link
        # The most general is first, the most specific is last
        fun linearize_mpropdefs(mpropdefs: Array[MPropDef])
@@ -189,6 +214,9 @@ redef class MModule
 
        private var object_type_cache: nullable MClassType
 
+       # 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
@@ -209,20 +237,34 @@ redef class MModule
                return get_primitive_class("Sys").mclass_type
        end
 
+       # The primitive type `Finalizable`
+       # Used to tag classes that need to be finalized.
+       fun finalizable_type: nullable MClassType
+       do
+               var clas = self.model.get_mclasses_by_name("Finalizable")
+               if clas == null then return null
+               return get_primitive_class("Finalizable").mclass_type
+       end
+
        # Force to get the primitive class named `name` or abort
        fun get_primitive_class(name: String): MClass
        do
                var cla = self.model.get_mclasses_by_name(name)
                if cla == null then
                        if name == "Bool" then
-                               var c = new MClass(self, name, 0, enum_kind, public_visibility)
-                               var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0), new Array[String])
+                               var c = new MClass(self, name, null, enum_kind, public_visibility)
+                               var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0))
                                return c
                        end
                        print("Fatal Error: no primitive class {name}")
                        exit(1)
                end
-               assert cla.length == 1 else print cla.join(", ")
+               if cla.length != 1 then
+                       var msg = "Fatal Error: more than one primitive class {name}:"
+                       for c in cla do msg += " {c.full_name}"
+                       print msg
+                       exit(1)
+               end
                return cla.first
        end
 
@@ -251,7 +293,8 @@ redef class MModule
 end
 
 private class MClassDefSorter
-       super AbstractSorter[MClassDef]
+       super Comparator
+       redef type COMPARED: MClassDef
        var mmodule: MModule
        redef fun compare(a, b)
        do
@@ -263,7 +306,8 @@ private class MClassDefSorter
 end
 
 private class MPropDefSorter
-       super AbstractSorter[MPropDef]
+       super Comparator
+       redef type COMPARED: MPropDef
        var mmodule: MModule
        redef fun compare(pa, pb)
        do
@@ -283,10 +327,23 @@ end
 #
 # This characteristic helps the reasoning about classes in a program since a
 # single `MClass` object always denote the same class.
-# However, because a `MClass` is global, it does not really have properties nor
-# belong to a hierarchy since the property and the
-# hierarchy of a class depends of a module.
+#
+# The drawback is that classes (`MClass`) contain almost nothing by themselves.
+# These do not really have properties nor belong to a hierarchy since the property and the
+# hierarchy of a class depends of the refinement in the modules.
+#
+# Most services on classes require the precision of a module, and no one can asks what are
+# the super-classes of a class nor what are properties of a class without precising what is
+# the module considered.
+#
+# For instance, during the typing of a source-file, the module considered is the module of the file.
+# eg. the question *is the method `foo` exists in the class `Bar`?* must be reformulated into
+# *is the method `foo` exists in the class `Bar` in the current module?*
+#
+# During some global analysis, the module considered may be the main module of the program.
 class MClass
+       super MEntity
+
        # The module that introduce the class
        # While classes are not bound to a specific module,
        # the introducing module is used for naming an visibility
@@ -294,7 +351,7 @@ class MClass
 
        # The short name of the class
        # In Nit, the name of a class cannot evolve in refinements
-       var name: String
+       redef var name: String
 
        # The canonical name of the class
        # Example: `"owner::module::MyClass"`
@@ -305,35 +362,30 @@ class MClass
 
        # The number of generic formal parameters
        # 0 if the class is not generic
-       var arity: Int
-
-       # The kind of the class (interface, abstract class, etc.)
-       # In Nit, the kind of a class cannot evolve in refinements
-       var kind: MClassKind
+       var arity: Int is noinit
 
-       # The visibility of the class
-       # In Nit, the visibility of a class cannot evolve in refinements
-       var visibility: MVisibility
+       # Each generic formal parameters in order.
+       # is empty if the class is not generic
+       var mparameters = new Array[MParameterType]
 
-       init(intro_mmodule: MModule, name: String, arity: Int, kind: MClassKind, visibility: MVisibility)
+       protected fun setup_parameter_names(parameter_names: nullable Array[String]) is
+               autoinit
        do
-               self.intro_mmodule = intro_mmodule
-               self.name = name
-               self.arity = arity
-               self.kind = kind
-               self.visibility = visibility
-               intro_mmodule.intro_mclasses.add(self)
-               var model = intro_mmodule.model
-               model.mclasses_by_name.add_one(name, self)
-               model.mclasses.add(self)
+               if parameter_names == null then
+                       self.arity = 0
+               else
+                       self.arity = parameter_names.length
+               end
 
                # Create the formal parameter types
                if arity > 0 then
+                       assert parameter_names != null
                        var mparametertypes = new Array[MParameterType]
                        for i in [0..arity[ do
-                               var mparametertype = new MParameterType(self, i)
+                               var mparametertype = new MParameterType(self, i, parameter_names[i])
                                mparametertypes.add(mparametertype)
                        end
+                       self.mparameters = mparametertypes
                        var mclass_type = new MGenericType(self, mparametertypes)
                        self.mclass_type = mclass_type
                        self.get_mtype_cache.add(mclass_type)
@@ -342,21 +394,35 @@ class MClass
                end
        end
 
+       # The kind of the class (interface, abstract class, etc.)
+       # 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
+       var visibility: MVisibility
+
+       init
+       do
+               intro_mmodule.intro_mclasses.add(self)
+               var model = intro_mmodule.model
+               model.mclasses_by_name.add_one(name, self)
+               model.mclasses.add(self)
+       end
+
+       redef fun model do return intro_mmodule.model
+
        # All class definitions (introduction and refinements)
-       var mclassdefs: Array[MClassDef] = new Array[MClassDef]
+       var mclassdefs = new Array[MClassDef]
 
        # Alias for `name`
        redef fun to_s do return self.name
 
-       # The definition that introduced the class
-       # Warning: the introduction is the first `MClassDef` object associated
-       # to self.  If self is just created without having any associated
-       # definition, this method will abort
-       fun intro: MClassDef
-       do
-               assert has_a_first_definition: not mclassdefs.is_empty
-               return mclassdefs.first
-       end
+       # The definition that introduces the class.
+       #
+       # Warning: such a definition may not exist in the early life of the object.
+       # In this case, the method will abort.
+       var intro: MClassDef is noinit
 
        # Return the class `self` in the class hierarchy of the module `mmodule`.
        #
@@ -382,7 +448,7 @@ class MClass
        # To get other types based on a generic class, see `get_mtype`.
        #
        # ENSURE: `mclass_type.mclass == self`
-       var mclass_type: MClassType
+       var mclass_type: MClassType is noinit
 
        # Return a generic type based on the class
        # Is the class is not generic, then the result is `mclass_type`
@@ -402,7 +468,7 @@ class MClass
                return res
        end
 
-       private var get_mtype_cache: Array[MGenericType] = new Array[MGenericType]
+       private var get_mtype_cache = new Array[MGenericType]
 end
 
 
@@ -410,13 +476,22 @@ end
 #
 # A `MClassDef` is associated with an explicit (or almost) definition of a
 # class. Unlike `MClass`, a `MClassDef` is a local definition that belong to
-# a specific module
+# a specific class and a specific module, and contains declarations like super-classes
+# or properties.
+#
+# It is the class definitions that are the backbone of most things in the model:
+# ClassDefs are defined with regard with other classdefs.
+# Refinement and specialization are combined to produce a big poset called the `Model::mclassdef_hierarchy`.
+#
+# Moreover, the extension and the intention of types is defined by looking at the MClassDefs.
 class MClassDef
+       super MEntity
+
        # The module where the definition is
        var mmodule: MModule
 
        # The associated `MClass`
-       var mclass: MClass
+       var mclass: MClass is noinit
 
        # The bounded type associated to the mclassdef
        #
@@ -430,32 +505,33 @@ class MClassDef
        # ENSURE: `bound_mtype.mclass == self.mclass`
        var bound_mtype: MClassType
 
-       # Name of each formal generic parameter (in order of declaration)
-       var parameter_names: Array[String]
-
        # The origin of the definition
        var location: Location
 
        # Internal name combining the module and the class
        # Example: "mymodule#MyClass"
-       redef var to_s: String
+       redef var to_s: String is noinit
 
-       init(mmodule: MModule, bound_mtype: MClassType, location: Location, parameter_names: Array[String])
+       init
        do
-               assert bound_mtype.mclass.arity == parameter_names.length
-               self.bound_mtype = bound_mtype
-               self.mmodule = mmodule
                self.mclass = bound_mtype.mclass
-               self.location = location
                mmodule.mclassdefs.add(self)
                mclass.mclassdefs.add(self)
-               self.parameter_names = parameter_names
+               if mclass.intro_mmodule == mmodule then
+                       assert not isset mclass._intro
+                       mclass.intro = self
+               end
                self.to_s = "{mmodule}#{mclass}"
        end
 
+       # Actually the name of the `mclass`
+       redef fun name do return mclass.name
+
+       redef fun model do return mmodule.model
+
        # All declared super-types
        # FIXME: quite ugly but not better idea yet
-       var supertypes: Array[MClassType] = new Array[MClassType]
+       var supertypes = new Array[MClassType]
 
        # Register some super-types for the class (ie "super SomeType")
        #
@@ -508,10 +584,10 @@ class MClassDef
        fun is_intro: Bool do return mclass.intro == self
 
        # All properties introduced by the classdef
-       var intro_mproperties: Array[MProperty] = new Array[MProperty]
+       var intro_mproperties = new Array[MProperty]
 
        # All property definitions in the class (introductions and redefinitions)
-       var mpropdefs: Array[MPropDef] = new Array[MPropDef]
+       var mpropdefs = new Array[MPropDef]
 end
 
 # A global static type
@@ -542,9 +618,9 @@ end
 #  * foo(anchor, mmodule, othertype)
 #  * foo(othertype, mmodule, anchor)
 abstract class MType
+       super MEntity
 
-       # The model of the type
-       fun model: Model is abstract
+       redef fun name do return to_s
 
        # Return true if `self` is an subtype of `sup`.
        # The typing is done using the standard typing policy of Nit.
@@ -564,8 +640,8 @@ abstract class MType
                end
 
                # First, resolve the formal types to a common version in the receiver
-               # The trick here is that fixed formal type will be associed to the bound
-               # And unfixed formal types will be associed to a canonical formal type.
+               # The trick here is that fixed formal type will be associated to the bound
+               # And unfixed formal types will be associated to a canonical formal type.
                if sub isa MParameterType or sub isa MVirtualType then
                        assert anchor != null
                        sub = sub.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, false)
@@ -725,7 +801,7 @@ abstract class MType
 
        # Replace formals generic types in self with resolved values in `mtype`
        # If `cleanup_virtual` is true, then virtual types are also replaced
-       # with their bounds
+       # with their bounds.
        #
        # This function returns self if `need_anchor` is false.
        #
@@ -786,8 +862,6 @@ abstract class MType
        #
        # The resolution can be done because `E` make sense for the class A (see `can_resolve_for`)
        #
-       # TODO: Explain the cleanup_virtual
-       #
        # FIXME: the parameter `cleanup_virtual` is just a bad idea, but having
        # two function instead of one seems also to be a bad idea.
        #
@@ -828,10 +902,20 @@ abstract class MType
                return res
        end
 
+       # Return the not nullable version of the type
+       # Is the type is already not nullable, then self is returned.
+       #
+       # Note: this just remove the `nullable` notation, but the result can still contains null.
+       # For instance if `self isa MNullType` or self is a formal type bounded by a nullable type.
+       fun as_notnullable: MType
+       do
+               return self
+       end
+
        private var as_nullable_cache: nullable MType = null
 
 
-       # The deph of the type seen as a tree.
+       # The depth of the type seen as a tree.
        #
        # * A -> 1
        # * G[A] -> 2
@@ -902,14 +986,11 @@ class MClassType
 
        redef fun model do return self.mclass.intro_mmodule.model
 
-       private init(mclass: MClass)
-       do
-               self.mclass = mclass
-       end
+       # TODO: private init because strongly bounded to its mclass. see `mclass.mclass_type`
 
        # The formal arguments of the type
        # ENSURE: `result.length == self.mclass.arity`
-       var arguments: Array[MType] = new Array[MType]
+       var arguments = new Array[MType]
 
        redef fun to_s do return mclass.to_s
 
@@ -984,9 +1065,9 @@ class MClassType
                collect_mtypes_cache[mmodule] = types
        end
 
-       private var collect_mclassdefs_cache: HashMap[MModule, Set[MClassDef]] = new HashMap[MModule, Set[MClassDef]]
-       private var collect_mclasses_cache: HashMap[MModule, Set[MClass]] = new HashMap[MModule, Set[MClass]]
-       private var collect_mtypes_cache: HashMap[MModule, Set[MClassType]] = new HashMap[MModule, Set[MClassType]]
+       private var collect_mclassdefs_cache = new HashMap[MModule, Set[MClassDef]]
+       private var collect_mclasses_cache = new HashMap[MModule, Set[MClass]]
+       private var collect_mtypes_cache = new HashMap[MModule, Set[MClassType]]
 
 end
 
@@ -995,11 +1076,13 @@ end
 class MGenericType
        super MClassType
 
-       private init(mclass: MClass, arguments: Array[MType])
+       redef var arguments
+
+       # TODO: private init because strongly bounded to its mclass. see `mclass.get_mtype`
+
+       init
        do
-               super(mclass)
                assert self.mclass.arity == arguments.length
-               self.arguments = arguments
 
                self.need_anchor = false
                for t in arguments do
@@ -1014,9 +1097,9 @@ class MGenericType
 
        # Recursively print the type of the arguments within brackets.
        # Example: `"Map[String, List[Int]]"`
-       redef var to_s: String
+       redef var to_s: String is noinit
 
-       redef var need_anchor: Bool
+       redef var need_anchor: Bool is noinit
 
        redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
        do
@@ -1094,6 +1177,20 @@ class MVirtualType
                abort
        end
 
+       # Is the virtual type fixed for a given resolved_receiver?
+       fun is_fixed(mmodule: MModule, resolved_receiver: MType): Bool
+       do
+               assert not resolved_receiver.need_anchor
+               var props = self.mproperty.lookup_definitions(mmodule, resolved_receiver)
+               if props.is_empty then
+                       abort
+               end
+               for p in props do
+                       if p.as(MVirtualTypeDef).is_fixed then return true
+               end
+               return false
+       end
+
        redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
        do
                assert can_resolve_for(mtype, anchor, mmodule)
@@ -1112,19 +1209,20 @@ class MVirtualType
                var verbatim_bound = lookup_bound(mmodule, resolved_reciever)
                # The bound is exactly as declared in the "type" property, so we must resolve it again
                var res = verbatim_bound.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
-               #print "{class_name}: {self}/{mtype}/{anchor} -> {self}/{resolved_reciever}/{anchor} -> {verbatim_bound}/{mtype}/{anchor} -> {res}"
+               #print "{class_name}: {self}/{mtype}/{anchor} -> {self}/{resolved_receiver}/{anchor} -> {verbatim_bound}/{mtype}/{anchor} -> {res}"
 
                # What to return here? There is a bunch a special cases:
                # If 'cleanup_virtual' we must return the resolved type, since we cannot return self
                if cleanup_virtual then return res
-               # 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
+               # If the receiver 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
                if resolved_reciever isa MNullableType then resolved_reciever = resolved_reciever.mtype
                if resolved_reciever.as(MClassType).mclass.kind == enum_kind then return res
                # 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.
                if res isa MVirtualType then return res
-               # 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
+               # If we are final, just return the resolution
+               if is_fixed(mmodule, resolved_reciever) then return res
+               # If the resolved type isa intern class, then there is no possible valid redefinition in any potential subclass. self is just fixed. so simply return the resolution
                if res isa MClassType and res.mclass.kind == enum_kind then return res
-               # TODO: Add 'fixed' virtual type in the specification.
                # TODO: What if bound to a MParameterType?
                # Note that Nullable types can always be redefined by the non nullable version, so there is no specific case on it.
 
@@ -1142,21 +1240,16 @@ class MVirtualType
        end
 
        redef fun to_s do return self.mproperty.to_s
-
-       init(mproperty: MProperty)
-       do
-               self.mproperty = mproperty
-       end
 end
 
-# The type associated the a formal parameter generic type of a class
+# The type associated to a formal parameter generic type of a class
 #
 # Each parameter type is associated to a specific class.
-# It's mean that all refinements of a same class "share" the parameter type,
-# but that a generic subclass has its on parameter types.
+# It means that all refinements of a same class "share" the parameter type,
+# but that a generic subclass has its own parameter types.
 #
-# However, in the sense of the meta-model, the a parameter type of a class is
-# a valid types in a subclass. The "in the sense of the meta-model" is
+# However, in the sense of the meta-model, a parameter type of a class is
+# a valid type in a subclass. The "in the sense of the meta-model" is
 # important because, in the Nit language, the programmer cannot refers
 # directly to the parameter types of the super-classes.
 #
@@ -1173,7 +1266,6 @@ end
 #
 # Note that parameter types are shared among class refinements.
 # Therefore parameter only have an internal name (see `to_s` for details).
-# TODO: Add a `name_for` to get better messages.
 class MParameterType
        super MType
 
@@ -1186,12 +1278,9 @@ class MParameterType
        # FIXME: is `position` a better name?
        var rank: Int
 
-       # Internal name of the parameter type
-       # Names of parameter types changes in each class definition
-       # Therefore, this method return an internal name.
-       # Example: return "G#1" for the second parameter of the class G
-       # FIXME: add a way to get the real name in a classdef
-       redef fun to_s do return "{mclass}#{rank}"
+       redef var name
+
+       redef fun to_s do return name
 
        # Resolve the bound for a given resolved_receiver
        # The result may be a other virtual type (or a parameter type)
@@ -1217,13 +1306,19 @@ class MParameterType
                #print "{class_name}: {self}/{mtype}/{anchor}?"
 
                if mtype isa MGenericType and mtype.mclass == self.mclass then
-                       return mtype.arguments[self.rank]
+                       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
                end
 
                # self is a parameter type of mtype (or of a super-class of mtype)
                # The point of the function it to get the bound of the virtual type that make sense for mtype
                # But because mtype is maybe a virtual/formal type, we need to get a real receiver first
-               # FIXME: What happend here is far from clear. Thus this part must be validated and clarified
+               # FIXME: What happens here is far from clear. Thus this part must be validated and clarified
                var resolved_receiver
                if mtype.need_anchor then
                        assert anchor != null
@@ -1269,12 +1364,6 @@ class MParameterType
                end
                return mtype.collect_mclassdefs(mmodule).has(mclass.intro)
        end
-
-       init(mclass: MClass, rank: Int)
-       do
-               self.mclass = mclass
-               self.rank = rank
-       end
 end
 
 # A type prefixed with "nullable"
@@ -1286,16 +1375,16 @@ class MNullableType
 
        redef fun model do return self.mtype.model
 
-       init(mtype: MType)
+       init
        do
-               self.mtype = mtype
                self.to_s = "nullable {mtype}"
        end
 
-       redef var to_s: String
+       redef var to_s: String is noinit
 
        redef fun need_anchor do return mtype.need_anchor
        redef fun as_nullable do return self
+       redef fun as_notnullable do return mtype
        redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
        do
                var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
@@ -1336,10 +1425,6 @@ end
 class MNullType
        super MType
        redef var model: Model
-       protected init(model: Model)
-       do
-               self.model = model
-       end
        redef fun to_s do return "null"
        redef fun as_nullable do return self
        redef fun need_anchor do return false
@@ -1353,15 +1438,13 @@ class MNullType
        redef fun collect_mtypes(mmodule) do return new HashSet[MClassType]
 end
 
-# A signature of a method (or a closure)
+# A signature of a method
 class MSignature
        super MType
 
        # The each parameter (in order)
        var mparameters: Array[MParameter]
 
-       var mclosures = new Array[MParameter]
-
        # The return type (null for a procedure)
        var return_mtype: nullable MType
 
@@ -1374,10 +1457,6 @@ class MSignature
                        var d = p.mtype.depth
                        if d > dmax then dmax = d
                end
-               for p in mclosures do
-                       var d = p.mtype.depth
-                       if d > dmax then dmax = d
-               end
                return dmax + 1
        end
 
@@ -1389,14 +1468,11 @@ class MSignature
                for p in mparameters do
                        res += p.mtype.length
                end
-               for p in mclosures do
-                       res += p.mtype.length
-               end
                return res
        end
 
        # REQUIRE: 1 <= mparameters.count p -> p.is_vararg
-       init(mparameters: Array[MParameter], return_mtype: nullable MType)
+       init
        do
                var vararg_rank = -1
                for i in [0..mparameters.length[ do
@@ -1406,22 +1482,20 @@ class MSignature
                                vararg_rank = i
                        end
                end
-               self.mparameters = mparameters
-               self.return_mtype = return_mtype
                self.vararg_rank = vararg_rank
        end
 
        # The rank of the ellipsis (`...`) for vararg (starting from 0).
        # value is -1 if there is no vararg.
        # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
-       var vararg_rank: Int
+       var vararg_rank: Int is noinit
 
        # The number or parameters
        fun arity: Int do return mparameters.length
 
        redef fun to_s
        do
-               var b = new Buffer
+               var b = new FlatBuffer
                if not mparameters.is_empty then
                        b.append("(")
                        for i in [0..mparameters.length[ do
@@ -1455,17 +1529,16 @@ class MSignature
                        ret = ret.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
                end
                var res = new MSignature(params, ret)
-               for p in self.mclosures do
-                       res.mclosures.add(p.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
-               end
                return res
        end
 end
 
 # A parameter in a signature
 class MParameter
+       super MEntity
+
        # The name of the parameter
-       var name: String
+       redef var name: String
 
        # The static type of the parameter
        var mtype: MType
@@ -1473,6 +1546,15 @@ class MParameter
        # Is the parameter a vararg?
        var is_vararg: Bool
 
+       redef fun to_s
+       do
+               if is_vararg then
+                       return "{name}: {mtype}..."
+               else
+                       return "{name}: {mtype}"
+               end
+       end
+
        fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MParameter
        do
                if not self.mtype.need_anchor then return self
@@ -1480,6 +1562,8 @@ class MParameter
                var res = new MParameter(self.name, newtype, self.is_vararg)
                return res
        end
+
+       redef fun model do return mtype.model
 end
 
 # A service (global property) that generalize method, attribute, etc.
@@ -1494,6 +1578,8 @@ end
 # of any dynamic type).
 # For instance, a call site "x.foo" is associated to a `MProperty`.
 abstract class MProperty
+       super MEntity
+
        # The associated MPropDef subclass.
        # The two specialization hierarchy are symmetric.
        type MPROPDEF: MPropDef
@@ -1504,7 +1590,7 @@ abstract class MProperty
        var intro_mclassdef: MClassDef
 
        # The (short) name of the property
-       var name: String
+       redef var name: String
 
        # The canonical name of the property
        # Example: "owner::my_module::MyClass::my_method"
@@ -1516,11 +1602,8 @@ abstract class MProperty
        # The visibility of the property
        var visibility: MVisibility
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
+       init
        do
-               self.intro_mclassdef = intro_mclassdef
-               self.name = name
-               self.visibility = visibility
                intro_mclassdef.intro_mproperties.add(self)
                var model = intro_mclassdef.mmodule.model
                model.mproperties_by_name.add_one(name, self)
@@ -1530,13 +1613,15 @@ abstract class MProperty
        # All definitions of the property.
        # The first is the introduction,
        # The other are redefinitions (in refinements and in subclasses)
-       var mpropdefs: Array[MPROPDEF] = new Array[MPROPDEF]
+       var mpropdefs = new Array[MPROPDEF]
 
-       # The definition that introduced the property
-       # Warning: the introduction is the first `MPropDef` object
-       # associated to self. If self is just created without having any
-       # associated definition, this method will abort
-       fun intro: MPROPDEF do return mpropdefs.first
+       # The definition that introduces the property.
+       #
+       # Warning: such a definition may not exist in the early life of the object.
+       # In this case, the method will abort.
+       var intro: MPROPDEF is noinit
+
+       redef fun model do return intro.model
 
        # Alias for `name`
        redef fun to_s do return name
@@ -1550,7 +1635,7 @@ abstract class MProperty
        fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
-               if mtype isa MNullableType then mtype = mtype.mtype
+               mtype = mtype.as_notnullable
 
                var cache = self.lookup_definitions_cache[mmodule, mtype]
                if cache != null then return cache
@@ -1573,40 +1658,10 @@ abstract class MProperty
                end
 
                # Second, filter the most specific ones
-               var res = new Array[MPROPDEF]
-               for pd1 in candidates do
-                       var cd1 = pd1.mclassdef
-                       var c1 = cd1.mclass
-                       var keep = true
-                       for pd2 in candidates do
-                               if pd2 == pd1 then continue # do not compare with self!
-                               var cd2 = pd2.mclassdef
-                               var c2 = cd2.mclass
-                               if c2.mclass_type == c1.mclass_type then
-                                       if cd2.mmodule.in_importation <= cd1.mmodule then
-                                               # cd2 refines cd1; therefore we skip pd1
-                                               keep = false
-                                               break
-                                       end
-                               else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
-                                       # cd2 < cd1; therefore we skip pd1
-                                       keep = false
-                                       break
-                               end
-                       end
-                       if keep then
-                               res.add(pd1)
-                       end
-               end
-               if res.is_empty then
-                       print "All lost! {candidates.join(", ")}"
-                       # FIXME: should be abort!
-               end
-               self.lookup_definitions_cache[mmodule, mtype] = res
-               return res
+               return select_most_specific(mmodule, candidates)
        end
 
-       private var lookup_definitions_cache: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
+       private var lookup_definitions_cache = new HashMap2[MModule, MType, Array[MPROPDEF]]
 
        # Return the most specific property definitions inherited by a type.
        # The selection knows that refinement is stronger than specialization;
@@ -1616,13 +1671,13 @@ abstract class MProperty
        # If you want the really most specific property, then look at `lookup_next_definition`
        #
        # FIXME: Move to `MPropDef`?
-       fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPropDef]
+       fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
-               if mtype isa MNullableType then mtype = mtype.mtype
+               mtype = mtype.as_notnullable
 
                # First, select all candidates
-               var candidates = new Array[MPropDef]
+               var candidates = new Array[MPROPDEF]
                for mpropdef in self.mpropdefs do
                        # If the definition is not imported by the module, then skip
                        if not mmodule.in_importation <= mpropdef.mclassdef.mmodule then continue
@@ -1637,7 +1692,14 @@ abstract class MProperty
                if candidates.length <= 1 then return candidates
 
                # Second, filter the most specific ones
-               var res = new Array[MPropDef]
+               return select_most_specific(mmodule, candidates)
+       end
+
+       # Return an array containing olny the most specific property definitions
+       # This is an helper function for `lookup_definitions` and `lookup_super_definitions`
+       private fun select_most_specific(mmodule: MModule, candidates: Array[MPROPDEF]): Array[MPROPDEF]
+       do
+               var res = new Array[MPROPDEF]
                for pd1 in candidates do
                        var cd1 = pd1.mclassdef
                        var c1 = cd1.mclass
@@ -1647,12 +1709,12 @@ abstract class MProperty
                                var cd2 = pd2.mclassdef
                                var c2 = cd2.mclass
                                if c2.mclass_type == c1.mclass_type then
-                                       if cd2.mmodule.in_importation <= cd1.mmodule then
+                                       if cd2.mmodule.in_importation < cd1.mmodule then
                                                # cd2 refines cd1; therefore we skip pd1
                                                keep = false
                                                break
                                        end
-                               else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then
+                               else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) and cd2.bound_mtype != cd1.bound_mtype then
                                        # cd2 < cd1; therefore we skip pd1
                                        keep = false
                                        break
@@ -1674,7 +1736,7 @@ abstract class MProperty
        # If you want to know the next properties in the linearization,
        # look at `MPropDef::lookup_next_definition`.
        #
-       # FIXME: the linearisation is still unspecified
+       # FIXME: the linearization is still unspecified
        #
        # REQUIRE: `not mtype.need_anchor`
        # REQUIRE: `mtype.has_mproperty(mmodule, self)`
@@ -1684,12 +1746,12 @@ abstract class MProperty
                return lookup_all_definitions(mmodule, mtype).first
        end
 
-       # Return all definitions in a linearisation order
-       # Most speficic first, most general last
+       # Return all definitions in a linearization order
+       # Most specific first, most general last
        fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
        do
                assert not mtype.need_anchor
-               if mtype isa MNullableType then mtype = mtype.mtype
+               mtype = mtype.as_notnullable
 
                var cache = self.lookup_all_definitions_cache[mmodule, mtype]
                if cache != null then return cache
@@ -1717,7 +1779,7 @@ abstract class MProperty
                return candidates
        end
 
-       private var lookup_all_definitions_cache: HashMap2[MModule, MType, Array[MPROPDEF]] = new HashMap2[MModule, MType, Array[MPROPDEF]]
+       private var lookup_all_definitions_cache = new HashMap2[MModule, MType, Array[MPROPDEF]]
 end
 
 # A global method
@@ -1726,18 +1788,20 @@ class MMethod
 
        redef type MPROPDEF: MMethodDef
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
-       do
-               super
-       end
+       # Is the property defined at the top_level of the module?
+       # Currently such a property are stored in `Object`
+       var is_toplevel: Bool = false is writable
 
        # Is the property a constructor?
        # Warning, this property can be inherited by subclasses with or without being a constructor
        # therefore, you should use `is_init_for` the verify if the property is a legal constructor for a given class
-       var is_init: Bool writable = false
+       var is_init: Bool = false is writable
 
-       # The the property a 'new' contructor?
-       var is_new: Bool writable = false
+       # The constructor is a (the) root init with empty signature but a set of initializers
+       var is_root_init: Bool = false is writable
+
+       # Is the property a 'new' constructor?
+       var is_new: Bool = false is writable
 
        # Is the property a legal constructor for a given class?
        # As usual, visibility is not considered.
@@ -1754,10 +1818,6 @@ class MAttribute
 
        redef type MPROPDEF: MAttributeDef
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
-       do
-               super
-       end
 end
 
 # A global virtual type
@@ -1766,13 +1826,8 @@ class MVirtualTypeProp
 
        redef type MPROPDEF: MVirtualTypeDef
 
-       init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
-       do
-               super
-       end
-
        # The formal type associated to the virtual type property
-       var mvirtualtype: MVirtualType = new MVirtualType(self)
+       var mvirtualtype = new MVirtualType(self)
 end
 
 # A definition of a property (local property)
@@ -1780,6 +1835,7 @@ end
 # Unlike `MProperty`, a `MPropDef` is a local definition that belong to a
 # specific class definition (which belong to a specific module)
 abstract class MPropDef
+       super MEntity
 
        # The associated `MProperty` subclass.
        # the two specialization hierarchy are symmetric
@@ -1788,28 +1844,34 @@ abstract class MPropDef
        # Self class
        type MPROPDEF: MPropDef
 
-       # The origin of the definition
-       var location: Location
-
        # The class definition where the property definition is
        var mclassdef: MClassDef
 
        # The associated global property
        var mproperty: MPROPERTY
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
+       # The origin of the definition
+       var location: Location
+
+       init
        do
-               self.mclassdef = mclassdef
-               self.mproperty = mproperty
-               self.location = location
                mclassdef.mpropdefs.add(self)
                mproperty.mpropdefs.add(self)
+               if mproperty.intro_mclassdef == mclassdef then
+                       assert not isset mproperty._intro
+                       mproperty.intro = self
+               end
                self.to_s = "{mclassdef}#{mproperty}"
        end
 
+       # Actually the name of the `mproperty`
+       redef fun name do return mproperty.name
+
+       redef fun model do return mclassdef.model
+
        # Internal name combining the module, the class and the property
        # Example: "mymodule#MyClass#mymethod"
-       redef var to_s: String
+       redef var to_s: String is noinit
 
        # Is self the definition that introduce the property?
        fun is_intro: Bool do return mproperty.intro == self
@@ -1840,16 +1902,40 @@ class MMethodDef
        redef type MPROPERTY: MMethod
        redef type MPROPDEF: MMethodDef
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
-       do
-               super
-       end
-
        # The signature attached to the property definition
-       var msignature: nullable MSignature writable = null
+       var msignature: nullable MSignature = null is writable
+
+       # The signature attached to the `new` call on a root-init
+       # This is a concatenation of the signatures of the initializers
+       #
+       # REQUIRE `mproperty.is_root_init == (new_msignature != null)`
+       var new_msignature: nullable MSignature = null is writable
+
+       # List of initialisers to call in root-inits
+       #
+       # They could be setters or attributes
+       #
+       # REQUIRE `mproperty.is_root_init == (new_msignature != null)`
+       var initializers = new Array[MProperty]
 
-       # The the method definition abstract?
-       var is_abstract: Bool writable = false
+       # Is the method definition abstract?
+       var is_abstract: Bool = false is writable
+
+       # Is the method definition intern?
+       var is_intern = false is writable
+
+       # Is the method definition extern?
+       var is_extern = false is writable
+
+       # An optional constant value returned in functions.
+       #
+       # Only some specific primitife value are accepted by engines.
+       # Is used when there is no better implementation available.
+       #
+       # Currently used only for the implementation of the `--define`
+       # command-line option.
+       # SEE: module `mixin`.
+       var constant_value: nullable Object = null is writable
 end
 
 # A local definition of an attribute
@@ -1859,13 +1945,8 @@ class MAttributeDef
        redef type MPROPERTY: MAttribute
        redef type MPROPDEF: MAttributeDef
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
-       do
-               super
-       end
-
        # The static type of the attribute
-       var static_mtype: nullable MType writable = null
+       var static_mtype: nullable MType = null is writable
 end
 
 # A local definition of a virtual type
@@ -1875,13 +1956,11 @@ class MVirtualTypeDef
        redef type MPROPERTY: MVirtualTypeProp
        redef type MPROPDEF: MVirtualTypeDef
 
-       init(mclassdef: MClassDef, mproperty: MPROPERTY, location: Location)
-       do
-               super
-       end
-
        # The bound of the virtual type
-       var bound: nullable MType writable = null
+       var bound: nullable MType = null is writable
+
+       # Is the bound fixed?
+       var is_fixed = false is writable
 end
 
 # A kind of class.
@@ -1899,15 +1978,35 @@ class MClassKind
 
        # Is a constructor required?
        var need_init: Bool
-       private init(s: String, need_init: Bool)
+
+       # TODO: private init because enumeration.
+
+       # Can a class of kind `self` specializes a class of kine `other`?
+       fun can_specialize(other: MClassKind): Bool
        do
-               self.to_s = s
-               self.need_init = need_init
+               if other == interface_kind then return true # everybody can specialize interfaces
+               if self == interface_kind or self == enum_kind then
+                       # no other case for interfaces
+                       return false
+               else if self == extern_kind then
+                       # only compatible with themselves
+                       return self == other
+               else if other == enum_kind or other == extern_kind then
+                       # abstract_kind and concrete_kind are incompatible
+                       return false
+               end
+               # remain only abstract_kind and concrete_kind
+               return true
        end
 end
 
+# The class kind `abstract`
 fun abstract_kind: MClassKind do return once new MClassKind("abstract class", true)
+# The class kind `concrete`
 fun concrete_kind: MClassKind do return once new MClassKind("class", true)
+# The class kind `interface`
 fun interface_kind: MClassKind do return once new MClassKind("interface", false)
+# The class kind `enum`
 fun enum_kind: MClassKind do return once new MClassKind("enum", false)
-fun extern_kind: MClassKind do return once new MClassKind("extern", false)
+# The class kind `extern`
+fun extern_kind: MClassKind do return once new MClassKind("extern class", false)