X-Git-Url: http://nitlanguage.org diff --git a/src/model/model.nit b/src/model/model.nit index 76a3839..941bae7 100644 --- a/src/model/model.nit +++ b/src/model/model.nit @@ -206,6 +206,24 @@ redef class MModule # The primitive type `Int` var int_type: MClassType = self.get_primitive_class("Int").mclass_type is lazy + # 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 @@ -251,7 +269,9 @@ redef class MModule fun get_primitive_class(name: String): MClass do var cla = self.model.get_mclasses_by_name(name) - if cla == null then + # Filter classes by introducing module + if cla != null then cla = [for c in cla do if self.in_importation <= c.intro_mmodule then c] + if cla == null or cla.is_empty then 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. @@ -261,11 +281,11 @@ redef class MModule cladef.add_in_hierarchy return c end - print("Fatal Error: no primitive class {name}") + print("Fatal Error: no primitive class {name} in {self}") exit(1) end if cla.length != 1 then - var msg = "Fatal Error: more than one primitive class {name}:" + var msg = "Fatal Error: more than one primitive class {name} in {self}:" for c in cla do msg += " {c.full_name}" print msg #exit(1) @@ -378,6 +398,29 @@ class MClass # is empty if the class is not generic var mparameters = new Array[MParameterType] + # A string version of the signature a generic class. + # + # eg. `Map[K: nullable Object, V: nullable Object]` + # + # If the class in non generic the name is just given. + # + # eg. `Object` + fun signature_to_s: String + do + if arity == 0 then return name + var res = new FlatBuffer + res.append name + res.append "[" + for i in [0..arity[ do + if i > 0 then res.append ", " + res.append mparameters[i].name + res.append ": " + res.append intro.bound_mtype.arguments[i].to_s + end + res.append "]" + return res.to_s + end + # Initialize `mparameters` from their names. protected fun setup_parameter_names(parameter_names: nullable Array[String]) is autoinit @@ -433,8 +476,17 @@ class MClass # # Warning: such a definition may not exist in the early life of the object. # In this case, the method will abort. + # + # Use `try_intro` instead var intro: MClassDef is noinit + # The definition that introduces the class or null if not yet known. + # + # See `intro` + fun try_intro: nullable MClassDef do + if isset _intro then return _intro else return null + end + # Return the class `self` in the class hierarchy of the module `mmodule`. # # SEE: `MModule::flatten_mclass_hierarchy` @@ -480,6 +532,18 @@ 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 end @@ -550,7 +614,7 @@ class MClassDef # 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 + 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}" @@ -566,7 +630,7 @@ class MClassDef 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}" @@ -627,7 +691,7 @@ class MClassDef var in_hierarchy: nullable POSetElement[MClassDef] = null # Is the definition the one that introduced `mclass`? - fun is_intro: Bool do return mclass.intro == self + fun is_intro: Bool do return isset mclass._intro and mclass.intro == self # All properties introduced by the classdef var intro_mproperties = new Array[MProperty] @@ -697,6 +761,8 @@ abstract class MType if sup isa MNullableType then sup_accept_null = true sup = sup.mtype + else if sup isa MNotNullType then + sup = sup.mtype else if sup isa MNullType then sup_accept_null = true end @@ -704,16 +770,20 @@ abstract class MType # Can `sub` provide null or not? # Thus we can match with `sup_accept_null` # Also discard the nullable marker if it exists + var sub_reject_null = false if sub isa MNullableType then if not sup_accept_null then return false sub = sub.mtype + else if sub isa MNotNullType then + sub_reject_null = true + sub = sub.mtype else if sub isa MNullType then return sup_accept_null end # Now the case of direct null and nullable is over. # If `sub` is a formal type, then it is accepted if its bound is accepted - while sub isa MParameterType or sub isa MVirtualType do + while sub isa MFormalType do #print "3.is {sub} a {sup}?" # A unfixed formal type can only accept itself @@ -721,12 +791,16 @@ abstract class MType assert anchor != null sub = sub.lookup_bound(mmodule, anchor) + if sub_reject_null then sub = sub.as_notnull #print "3.is {sub} a {sup}?" # Manage the second layer of null/nullable if sub isa MNullableType then - if not sup_accept_null then return false + if not sup_accept_null and not sub_reject_null then return false + sub = sub.mtype + else if sub isa MNotNullType then + sub_reject_null = true sub = sub.mtype else if sub isa MNullType then return sup_accept_null @@ -734,10 +808,10 @@ abstract class MType end #print "4.is {sub} a {sup}? <- no more resolution" - assert sub isa MClassType # It is the only remaining type + assert sub isa MClassType else print "{sub} vararg_rank=1 var vararg_rank: Int is noinit - # The number or parameters + # The number of parameters fun arity: Int do return mparameters.length redef fun to_s @@ -1756,7 +1932,7 @@ abstract class MProperty # 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" + # Example: "my_package::my_module::MyClass::my_method" redef var full_name is lazy do return "{intro_mclassdef.mmodule.namespace_for(visibility)}::{intro_mclassdef.mclass.name}::{name}" end @@ -1808,7 +1984,7 @@ abstract class MProperty fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF] do assert not mtype.need_anchor - mtype = mtype.as_notnullable + mtype = mtype.undecorate var cache = self.lookup_definitions_cache[mmodule, mtype] if cache != null then return cache @@ -1848,7 +2024,7 @@ abstract class MProperty fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF] do assert not mtype.need_anchor - mtype = mtype.as_notnullable + mtype = mtype.undecorate # First, select all candidates var candidates = new Array[MPROPDEF] @@ -1926,7 +2102,7 @@ abstract class MProperty # REQUIRE: `mtype.has_mproperty(mmodule, self)` fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF] do - mtype = mtype.as_notnullable + mtype = mtype.undecorate var cache = self.lookup_all_definitions_cache[mmodule, mtype] if cache != null then return cache @@ -1988,6 +2164,10 @@ class MMethod do return self.is_init end + + # A specific method that is safe to call on null. + # Currently, only `==`, `!=` and `is_same_instance` are safe + fun is_null_safe: Bool do return name == "==" or name == "!=" or name == "is_same_instance" end # A global attribute @@ -2070,14 +2250,14 @@ abstract class MPropDef 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 "::" 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 "::" @@ -2121,7 +2301,7 @@ abstract class MPropDef redef var to_s: String 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`. #