# The signature of the property (where it is declared)
readable writable attr _signature: MMSignature
+ attr _signatures_cache: HashMap[MMType, MMSignature] = new HashMap[MMType, MMSignature]
+
# Return the adapted signature of self for a receiver of type t
meth signature_for(t: MMType): MMSignature do
- var x = self
- assert x isa MMConcreteProperty
- return x.signature.adaptation_to(t)
+ if t == local_class.get_type then return signature
+
+ if _signatures_cache.has_key(t) then return _signatures_cache[t]
+
+ var res = signature.adaptation_to(t)
+ _signatures_cache[t] = res
+ return res
end
end
# The return type
readable attr _return_type: MMType
+ # The closure parameters
+ readable attr _closures: Array[MMClosure] = new Array[MMClosure]
+
# Number of parameters
meth arity: Int
do
return true
end
assert _recv.module == s.recv.module
- assert arity == s.arity
- assert (_return_type == null) == (s.return_type == null)
+ if arity != s.arity or (_return_type == null) != (s.return_type == null) then return false
if _return_type != null and not _return_type < s.return_type then
return false
end
return false
end
end
+
+ if closures.length != s.closures.length then return false
+ for i in [0..closures.length[ do
+ if not s.closures[i] < closures[i] then return false
+ end
return true
end
redef meth to_s
do
- var s: String
+ var s = new Buffer
if _params != null and _params.length > 0 then
var tmp: String
var a = new Array[String].with_capacity(_params.length)
#a.add("{pn}: {p}")
a.add(p.to_s)
end
- s = "({a.join(",")})"
- else
- s = ""
+ s.append("({a.join(",")})")
end
if _return_type != null then
s.append(": {_return_type}")
end
- return s
+ return s.to_s
end
# Adapt the signature to a different receiver
if rv != null then
rv = rv.for_module(mod).adapt_to(r)
end
- return new MMSignature(p,rv,r)
+ var res = new MMSignature(p,rv,r)
+ for clos in _closures do
+ res.closures.add(clos.adaptation_to(r))
+ end
+ return res
+ end
+
+ attr _not_for_self_cache: MMSignature = null
+
+ # Return a type approximation if the reveiver is not self
+ # Useful for virtual types
+ meth not_for_self: MMSignature
+ do
+ var res = _not_for_self_cache
+ if res != null then return res
+
+ var need_for_self = false
+ var p = _params
+ if p != null then
+ p = new Array[MMType]
+ for i in _params do
+ var i2 = i.not_for_self
+ if i != i2 then need_for_self = true
+ p.add(i2)
+ end
+ end
+
+ var rv = _return_type
+ if rv != null then
+ rv = rv.not_for_self
+ if rv != _return_type then need_for_self = true
+ end
+
+ var clos = _closures
+ if clos != null then
+ clos = new Array[MMClosure]
+ for c in _closures do
+ var c2 = c.not_for_self
+ if c2 != c then need_for_self = true
+ clos.add(c2)
+ end
+ end
+
+ if need_for_self then
+ res = new MMSignature(p, rv, _recv)
+ res.closures.add_all(clos)
+ else
+ res = self
+ end
+
+ _not_for_self_cache = res
+ return res
end
init(params: Array[MMType], return_type: MMType, r: MMType)
end
end
+# A closure in a signature
+class MMClosure
+ # The signature of the closure
+ readable attr _signature: MMSignature
+
+ # Is the closure a brek one
+ # aka is defined with the break keyword thus does not return
+ readable attr _is_break: Bool
+
+ # Is the closure optional?
+ # ie is there a default definition
+ readable attr _is_optional: Bool
+
+ # Adapt the signature to a different receiver
+ meth adaptation_to(r: MMType): MMClosure
+ do
+ return new MMClosure(_signature.adaptation_to(r), _is_break, _is_optional)
+ end
+
+ init(s: MMSignature, is_break: Bool, is_optional: Bool)
+ do
+ _signature = s
+ _is_break = is_break
+ _is_optional = is_optional
+ end
+
+ meth not_for_self: MMClosure
+ do
+ var sig = _signature.not_for_self
+ if sig != _signature then
+ return new MMClosure(sig, _is_break, _is_optional)
+ else
+ return self
+ end
+ end
+
+ meth <(c: MMClosure): Bool
+ do
+ if c.is_optional and not is_optional then return false
+ if not c.is_break and is_break then return false
+ return c.signature < signature
+ end
+end
+
# Inheritance relation between two types
abstract class MMAncestor
# The inherited type
- readable writable attr _stype: MMType
+ readable writable attr _stype: MMType = null
# The inheriter (heir) type
- readable writable attr _inheriter: MMType
+ readable writable attr _inheriter: MMType = null
meth is_reffinement: Bool do
return stype.module != stype.module
# a double dispatch is needed
meth is_supertype(t: MMType): Bool is abstract
- # Select a method from its name
- meth select_method(name: Symbol): MMMethod
- do
- assert local_class != null
- assert name != null
- var res = select_property(local_class.method(name))
- assert res isa MMMethod
- return res
- end
-
- # Select an attribute from its name
- meth select_attribute(name: Symbol): MMAttribute
- do
- assert name != null
- assert local_class != null
- var res = select_property(local_class.attribute(name))
- assert res isa MMAttribute
- return res
- end
-
- # Select a local property from its global property
- meth select_property(t: MMGlobalProperty): MMLocalProperty is abstract
-
# Adapt self to another module
meth for_module(mod: MMModule): MMType is abstract
# Adapt self to another local class context
# Useful for genericity
+ # 'c' Must be a super-class of self
+ # Example:
+ # class A[E]
+ # class B[F] special A[F]
+ # class C[G] special B[String]
+ # class D special C[Float]
+ # 'A[Int]'.upcast_for('A') -> 'A[Int]'
+ # 'A[Int]'.upcast_for('B') -> abort
+ # 'B[Int]'.upcast_for('B') -> 'B[Int]'
+ # 'B[Int]'.upcast_for('A') -> 'A[Int]'
+ # 'B[Int]'.upcast_for('C') -> abort
+ # 'C[Int]'.upcast_for('C') -> 'C[Int]'
+ # 'C[Int]'.upcast_for('B') -> 'B[String]'
+ # 'C[Int]'.upcast_for('A') -> 'A[String]'
+ # 'D'.upcast_for('D') -> 'D'
+ # 'D'.upcast_for('C') -> 'C[Float]'
+ # 'D'.upcast_for('B') -> 'C[String]'
+ # 'D'.upcast_for('A') -> 'A[String]'
meth upcast_for(c: MMLocalClass): MMType is abstract
# Return a type approximation if the reveiver is not self
return t.local_class.cshe <= _local_class
end
- redef meth select_property(g)
- do
- assert _local_class != null
- if g == null then
- return null
- end
- return _local_class[g]
- end
-
redef meth for_module(mod)
do
var t: MMType = self
redef meth adapt_to(recv) do return self
- redef init(c: MMLocalClass)
+ init(c: MMLocalClass)
do
super(c)
end
# The type of null
class MMTypeNone
special MMType
- redef readable attr _module: MMModule
- redef meth <(t) do return true
- redef meth is_supertype(t) do return false
- redef meth local_class do abort
- redef meth upcast_for(c) do return self
+ redef readable attr _module: MMModule
+ redef meth <(t) do return true
+ redef meth to_s do return "null"
+ redef meth is_supertype(t) do return false
+ redef meth local_class do abort
+ redef meth upcast_for(c) do abort
private init(m: MMModule) do _module = m
end