package xhl.core.validator;

import com.google.common.collect.ImmutableList;
import xhl.core.elements.*;

public class Type {
    public static final Type AnyType = new Type("AnyType");
    public static final Type Null = new Type("Null");
    public static final Type Element = new Type("Element");
    public static final Type Boolean = new Type("Boolean");
    public static final Type Number = new Type("Number");
    public static final Type String = new Type("String");
    public static final Type Symbol = new Type("Symbol");
    public static final Type List = new Type("List");
    public static final Type Map = new Type("Map");
    public static final Type Block = new Type("Block");
    public static final Type Combination = new Type("Combination");

    public static final ImmutableList<Type> defaultTypes = ImmutableList.of
            (AnyType, Null, Element, Boolean, Number, String, Symbol, List,
                    Map, Block, Combination);

    private final Symbol name;

    public Type(Symbol name) {
        this.name = name;
    }

    private Type(String name) {
        this(new Symbol(name));
    }

    public Symbol getName() {
        return name;
    }

    @Override
    public boolean equals(Object obj) {
        return obj instanceof Type && name.equals(((Type) obj).name);
    }

    @Override
    public java.lang.String toString() {
        return name.toString();
    }

    /**
     * Check is a type is compatible with <code>that</code> type.
     */
    public boolean is(Type that) {
        return this.equals(AnyType) || that.equals(AnyType) || this.equals
                (that);
    }

    public boolean isNamed(String n) {
        return name.isNamed(n);
    }

    public static Type typeOfElement(Expression ex) {
        if (ex instanceof Symbol)
            return Symbol;
        if (ex instanceof SString)
            return String;
        if (ex instanceof SNumber)
            return Number;
        if (ex instanceof SBoolean)
            return Boolean;
        if (ex instanceof SList)
            return List;
        if (ex instanceof SMap)
            return Map;
        if (ex instanceof Combination)
            return Combination;
        if (ex instanceof Block)
            return Block;
        return AnyType;
    }
}
@@ -99,16 +99,97 @@
 nts.*;%0A%0A
+import java.util.Set;%0A%0Aimport static com.google.common.collect.Sets.newHashSet;%0A%0A
 public c
@@ -1068,16 +1068,71 @@
 ol name;
+%0A    private final Set%3CType%3E supertypes = newHashSet();
 %0A%0A    pu
@@ -1310,32 +1310,121 @@
 rn name;%0A    %7D%0A%0A
+    public boolean addSupertype(Type type) %7B%0A        return supertypes.add(type);%0A    %7D%0A%0A
     @Override%0A  
@@ -1811,28 +1811,16 @@
 Type) %7C%7C
- this.equals
 %0A       
@@ -1828,16 +1828,56 @@
         
+this.equals(that) %7C%7C supertypes.contains
 (that);%0A

Implement a concept of supertypes