lib: Split collections into readable and writable
[nit.git] / src / metamodel / static_type.nit
index d6edfde..6cf53b7 100644 (file)
@@ -82,6 +82,9 @@ class MMSignature
        # 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
@@ -97,8 +100,7 @@ class MMSignature
                        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
@@ -120,7 +122,7 @@ class MMSignature
 
        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)
@@ -130,14 +132,12 @@ class MMSignature
                                #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
@@ -158,7 +158,58 @@ class MMSignature
                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)
@@ -170,13 +221,50 @@ class MMSignature
        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
+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
@@ -216,29 +304,6 @@ abstract class MMType
        # 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
 
@@ -292,15 +357,6 @@ special MMTypeClass
                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
@@ -313,7 +369,7 @@ special MMTypeClass
 
        redef meth adapt_to(recv) do return self
 
-       redef init(c: MMLocalClass)
+       init(c: MMLocalClass)
        do
                super(c)
        end