X-Git-Url: http://nitlanguage.org diff --git a/src/model/model.nit b/src/model/model.nit index 4e9be82..3d9a364 100644 --- a/src/model/model.nit +++ b/src/model/model.nit @@ -119,7 +119,17 @@ redef class Model end end -# An OrderedTree that can be easily refined for display purposes +# An OrderedTree bound to MEntity. +# +# We introduce a new class so it can be easily refined by tools working +# with a Model. +class MEntityTree + super OrderedTree[MEntity] +end + +# A MEntityTree borned to MConcern. +# +# TODO remove when nitdoc is fully merged with model_collect class ConcernsTree super OrderedTree[MConcern] end @@ -209,6 +219,21 @@ redef class MModule # The primitive type `Byte` var byte_type: MClassType = self.get_primitive_class("Byte").mclass_type is lazy + # The primitive type `Int8` + var int8_type: MClassType = self.get_primitive_class("Int8").mclass_type is lazy + + # The primitive type `Int16` + var int16_type: MClassType = self.get_primitive_class("Int16").mclass_type is lazy + + # The primitive type `UInt16` + var uint16_type: MClassType = self.get_primitive_class("UInt16").mclass_type is lazy + + # The primitive type `Int32` + var int32_type: MClassType = self.get_primitive_class("Int32").mclass_type is lazy + + # The primitive type `UInt32` + var uint32_type: MClassType = self.get_primitive_class("UInt32").mclass_type is lazy + # The primitive type `Char` var char_type: MClassType = self.get_primitive_class("Char").mclass_type is lazy @@ -260,14 +285,16 @@ redef class MModule if name == "Bool" and self.model.get_mclasses_by_name("Object") != null then # Bool is injected because it is needed by engine to code the result # of the implicit casts. - var c = new MClass(self, name, null, enum_kind, public_visibility) - var cladef = new MClassDef(self, c.mclass_type, new Location(null, 0,0,0,0)) + var loc = model.no_location + var c = new MClass(self, name, loc, null, enum_kind, public_visibility) + var cladef = new MClassDef(self, c.mclass_type, loc) cladef.set_supertypes([object_type]) cladef.add_in_hierarchy return c end print("Fatal Error: no primitive class {name} in {self}") exit(1) + abort end if cla.length != 1 then var msg = "Fatal Error: more than one primitive class {name} in {self}:" @@ -284,18 +311,15 @@ redef class MModule var props = self.model.get_mproperties_by_name(name) if props == null then return null var res: nullable MMethod = null + var recvtype = recv.intro.bound_mtype for mprop in props do assert mprop isa MMethod - var intro = mprop.intro_mclassdef - for mclassdef in recv.mclassdefs do - if not self.in_importation.greaters.has(mclassdef.mmodule) then continue - if not mclassdef.in_hierarchy.greaters.has(intro) then continue - if res == null then - res = mprop - else if res != mprop then - print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}") - abort - end + if not recvtype.has_mproperty(self, mprop) then continue + if res == null then + res = mprop + else if res != mprop then + print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}") + abort end end return res @@ -361,7 +385,9 @@ class MClass # The short name of the class # In Nit, the name of a class cannot evolve in refinements - redef var name: String + redef var name + + redef var location # The canonical name of the class # @@ -517,6 +543,20 @@ class MClass # Is there a `new` factory to allow the pseudo instantiation? var has_new_factory = false is writable + + # Is `self` a standard or abstract class kind? + var is_class: Bool is lazy do return kind == concrete_kind or kind == abstract_kind + + # Is `self` an interface kind? + var is_interface: Bool is lazy do return kind == interface_kind + + # Is `self` an enum kind? + var is_enum: Bool is lazy do return kind == enum_kind + + # Is `self` and abstract class? + var is_abstract: Bool is lazy do return kind == abstract_kind + + redef fun mdoc_or_fallback do return intro.mdoc_or_fallback end @@ -553,12 +593,11 @@ class MClassDef # ENSURE: `bound_mtype.mclass == self.mclass` var bound_mtype: MClassType - # The origin of the definition - var location: Location + redef var location: Location # Internal name combining the module and the class - # Example: "mymodule#MyClass" - redef var to_s: String is noinit + # Example: "mymodule$MyClass" + redef var to_s is noinit init do @@ -569,41 +608,41 @@ class MClassDef assert not isset mclass._intro mclass.intro = self end - self.to_s = "{mmodule}#{mclass}" + self.to_s = "{mmodule}${mclass}" end # Actually the name of the `mclass` redef fun name do return mclass.name - # The module and class name separated by a '#'. + # The module and class name separated by a '$'. # # The short-name of the class is used for introduction. - # Example: "my_module#MyClass" + # Example: "my_module$MyClass" # # The full-name of the class is used for refinement. - # Example: "my_module#intro_module::MyClass" + # Example: "my_module$intro_module::MyClass" redef var full_name is lazy do if is_intro then - # public gives 'p#A' - # private gives 'p::m#A' - return "{mmodule.namespace_for(mclass.visibility)}#{mclass.name}" - else if mclass.intro_mmodule.mproject != mmodule.mproject then - # public gives 'q::n#p::A' - # private gives 'q::n#p::m::A' - return "{mmodule.full_name}#{mclass.full_name}" + # public gives 'p$A' + # private gives 'p::m$A' + return "{mmodule.namespace_for(mclass.visibility)}${mclass.name}" + else if mclass.intro_mmodule.mpackage != mmodule.mpackage then + # public gives 'q::n$p::A' + # private gives 'q::n$p::m::A' + return "{mmodule.full_name}${mclass.full_name}" else if mclass.visibility > private_visibility then - # public gives 'p::n#A' - return "{mmodule.full_name}#{mclass.name}" + # public gives 'p::n$A' + return "{mmodule.full_name}${mclass.name}" else - # private gives 'p::n#::m::A' (redundant p is omitted) - return "{mmodule.full_name}#::{mclass.intro_mmodule.name}::{mclass.name}" + # private gives 'p::n$::m::A' (redundant p is omitted) + return "{mmodule.full_name}$::{mclass.intro_mmodule.name}::{mclass.name}" end end redef var c_name is lazy do if is_intro then return "{mmodule.c_namespace_for(mclass.visibility)}___{mclass.c_name}" - else if mclass.intro_mmodule.mproject == mmodule.mproject and mclass.visibility > private_visibility then + else if mclass.intro_mmodule.mpackage == mmodule.mpackage and mclass.visibility > private_visibility then return "{mmodule.c_name}___{mclass.name.to_cmangle}" else return "{mmodule.c_name}___{mclass.c_name}" @@ -781,19 +820,19 @@ abstract class MType end #print "4.is {sub} a {sup}? <- no more resolution" - assert sub isa MClassType else print "{sub} = 0 then + # If there is more than one vararg, + # consider that additional arguments cannot be mapped. + vararg_rank = -1 + break + end vararg_rank = i end end self.vararg_rank = vararg_rank end - # The rank of the ellipsis (`...`) for vararg (starting from 0). + # The rank of the main ellipsis (`...`) for vararg (starting from 0). # value is -1 if there is no vararg. # Example: for "(a: Int, b: Bool..., c: Char)" #-> vararg_rank=1 + # + # From a model POV, a signature can contain more than one vararg parameter, + # the `vararg_rank` just indicates the one that will receive the additional arguments. + # However, currently, if there is more that one vararg parameter, no one will be the main one, + # and additional arguments will be refused. var vararg_rank: Int is noinit # The number of parameters fun arity: Int do return mparameters.length - # The number of non-default parameters - # - # The number of default parameters is then `arity-min_arity`. - # - # Note that there cannot be both varargs and default prameters, thus - # if `vararg_rank != -1` then `min_arity` == `arity` - fun min_arity: Int - do - if vararg_rank != -1 then return arity - var res = 0 - for p in mparameters do - if not p.is_default then res += 1 - end - return res - end - redef fun to_s do var b = new FlatBuffer @@ -1862,7 +1907,7 @@ class MParameter super MEntity # The name of the parameter - redef var name: String + redef var name # The static type of the parameter var mtype: MType @@ -1870,9 +1915,6 @@ class MParameter # Is the parameter a vararg? var is_vararg: Bool - # Is the parameter a default one? - var is_default: Bool - redef fun to_s do if is_vararg then @@ -1888,7 +1930,7 @@ class MParameter do if not self.mtype.need_anchor then return self var newtype = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual) - var res = new MParameter(self.name, newtype, self.is_vararg, self.is_default) + var res = new MParameter(self.name, newtype, self.is_vararg) return res end @@ -1919,14 +1961,29 @@ abstract class MProperty var intro_mclassdef: MClassDef # The (short) name of the property - redef var name: String + redef var name + + redef var location + + redef fun mdoc_or_fallback do return intro.mdoc_or_fallback # The canonical name of the property. # - # It is the short-`name` prefixed by the short-name of the class and the full-name of the module. - # Example: "my_project::my_module::MyClass::my_method" + # It is currently the short-`name` prefixed by the short-name of the class and the full-name of the module. + # Example: "my_package::my_module::MyClass::my_method" + # + # The full-name of the module is needed because two distinct modules of the same package can + # still refine the same class and introduce homonym properties. + # + # For public properties not introduced by refinement, the module name is not used. + # + # Example: `my_package::MyClass::My_method` redef var full_name is lazy do - return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}" + if intro_mclassdef.is_intro then + return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}" + else + return "{intro_mclassdef.mmodule.full_name}::{intro_mclassdef.mclass.name}::{name}" + end end redef var c_name is lazy do @@ -2200,8 +2257,7 @@ abstract class MPropDef # The associated global property var mproperty: MPROPERTY - # The origin of the definition - var location: Location + redef var location: Location init do @@ -2211,7 +2267,7 @@ abstract class MPropDef assert not isset mproperty._intro mproperty.intro = self end - self.to_s = "{mclassdef}#{mproperty}" + self.to_s = "{mclassdef}${mproperty}" end # Actually the name of the `mproperty` @@ -2225,31 +2281,31 @@ abstract class MPropDef # * a property "p::m::A::x" # * redefined in a refinement of a class "q::n::B" # * in a module "r::o" - # * so "r::o#q::n::B#p::m::A::x" + # * so "r::o$q::n::B$p::m::A::x" # # Fortunately, the full-name is simplified when entities are repeated. - # For the previous case, the simplest form is "p#A#x". + # For the previous case, the simplest form is "p$A$x". redef var full_name is lazy do var res = new FlatBuffer - # The first part is the mclassdef. Worst case is "r::o#q::n::B" + # The first part is the mclassdef. Worst case is "r::o$q::n::B" res.append mclassdef.full_name - res.append "#" + res.append "$" if mclassdef.mclass == mproperty.intro_mclassdef.mclass then # intro are unambiguous in a class res.append name else # Just try to simplify each part - if mclassdef.mmodule.mproject != mproperty.intro_mclassdef.mmodule.mproject then + if mclassdef.mmodule.mpackage != mproperty.intro_mclassdef.mmodule.mpackage then # precise "p::m" only if "p" != "r" - res.append mproperty.intro_mclassdef.mmodule.full_name + res.append mproperty.intro_mclassdef.mmodule.namespace_for(mproperty.visibility) res.append "::" else if mproperty.visibility <= private_visibility then - # Same project ("p"=="q"), but private visibility, + # Same package ("p"=="q"), but private visibility, # does the module part ("::m") need to be displayed - if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mproject then + if mclassdef.mmodule.namespace_for(mclassdef.mclass.visibility) != mproperty.intro_mclassdef.mmodule.mpackage then res.append "::" res.append mproperty.intro_mclassdef.mmodule.name res.append "::" @@ -2289,11 +2345,11 @@ abstract class MPropDef redef fun model do return mclassdef.model # Internal name combining the module, the class and the property - # Example: "mymodule#MyClass#mymethod" - redef var to_s: String is noinit + # Example: "mymodule$MyClass$mymethod" + redef var to_s is noinit # Is self the definition that introduce the property? - fun is_intro: Bool do return mproperty.intro == self + fun is_intro: Bool do return isset mproperty._intro and mproperty.intro == self # Return the next definition in linearization of `mtype`. # @@ -2393,7 +2449,7 @@ end # Note this class is basically an enum. # FIXME: use a real enum once user-defined enums are available class MClassKind - redef var to_s: String + redef var to_s # Is a constructor required? var need_init: Bool