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
# 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.
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)
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
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.
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
do
if node == null then return
node.accept_rapid_type_vistor(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
node.visit_all(self)
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
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
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)
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
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