nitc :: MVirtualType :: defaultinit
# A virtual formal type.
class MVirtualType
super MFormalType
# The property associated with the type.
# Its the definitions of this property that determine the bound or the virtual type.
var mproperty: MVirtualTypeProp
redef fun location do return mproperty.location
redef fun model do return self.mproperty.intro_mclassdef.mmodule.model
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
private fun lookup_single_definition(mmodule: MModule, resolved_receiver: MType): MVirtualTypeDef
do
assert not resolved_receiver.need_anchor
var props = self.mproperty.lookup_definitions(mmodule, resolved_receiver)
if props.is_empty then
abort
else if props.length == 1 then
return props.first
end
var types = new ArraySet[MType]
var res = props.first
for p in props do
types.add(p.bound.as(not null))
if not res.is_fixed then res = p
end
if types.length == 1 then
return res
end
abort
end
# A VT is fixed when:
# * the VT is (re-)defined with the annotation `is fixed`
# * the receiver is an enum class since there is no subtype that can
# redefine this virtual type
redef fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType
do
assert not resolved_receiver.need_anchor
resolved_receiver = resolved_receiver.undecorate
assert resolved_receiver isa MClassType # It is the only remaining type
var prop = lookup_single_definition(mmodule, resolved_receiver)
var res = prop.bound
if res == null then return new MErrorType(model)
# Recursively lookup the fixed result
res = res.lookup_fixed(mmodule, resolved_receiver)
# For a fixed VT, return the resolved bound
if prop.is_fixed then return res
# For a enum receiver return the bound
if resolved_receiver.mclass.kind == enum_kind then return res
return self
end
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
if not cleanup_virtual then return self
assert can_resolve_for(mtype, anchor, mmodule)
if mproperty.is_selftype then return mtype
# self is a virtual type declared (or inherited) in mtype
# The point of the function it to get the bound of the virtual type that make sense for mtype
# But because mtype is maybe a virtual/formal type, we need to get a real receiver first
#print "{class_name}: {self}/{mtype}/{anchor}?"
var resolved_receiver
if mtype.need_anchor then
assert anchor != null
resolved_receiver = mtype.resolve_for(anchor, null, mmodule, true)
else
resolved_receiver = mtype
end
# Now, we can get the bound
var verbatim_bound = lookup_bound(mmodule, resolved_receiver)
# The bound is exactly as declared in the "type" property, so we must resolve it again
var res = verbatim_bound.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
return res
end
redef fun can_resolve_for(mtype, anchor, mmodule)
do
if mtype.need_anchor then
assert anchor != null
mtype = mtype.anchor_to(mmodule, anchor)
end
return mtype.has_mproperty(mmodule, mproperty)
end
redef fun to_s do return self.mproperty.to_s
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
src/model/model.nit:1515,1--1623,3