X-Git-Url: http://nitlanguage.org diff --git a/src/model/model.nit b/src/model/model.nit index b19e124..7481338 100644 --- a/src/model/model.nit +++ b/src/model/model.nit @@ -32,6 +32,8 @@ module model import poset import location import mmodule +import mdoc +import ordered_tree private import more_collections redef class Model @@ -105,6 +107,35 @@ redef class Model # The only null type var null_type: MNullType = new MNullType(self) + + # Build an ordered tree with from `concerns` + fun concerns_tree(mconcerns: Collection[MConcern]): ConcernsTree do + var seen = new HashSet[MConcern] + var res = new ConcernsTree + + var todo = new Array[MConcern] + todo.add_all mconcerns + + while not todo.is_empty do + var c = todo.pop + if seen.has(c) then continue + var pc = c.parent_concern + if pc == null then + res.add(null, c) + else + res.add(pc, c) + todo.add(pc) + end + seen.add(c) + end + + return res + end +end + +# An OrderedTree that can be easily refined for display purposes +class ConcernsTree + super OrderedTree[MConcern] end redef class MModule @@ -222,7 +253,12 @@ redef class MModule print("Fatal Error: no primitive class {name}") exit(1) end - assert cla.length == 1 else print cla.join(", ") + if cla.length != 1 then + var msg = "Fatal Error: more than one primitive class {name}:" + for c in cla do msg += " {c.full_name}" + print msg + exit(1) + end return cla.first end @@ -287,6 +323,8 @@ end # belong to a hierarchy since the property and the # hierarchy of a class depends of a module. class MClass + super MEntity + # The module that introduce the class # While classes are not bound to a specific module, # the introducing module is used for naming an visibility @@ -294,7 +332,7 @@ class MClass # The short name of the class # In Nit, the name of a class cannot evolve in refinements - var name: String + redef var name: String # The canonical name of the class # Example: `"owner::module::MyClass"` @@ -412,6 +450,8 @@ end # class. Unlike `MClass`, a `MClassDef` is a local definition that belong to # a specific module class MClassDef + super MEntity + # The module where the definition is var mmodule: MModule @@ -453,6 +493,9 @@ class MClassDef self.to_s = "{mmodule}#{mclass}" end + # Actually the name of the `mclass` + redef fun name do return mclass.name + # All declared super-types # FIXME: quite ugly but not better idea yet var supertypes: Array[MClassType] = new Array[MClassType] @@ -542,6 +585,7 @@ end # * foo(anchor, mmodule, othertype) # * foo(othertype, mmodule, anchor) abstract class MType + super MEntity # The model of the type fun model: Model is abstract @@ -1412,7 +1456,7 @@ class MSignature redef fun to_s do - var b = new Buffer + var b = new FlatBuffer if not mparameters.is_empty then b.append("(") for i in [0..mparameters.length[ do @@ -1461,6 +1505,15 @@ class MParameter # Is the parameter a vararg? var is_vararg: Bool + redef fun to_s + do + if is_vararg then + return "{name}: {mtype}..." + else + return "{name}: {mtype}" + end + end + fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MParameter do if not self.mtype.need_anchor then return self @@ -1482,6 +1535,8 @@ end # of any dynamic type). # For instance, a call site "x.foo" is associated to a `MProperty`. abstract class MProperty + super MEntity + # The associated MPropDef subclass. # The two specialization hierarchy are symmetric. type MPROPDEF: MPropDef @@ -1492,7 +1547,7 @@ abstract class MProperty var intro_mclassdef: MClassDef # The (short) name of the property - var name: String + redef var name: String # The canonical name of the property # Example: "owner::my_module::MyClass::my_method" @@ -1612,12 +1667,12 @@ abstract class MProperty var cd2 = pd2.mclassdef var c2 = cd2.mclass if c2.mclass_type == c1.mclass_type then - if cd2.mmodule.in_importation <= cd1.mmodule then + if cd2.mmodule.in_importation < cd1.mmodule then # cd2 refines cd1; therefore we skip pd1 keep = false break end - else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) then + else if cd2.bound_mtype.is_subtype(mmodule, null, cd1.bound_mtype) and cd2.bound_mtype != cd1.bound_mtype then # cd2 < cd1; therefore we skip pd1 keep = false break @@ -1696,6 +1751,10 @@ class MMethod super end + # Is the property defined at the top_level of the module? + # Currently such a property are stored in `Object` + var is_toplevel: Bool writable = false + # Is the property a constructor? # Warning, this property can be inherited by subclasses with or without being a constructor # therefore, you should use `is_init_for` the verify if the property is a legal constructor for a given class @@ -1745,6 +1804,7 @@ end # Unlike `MProperty`, a `MPropDef` is a local definition that belong to a # specific class definition (which belong to a specific module) abstract class MPropDef + super MEntity # The associated `MProperty` subclass. # the two specialization hierarchy are symmetric @@ -1772,6 +1832,9 @@ abstract class MPropDef self.to_s = "{mclassdef}#{mproperty}" end + # Actually the name of the `mproperty` + redef fun name do return mproperty.name + # Internal name combining the module, the class and the property # Example: "mymodule#MyClass#mymethod" redef var to_s: String @@ -1813,8 +1876,14 @@ class MMethodDef # The signature attached to the property definition var msignature: nullable MSignature writable = null - # The the method definition abstract? + # Is the method definition abstract? var is_abstract: Bool writable = false + + # Is the method definition intern? + var is_intern writable = false + + # Is the method definition extern? + var is_extern writable = false end # A local definition of an attribute @@ -1869,10 +1938,28 @@ class MClassKind self.to_s = s self.need_init = need_init end + + # Can a class of kind `self` specializes a class of kine `other`? + fun can_specialize(other: MClassKind): Bool + do + if other == interface_kind then return true # everybody can specialize interfaces + if self == interface_kind or self == enum_kind then + # no other case for interfaces + return false + else if self == extern_kind then + # only compatible with themselve + return self == other + else if other == enum_kind or other == extern_kind then + # abstract_kind and concrete_kind are incompatible + return false + end + # remain only abstract_kind and concrete_kind + return true + end end fun abstract_kind: MClassKind do return once new MClassKind("abstract class", true) fun concrete_kind: MClassKind do return once new MClassKind("class", true) fun interface_kind: MClassKind do return once new MClassKind("interface", false) fun enum_kind: MClassKind do return once new MClassKind("enum", false) -fun extern_kind: MClassKind do return once new MClassKind("extern", false) +fun extern_kind: MClassKind do return once new MClassKind("extern class", false)