model: make `MPropDef::is_intro` more robust
[nit.git] / src / model / model.nit
index cd1e570..941bae7 100644 (file)
@@ -206,6 +206,24 @@ redef class MModule
        # The primitive type `Int`
        var int_type: MClassType = self.get_primitive_class("Int").mclass_type is lazy
 
+       # The primitive type `Byte`
+       var byte_type: MClassType = self.get_primitive_class("Byte").mclass_type is lazy
+
+       # The primitive type `Int8`
+       var int8_type: MClassType = self.get_primitive_class("Int8").mclass_type is lazy
+
+       # The primitive type `Int16`
+       var int16_type: MClassType = self.get_primitive_class("Int16").mclass_type is lazy
+
+       # The primitive type `UInt16`
+       var uint16_type: MClassType = self.get_primitive_class("UInt16").mclass_type is lazy
+
+       # The primitive type `Int32`
+       var int32_type: MClassType = self.get_primitive_class("Int32").mclass_type is lazy
+
+       # The primitive type `UInt32`
+       var uint32_type: MClassType = self.get_primitive_class("UInt32").mclass_type is lazy
+
        # The primitive type `Char`
        var char_type: MClassType = self.get_primitive_class("Char").mclass_type is lazy
 
@@ -514,6 +532,18 @@ class MClass
 
        # Is there a `new` factory to allow the pseudo instantiation?
        var has_new_factory = false is writable
+
+       # Is `self` a standard or abstract class kind?
+       var is_class: Bool is lazy do return kind == concrete_kind or kind == abstract_kind
+
+       # Is `self` an interface kind?
+       var is_interface: Bool is lazy do return kind == interface_kind
+
+       # Is `self` an enum kind?
+       var is_enum: Bool is lazy do return kind == enum_kind
+
+       # Is `self` and abstract class?
+       var is_abstract: Bool is lazy do return kind == abstract_kind
 end
 
 
@@ -584,7 +614,7 @@ class MClassDef
                        # public gives 'p#A'
                        # private gives 'p::m#A'
                        return "{mmodule.namespace_for(mclass.visibility)}#{mclass.name}"
-               else if mclass.intro_mmodule.mproject != mmodule.mproject then
+               else if mclass.intro_mmodule.mpackage != mmodule.mpackage then
                        # public gives 'q::n#p::A'
                        # private gives 'q::n#p::m::A'
                        return "{mmodule.full_name}#{mclass.full_name}"
@@ -600,7 +630,7 @@ class MClassDef
        redef var c_name is lazy do
                if is_intro then
                        return "{mmodule.c_namespace_for(mclass.visibility)}___{mclass.c_name}"
-               else if mclass.intro_mmodule.mproject == mmodule.mproject and mclass.visibility > private_visibility then
+               else if mclass.intro_mmodule.mpackage == mmodule.mpackage and mclass.visibility > private_visibility then
                        return "{mmodule.c_name}___{mclass.name.to_cmangle}"
                else
                        return "{mmodule.c_name}___{mclass.c_name}"
@@ -1250,7 +1280,7 @@ class MGenericType
        redef var to_s: String is noinit
 
        # The full-name of the class, then the full-name of each type arguments within brackets.
-       # Example: `"standard::Map[standard::String, standard::List[standard::Int]]"`
+       # Example: `"core::Map[core::String, core::List[core::Int]]"`
        redef var full_name is lazy do
                var args = new Array[String]
                for t in arguments do
@@ -1697,8 +1727,32 @@ class MNullType
        redef fun c_name do return "null"
        redef fun as_nullable do return self
 
-       # Aborts on `null`
-       redef fun as_notnull do abort # sorry...
+       redef var as_notnull = 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
+
+       redef fun collect_mclassdefs(mmodule) do return new HashSet[MClassDef]
+
+       redef fun collect_mclasses(mmodule) do return new HashSet[MClass]
+
+       redef fun collect_mtypes(mmodule) do return new HashSet[MClassType]
+end
+
+# The special universal most specific type.
+#
+# This type is intended to be only used internally for type computation or analysis and should not be exposed to the user.
+# The bottom type can de used to denote things that are absurd, dead, or the absence of knowledge.
+#
+# Semantically it is the singleton `null.as_notnull`.
+class MBottomType
+       super MType
+       redef var model: Model
+       redef fun to_s do return "bottom"
+       redef fun full_name do return "bottom"
+       redef fun c_name do return "bottom"
+       redef fun as_nullable do return model.null_type
+       redef fun as_notnull do return self
        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
@@ -1717,6 +1771,15 @@ class MSignature
        # The each parameter (in order)
        var mparameters: Array[MParameter]
 
+       # Returns a parameter named `name`, if any.
+       fun mparameter_by_name(name: String): nullable MParameter
+       do
+               for p in mparameters do
+                       if p.name == name then return p
+               end
+               return null
+       end
+
        # The return type (null for a procedure)
        var return_mtype: nullable MType
 
@@ -1762,7 +1825,7 @@ class MSignature
        # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1
        var vararg_rank: Int is noinit
 
-       # The number or parameters
+       # The number of parameters
        fun arity: Int do return mparameters.length
 
        redef fun to_s
@@ -1869,7 +1932,7 @@ abstract class MProperty
        # The canonical name of the property.
        #
        # It is the short-`name` prefixed by the short-name of the class and the full-name of the module.
-       # Example: "my_project::my_module::MyClass::my_method"
+       # Example: "my_package::my_module::MyClass::my_method"
        redef var full_name is lazy do
                return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}"
        end
@@ -2101,6 +2164,10 @@ class MMethod
        do
                return self.is_init
        end
+
+       # A specific method that is safe to call on null.
+       # Currently, only `==`, `!=` and `is_same_instance` are safe
+       fun is_null_safe: Bool do return name == "==" or name == "!=" or name == "is_same_instance"
 end
 
 # A global attribute
@@ -2183,14 +2250,14 @@ abstract class MPropDef
                        res.append name
                else
                        # Just try to simplify each part
-                       if mclassdef.mmodule.mproject != mproperty.intro_mclassdef.mmodule.mproject then
+                       if mclassdef.mmodule.mpackage != mproperty.intro_mclassdef.mmodule.mpackage then
                                # precise "p::m" only if "p" != "r"
                                res.append mproperty.intro_mclassdef.mmodule.full_name
                                res.append "::"
                        else if mproperty.visibility <= private_visibility then
-                               # Same project ("p"=="q"), but private visibility,
+                               # Same package ("p"=="q"), but private visibility,
                                # does the module part ("::m") need to be displayed
-                               if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mproject then
+                               if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mpackage then
                                        res.append "::"
                                        res.append mproperty.intro_mclassdef.mmodule.name
                                        res.append "::"
@@ -2234,7 +2301,7 @@ abstract class MPropDef
        redef var to_s: String is noinit
 
        # Is self the definition that introduce the property?
-       fun is_intro: Bool do return mproperty.intro == self
+       fun is_intro: Bool do return isset mproperty._intro and mproperty.intro == self
 
        # Return the next definition in linearization of `mtype`.
        #