ni_nitdoc: added fast copy past utility to signatures.
[nit.git] / src / rapid_type_analysis.nit
index d1fbbed..e383656 100644 (file)
@@ -47,6 +47,9 @@ import auto_super_init
 redef class ModelBuilder
        fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis
        do
+               var time0 = get_time
+               self.toolcontext.info("*** RAPID TYPE ANALYSIS ***", 1)
+
                var model = self.model
                var analysis = new RapidTypeAnalysis(self, mainmodule)
                var nmodule = self.nmodules.first
@@ -62,6 +65,10 @@ redef class ModelBuilder
                        analysis.add_monomorphic_send(maintype, mainprop)
                end
                analysis.run_analysis
+
+               var time1 = get_time
+               self.toolcontext.info("*** END RAPID TYPE ANALYSIS: {time1-time0} ***", 2)
+
                return analysis
        end
 end
@@ -102,6 +109,18 @@ class RapidTypeAnalysis
        # The customized method definitions that remain to visit
        private var todo: List[CustomizedMethodDef] = new List[CustomizedMethodDef]
 
+       # Adapt and remove nullable
+       # return null if we got the null type
+       fun cleanup_type(mtype: MType, recvtype: MClassType): nullable MClassType
+       do
+               mtype = mtype.anchor_to(self.mainmodule, recvtype)
+               if mtype isa MNullType then return null
+               if mtype isa MNullableType then mtype = mtype.mtype
+               assert mtype isa MClassType
+               assert not mtype.need_anchor
+               return mtype
+       end
+
        # Add a live type to the pool
        #
        # If the types is already live, then do nothing.
@@ -113,6 +132,7 @@ class RapidTypeAnalysis
 
                assert not mtype.need_anchor
                self.live_types.add(mtype)
+               self.check_depth(mtype)
 
                # Collect default attributes
                for cd in mtype.collect_mclassdefs(self.mainmodule)
@@ -160,10 +180,9 @@ class RapidTypeAnalysis
        fun add_monomorphic_send(mtype: MClassType, mmethod: MMethod)
        do
                assert self.live_types.has(mtype)
-               var defs = mmethod.lookup_definitions(self.mainmodule, mtype)
-               if defs.is_empty then return
-               assert defs.length == 1 else print "conflict on {mtype} for {mmethod}: {defs.join(" ")}"
-               self.add_static_call(mtype, defs.first)
+               if not mtype.has_mproperty(self.mainmodule, mmethod) then return
+               var def = mmethod.lookup_first_definition(self.mainmodule, mtype)
+               self.add_static_call(mtype, def)
        end
 
        # Add a customized_methoddefs to the pool
@@ -185,6 +204,15 @@ class RapidTypeAnalysis
 
                assert not mtype.need_anchor
                self.live_cast_types.add(mtype)
+               self.check_depth(mtype)
+       end
+
+       fun check_depth(mtype: MClassType)
+       do
+               var d = mtype.depth
+               if d > 255 then
+                       self.modelbuilder.toolcontext.fatal_error(null, "Fatal error: limitation in the rapidtype analysis engine: a type depth of {d} is too important, the problematic type is {mtype}.")
+               end
        end
 
        # Run the analysis until all visitable method definitions are visited.
@@ -199,15 +227,24 @@ class RapidTypeAnalysis
 
                        var vararg_rank = mr.mmethoddef.msignature.vararg_rank
                        if vararg_rank > -1 then
+                               var node = self.modelbuilder.mpropdef2npropdef[mr.mmethoddef]
                                var elttype = mr.mmethoddef.msignature.mparameters[vararg_rank].mtype
                                elttype = elttype.anchor_to(self.mainmodule, mr.receiver)
                                var vararg = self.mainmodule.get_primitive_class("Array").get_mtype([elttype])
                                self.add_type(vararg)
-                               self.add_monomorphic_send(vararg, self.mainmodule.force_get_primitive_method("with_native", vararg))
+                               self.add_monomorphic_send(vararg, self.modelbuilder.force_get_primitive_method(node, "with_native", vararg, self.mainmodule))
                                var native = self.mainmodule.get_primitive_class("NativeArray").get_mtype([elttype])
                                self.add_type(native)
                        end
 
+                       for i in [0..mr.mmethoddef.msignature.arity[ do
+                               var origtype = mr.mmethoddef.mproperty.intro.msignature.mparameters[i].mtype
+                               if not origtype.need_anchor then continue # skip non covariant stuff
+                               var paramtype = mr.mmethoddef.msignature.mparameters[i].mtype
+                               paramtype = self.cleanup_type(paramtype, mr.receiver).as(not null)
+                               self.add_cast_type(paramtype)
+                       end
+
                        if not self.modelbuilder.mpropdef2npropdef.has_key(mr.mmethoddef) then
                                # It is an init for a class?
                                if mr.mmethoddef.mproperty.name == "init" then
@@ -367,7 +404,14 @@ private class RapidTypeVisitor
        do
                if node == null then return
                node.accept_rapid_type_vistor(self)
-               node.visit_all(self)
+               if node isa AExpr then
+                       var implicit_cast_to = node.implicit_cast_to
+                       if implicit_cast_to != null then self.add_cast_type(implicit_cast_to)
+               end
+               # RTA does not enter in AAnnotations
+               if not node isa AAnnotations then
+                       node.visit_all(self)
+               end
        end
 
        # Force to get the primitive class named `name' or abort
@@ -382,7 +426,7 @@ private class RapidTypeVisitor
                var rapidtype = cleanup_type(recv)
                if rapidtype == null then abort
 
-               return self.analysis.mainmodule.force_get_primitive_method(name, rapidtype)
+               return self.analysis.modelbuilder.force_get_primitive_method(self.current_node.as(not null), name, rapidtype, self.analysis.mainmodule)
        end
 end
 
@@ -418,9 +462,9 @@ end
 redef class AArrayExpr
        redef fun accept_rapid_type_vistor(v)
        do
-               var mtype = self.mtype.as(not null)
+               var mtype = self.mtype.as(MClassType)
                v.add_type(mtype)
-               var native = v.get_class("NativeArray").get_mtype([mtype.as(MGenericType).arguments.first])
+               var native = v.get_class("NativeArray").get_mtype([mtype.arguments.first])
                v.add_type(native)
                var prop = v.get_method(mtype, "with_native")
                v.add_monomorphic_send(mtype, prop)
@@ -447,6 +491,8 @@ redef class ASuperstringExpr
                v.add_type(v.get_class("NativeArray").get_mtype([v.get_class("Object").mclass_type]))
                var prop = v.get_method(arraytype, "join")
                v.add_monomorphic_send(arraytype, prop)
+               var prop2 = v.get_method(arraytype, "with_native")
+               v.add_monomorphic_send(arraytype, prop2)
        end
 end
 
@@ -553,15 +599,9 @@ redef class ASuperExpr
                        return
                end
 
-               #FIXME: we do not want an ugly static call!
-               var mpropdef = v.mpropdef
-               var mpropdefs = mpropdef.mproperty.lookup_super_definitions(mpropdef.mclassdef.mmodule, mpropdef.mclassdef.bound_mtype)
-               if mpropdefs.length != 1 then
-                       debug("MPRODFEFS for super {mpropdef} for {v.receiver}: {mpropdefs.join(", ")}")
-               end
-               var msuperpropdef = mpropdefs.first
-               assert msuperpropdef isa MMethodDef
-               v.analysis.add_static_call(v.receiver, msuperpropdef)
+               var mpropdef = v.mpropdef.lookup_next_definition(v.analysis.mainmodule, v.receiver)
+               assert mpropdef isa MMethodDef
+               v.analysis.add_static_call(v.receiver, mpropdef)
        end
 end
 
@@ -572,7 +612,7 @@ redef class AForExpr
                var colltype = self.coltype.as(not null)
                var itmeth = v.get_method(colltype, "iterator")
                v.add_send(recvtype, itmeth)
-               var iteratortype = itmeth.intro.msignature.return_mtype.as(MClassType).mclass.mclassdefs.first.bound_mtype
+               var iteratortype = itmeth.intro.msignature.return_mtype.as(MClassType).mclass.intro.bound_mtype
                var objtype = v.get_class("Object").mclass_type
                v.add_send(objtype, v.get_method(iteratortype, "is_ok"))
                if self.variables.length == 1 then