model: check if specialization is allowed between class kinds
authorJean Privat <jean@pryen.org>
Mon, 2 Jun 2014 15:03:24 +0000 (11:03 -0400)
committerJean Privat <jean@pryen.org>
Mon, 2 Jun 2014 15:03:24 +0000 (11:03 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/model/model.nit
src/modelize_class.nit

index e20f44a..629dadb 100644 (file)
@@ -1898,6 +1898,24 @@ class MClassKind
                self.to_s = s
                self.need_init = need_init
        end
+
+       # Can a class of kind `self` specializes a class of kine `other`?
+       fun can_specialize(other: MClassKind): Bool
+       do
+               if other == interface_kind then return true # everybody can specialize interfaces
+               if self == interface_kind or self == enum_kind then
+                       # no other case for interfaces
+                       return false
+               else if self == extern_kind then
+                       # only compatible with themselve
+                       return self == other
+               else if other == enum_kind or other == extern_kind then
+                       # abstract_kind and concrete_kind are incompatible
+                       return false
+               end
+               # remain only abstract_kind and concrete_kind
+               return true
+       end
 end
 
 fun abstract_kind: MClassKind do return once new MClassKind("abstract class", true)
index a55d4c4..a72bfec 100644 (file)
@@ -200,6 +200,9 @@ redef class ModelBuilder
                                        error(ntype, "Error: supertypes cannot be a formal type")
                                        return
                                end
+                               if not mclass.kind.can_specialize(mtype.mclass.kind) then
+                                       error(ntype, "Error: {mclass.kind} {mclass} cannot specialize {mtype.mclass.kind} {mtype.mclass}")
+                               end
                                supertypes.add mtype
                                #print "new super : {mclass} < {mtype}"
                                if mtype.mclass.kind == extern_kind then specpointer = false