for m in self.in_importation.greaters do
for cd in m.mclassdefs do
var c = cd.mclass
+ res.add_node(c)
for s in cd.supertypes do
res.add_edge(c, s.mclass)
end
end
# Try to get the primitive method named `name' on the type `recv'
- fun try_get_primitive_method(name: String, recv: MType): nullable MMethod
+ fun try_get_primitive_method(name: String, recv: MClass): nullable MMethod
do
var props = self.model.get_mproperties_by_name(name)
if props == null then return null
var res: nullable MMethod = null
for mprop in props do
assert mprop isa MMethod
- if not recv.has_mproperty(self, mprop) then continue
- if res == null then
- res = mprop
- else
- print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
- abort
+ var intro = mprop.intro_mclassdef
+ for mclassdef in recv.mclassdefs do
+ if not self.in_importation.greaters.has(mclassdef.mmodule) then continue
+ if not mclassdef.in_hierarchy.greaters.has(intro) then continue
+ if res == null then
+ res = mprop
+ else if res != mprop then
+ print("Fatal Error: ambigous property name '{name}'; conflict between {mprop.full_name} and {res.full_name}")
+ abort
+ end
end
end
return res
# Internal name combining the module and the class
# Example: "mymodule#MyClass"
- redef fun to_s do return "{mmodule}#{mclass}"
+ redef var to_s: String
init(mmodule: MModule, bound_mtype: MClassType, location: Location, parameter_names: Array[String])
do
mmodule.mclassdefs.add(self)
mclass.mclassdefs.add(self)
self.parameter_names = parameter_names
+ self.to_s = "{mmodule}#{mclass}"
end
# All declared super-types
# * foo(othertype, anchor, mmodule)
# * foo(anchor, mmodule, othertype)
# * foo(othertype, mmodule, anchor)
-#
-# FIXME: Add a 'is_valid_anchor' to improve imputability.
-# Currently, anchors are used "as it" without check thus if the caller gives a
-# bad anchor, then the method will likely crash (abort) in a bad case
abstract class MType
# The model of the type
# The typing is done using the standard typing policy of Nit.
#
# REQUIRE: anchor == null implies not self.need_anchor and not sup.need_anchor
+ # REQUIRE: anchor != null implies self.can_resolve_for(anchor, null, mmodule) and sup.can_resolve_for(anchor, null, mmodule)
fun is_subtype(mmodule: MModule, anchor: nullable MClassType, sup: MType): Bool
do
var sub = self
if anchor == null then
assert not sub.need_anchor
assert not sup.need_anchor
+ else
+ assert sub.can_resolve_for(anchor, null, mmodule)
+ assert sup.can_resolve_for(anchor, null, mmodule)
end
# First, resolve the formal types to a common version in the receiver
# H[Int] supertype_to G #-> G[Int, Bool]
#
# REQUIRE: `super_mclass' is a super-class of `self'
+ # REQUIRE: self.need_anchor implies anchor != null and self.can_resolve_for(anchor, null, mmodule)
# ENSURE: return.mclass = mclass
fun supertype_to(mmodule: MModule, anchor: nullable MClassType, super_mclass: MClass): MClassType
do
#
# E.resolve_for(A[Array[F]],B[nullable Object]) #-> Array[F]
#
+ # The resolution can be done because `E` make sense for the class A (see `can_resolve_for`)
+ #
# TODO: Explain the cleanup_virtual
#
# FIXME: the parameter `cleanup_virtual' is just a bad idea, but having
# ENSURE: not self.need_anchor implies return == self
fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MType is abstract
+ # Can the type be resolved?
+ #
+ # In order to resolve open types, the formal types must make sence.
+ #
+ # ## Example
+ #
+ # class A[E]
+ # end
+ # class B[F]
+ # end
+ #
+ # E.can_resolve_for(A[Int]) #-> true, E make sense in A
+ # E.can_resolve_for(B[Int]) #-> false, E does not make sense in B
+ # B[E].can_resolve_for(A[F], B[Object]) #-> true,
+ # B[E] is a red hearing only the E is important,
+ # E make sense in A
+ #
+ # REQUIRE: anchor != null implies not anchor.need_anchor
+ # REQUIRE: mtype.need_anchor implies anchor != null and mtype.can_resolve_for(anchor, null, mmodule)
+ # ENSURE: not self.need_anchor implies return == true
+ fun can_resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule): Bool is abstract
+
# Return the nullable version of the type
# If the type is already nullable then self is returned
fun as_nullable: MType
redef fun resolve_for(mtype: MType, anchor: nullable MClassType, mmodule: MModule, cleanup_virtual: Bool): MClassType do return self
+ redef fun can_resolve_for(mtype, anchor, mmodule) do return true
+
redef fun collect_mclassdefs(mmodule)
do
assert not self.need_anchor
break
end
end
+
+ self.to_s = "{mclass}[{arguments.join(", ")}]"
end
# Recursively print the type of the arguments within brackets.
# Example: "Map[String, List[Int]]"
- redef fun to_s
- do
- return "{mclass}[{arguments.join(", ")}]"
- end
+ redef var to_s: String
redef var need_anchor: Bool
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))
return mclass.get_mtype(types)
end
+ redef fun can_resolve_for(mtype, anchor, mmodule)
+ do
+ if not need_anchor then return true
+ for t in arguments do
+ if not t.can_resolve_for(mtype, anchor, mmodule) then return false
+ end
+ return true
+ end
+
+
redef fun depth
do
var dmax = 0
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
+ assert can_resolve_for(mtype, anchor, mmodule)
# 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
return self
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
init(mproperty: MProperty)
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 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.collect_mclassdefs(mmodule).has(mclass.intro)
+ end
+
init(mclass: MClass, rank: Int)
do
self.mclass = mclass
init(mtype: MType)
do
self.mtype = mtype
+ self.to_s = "nullable {mtype}"
end
- redef fun to_s do return "nullable {mtype}"
+ redef var to_s: String
redef fun need_anchor do return mtype.need_anchor
redef fun as_nullable do return self
return res.as_nullable
end
+ redef fun can_resolve_for(mtype, anchor, mmodule)
+ do
+ return self.mtype.can_resolve_for(mtype, anchor, mmodule)
+ end
+
redef fun depth do return self.mtype.depth
redef fun length do return self.mtype.length
redef fun as_nullable do return self
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 fun collect_mclassdefs(mmodule) do return new HashSet[MClassDef]
self.location = location
mclassdef.mpropdefs.add(self)
mproperty.mpropdefs.add(self)
+ self.to_s = "{mclassdef}#{mproperty}"
end
# Internal name combining the module, the class and the property
# Example: "mymodule#MyClass#mymethod"
- redef fun to_s
- do
- return "{mclassdef}#{mproperty}"
- end
+ redef var to_s: String
# Is self the definition that introduce the property?
fun is_intro: Bool do return mproperty.intro == self
# The signature attached to the property definition
var msignature: nullable MSignature writable = null
+
+ # The the method definition abstract?
+ var is_abstract: Bool writable = false
end
# A local definition of an attribute