v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
end
return
- else if mclassdef.auto_init == mpropdef then
+ else if mclassdef.default_init == mpropdef then
var recv = arguments.first
var initializers = mpropdef.initializers
var no_init = false
- if not initializers.is_empty then
-
+ if not initializers.is_empty and not mpropdef.is_old_style_init then
var i = 1
for p in initializers do
if p isa MMethod then
v.call(superpd, arguments)
end
return null
- else if mclassdef.auto_init == mpropdef then
+ else if mclassdef.default_init == mpropdef then
var recv = arguments.first
var initializers = mpropdef.initializers
var no_init = false
- if not initializers.is_empty then
+ if not initializers.is_empty and not mpropdef.is_old_style_init then
var i = 1
for p in initializers do
if p isa MMethod then
super Visitor
var phase: AstMetricsPhase
- init(phase: AstMetricsPhase) do self.phase = phase
redef fun visit(n)
do
var typecount: Counter[MType]
- # Get a new visitor on a classef to add type count in `typecount`.
- init(modelbuilder: ModelBuilder, nclassdef: AClassdef, typecount: Counter[MType])
- do
- self.modelbuilder = modelbuilder
- self.nclassdef = nclassdef
- self.typecount = typecount
- end
-
redef fun visit(n)
do
if n isa AAnnotation then return
# All property introductions and redefinitions in `self` (not inheritance).
var mpropdefs = new Array[MPropDef]
- # The special autoinit constructor
- var auto_init: nullable MMethodDef = null is writable
+ # The special default_init constructor
+ var default_init: nullable MMethodDef = null is writable
# All property introductions and redefinitions (not inheritance) in `self` by its associated property.
var mpropdefs_by_property = new HashMap[MProperty, MPropDef]
# using this information prevents to call `init` twice.
var is_calling_init = false is writable
+ # Does the method is a old_style_init?
+ #
+ var is_old_style_init = false is writable
+
# Is the method definition abstract?
var is_abstract: Bool = false is writable
if mpropdef.mproperty.is_root_init then
assert defined_init == null
defined_init = mpropdef
- else if mpropdef.mproperty.name == "autoinit" then
- # An explicit old-style init named "init", so return
+ end
+ if mpropdef.name == "defaultinit" then
return
end
end
- if mclassdef.auto_init != null then
- return
- end
+ if mclassdef.default_init != null then return
if not nclassdef isa AStdClassdef then return
if mpropdef == null then return # Skip broken method
var sig = mpropdef.msignature
if sig == null then continue # Skip broken method
-
mparameters.add_all sig.mparameters
initializers.add(mpropdef.mproperty)
mpropdef.mproperty.is_autoinit = true
# Look for most-specific new-stype init definitions
var spropdefs = new ArraySet[MMethodDef]
for x in mclassdef.in_hierarchy.direct_greaters do
- var y = x.mclass.intro.auto_init
+ var y = x.mclass.intro.default_init
if y == null then continue
if y.is_broken or y.msignature == null then return
spropdefs.add y
end
end
else if spropdefs.not_empty then
- # Search for inherited manual autoinit
- var manual = null
- for s in spropdefs do
- if mpropdef2npropdef.has_key(s) then
- self.toolcontext.info("{mclassdef} inherits a manual autoinit {s}", 3)
- #mclassdef.autoinit = s
- #return
- manual = s
- end
- end
-
# Search the longest-one and checks for conflict
var longest = spropdefs.first
if spropdefs.length > 1 then
# part 1. find the longest list
for spd in spropdefs do
if spd.initializers.length > longest.initializers.length then longest = spd
- if spd != manual and manual != null then
- self.toolcontext.info("{mclassdef} conflict between manual autoinit {manual} and automatic autoinit {spd}.", 3)
- end
- end
- # conflict with manual autoinit?
- if longest != manual and manual != null then
- self.error(nclassdef, "Error: conflict between manual autoinit {manual} and automatic autoinit {longest}.")
end
# part 2. compare
# Check for conflict in the order of initializers
# Create a specific new autoinit constructor
do
- var mprop = new MMethod(mclassdef, "autoinit", nclassdef.location, public_visibility)
+ var mprop = new MMethod(mclassdef, "defaultinit", nclassdef.location, public_visibility)
mprop.is_init = true
var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
mpropdef.initializers.add_all(initializers)
var msignature = new MSignature(mparameters, null)
mpropdef.msignature = msignature
- mclassdef.auto_init = mpropdef
+ mclassdef.default_init = mpropdef
self.toolcontext.info("{mclassdef} gets a free auto constructor `{mpropdef}{msignature}`. {spropdefs}", 3)
mclassdef.mclass.the_root_init_mmethod = the_root_init_mmethod
end
var name: String
var amethodid = self.n_methid
var name_node: ANode
+ var is_old_style_init = false
if amethodid == null then
if n_kwinit != null then
name = "init"
name_node = n_kwinit
- if self.n_signature.n_params.not_empty or get_single_annotation("old_style_init", modelbuilder) != null then
- name = "autoinit"
+ var old_style_annot = get_single_annotation("old_style_init", modelbuilder)
+ if old_style_annot != null or self.n_signature.n_params.not_empty then
+ name = "defaultinit"
+ if old_style_annot != null then is_old_style_init = true
end
else if n_kwnew != null then
name = "new"
mclassdef.mprop2npropdef[mprop] = self
var mpropdef = new MMethodDef(mclassdef, mprop, self.location)
- if mprop.name == "autoinit" and mclassdef.is_intro then
- assert mclassdef.auto_init == null
- mclassdef.auto_init = mpropdef
+ if mpropdef.name == "defaultinit" and mclassdef.is_intro then
+ assert mclassdef.default_init == null
+ mpropdef.is_old_style_init = is_old_style_init
+ mclassdef.default_init = mpropdef
if mpropdef.is_intro then
mpropdef.initializers.add mprop
mpropdef.is_calling_init = true
var cname
if mproperty.is_init then
- if mproperty.name == "init" or mproperty.name == "new" or mproperty.name == "autoinit" then
+ if mproperty.name == "init" or mproperty.name == "new" or mproperty.name == "defaultinit" then
cname = "new_{recv_mtype.mangled_cname}"
else
cname = "new_{recv_mtype.mangled_cname}_{mproperty.short_cname}"
mmodule, mtype, meth_name )
if meth == null then
- meth_name = "autoinit"
+ meth_name = "defaultinit"
meth = toolcontext.modelbuilder.try_get_mproperty_by_name2( self,
mmodule, mtype, meth_name )
end
do
var cname
if self.is_init then
- if self.name == "init" or self.name == "new" or self.name == "autoinit" then
+ if self.name == "init" or self.name == "new" or self.name == "defaultinit" then
cname = "new_{recv_mtype.mangled_cname}"
else
cname = "new_{recv_mtype.mangled_cname}_{self.short_cname}"
if not mmethoddef.is_intro then
self.add_super_send(v.receiver, mmethoddef)
end
- else if mmethoddef.mclassdef.auto_init == mmethoddef then
- # autoinit call
+ else if mmethoddef.mclassdef.default_init == mmethoddef then
+ # default_init call
for i in mmethoddef.initializers do
if i isa MMethod then self.add_send(v.receiver, i)
end
var auto_super_inits = new Array[CallSite]
# The look for new-style super constructors (called from a old style constructor)
- var the_root_init_mmethod = modelbuilder.the_root_init_mmethod
- if the_root_init_mmethod != null and auto_super_inits.is_empty then
- var candidatedefs = the_root_init_mmethod.lookup_definitions(mmodule, anchor)
- if candidatedefs.is_empty then
- # skip broken
- is_broken = true
- return
- end
+ var candidatedefs = get_super_candidatedefs(modelbuilder)
+
+ if not candidatedefs.is_empty and auto_super_inits.is_empty then
var candidatedef = candidatedefs.first
if candidatedefs.length > 1 then
var msignature = candidatedef.msignature
msignature = msignature.resolve_for(recvtype, anchor, mmodule, true)
- if msignature.arity > 0 then
+ if msignature.arity > mpropdef.msignature.arity then
modelbuilder.error(self, "Error: cannot do an implicit constructor call to `{candidatedef}{msignature}`. Expected at least `{msignature.arity}` arguments.")
is_broken = true
return
end
- var callsite = new CallSite(hot_location, recvtype, mmodule, anchor, true, the_root_init_mmethod, candidatedef, msignature, false)
+ if candidatedef.mproperty != mpropdef.mproperty then
+ var i = 0
+ for candidat_mparameter in msignature.mparameters do
+ var actual_mparameter = mpropdef.msignature.mparameters[i]
+ if not candidat_mparameter.mtype.is_subtype(mmodule, anchor, actual_mparameter.mtype) then
+ modelbuilder.error(self, "Type Error: expected argument #{i} of type `{candidat_mparameter.mtype}`, got implicit argument `{candidat_mparameter.name}` of type `{actual_mparameter.mtype}`. Signature is {msignature}")
+ return
+ end
+ i += 1
+ end
+ end
+
+ var callsite = new CallSite(hot_location, recvtype, mmodule, anchor, true, candidatedef.mproperty, candidatedef, msignature, false)
auto_super_inits.add(callsite)
- modelbuilder.toolcontext.info("Auto-super init for {mpropdef} to {the_root_init_mmethod.full_name}", 4)
+ modelbuilder.toolcontext.info("Auto-super init for {mpropdef} to {candidatedef.full_name}", 4)
+ else if candidatedefs.is_empty then
+ # skip broken
+ is_broken = true
+ return
end
if auto_super_inits.is_empty then
modelbuilder.error(self, "Error: no constructors to call implicitly in `{mpropdef}`. Call one explicitly.")
self.auto_super_inits = auto_super_inits
end
+ # This method returns the list of possible candidates for the current definition.
+ #
+ # Warning this method supports super call from old_style_init to default_inits without signature verification!!!
+ private fun get_super_candidatedefs(modelbuilder: ModelBuilder): Array[MMethodDef]
+ do
+ var candidatedefs = new Array[MMethodDef]
+
+ var mclassdef = self.parent.as(AClassdef).mclassdef
+ if mclassdef == null or mclassdef.is_broken then return candidatedefs # skip error
+ var mpropdef = self.mpropdef
+ if mpropdef == null or mpropdef.is_broken then return candidatedefs # skip error
+ var mmodule = mpropdef.mclassdef.mmodule
+ var anchor = mclassdef.bound_mtype
+ var mproperty = mpropdef.mproperty
+
+ # The look for new-style super constructors (called from a old style constructor)
+ var the_root_init_mmethod = modelbuilder.the_root_init_mmethod
+
+ if mpropdef.is_old_style_init then
+ var superprop: nullable MMethodDef = null
+ for mclass in mclassdef.mclass.in_hierarchy(mmodule).direct_greaters do
+ candidatedefs.add(mclass.intro.default_init.as(not null))
+ end
+ else
+ candidatedefs = the_root_init_mmethod.lookup_definitions(mmodule, anchor)
+ end
+ return candidatedefs
+ end
end
redef class ANode
var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
if name == "new" and mproperty == null then
- name = "autoinit"
+ name = "defaultinit"
mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
if mproperty == null then
name = "init"
# get the constructor
var callsite
if self isa ACrangeExpr then
- callsite = v.build_callsite_by_name(self, mtype, "autoinit", false)
+ callsite = v.build_callsite_by_name(self, mtype, "defaultinit", false)
else if self isa AOrangeExpr then
callsite = v.build_callsite_by_name(self, mtype, "without_last", false)
else
end
redef class AInitExpr
- redef fun property_name do if n_args.n_exprs.is_empty then return "init" else return "autoinit"
+ redef fun property_name do if n_args.n_exprs.is_empty then return "init" else return "defaultinit"
redef fun property_node do return n_kwinit
redef fun compute_raw_arguments do return n_args.to_a
end