From: Jean Privat Date: Mon, 16 Jun 2014 22:42:43 +0000 (-0400) Subject: Merge: No duplicated mclassdefs X-Git-Tag: v0.6.6~31 X-Git-Url: http://nitlanguage.org?hp=5493586589cf701bebd72f7e18ebb2d9d222cb9a Merge: No duplicated mclassdefs This series avoid the creation of multiple mclassdefs for a same class in a same module. It appended for implicit classes: Object for top-level methods and Sys for top-level main. The series was more complex than expected because it breaks the symmetry between AClassdef and MClassDef. However, thanks to the separation of the AST and the model, it was sill feasible. Pull-Request: #503 Reviewed-by: Alexandre Terrasa --- diff --git a/src/modelize_class.nit b/src/modelize_class.nit index 4cd9475..09b7081 100644 --- a/src/modelize_class.nit +++ b/src/modelize_class.nit @@ -97,7 +97,12 @@ redef class ModelBuilder error(nvisibility, "Error: refinement changed the visibility from a {mclass.visibility} to a {mvisibility}") end nclassdef.mclass = mclass - nmodule.mclass2nclassdef[mclass] = nclassdef + if not nmodule.mclass2nclassdef.has_key(mclass) then + nmodule.mclass2nclassdef[mclass] = nclassdef + nclassdef.all_defs = [nclassdef] + else + nmodule.mclass2nclassdef[mclass].all_defs.add(nclassdef) + end end # Visit the AST and create the `MClassDef` objects @@ -107,7 +112,14 @@ redef class ModelBuilder var objectclass = try_get_mclass_by_name(nmodule, mmodule, "Object") var mclass = nclassdef.mclass if mclass == null then return # Skip error - #var mclassdef = nclassdef.mclassdef.as(not null) + + # In case of non-standard AClassdef, try to attach to an already existing mclassdef + var other_nclassdef = nmodule.mclass2nclassdef[mclass] + if other_nclassdef != nclassdef then + assert not nclassdef isa AStdClassdef + nclassdef.mclassdef = other_nclassdef.mclassdef + return + end var names = new Array[String] var bounds = new Array[MType] @@ -281,8 +293,7 @@ redef class ModelBuilder if errcount != toolcontext.error_count then return # Create the mclassdef hierarchy - for nclassdef in nmodule.n_classdefs do - var mclassdef = nclassdef.mclassdef.as(not null) + for mclassdef in mmodule.mclassdefs do mclassdef.add_in_hierarchy end @@ -505,6 +516,8 @@ redef class AClassdef var mclass: nullable MClass # The associated MClassDef once build by a `ModelBuilder` var mclassdef: nullable MClassDef + # All (self and other) definitions for the same mclassdef + var all_defs: nullable Array[AClassdef] end redef class AClasskind diff --git a/src/modelize_property.nit b/src/modelize_property.nit index e24541e..3563862 100644 --- a/src/modelize_property.nit +++ b/src/modelize_property.nit @@ -28,6 +28,7 @@ private class ModelizePropertyPhase redef fun process_nmodule(nmodule) do for nclassdef in nmodule.n_classdefs do + if nclassdef.all_defs == null then continue # skip non principal classdef toolcontext.modelbuilder.build_properties(nclassdef) end end @@ -52,14 +53,16 @@ redef class ModelBuilder build_properties(mclassdef2nclassdef[superclassdef]) end - for npropdef in nclassdef.n_propdefs do - npropdef.build_property(self, nclassdef) - end - for npropdef in nclassdef.n_propdefs do - npropdef.build_signature(self) - end - for npropdef in nclassdef.n_propdefs do - npropdef.check_signature(self) + for nclassdef2 in nclassdef.all_defs do + for npropdef in nclassdef2.n_propdefs do + npropdef.build_property(self, mclassdef) + end + for npropdef in nclassdef2.n_propdefs do + npropdef.build_signature(self) + end + for npropdef in nclassdef2.n_propdefs do + npropdef.check_signature(self) + end end process_default_constructors(nclassdef) end @@ -225,7 +228,9 @@ redef class AClassdef # The free init (implicitely constructed by the class if required) var mfree_init: nullable MMethodDef = null +end +redef class MClassDef # What is the `APropdef` associated to a `MProperty`? # Used to check multiple definition of a property. var mprop2npropdef: Map[MProperty, APropdef] = new HashMap[MProperty, APropdef] @@ -260,7 +265,7 @@ redef class APropdef # The associated propdef once build by a `ModelBuilder` var mpropdef: nullable MPROPDEF writable - private fun build_property(modelbuilder: ModelBuilder, nclassdef: AClassdef) is abstract + private fun build_property(modelbuilder: ModelBuilder, mclassdef: MClassDef) is abstract private fun build_signature(modelbuilder: ModelBuilder) is abstract private fun check_signature(modelbuilder: ModelBuilder) is abstract private fun new_property_visibility(modelbuilder: ModelBuilder, mclassdef: MClassDef, nvisibility: nullable AVisibility): MVisibility @@ -306,13 +311,13 @@ redef class APropdef end end - private fun check_redef_keyword(modelbuilder: ModelBuilder, nclassdef: AClassdef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty): Bool + private fun check_redef_keyword(modelbuilder: ModelBuilder, mclassdef: MClassDef, kwredef: nullable Token, need_redef: Bool, mprop: MProperty): Bool do - if nclassdef.mprop2npropdef.has_key(mprop) then - modelbuilder.error(self, "Error: A property {mprop} is already defined in class {nclassdef.mclassdef.mclass} at line {nclassdef.mprop2npropdef[mprop].location.line_start}.") + if mclassdef.mprop2npropdef.has_key(mprop) then + modelbuilder.error(self, "Error: A property {mprop} is already defined in class {mclassdef.mclass} at line {mclassdef.mprop2npropdef[mprop].location.line_start}.") return false end - if mprop isa MMethod and mprop.is_toplevel != (nclassdef isa ATopClassdef) then + if mprop isa MMethod and mprop.is_toplevel != (parent isa ATopClassdef) then if mprop.is_toplevel then modelbuilder.error(self, "Error: {mprop} is a top level method.") else @@ -323,12 +328,12 @@ redef class APropdef end if kwredef == null then if need_redef then - modelbuilder.error(self, "Redef error: {nclassdef.mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.") + modelbuilder.error(self, "Redef error: {mclassdef.mclass}::{mprop.name} is an inherited property. To redefine it, add the redef keyword.") return false end else if not need_redef then - modelbuilder.error(self, "Error: No property {nclassdef.mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.") + modelbuilder.error(self, "Error: No property {mclassdef.mclass}::{mprop.name} is inherited. Remove the redef keyword to define a new property.") return false end end @@ -416,12 +421,11 @@ end redef class AMethPropdef redef type MPROPDEF: MMethodDef - redef fun build_property(modelbuilder, nclassdef) + redef fun build_property(modelbuilder, mclassdef) do var n_kwinit = n_kwinit var n_kwnew = n_kwnew var is_init = n_kwinit != null or n_kwnew != null - var mclassdef = nclassdef.mclassdef.as(not null) var name: String var amethodid = self.n_methid var name_node: ANode @@ -458,13 +462,13 @@ redef class AMethPropdef mprop = new MMethod(mclassdef, name, mvisibility) mprop.is_init = is_init mprop.is_new = n_kwnew != null - if nclassdef isa ATopClassdef then mprop.is_toplevel = true - if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mprop) then return + if parent isa ATopClassdef then mprop.is_toplevel = true + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mprop) then return else - if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, not self isa AMainMethPropdef, mprop) then return check_redef_property_visibility(modelbuilder, self.n_visibility, mprop) end - nclassdef.mprop2npropdef[mprop] = self + mclassdef.mprop2npropdef[mprop] = self var mpropdef = new MMethodDef(mclassdef, mprop, self.location) @@ -624,9 +628,8 @@ redef class AAttrPropdef var mreadpropdef: nullable MMethodDef writable # The associated setter (write accessor) if any var mwritepropdef: nullable MMethodDef writable - redef fun build_property(modelbuilder, nclassdef) + redef fun build_property(modelbuilder, mclassdef) do - var mclassdef = nclassdef.mclassdef.as(not null) var mclass = mclassdef.mclass var name: String @@ -651,13 +654,13 @@ redef class AAttrPropdef if mprop == null then var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) mprop = new MAttribute(mclassdef, name, mvisibility) - if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return else assert mprop isa MAttribute check_redef_property_visibility(modelbuilder, self.n_visibility, mprop) - if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, true, mprop) then return end - nclassdef.mprop2npropdef[mprop] = self + mclassdef.mprop2npropdef[mprop] = self var mpropdef = new MAttributeDef(mclassdef, mprop, self.location) self.mpropdef = mpropdef @@ -671,12 +674,12 @@ redef class AAttrPropdef if mreadprop == null then var mvisibility = new_property_visibility(modelbuilder, mclassdef, nreadable.n_visibility) mreadprop = new MMethod(mclassdef, readname, mvisibility) - if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, false, mreadprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, nreadable.n_kwredef, false, mreadprop) then return else - if not self.check_redef_keyword(modelbuilder, nclassdef, nreadable.n_kwredef, true, mreadprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, nreadable.n_kwredef, true, mreadprop) then return check_redef_property_visibility(modelbuilder, nreadable.n_visibility, mreadprop) end - nclassdef.mprop2npropdef[mreadprop] = self + mclassdef.mprop2npropdef[mreadprop] = self var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location) self.mreadpropdef = mreadpropdef @@ -691,12 +694,12 @@ redef class AAttrPropdef if mwriteprop == null then var mvisibility = new_property_visibility(modelbuilder, mclassdef, nwritable.n_visibility) mwriteprop = new MMethod(mclassdef, writename, mvisibility) - if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, false, mwriteprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, nwritable.n_kwredef, false, mwriteprop) then return else - if not self.check_redef_keyword(modelbuilder, nclassdef, nwritable.n_kwredef, true, mwriteprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, nwritable.n_kwredef, true, mwriteprop) then return check_redef_property_visibility(modelbuilder, nwritable.n_visibility, mwriteprop) end - nclassdef.mprop2npropdef[mwriteprop] = self + mclassdef.mprop2npropdef[mwriteprop] = self var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location) self.mwritepropdef = mwritepropdef @@ -717,12 +720,12 @@ redef class AAttrPropdef if mreadprop == null then var mvisibility = new_property_visibility(modelbuilder, mclassdef, self.n_visibility) mreadprop = new MMethod(mclassdef, readname, mvisibility) - if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, false, mreadprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, false, mreadprop) then return else - if not self.check_redef_keyword(modelbuilder, nclassdef, n_kwredef, true, mreadprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, n_kwredef, true, mreadprop) then return check_redef_property_visibility(modelbuilder, self.n_visibility, mreadprop) end - nclassdef.mprop2npropdef[mreadprop] = self + mclassdef.mprop2npropdef[mreadprop] = self var mreadpropdef = new MMethodDef(mclassdef, mreadprop, self.location) self.mreadpropdef = mreadpropdef @@ -742,14 +745,14 @@ redef class AAttrPropdef mvisibility = private_visibility end mwriteprop = new MMethod(mclassdef, writename, mvisibility) - if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, false, mwriteprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, false, mwriteprop) then return else - if not self.check_redef_keyword(modelbuilder, nclassdef, nwkwredef, true, mwriteprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, nwkwredef, true, mwriteprop) then return if nwritable != null then check_redef_property_visibility(modelbuilder, nwritable.n_visibility, mwriteprop) end end - nclassdef.mprop2npropdef[mwriteprop] = self + mclassdef.mprop2npropdef[mwriteprop] = self var mwritepropdef = new MMethodDef(mclassdef, mwriteprop, self.location) self.mwritepropdef = mwritepropdef @@ -934,9 +937,8 @@ end redef class ATypePropdef redef type MPROPDEF: MVirtualTypeDef - redef fun build_property(modelbuilder, nclassdef) + redef fun build_property(modelbuilder, mclassdef) do - var mclassdef = nclassdef.mclassdef.as(not null) var name = self.n_id.text var mprop = modelbuilder.try_get_mproperty_by_name(self.n_id, mclassdef, name) if mprop == null then @@ -946,13 +948,13 @@ redef class ATypePropdef modelbuilder.warning(n_id, "Warning: lowercase in the virtual type {name}") break end - if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, false, mprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, false, mprop) then return else - if not self.check_redef_keyword(modelbuilder, nclassdef, self.n_kwredef, true, mprop) then return + if not self.check_redef_keyword(modelbuilder, mclassdef, self.n_kwredef, true, mprop) then return assert mprop isa MVirtualTypeProp check_redef_property_visibility(modelbuilder, self.n_visibility, mprop) end - nclassdef.mprop2npropdef[mprop] = self + mclassdef.mprop2npropdef[mprop] = self var mpropdef = new MVirtualTypeDef(mclassdef, mprop, self.location) self.mpropdef = mpropdef diff --git a/tests/error_defs.nit b/tests/error_defs.nit index 4a5036c..ee4652c 100644 --- a/tests/error_defs.nit +++ b/tests/error_defs.nit @@ -42,7 +42,7 @@ end #alt8# redef fun foo: Int do return 300 + bar #alt8#end - +#alt9#fun baz do abort fun baz: Int do return 1 baz.output diff --git a/tests/sav/error_defs_alt9.res b/tests/sav/error_defs_alt9.res new file mode 100644 index 0000000..8c547a1 --- /dev/null +++ b/tests/sav/error_defs_alt9.res @@ -0,0 +1 @@ +alt/error_defs_alt9.nit:46,5--7: Error: A property baz is already defined in class Object at line 45. diff --git a/tests/sav/nitlight_args1.res b/tests/sav/nitlight_args1.res index 0b82282..f14eb40 100644 --- a/tests/sav/nitlight_args1.res +++ b/tests/sav/nitlight_args1.res @@ -16,7 +16,7 @@ import end -interface Object +interface Object end enum Bool diff --git a/tests/sav/nitmetrics_args1.res b/tests/sav/nitmetrics_args1.res index 0c177f8..4540753 100644 --- a/tests/sav/nitmetrics_args1.res +++ b/tests/sav/nitmetrics_args1.res @@ -41,11 +41,11 @@ std: 0.0 sum: 7 mnbr: number of refinement in module - avg: 3.0 - max: base_simple3 (3) - min: base_simple3 (3) + avg: 0.0 + max: base_simple3 (0) + min: base_simple3 (0) std: 0.0 - sum: 3 + sum: 0 mnbcc: number of concrete class in module (intro + redef) avg: 4.0 max: base_simple3 (4) @@ -59,11 +59,11 @@ std: 0.0 sum: 0 mnbic: number of interface in module (intro + redef) - avg: 4.0 - max: base_simple3 (4) - min: base_simple3 (4) + avg: 1.0 + max: base_simple3 (1) + min: base_simple3 (1) std: 0.0 - sum: 4 + sum: 1 ## project base_empty_module `- group base_empty_module @@ -166,11 +166,11 @@ std: 3.0 sum: 8 mnbr: number of refinement in module - avg: 1.0 - max: base_simple3 (3) - min: base_empty_module (0) - std: 1.581 - sum: 3 + avg: 0.0 + max: base_simple3 (0) + min: base_simple3 (0) + std: 0.0 + sum: 0 mnbcc: number of concrete class in module (intro + redef) avg: 2.0 max: base_simple3 (4) @@ -184,11 +184,11 @@ std: 0.0 sum: 0 mnbic: number of interface in module (intro + redef) - avg: 2.0 - max: base_simple3 (4) + avg: 0.0 + max: base_simple3 (1) min: base_empty_module (0) - std: 2.0 - sum: 4 + std: 0.707 + sum: 1 # MClasses metrics @@ -421,48 +421,45 @@ Distribution of direct smallers <=0: sub-population=1 (33.33%); cumulated value=0 (0.0%) <=1: sub-population=2 (66.66%); cumulated value=2 (100.00%) ## Classdef hierarchy -Number of nodes: 11 -Number of edges: 47 (4.27 per node) -Number of direct edges: 9 (0.81 per node) +Number of nodes: 8 +Number of edges: 14 (1.75 per node) +Number of direct edges: 6 (0.75 per node) Distribution of greaters - population: 11 + population: 8 minimum value: 1 - maximum value: 5 - total value: 47 - average value: 4.27 + maximum value: 2 + total value: 14 + average value: 1.75 distribution: - <=1: sub-population=1 (9.09%); cumulated value=1 (2.12%) - <=4: sub-population=4 (36.36%); cumulated value=16 (34.04%) - <=8: sub-population=6 (54.54%); cumulated value=30 (63.82%) + <=1: sub-population=2 (25.00%); cumulated value=2 (14.28%) + <=2: sub-population=6 (75.00%); cumulated value=12 (85.71%) Distribution of direct greaters - population: 11 + population: 8 minimum value: 0 - maximum value: 3 - total value: 9 - average value: 0.81 + maximum value: 1 + total value: 6 + average value: 0.75 distribution: - <=0: sub-population=4 (36.36%); cumulated value=0 (0.0%) - <=1: sub-population=6 (54.54%); cumulated value=6 (66.66%) - <=4: sub-population=1 (9.09%); cumulated value=3 (33.33%) + <=0: sub-population=2 (25.00%); cumulated value=0 (0.0%) + <=1: sub-population=6 (75.00%); cumulated value=6 (100.00%) Distribution of smallers - population: 11 + population: 8 minimum value: 1 - maximum value: 10 - total value: 47 - average value: 4.27 + maximum value: 7 + total value: 14 + average value: 1.75 distribution: - <=1: sub-population=7 (63.63%); cumulated value=7 (14.89%) - <=16: sub-population=4 (36.36%); cumulated value=40 (85.10%) + <=1: sub-population=7 (87.50%); cumulated value=7 (50.00%) + <=8: sub-population=1 (12.50%); cumulated value=7 (50.00%) Distribution of direct smallers - population: 11 + population: 8 minimum value: 0 maximum value: 6 - total value: 9 - average value: 0.81 + total value: 6 + average value: 0.75 distribution: - <=0: sub-population=7 (63.63%); cumulated value=0 (0.0%) - <=1: sub-population=3 (27.27%); cumulated value=3 (33.33%) - <=8: sub-population=1 (9.09%); cumulated value=6 (66.66%) + <=0: sub-population=7 (87.50%); cumulated value=0 (0.0%) + <=8: sub-population=1 (12.50%); cumulated value=6 (100.00%) ## Class hierarchy Number of nodes: 8 Number of edges: 14 (1.75 per node) @@ -580,10 +577,10 @@ Number of classes: 8 Number of enum kind: 2 (25.00%) Number of class kind: 5 (62.50%) -Number of class definitions: 11 -Number of refined classes: 1 (12.50%) -Average number of class refinments by classes: 0.37 -Average number of class refinments by refined classes: 3.00 +Number of class definitions: 8 +Number of refined classes: 0 (0.0%) +Average number of class refinments by classes: 0.0 +Average number of class refinments by refined classes: na Number of properties: 20 Number of MAttribute: 3 (15.00%) @@ -614,7 +611,7 @@ Total number of self: 5 Total number of implicit self: 4 (80.00%) --- Construction of tables --- Number of runtime classes: 7 (excluding interfaces and abstract classes) -Average number of composing class definition by runtime class: 4.42 +Average number of composing class definition by runtime class: 1.85 Total size of tables (classes and instances): 35 (not including stuff like info for subtyping or call-next-method) Average size of table by runtime class: 5.00 Values never redefined: 35 (100.00%) @@ -632,6 +629,8 @@ Values never redefined: 35 (100.00%) blooming mclasses (threshold: 2.388) B: 3.0 C: 3.0 +generating out/nitmetrics_args1.write/project_hierarchy.dot +generating out/nitmetrics_args1.write/module_hierarchy.dot # Nullable metrics @@ -1075,8 +1074,6 @@ MMethodDef possibly invoked at runtime (by number of CallSites) base_simple3#Object#bar: 1 (4.54%) base_simple3#Object#foo: 1 (4.54%) base_simple3#C#init: 1 (4.54%) -generating out/nitmetrics_args1.write/project_hierarchy.dot -generating out/nitmetrics_args1.write/module_hierarchy.dot class_hierarchy.dot classdef_hierarchy.dot inheritance/ diff --git a/tests/sav/nitx_args3.res b/tests/sav/nitx_args3.res index 264e277..e3174b3 100644 --- a/tests/sav/nitx_args3.res +++ b/tests/sav/nitx_args3.res @@ -25,15 +25,4 @@ class Sys base_simple3::Sys (lines 53-66) - - == refined classes - - redef interface Object - base_simple3::Object (lines 49-49) - - redef interface Object - base_simple3::Object (lines 50-50) - - redef interface Object - base_simple3::Object (lines 51-51)