v.supercall(mpropdef, arguments.first.mtype.as(MClassType), arguments)
end
return
+ else if mclassdef.auto_init == mpropdef then
+ var recv = arguments.first
+ var initializers = mpropdef.initializers
+ var no_init = false
+ if not initializers.is_empty then
+
+ var i = 1
+ for p in initializers do
+ if p isa MMethod then
+ var args = [recv]
+ for x in p.intro.msignature.mparameters do
+ args.add arguments[i]
+ i += 1
+ end
+ v.send(p, args)
+ if p.intro.is_calling_init then no_init = true
+ else if p isa MAttribute then
+ v.write_attribute(p, recv, arguments[i])
+ i += 1
+ else abort
+ end
+ assert i == arguments.length
+
+ end
+ if not no_init then v.send(mclass.the_root_init_mmethod.as(not null), [recv])
+ return
else
abort
end
v.call(superpd, arguments)
end
return null
+ else if mclassdef.auto_init == mpropdef then
+ var recv = arguments.first
+ var initializers = mpropdef.initializers
+ var no_init = false
+ if not initializers.is_empty then
+ var i = 1
+ for p in initializers do
+ if p isa MMethod then
+ var args = [recv]
+ for x in p.intro.msignature.mparameters do
+ args.add arguments[i]
+ i += 1
+ end
+ v.send(p, args)
+ if p.intro.is_calling_init then no_init = true
+ else if p isa MAttribute then
+ assert recv isa MutableInstance
+ v.write_attribute(p, recv, arguments[i])
+ i += 1
+ else abort
+ end
+ assert i == arguments.length
+ end
+ if not no_init then v.send(mclass.the_root_init_mmethod.as(not null), [recv])
+ return null
else
abort
end
mprop.is_init = true
self.toolcontext.info("{mclassdef} gets a free empty constructor {mpropdef}{msignature}", 3)
the_root_init_mmethod = mprop
- return
end
# Is there already a constructor defined?
end
end
+ if mclassdef.auto_init != null then
+ return
+ end
+
if not nclassdef isa AStdClassdef then return
# Collect undefined attributes
if the_root_init_mmethod == null then return
# Look for most-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.error(nclassdef.location, "Error: `{mclassdef}` does not specialize `{the_root_init_mmethod.intro_mclassdef}`. Possible duplication of the root class `Object`?")
- return
+ var spropdefs = new ArraySet[MMethodDef]
+ for x in mclassdef.in_hierarchy.direct_greaters do
+ var y = x.mclass.intro.auto_init
+ if y == null then continue
+ if y.is_broken or y.msignature == null then return
+ spropdefs.add y
end
# Look at the autoinit class-annotation
end
end
- # If we already have a basic init definition, then setup its initializers
- if defined_init != null then
- defined_init.initializers.add_all(initializers)
+ # Create a specific new autoinit constructor
+ do
+ var mprop = new MMethod(mclassdef, "autoinit", 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)
- defined_init.new_msignature = msignature
- self.toolcontext.info("{mclassdef} extends its basic constructor signature to {defined_init}{msignature}", 3)
- mclassdef.mclass.root_init = defined_init
- return
+ mpropdef.msignature = msignature
+ mclassdef.auto_init = mpropdef
+ self.toolcontext.info("{mclassdef} gets a free auto constructor `{mpropdef}{msignature}`. {spropdefs}", 3)
+ #mclassdef.mclass.root_init = mpropdef
+ mclassdef.mclass.the_root_init_mmethod = the_root_init_mmethod
end
-
- # Else create the local implicit basic init definition
- var mprop = the_root_init_mmethod
- var mpropdef = new MMethodDef(mclassdef, mprop, nclassdef.location)
- mpropdef.has_supercall = true
- mpropdef.initializers.add_all(initializers)
- var msignature = new MSignature(mparameters, null)
- mpropdef.new_msignature = msignature
- mpropdef.msignature = new MSignature(new Array[MParameter], null) # always an empty real signature
- self.toolcontext.info("{mclassdef} gets a free constructor for attributes {mpropdef}{msignature}", 3)
- mclassdef.mclass.root_init = mpropdef
end
# Check the visibility of `mtype` as an element of the signature of `mpropdef`.
redef class MClass
# The base init of the class.
- # Used to get the common new_msignature and initializers
#
# TODO: Where to put this information is not clear because unlike other
# informations, the initialisers are stable in a same class.
var root_init: nullable MMethodDef = null
+
+ # The base init of the class.
+ #
+ # TODO: merge with `root_init` and `ModelBuilder::the_root_init_mmethod` if possible
+ var the_root_init_mmethod: nullable MMethod = null
end
redef class MClassDef
# Add optimization of the method dispatch
redef fun callsite(callsite: nullable CallSite, arguments: Array[Instance]): nullable Instance
do
- var initializers = callsite.mpropdef.initializers
- if initializers.is_empty then return send_optimize(callsite.as(not null), arguments)
-
- var recv = arguments.first
- var i = 1
- for p in initializers do
- if p isa MMethod then
- var args = [recv]
- for x in p.intro.msignature.mparameters do
- args.add arguments[i]
- i += 1
- end
- self.send(p, args)
- else if p isa MAttribute then
- assert recv isa MutableInstance
- write_attribute(p, recv, arguments[i])
- i += 1
- else abort
- end
- assert i == arguments.length
-
- return send_optimize(callsite.as(not null), [recv])
+ return send_optimize(callsite.as(not null), arguments)
end
# Try to have the most efficient implementation of the method dispatch