# The only null type
var null_type = new MNullType(self)
+ # The only bottom type
+ var bottom_type: MBottomType = null_type.as_notnull
+
# Build an ordered tree with from `concerns`
fun concerns_tree(mconcerns: Collection[MConcern]): ConcernsTree do
var seen = new HashSet[MConcern]
# (introduction and refinement)
var mclassdefs = new Array[MClassDef]
+ private var mclassdef_sorter: MClassDefSorter is lazy do
+ return new MClassDefSorter(self)
+ end
+
+ private var mpropdef_sorter: MPropDefSorter is lazy do
+ return new MPropDefSorter(self)
+ end
+
# Does the current module has a given class `mclass`?
# Return true if the mmodule introduces, refines or imports a class.
# Visibility is not considered.
# The most general is first, the most specific is last
fun linearize_mclassdefs(mclassdefs: Array[MClassDef])
do
- var sorter = new MClassDefSorter(self)
- sorter.sort(mclassdefs)
+ mclassdef_sorter.sort(mclassdefs)
end
# Sort a given array of property definitions using the linearization order of the module
# The most general is first, the most specific is last
fun linearize_mpropdefs(mpropdefs: Array[MPropDef])
do
- var sorter = new MPropDefSorter(self)
- sorter.sort(mpropdefs)
+ mpropdef_sorter.sort(mpropdefs)
end
private var flatten_mclass_hierarchy_cache: nullable POSet[MClass] = null
# The primitive type `String`
var string_type: MClassType = self.get_primitive_class("String").mclass_type is lazy
- # The primitive type `NativeString`
- var native_string_type: MClassType = self.get_primitive_class("NativeString").mclass_type is lazy
+ # The primitive type `CString`
+ var c_string_type: MClassType = self.get_primitive_class("CString").mclass_type is lazy
# A primitive type of `Array`
fun array_type(elt_type: MType): MClassType do return array_class.get_mtype([elt_type])
super Comparator
redef type COMPARED: MPropDef
var mmodule: MModule
+
redef fun compare(pa, pb)
do
var a = pa.mclassdef
var b = pb.mclassdef
- var ca = a.mclass
- var cb = b.mclass
- if ca != cb then return mmodule.flatten_mclass_hierarchy.compare(ca, cb)
- return mmodule.model.mclassdef_hierarchy.compare(a, b)
+ return mmodule.mclassdef_sorter.compare(a, b)
end
end
# 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
+ redef fun mdoc_or_fallback
+ do
+ # Don’t use `intro.mdoc_or_fallback` because it would create an infinite
+ # recursion.
+ return intro.mdoc
+ end
end
# ENSURE: `bound_mtype.mclass == self.mclass`
var bound_mtype: MClassType
- redef var location: Location
+ redef var location
redef fun visibility do return mclass.visibility
# All property introductions and redefinitions (not inheritance) in `self` by its associated property.
var mpropdefs_by_property = new HashMap[MProperty, MPropDef]
+
+ redef fun mdoc_or_fallback do return mdoc or else mclass.mdoc_or_fallback
end
# A global static type
#
# Explanation of the example:
# In H, T is set to B, because "H super G[B]", and U is bound to Y,
- # because "redef type U: Y". Therefore, Map[T, U] is bound to
+ # because "redef type U: Y". Therefore, Map[T, U] is bound to
# Map[B, Y]
#
+ # REQUIRE: `self.need_anchor implies anchor != null`
# ENSURE: `not self.need_anchor implies result == self`
# ENSURE: `not result.need_anchor`
- fun anchor_to(mmodule: MModule, anchor: MClassType): MType
+ fun anchor_to(mmodule: MModule, anchor: nullable MClassType): MType
do
if not need_anchor then return self
- assert not anchor.need_anchor
+ assert anchor != null and not anchor.need_anchor
# Just resolve to the anchor and clear all the virtual types
var res = self.resolve_for(anchor, null, mmodule, true)
assert not res.need_anchor
#
# `MErrorType` are used in result with conflict or inconsistencies.
#
+ # See `is_legal_in` to check conformity with generic bounds.
fun is_ok: Bool do return true
+ # Is the type legal in a given `mmodule` (with an optional `anchor`)?
+ #
+ # A type is valid if:
+ #
+ # * it does not contain a `MErrorType` (see `is_ok`).
+ # * its generic formal arguments are within their bounds.
+ fun is_legal_in(mmodule: MModule, anchor: nullable MClassType): Bool do return is_ok
+
# Can the type be resolved?
#
# In order to resolve open types, the formal types must make sence.
# * H[G[A], B] -> 3
#
# Formal types have a depth of 1.
+ # Only `MClassType` and `MFormalType` nodes are counted.
fun depth: Int
do
return 1
# * H[G[A], B] -> 4
#
# Formal types have a length of 1.
+ # Only `MClassType` and `MFormalType` nodes are counted.
fun length: Int
do
return 1
redef fun need_anchor do return false
- redef fun anchor_to(mmodule: MModule, anchor: MClassType): MClassType
+ redef fun anchor_to(mmodule, anchor): MClassType
do
return super.as(MClassType)
end
private var collect_mclasses_cache = new HashMap[MModule, Set[MClass]]
private var collect_mtypes_cache = new HashMap[MModule, Set[MClassType]]
+ redef fun mdoc_or_fallback do return mclass.mdoc_or_fallback
end
# A type based on a generic class.
return super
end
+ redef fun is_legal_in(mmodule, anchor)
+ do
+ var mtype
+ if need_anchor then
+ assert anchor != null
+ mtype = anchor_to(mmodule, anchor)
+ else
+ mtype = self
+ end
+ if not mtype.is_ok then return false
+ return mtype.is_subtype(mmodule, null, mtype.mclass.intro.bound_mtype)
+ end
redef fun depth
do
redef fun model do return self.mproperty.intro_mclassdef.mmodule.model
- redef fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
+ redef fun lookup_bound(mmodule, resolved_receiver)
do
+ # There is two possible invalid cases: the vt does not exists in resolved_receiver or the bound is broken
+ if not resolved_receiver.has_mproperty(mmodule, mproperty) then return new MErrorType(model)
return lookup_single_definition(mmodule, resolved_receiver).bound or else new MErrorType(model)
end
redef fun full_name do return self.mproperty.full_name
redef fun c_name do return self.mproperty.c_name
+
+ redef fun mdoc_or_fallback do return mproperty.mdoc_or_fallback
end
# The type associated to a formal parameter generic type of a class
return res
end
end
- abort
+ # Cannot found `self` in `resolved_receiver`
+ return new MErrorType(model)
end
# A PT is fixed when:
redef fun is_ok do return mtype.is_ok
+ redef fun is_legal_in(mmodule, anchor) do return mtype.is_legal_in(mmodule, anchor)
+
redef fun lookup_fixed(mmodule, resolved_receiver)
do
var t = mtype.lookup_fixed(mmodule, resolved_receiver)
redef fun c_name do return "null"
redef fun as_nullable do return self
- redef var as_notnull = new MBottomType(model) is lazy
+ redef var as_notnull: MBottomType = new MBottomType(model) is lazy
redef fun need_anchor do return false
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
redef fun can_resolve_for(mtype, anchor, mmodule) do return true
redef var location
- redef fun mdoc_or_fallback do return intro.mdoc_or_fallback
+ redef fun mdoc_or_fallback
+ do
+ # Don’t use `intro.mdoc_or_fallback` because it would create an infinite
+ # recursion.
+ return intro.mdoc
+ end
# The canonical name of the property.
#
assert has_next_property: i.is_ok
return i.item
end
+
+ redef fun mdoc_or_fallback do return mdoc or else mproperty.mdoc_or_fallback
end
# A local definition of a method