nitc :: MType :: resolve_for
mtype
If cleanup_virtual
is true, then virtual types are also replaced
with their bounds.
This function returns self if need_anchor
is false.
class G[E] end
class H[F] super G[F] end
class X[Z] end
Explanation of the example:
This function is mainly used to inherit a signature.
Because, unlike anchor_to
, we do not want a full resolution of
a type but only an adapted version of it.
class A[E]
fun foo(e:E):E is abstract
end
class B super A[Int] end
The signature on foo is (e: E): E If we resolve the signature for B, we get (e:Int):Int
class A[E]
fun foo(e:E):E is abstract
end
class C[F]
var a: A[Array[F]]
fun bar do a.foo(x) # <- x is here
end
The first question is: is foo available on a
?
The static type of a is A[Array[F]]
, that is an open type.
in order to find a method foo
, whe must look at a resolved type.
A[Array[F]].anchor_to(C[nullable Object]) #-> A[Array[nullable Object]]
the method foo
exists in A[Array[nullable Object]]
, therefore foo
exists for a
.
The next question is: what is the accepted types for x
?
the signature of foo
is foo(e:E)
, thus we must resolve the type E
E.resolve_for(A[Array[F]],C[nullable Object]) #-> Array[F]
The resolution can be done because E
make sense for the class A (see can_resolve_for
)
FIXME: the parameter cleanup_virtual
is just a bad idea, but having
two function instead of one seems also to be a bad idea.
REQUIRE: can_resolve_for(mtype, anchor, mmodule)
ENSURE: not self.need_anchor implies result == self
# Replace formals generic types in self with resolved values in `mtype`
# If `cleanup_virtual` is true, then virtual types are also replaced
# with their bounds.
#
# This function returns self if `need_anchor` is false.
#
# ## Example 1
#
# ~~~
# class G[E] end
# class H[F] super G[F] end
# class X[Z] end
# ~~~
#
# * Array[E].resolve_for(H[Int]) #-> Array[Int]
# * Array[E].resolve_for(G[Z], X[Int]) #-> Array[Z]
#
# Explanation of the example:
# * Array[E].need_anchor is true because there is a formal generic parameter type E
# * E makes sense for H[Int] because E is a formal parameter of G and H specialize G
# * Since "H[F] super G[F]", E is in fact F for H
# * More specifically, in H[Int], E is Int
# * So, in H[Int], Array[E] is Array[Int]
#
# This function is mainly used to inherit a signature.
# Because, unlike `anchor_to`, we do not want a full resolution of
# a type but only an adapted version of it.
#
# ## Example 2
#
# ~~~
# class A[E]
# fun foo(e:E):E is abstract
# end
# class B super A[Int] end
# ~~~
#
# The signature on foo is (e: E): E
# If we resolve the signature for B, we get (e:Int):Int
#
# ## Example 3
#
# ~~~nitish
# class A[E]
# fun foo(e:E):E is abstract
# end
# class C[F]
# var a: A[Array[F]]
# fun bar do a.foo(x) # <- x is here
# end
# ~~~
#
# The first question is: is foo available on `a`?
#
# The static type of a is `A[Array[F]]`, that is an open type.
# in order to find a method `foo`, whe must look at a resolved type.
#
# A[Array[F]].anchor_to(C[nullable Object]) #-> A[Array[nullable Object]]
#
# the method `foo` exists in `A[Array[nullable Object]]`, therefore `foo` exists for `a`.
#
# The next question is: what is the accepted types for `x`?
#
# the signature of `foo` is `foo(e:E)`, thus we must resolve the type E
#
# E.resolve_for(A[Array[F]],C[nullable Object]) #-> Array[F]
#
# The resolution can be done because `E` make sense for the class A (see `can_resolve_for`)
#
# FIXME: the parameter `cleanup_virtual` is just a bad idea, but having
# two function instead of one seems also to be a bad idea.
#
# REQUIRE: `can_resolve_for(mtype, anchor, mmodule)`
# ENSURE: `not self.need_anchor implies result == self`
fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MType is abstract
src/model/model.nit:1050,2--1124,119
redef fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MClassType do return self
src/model/model.nit:1318,2--133
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
return res
end
src/model/model.nit:1786,2--1790,4
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
src/model/model.nit:1903,2--78
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
src/model/model.nit:1929,2--78
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
src/model/model.nit:1953,2--78
redef fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MSignature
do
var params = new Array[MParameter]
for p in self.mparameters do
params.add(p.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
end
var ret = self.return_mtype
if ret != null then
ret = ret.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
end
var res = new MSignature(params, ret)
return res
end
src/model/model.nit:2081,2--2093,4
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
src/vm/virtual_machine.nit:900,2--78
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do
not_available
return self
end
src/doc/model_ext.nit:40,2--43,4
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
if not need_anchor then return self
assert can_resolve_for(mtype, anchor, mmodule)
var types = new Array[MType]
for t in arguments do
types.add(t.resolve_for(mtype, anchor, mmodule, cleanup_virtual))
end
return mclass.get_mtype(types)
end
src/model/model.nit:1446,2--1455,4
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
src/model/model.nit:1581,2--1605,4
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
assert can_resolve_for(mtype, anchor, mmodule)
#print "{class_name}: {self}/{mtype}/{anchor}?"
if mtype isa MGenericType and mtype.mclass == self.mclass then
return mtype.arguments[self.rank]
end
# self is a parameter type of mtype (or of a super-class of 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
# FIXME: What happens here is far from clear. Thus this part must be validated and clarified
var resolved_receiver
if mtype.need_anchor then
assert anchor != null
resolved_receiver = mtype.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, true)
else
resolved_receiver = mtype
end
if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
if resolved_receiver isa MParameterType then
assert anchor != null
assert resolved_receiver.mclass == anchor.mclass
resolved_receiver = anchor.arguments[resolved_receiver.rank]
if resolved_receiver isa MNullableType then resolved_receiver = resolved_receiver.mtype
end
assert resolved_receiver isa MClassType # It is the only remaining type
# Eh! The parameter is in the current class.
# So we return the corresponding argument, no mater what!
if resolved_receiver.mclass == self.mclass then
var res = resolved_receiver.arguments[self.rank]
#print "{class_name}: {self}/{mtype}/{anchor} -> direct {res}"
return res
end
if resolved_receiver.need_anchor then
assert anchor != null
resolved_receiver = resolved_receiver.resolve_for(anchor, null, mmodule, false)
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)
#print "{class_name}: {self}/{mtype}/{anchor} -> indirect {res}"
return res
end
src/model/model.nit:1709,2--1758,4
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
var res = super
return res.as_nullable
end
src/model/model.nit:1846,2--1850,4
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
var res = super
return res.as_notnull
end
src/model/model.nit:1875,2--1879,4