X-Git-Url: http://nitlanguage.org diff --git a/src/model_utils.nit b/src/model_utils.nit index 2591da1..24105e6 100644 --- a/src/model_utils.nit +++ b/src/model_utils.nit @@ -17,10 +17,123 @@ # Model exploration and traversing facilities module model_utils -import toolcontext -import exprbuilder +import model + +redef class MConcern + + # Boost a MConcern rank + # see: `MConcernRankSorter` + # Use a positive booster to push down a result in the list + # A negative booster can be used to push up the result + var booster_rank: Int = 0 is writable + + # Concern ranking used for ordering + # see: `MConcernRankSorter` + # Rank can be positive or negative + fun concern_rank: Int is abstract +end + +redef class MProject + redef var concern_rank is lazy do + var max = 0 + for mgroup in mgroups do + var mmax = mgroup.concern_rank + if mmax > max then max = mmax + end + return max + 1 + end +end + +redef class MGroup + fun in_nesting_intro_mclasses(min_visibility: MVisibility): Set[MClass] do + var res = new HashSet[MClass] + var lst = in_nesting.direct_smallers + for mmodule in mmodules do res.add_all mmodule.filter_intro_mclasses(min_visibility) + for mgrp in lst do res.add_all mgrp.in_nesting_intro_mclasses(min_visibility) + return res + end + + fun in_nesting_redef_mclasses(min_visibility: MVisibility): Set[MClass] do + var res = new HashSet[MClass] + var lst = in_nesting.direct_smallers + for mmodule in mmodules do res.add_all mmodule.filter_redef_mclasses(min_visibility) + for mgrp in lst do res.add_all mgrp.in_nesting_redef_mclasses(min_visibility) + return res + end + + fun in_nesting_intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do + var res = new HashSet[MClassDef] + var lst = in_nesting.direct_smallers + for mmodule in mmodules do res.add_all mmodule.intro_mclassdefs(min_visibility) + for mgrp in lst do res.add_all mgrp.in_nesting_intro_mclassdefs(min_visibility) + return res + end + + fun in_nesting_redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do + var res = new HashSet[MClassDef] + var lst = in_nesting.direct_smallers + for mmodule in mmodules do res.add_all mmodule.redef_mclassdefs(min_visibility) + for mgrp in lst do res.add_all mgrp.in_nesting_redef_mclassdefs(min_visibility) + return res + end + + # Collect nested modules + fun collect_mmodules: Set[MModule] do + var res = new HashSet[MModule] + res.add_all mmodules + for mgroup in in_nesting.direct_smallers do + res.add_all mgroup.collect_mmodules + end + return res + end + + redef var concern_rank is lazy do + var max = 0 + for mmodule in collect_mmodules do + var mmax = mmodule.concern_rank + if mmax > max then max = mmax + end + return max + 1 + end +end redef class MModule + + # The list of intro mclassdef in the module. + # with visibility >= to min_visibility + fun intro_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do + var res = new HashSet[MClassDef] + for mclassdef in mclassdefs do + if not mclassdef.is_intro then continue + if mclassdef.mclass.visibility < min_visibility then continue + res.add mclassdef + end + return res + end + + # The list of redef mclassdef in the module. + # with visibility >= to min_visibility + fun redef_mclassdefs(min_visibility: MVisibility): Set[MClassDef] do + var res = new HashSet[MClassDef] + for mclassdef in mclassdefs do + if mclassdef.is_intro then continue + if mclassdef.mclass.visibility < min_visibility then continue + res.add mclassdef + end + return res + end + + # The list of intro mclass in the module. + # with visibility >= to min_visibility + fun filter_intro_mclasses(min_visibility: MVisibility): Set[MClass] do + var res = new HashSet[MClass] + for mclass in intro_mclasses do + if mclass.visibility < min_visibility then continue + res.add mclass + end + return res + end + # Get the list of mclasses refined in 'self'. fun redef_mclasses: Set[MClass] do var mclasses = new HashSet[MClass] @@ -30,6 +143,16 @@ redef class MModule return mclasses end + # Get the list of mclasses refined in 'self'. + fun filter_redef_mclasses(min_visibility: MVisibility): Set[MClass] do + var mclasses = new HashSet[MClass] + for c in mclassdefs do + if c.mclass.visibility < min_visibility then continue + if not c.is_intro then mclasses.add(c.mclass) + end + return mclasses + end + # Get the list of all mclasses imported by 'self'. fun imported_mclasses: Set[MClass] do var mclasses = new HashSet[MClass] @@ -40,13 +163,30 @@ redef class MModule return mclasses end - # Get all mclasses in 'self' with their state - fun mclasses: HashMap[MClass, Int] do - var mclasses = new HashMap[MClass, Int] - for c in intro_mclasses do mclasses[c] = c_is_intro - for r in redef_mclasses do mclasses[r] = c_is_refined - for i in imported_mclasses do mclasses[i] = c_is_imported - return mclasses + redef var concern_rank is lazy do + var max = 0 + for p in in_importation.direct_greaters do + var pmax = p.concern_rank + if pmax > max then max = pmax + end + return max + 1 + end + + # Find all mmodules nested in `self` if `self` is the default module of a `MGroup`. + fun nested_mmodules: Array[MModule] do + var res = new Array[MModule] + var mgroup = mgroup + if mgroup == null or self != mgroup.default_mmodule then return res + for mmodule in mgroup.mmodules do + if mmodule == self then continue + res.add mmodule + end + for nested in mgroup.in_nesting.direct_smallers do + var default = nested.default_mmodule + if default == null then continue + res.add default + end + return res end end @@ -125,58 +265,107 @@ redef class MClass return res end - # Get the set of properties introduced in 'self'. - fun intro_mproperties: Set[MProperty] do - var res = new HashSet[MProperty] + # the set of properties introduced in 'self'. + fun intro_mproperties(min_visibility: MVisibility): Set[MProperty] do + var set = new HashSet[MProperty] + for mclassdef in mclassdefs do + for mprop in mclassdef.intro_mproperties do + if mprop.visibility < min_visibility then continue + set.add(mprop) + end + end + return set + end + + fun intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do + var set = new HashSet[MPropDef] for mclassdef in mclassdefs do for mpropdef in mclassdef.mpropdefs do - if mpropdef.is_intro then res.add(mpropdef.mproperty) + if not mpropdef.is_intro then continue + if mpropdef.mproperty.visibility < min_visibility then continue + set.add(mpropdef) end end - return res + return set end - # Get the list of locally refined methods in 'self'. - fun redef_methods: Set[MMethod] do - var res = new HashSet[MMethod] + # the set of locally refined properties in 'self'. + fun redef_mproperties(min_visibility: MVisibility): Set[MProperty] do + var set = new HashSet[MProperty] for mclassdef in mclassdefs do for mpropdef in mclassdef.mpropdefs do - if mpropdef isa MMethodDef then - if not mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty) - end + if mpropdef.mproperty.visibility < min_visibility then continue + if mpropdef.mproperty.intro_mclassdef.mclass != self then set.add(mpropdef.mproperty) end end - return res + return set end - # Get the set of locally refined properties in 'self'. - fun redef_mproperties: Set[MProperty] do - var res = new HashSet[MProperty] + fun redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do + var set = new HashSet[MPropDef] for mclassdef in mclassdefs do for mpropdef in mclassdef.mpropdefs do - if not mpropdef.is_intro then res.add(mpropdef.mproperty) + if mpropdef.is_intro then continue + if mpropdef.mproperty.visibility < min_visibility then continue + set.add(mpropdef) end end - return res + return set end - # Get the list of methods inherited by 'self'. - fun inherited_methods: Set[MMethod] do + # the set of methods inherited by 'self'. + fun inherited_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do + var set = new HashSet[MProperty] + for parent in in_hierarchy(mainmodule).direct_greaters do + set.add_all(parent.intro_mproperties(min_visibility)) + set.add_all(parent.inherited_mproperties(mainmodule, min_visibility)) + end + return set + end + + # the set of introduced and redefined mproperties + fun local_mproperties(min_visibility: MVisibility): Set[MProperty] do + var set = new HashSet[MProperty] + set.add_all(intro_mproperties(min_visibility)) + set.add_all(redef_mproperties(min_visibility)) + return set + end + + # the set of all accessible mproperties for this class + fun all_mproperties(mainmodule: MModule, min_visibility: MVisibility): Set[MProperty] do + var set = new HashSet[MProperty] + set.add_all(local_mproperties(min_visibility)) + set.add_all(inherited_mproperties(mainmodule, min_visibility)) + return set + end + + # the set of all accessible mattributes for this class + fun all_mattributes(mainmodule: MModule, min_visibility: MVisibility): Set[MAttribute] do + var set = new HashSet[MAttribute] + for mprop in all_mproperties(mainmodule, min_visibility) do + if mprop isa MAttribute then set.add(mprop) + end + return set + end + + # Get the list of locally refined methods in 'self'. + fun redef_methods: Set[MMethod] do var res = new HashSet[MMethod] - for s in ancestors do - for m in s.intro_methods do - if not self.intro_methods.has(m) and not self.redef_methods.has(m) then res.add(m) + for mclassdef in mclassdefs do + for mpropdef in mclassdef.mpropdefs do + if mpropdef isa MMethodDef then + if not mpropdef.is_intro and not mpropdef.mproperty.is_init then res.add(mpropdef.mproperty) + end end end return res end - # Get the set of all properties inherited by self - fun inherited_mproperties: Set[MProperty] do - var res = new HashSet[MProperty] + fun inherited_methods: Set[MMethod] do + var res = new HashSet[MMethod] for s in ancestors do - for m in s.intro_mproperties do - if not self.intro_mproperties.has(m) and not self.redef_mproperties.has(m) then res.add(m) + for m in s.intro_methods do + if not self.intro_methods.has(m) and not self.redef_methods.has(m) then res.add(m) end end return res @@ -207,37 +396,12 @@ redef class MClass # Get the list of all parameter types in 'self'. fun parameter_types: Map[String, MType] do var res = new HashMap[String, MType] - for i in [0..intro.parameter_names.length[ do - res[intro.parameter_names[i]] = intro.bound_mtype.arguments[i] + for p in mparameters do + res[p.name] = p end return res end - fun mmodules: Set[MModule] do - var mdls = new HashSet[MModule] - for mclassdef in mclassdefs do mdls.add(mclassdef.mmodule) - return mdls - end - - # Get the list of MModule concern in 'self' - fun concerns: HashMap[MModule, nullable List[MModule]] do - var hm = new HashMap[MModule, nullable List[MModule]] - for mmodule in mmodules do - var owner = mmodule.public_owner - if owner == null then - hm[mmodule] = null - else - if hm.has_key(owner) then - hm[owner].add(mmodule) - else - hm[owner] = new List[MModule] - hm[owner].add(mmodule) - end - end - end - return hm - end - fun is_class: Bool do return self.kind == concrete_kind or self.kind == abstract_kind end @@ -255,7 +419,115 @@ redef class MClass end end -# MClass State -fun c_is_intro: Int do return 1 -fun c_is_refined: Int do return 2 -fun c_is_imported: Int do return 3 +redef class MAttribute + # Is this attribute nullable for sure? + # + # This mean that its introduction is declarred with a nullable static type + # since attributes are invariant this will work on most cases + # attributes with static type anchored with a virtual type are not "nullable for-sure" + # because this type can be redefined in subclasses + fun is_nullable: Bool do return intro.static_mtype isa MNullableType +end + +redef class MClassDef + # modifiers are keywords like redef, private etc. + fun modifiers: Array[String] do + var res = new Array[String] + if not is_intro then + res.add "redef" + else + res.add mclass.visibility.to_s + end + res.add mclass.kind.to_s + return res + end + + fun collect_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do + var res = new HashSet[MPropDef] + for mpropdef in mpropdefs do + if mpropdef.mproperty.visibility < min_visibility then continue + res.add mpropdef + end + return res + end + + fun collect_intro_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do + var res = new HashSet[MPropDef] + for mpropdef in mpropdefs do + if not mpropdef.is_intro then continue + if mpropdef.mproperty.visibility < min_visibility then continue + res.add mpropdef + end + return res + end + + fun collect_redef_mpropdefs(min_visibility: MVisibility): Set[MPropDef] do + var res = new HashSet[MPropDef] + for mpropdef in mpropdefs do + if mpropdef.is_intro then continue + if mpropdef.mproperty.visibility < min_visibility then continue + res.add mpropdef + end + return res + end +end + +redef class MPropDef + # modifiers are keywords like redef, private etc. + fun modifiers: Array[String] do + var res = new Array[String] + if not is_intro then + res.add "redef" + else + res.add mproperty.visibility.to_s + end + var mprop = self + if mprop isa MVirtualTypeDef then + res.add "type" + else if mprop isa MMethodDef then + if mprop.is_abstract then + res.add "abstract" + else if mprop.is_intern then + res.add "intern" + end + if mprop.mproperty.is_init then + res.add "init" + else + res.add "fun" + end + end + return res + end +end + +# Sorters + +# Sort mentities by their name +class MEntityNameSorter + super Comparator + redef type COMPARED: MEntity + redef fun compare(a, b) do return a.name <=> b.name +end + +# Sort MConcerns based on the module importation hierarchy ranking +# see also: `MConcern::concern_rank` and `MConcern::booster_rank` +# +# Comparison is made with the formula: +# +# ~~~nitish +# a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran +# ~~~ +# +# If both `a` and `b` have the same ranking, +# ordering is based on lexicographic comparison of `a.name` and `b.name` +class MConcernRankSorter + super Comparator + redef type COMPARED: MConcern + + redef fun compare(a, b) do + if a.concern_rank == b.concern_rank then + return a.name <=> b.name + end + return a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_rank + end +end