From 5a33e760f2ec4a4a5b25bf4c13b9b2b4b98880ca Mon Sep 17 00:00:00 2001 From: Florian Deljarry Date: Wed, 13 Nov 2019 18:29:22 -0500 Subject: [PATCH] src: Update init Remove useless init and add old_style_init if it's necessary Signed-off-by: Florian Deljarry --- src/compiler/abstract_compiler.nit | 5 ++- src/interpreter/naive_interpreter.nit | 4 +-- src/metrics/ast_metrics.nit | 1 - src/metrics/static_types_metrics.nit | 8 ----- src/model/model.nit | 8 +++-- src/modelize/modelize_property.nit | 47 ++++++++----------------- src/nitni/nitni_callbacks.nit | 4 +-- src/nitni/nitni_utilities.nit | 2 +- src/rapid_type_analysis.nit | 4 +-- src/semantize/auto_super_init.nit | 61 +++++++++++++++++++++++++++------ src/semantize/typing.nit | 6 ++-- 11 files changed, 83 insertions(+), 67 deletions(-) diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index 44cad4f..1f26f6e 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -3687,12 +3687,11 @@ redef class AClassdef 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 diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index 4125cfa..527f16e 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -1635,11 +1635,11 @@ redef class AClassdef 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 diff --git a/src/metrics/ast_metrics.nit b/src/metrics/ast_metrics.nit index d34899e..e5f1e10 100644 --- a/src/metrics/ast_metrics.nit +++ b/src/metrics/ast_metrics.nit @@ -49,7 +49,6 @@ private class AstMetricsVisitor super Visitor var phase: AstMetricsPhase - init(phase: AstMetricsPhase) do self.phase = phase redef fun visit(n) do diff --git a/src/metrics/static_types_metrics.nit b/src/metrics/static_types_metrics.nit index 45c429b..4dd38d0 100644 --- a/src/metrics/static_types_metrics.nit +++ b/src/metrics/static_types_metrics.nit @@ -41,14 +41,6 @@ private class ATypeCounterVisitor 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 diff --git a/src/model/model.nit b/src/model/model.nit index c60a8fa..3331d6d 100644 --- a/src/model/model.nit +++ b/src/model/model.nit @@ -778,8 +778,8 @@ class MClassDef # 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] @@ -2636,6 +2636,10 @@ class MMethodDef # 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 diff --git a/src/modelize/modelize_property.nit b/src/modelize/modelize_property.nit index c236170..8529ed6 100644 --- a/src/modelize/modelize_property.nit +++ b/src/modelize/modelize_property.nit @@ -173,15 +173,13 @@ redef class ModelBuilder 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 @@ -195,7 +193,6 @@ redef class ModelBuilder 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 @@ -241,7 +238,7 @@ redef class ModelBuilder # 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 @@ -299,30 +296,12 @@ redef class ModelBuilder 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 @@ -365,13 +344,13 @@ redef class ModelBuilder # 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 @@ -789,12 +768,15 @@ redef class AMethPropdef 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" @@ -874,9 +856,10 @@ redef class AMethPropdef 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 diff --git a/src/nitni/nitni_callbacks.nit b/src/nitni/nitni_callbacks.nit index 3962597..c9725d0 100644 --- a/src/nitni/nitni_callbacks.nit +++ b/src/nitni/nitni_callbacks.nit @@ -219,7 +219,7 @@ class MExplicitCall 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}" @@ -350,7 +350,7 @@ redef class AInitPropExternCall 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 diff --git a/src/nitni/nitni_utilities.nit b/src/nitni/nitni_utilities.nit index d16e844..b1b5917 100644 --- a/src/nitni/nitni_utilities.nit +++ b/src/nitni/nitni_utilities.nit @@ -28,7 +28,7 @@ redef class MMethod 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}" diff --git a/src/rapid_type_analysis.nit b/src/rapid_type_analysis.nit index 2da2a47..d5bc7d1 100644 --- a/src/rapid_type_analysis.nit +++ b/src/rapid_type_analysis.nit @@ -264,8 +264,8 @@ class RapidTypeAnalysis 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 diff --git a/src/semantize/auto_super_init.nit b/src/semantize/auto_super_init.nit index 454e9fb..0be7107 100644 --- a/src/semantize/auto_super_init.nit +++ b/src/semantize/auto_super_init.nit @@ -104,14 +104,9 @@ redef class AMethPropdef 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 @@ -124,15 +119,31 @@ redef class AMethPropdef 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.") @@ -142,6 +153,34 @@ redef class AMethPropdef 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 diff --git a/src/semantize/typing.nit b/src/semantize/typing.nit index 8258cbf..3176e35 100644 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@ -315,7 +315,7 @@ private class TypeVisitor 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" @@ -1778,7 +1778,7 @@ redef class ARangeExpr # 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 @@ -2160,7 +2160,7 @@ redef class ABraReassignExpr 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 -- 1.7.9.5