process_default_constructors(nclassdef)
end
+ # the root init of the Object class
+ # Is usually implicitly defined
+ # Then explicit or implicit definitions of root-init are attached to it
+ var the_root_init_mmethod: nullable MMethod
+
# Introduce or inherit default constructor
# This is the last part of `build_properties`.
private fun process_default_constructors(nclassdef: AClassdef)
# Are we a refinement
if not mclassdef.is_intro then return
+ var mmodule = nclassdef.mclassdef.mmodule
+
+ # Look for the init in Object, or create it
+ if mclassdef.mclass.name == "Object" and the_root_init_mmethod == null then
+ # Create the implicit root-init method
+ var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+ mprop.is_root_init = true
+ var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
+ var mparameters = new Array[MParameter]
+ var msignature = new MSignature(mparameters, null)
+ mpropdef.msignature = msignature
+ mpropdef.new_msignature = msignature
+ mprop.is_init = true
+ nclassdef.mfree_init = mpropdef
+ self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
+ the_root_init_mmethod = mprop
+ return
+ end
+
# Is the class forbid constructors?
if not mclassdef.mclass.kind.need_init then return
# Is there already a constructor defined?
+ var defined_init: nullable MMethodDef = null
for mpropdef in mclassdef.mpropdefs do
if not mpropdef isa MMethodDef then continue
- if mpropdef.mproperty.is_init then return
+ if not mpropdef.mproperty.is_init then continue
+ if mpropdef.mproperty.is_root_init then
+ assert defined_init == null
+ defined_init = mpropdef
+ else
+ # An explicit old-style init, so return
+ return
+ end
end
if not nclassdef isa AStdClassdef then return
- var mmodule = mclassdef.mmodule
- # Do we inherit for a constructor?
- var combine = new Array[MMethod]
- var inhc: nullable MClass = null
- for st in mclassdef.supertypes do
+ # Do we inherit a old-style constructor?
+ var combine = new Array[MMethod] # old-style constructors without arguments
+ var inhc: nullable MClass = null # single super-class with a constructor with arguments
+ if defined_init == null then for st in mclassdef.supertypes do
var c = st.mclass
if not c.kind.need_init then continue
st = st.anchor_to(mmodule, mclassdef.bound_mtype)
var candidate = self.try_get_mproperty_by_name2(nclassdef, mmodule, st, "init").as(nullable MMethod)
if candidate != null then
+ if candidate.is_root_init then continue
if candidate.intro.msignature != null then
if candidate.intro.msignature.arity == 0 then
combine.add(candidate)
# Collect undefined attributes
var mparameters = new Array[MParameter]
+ var initializers = new Array[MProperty]
var anode: nullable ANode = null
for npropdef in nclassdef.n_propdefs do
if npropdef isa AAttrPropdef then
if ret_type == null then return
var mparameter = new MParameter(paramname, ret_type, false)
mparameters.add(mparameter)
+ var msetter = npropdef.mwritepropdef
+ if msetter == null then
+ # No setter, it is a old-style attribute, so just add it
+ initializers.add(npropdef.mpropdef.mproperty)
+ else
+ # Add the setter to the list
+ initializers.add(msetter.mproperty)
+ end
if anode == null then anode = npropdef
end
end
# TODO: actively inherit the consturctor
self.toolcontext.info("{mclassdef} inherits all constructors from {inhc}", 3)
- mclassdef.mclass.inherit_init_from = inhc
- return
+ #mclassdef.mclass.inherit_init_from = inhc
+ #return
end
if not combine.is_empty and inhc != null then
self.error(nclassdef, "Error: Cannot provide a defaut constructor: conflict for {combine.join(", ")} and {inhc}")
return
end
-
if not combine.is_empty then
if mparameters.is_empty and combine.length == 1 then
# No need to create a local init, the inherited one is enough
return
end
nclassdef.super_inits = combine
+ var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+ var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
+ var msignature = new MSignature(mparameters, null)
+ mpropdef.msignature = msignature
+ mprop.is_init = true
+ nclassdef.mfree_init = mpropdef
+ self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
+ return
+ end
+
+ if the_root_init_mmethod == null then return
+
+ # Look for nost-specific new-stype init definitions
+ var spropdefs = the_root_init_mmethod.lookup_super_definitions(mclassdef.mmodule, mclassdef.bound_mtype)
+ if spropdefs.is_empty then
+ toolcontext.fatal_error(nclassdef.location, "Fatal error: {mclassdef} does not specialize {the_root_init_mmethod.intro_mclassdef}. Possible duplication of the root class `Object`?")
end
- var mprop = new MMethod(mclassdef, "init", mclassdef.mclass.visibility)
+ # Search the longest-one and checks for conflict
+ var longest = spropdefs.first
+ if spropdefs.length > 1 then
+ # Check for conflict in the order of initializers
+ # Each initializer list must me a prefix of the longest list
+ # part 1. find the longest list
+ for spd in spropdefs do
+ if spd.initializers.length > longest.initializers.length then longest = spd
+ end
+ # part 2. compare
+ for spd in spropdefs do
+ var i = 0
+ for p in spd.initializers do
+ if p != longest.initializers[i] then
+ self.error(nclassdef, "Error: conflict for inherited inits {spd}({spd.initializers.join(", ")}) and {longest}({longest.initializers.join(", ")})")
+ return
+ end
+ i += 1
+ end
+ end
+ end
+
+ # Can we just inherit?
+ if spropdefs.length == 1 and mparameters.is_empty and defined_init == null then
+ self.toolcontext.info("{mclassdef} inherits the basic constructor {longest}", 3)
+ return
+ end
+
+ # Combine the inherited list to what is collected
+ if longest.initializers.length > 0 then
+ mparameters.prepend longest.new_msignature.mparameters
+ initializers.prepend longest.initializers
+ end
+
+ # If we already have a basic init definition, then setup its initializers
+ if defined_init != null then
+ defined_init.initializers.add_all(initializers)
+ var msignature = new MSignature(mparameters, null)
+ defined_init.new_msignature = msignature
+ self.toolcontext.info("{mclassdef} extends its basic constructor signature to {defined_init}{msignature}", 3)
+ return
+ end
+
+ # Else create the local implicit basic init definition
+ var mprop = the_root_init_mmethod.as(not null)
var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
+ mpropdef.has_supercall = true
+ mpropdef.initializers.add_all(initializers)
var msignature = new MSignature(mparameters, null)
- mpropdef.msignature = msignature
- mprop.is_init = true
+ mpropdef.new_msignature = msignature
+ mpropdef.msignature = new MSignature(new Array[MParameter], null) # always an empty real signature
nclassdef.mfree_init = mpropdef
self.toolcontext.info("{mclassdef} gets a free constructor for attributes {mpropdef}{msignature}", 3)
end