model: MGenericType::to_s add space between formal types
[nit.git] / src / model / model.nit
index 30fa17f..e029faf 100644 (file)
@@ -295,7 +295,7 @@ class MClass
        # 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
-       private fun intro: MClassDef
+       fun intro: MClassDef
        do
                assert has_a_first_definition: not mclassdefs.is_empty
                return mclassdefs.first
@@ -550,7 +550,6 @@ abstract class MType
                if not sup isa MGenericType then return true
                var sub2 = sub.supertype_to(mmodule, anchor, sup.mclass)
                assert sub2.mclass == sup.mclass
-               assert sub2 isa MGenericType
                for i in [0..sup.mclass.arity[ do
                        var sub_arg = sub2.arguments[i]
                        var sup_arg = sup.arguments[i]
@@ -684,6 +683,20 @@ abstract class MType
 
        private var as_nullable_cache: nullable MType = null
 
+
+       # The deph of the type seen as a tree.
+       #
+       # A -> 1
+       # G[A] -> 2
+       # H[A, B] -> 2
+       # H[G[A], B] -> 3
+       #
+       # Formal types have a depth of 1.
+       fun depth: Int
+       do
+               return 1
+       end
+
        # Compute all the classdefs inherited/imported.
        # The returned set contains:
        #  * the class definitions from `mmodule` and its imported modules
@@ -734,6 +747,10 @@ class MClassType
                self.mclass = mclass
        end
 
+       # The formal arguments of the type
+       # ENSURE: return.length == self.mclass.arity
+       var arguments: Array[MType] = new Array[MType]
+
        redef fun to_s do return mclass.to_s
 
        redef fun need_anchor do return false
@@ -831,15 +848,11 @@ class MGenericType
                end
        end
 
-       # The formal arguments of the type
-       # ENSURE: return.length == self.mclass.arity
-       var arguments: Array[MType]
-
        # Recursively print the type of the arguments within brackets.
-       # Example: "Map[String,List[Int]]"
+       # Example: "Map[String, List[Int]]"
        redef fun to_s
        do
-               return "{mclass}[{arguments.join(",")}]"
+               return "{mclass}[{arguments.join(", ")}]"
        end
 
        redef var need_anchor: Bool
@@ -853,6 +866,16 @@ class MGenericType
                end
                return mclass.get_mtype(types)
        end
+
+       redef fun depth
+       do
+               var dmax = 0
+               for a in self.arguments do
+                       var d = a.depth
+                       if d > dmax then dmax = d
+               end
+               return dmax + 1
+       end
 end
 
 # A virtual formal type.
@@ -969,7 +992,6 @@ class MParameterType
                        if t.mclass == goalclass then
                                # Yeah! c specialize goalclass with a "super `t'". So the question is what is the argument of f
                                # FIXME: Here, we stop on the first goal. Should we check others and detect inconsistencies?
-                               assert t isa MGenericType
                                var res = t.arguments[self.rank]
                                return res
                        end
@@ -993,7 +1015,7 @@ class MParameterType
                if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
                if resolved_receiver isa MParameterType then
                        assert resolved_receiver.mclass == anchor.mclass
-                       resolved_receiver = anchor.as(MGenericType).arguments[resolved_receiver.rank]
+                       resolved_receiver = anchor.arguments[resolved_receiver.rank]
                        if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
                end
                assert resolved_receiver isa MClassType else print "{class_name}: {self}/{mtype}/{anchor}? {resolved_receiver}"
@@ -1001,7 +1023,6 @@ class MParameterType
                # Eh! The parameter is in the current class.
                # So we return the corresponding argument, no mater what!
                if resolved_receiver.mclass == self.mclass then
-                       assert resolved_receiver isa MGenericType
                        var res = resolved_receiver.arguments[self.rank]
                        #print "{class_name}: {self}/{mtype}/{anchor} -> direct {res}"
                        return res
@@ -1050,6 +1071,8 @@ class MNullableType
                return res.as_nullable
        end
 
+       redef fun depth do return self.mtype.depth
+
        redef fun collect_mclassdefs(mmodule)
        do
                assert not self.need_anchor
@@ -1103,6 +1126,22 @@ class MSignature
        # The return type (null for a procedure)
        var return_mtype: nullable MType
 
+       redef fun depth
+       do
+               var dmax = 0
+               var t = self.return_mtype
+               if t != null then dmax = t.depth
+               for p in mparameters do
+                       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
+
        # REQUIRE: 1 <= mparameters.count p -> p.is_vararg
        init(mparameters: Array[MParameter], return_mtype: nullable MType)
        do