nitmetrics: refactor tables metrics computation
[nit.git] / src / rapid_type_analysis.nit
index 3655ffd..ed0c6fc 100644 (file)
@@ -44,35 +44,23 @@ import modelbuilder
 import typing
 import auto_super_init
 
-redef class MModule
-       var main_type: nullable MClassType
-       var main_init: nullable MMethod
-       var main_method: nullable MMethod
-end
-
 redef class ModelBuilder
        fun do_rapid_type_analysis(mainmodule: MModule): RapidTypeAnalysis
        do
                var model = self.model
                var analysis = new RapidTypeAnalysis(self, mainmodule)
                var nmodule = self.nmodules.first
-               var mainclass = self.try_get_mclass_by_name(nmodule, mainmodule, "Sys")
-               if mainclass == null then return analysis # No entry point
-               var maintype = mainclass.mclass_type
+               var maintype = mainmodule.sys_type
+               if maintype == null then return analysis # No entry point
                analysis.add_type(maintype)
-               mainmodule.main_type = maintype
-               var initprop = self.try_get_mproperty_by_name2(nmodule, mainmodule, maintype, "init")
+               var initprop = mainmodule.try_get_primitive_method("init", maintype)
                if initprop != null then
-                       assert initprop isa MMethod
                        analysis.add_monomorphic_send(maintype, initprop)
                end
-               mainmodule.main_init = initprop
-               var mainprop = self.try_get_mproperty_by_name2(nmodule, mainmodule, maintype, "main")
+               var mainprop = mainmodule.try_get_primitive_method("main", maintype)
                if mainprop != null then
-                       assert mainprop isa MMethod
                        analysis.add_monomorphic_send(maintype, mainprop)
                end
-               mainmodule.main_method = mainprop
                analysis.run_analysis
                return analysis
        end
@@ -208,6 +196,19 @@ class RapidTypeAnalysis
 
                while not todo.is_empty do
                        var mr = todo.shift
+
+                       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.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
+
                        if not self.modelbuilder.mpropdef2npropdef.has_key(mr.mmethoddef) then
                                # It is an init for a class?
                                if mr.mmethoddef.mproperty.name == "init" then
@@ -373,19 +374,7 @@ private class RapidTypeVisitor
        # Force to get the primitive class named `name' or abort
        fun get_class(name: String): MClass
        do
-               var cla = analysis.mainmodule.model.get_mclasses_by_name(name)
-               if cla == null then
-                       if name == "Bool" then
-                               var c = new MClass(analysis.mainmodule, name, 0, enum_kind, public_visibility)
-                               var cladef = new MClassDef(analysis.mainmodule, c.mclass_type, new Location(null, 0,0,0,0), new Array[String])
-                               self.add_type(c.mclass_type)
-                               return c
-                       end
-                       self.current_node.debug("Fatal Error: no primitive class {name}")
-                       abort
-               end
-               assert cla.length == 1 else print cla.join(", ")
-               return cla.first
+               return self.analysis.mainmodule.get_primitive_class(name)
        end
 
        # Force to get the primitive property named `name' in the instance `recv' or abort
@@ -394,28 +383,7 @@ private class RapidTypeVisitor
                var rapidtype = cleanup_type(recv)
                if rapidtype == null then abort
 
-               var props = self.analysis.mainmodule.model.get_mproperties_by_name(name)
-               if props == null then
-                       self.current_node.debug("Fatal Error: no primitive property {name} on {rapidtype}")
-                       abort
-               end
-               var res: nullable MMethod = null
-               for mprop in props do
-                       assert mprop isa MMethod
-                       if not rapidtype.has_mproperty(self.analysis.mainmodule, mprop) then continue
-                       if mprop.is_init and mprop.intro_mclassdef.mclass != rapidtype.mclass then continue
-                       if res == null then
-                               res = mprop
-                       else
-                               self.current_node.debug("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
-                               abort
-                       end
-               end
-               if res == null then
-                       self.current_node.debug("Fatal Error: no primitive property {name} on {rapidtype}")
-                       abort
-               end
-               return res
+               return self.analysis.modelbuilder.force_get_primitive_method(self.current_node.as(not null), name, rapidtype, self.analysis.mainmodule)
        end
 end
 
@@ -602,12 +570,20 @@ redef class AForExpr
        redef fun accept_rapid_type_vistor(v)
        do
                var recvtype = self.n_expr.mtype.as(not null)
-               var colltype = v.get_class("Collection").mclassdefs.first.bound_mtype
-               v.add_send(recvtype, v.get_method(colltype, "iterator"))
-               var iteratortype = v.get_class("Iterator").mclassdefs.first.bound_mtype
+               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 objtype = v.get_class("Object").mclass_type
                v.add_send(objtype, v.get_method(iteratortype, "is_ok"))
-               v.add_send(objtype, v.get_method(iteratortype, "item"))
+               if self.variables.length == 1 then
+                       v.add_send(objtype, v.get_method(iteratortype, "item"))
+               else if self.variables.length == 2 then
+                       v.add_send(objtype, v.get_method(iteratortype, "key"))
+                       v.add_send(objtype, v.get_method(iteratortype, "item"))
+               else
+                       abort
+               end
                v.add_send(objtype, v.get_method(iteratortype, "next"))
        end
 end