X-Git-Url: http://nitlanguage.org diff --git a/src/rapid_type_analysis.nit b/src/rapid_type_analysis.nit index 3655ffd..e383656 100644 --- a/src/rapid_type_analysis.nit +++ b/src/rapid_type_analysis.nit @@ -44,36 +44,31 @@ 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 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 - 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 + + var time1 = get_time + self.toolcontext.info("*** END RAPID TYPE ANALYSIS: {time1-time0} ***", 2) + return analysis end end @@ -114,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. @@ -125,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) @@ -172,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 @@ -197,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. @@ -208,6 +224,27 @@ 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 + + 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,25 +404,20 @@ 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 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 +426,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 @@ -451,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) @@ -480,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 @@ -586,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 @@ -602,12 +609,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.intro.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