package org.simantics.scl.compiler.types; import java.util.ArrayList; import java.util.Map; import org.simantics.scl.compiler.environment.Environment; import org.simantics.scl.compiler.internal.types.HashCodeUtils; import org.simantics.scl.compiler.internal.types.TypeHashCodeContext; import org.simantics.scl.compiler.internal.types.ast.TypeAst; import org.simantics.scl.compiler.types.exceptions.KindUnificationException; import org.simantics.scl.compiler.types.kinds.KMetaVar; import org.simantics.scl.compiler.types.kinds.Kind; import org.simantics.scl.compiler.types.kinds.Kinds; import org.simantics.scl.compiler.types.util.Polarity; import org.simantics.scl.compiler.types.util.TypeUnparsingContext; import gnu.trove.map.hash.THashMap; import gnu.trove.set.hash.THashSet; /** * This class represents the types of variables and constants in SCL. * It is not meant to be extended outside of this package. * * @author Hannu Niemistö */ public abstract class Type { public static final boolean NULL_CHECKS = true; public static final Type[] EMPTY_ARRAY = new Type[0]; public static final int FUN_ID = 0; public static final int APPLY_ID = 1; public static final int CON_ID = 2; public static final int FORALL_ID = 3; public static final int PRED_ID = 4; public static final int METAVAR_ID = 5; public static final int VAR_ID = 6; public static final int UNION_ID = 7; protected static final int APPLY_HASH = HashCodeUtils.preprocessValue(0); protected static final int FORALL_HASH = HashCodeUtils.preprocessValue(1); protected static final int FUN_HASH = HashCodeUtils.preprocessValue(2); protected static final int PRED_HASH = HashCodeUtils.preprocessValue(3); protected static final int UNION_HASH = HashCodeUtils.preprocessValue(4); protected static final int BOUND_VAR_HASH = HashCodeUtils.preprocessValue(5); /* * This class is not meant to be extended outside of this package. */ Type() { } /** * Recursively replace a type variable with a type in this type expression. * @param var A type variable to be replaced * @param replacement A the replacement type * @return A new type instance, or this, if no changes are necessary */ public abstract Type replace(TVar var, Type replacement); public Type replace(TVar[] var, Type[] replacement) { Type cur = this; for(int i=0;i Type replace(THashMap substitution) { Type cur = this; for(Map.Entry entry : substitution.entrySet()) cur = cur.replace(entry.getKey(), entry.getValue()); return cur; } abstract TypeAst toTypeAst(TypeUnparsingContext context); @Override public String toString() { return toString(new TypeUnparsingContext()); } public String toString(TypeUnparsingContext context) { return toTypeAst(context).toString(); } public void toString(TypeUnparsingContext context, StringBuilder b) { toTypeAst(context).toString(b); } public void toString(TypeUnparsingContext context, StringBuilder b, int precedence) { toTypeAst(context).toString(b, precedence); } public String toName() { TypeUnparsingContext context = new TypeUnparsingContext(); StringBuilder b = new StringBuilder(); toName(context, b); return b.toString(); } public abstract void toName(TypeUnparsingContext context, StringBuilder b); @Override public boolean equals(Object obj) { if(this == obj) return true; if(obj == null || !(obj instanceof Type)) return false; return Types.equals(this, (Type)obj); } @Override public int hashCode() { return hashCode(HashCodeUtils.SEED); } public abstract void updateHashCode(TypeHashCodeContext context); public abstract int hashCode(int hash); public abstract int hashCode(int hash, TVar[] boundVars); public abstract void collectFreeVars(ArrayList vars); public abstract void collectMetaVars(ArrayList vars); public abstract void collectMetaVars(THashSet vars); public abstract void collectEffectMetaVars(ArrayList vars); public abstract boolean contains(TMetaVar other); public abstract Type convertMetaVarsToVars(); public abstract boolean isGround(); public Kind inferKind(Environment context) throws KindUnificationException { KMetaVar var = Kinds.metaVar(); checkKind(context, var); return Kinds.canonical(var); } public void checkKind(Environment context, Kind requiredKind) throws KindUnificationException { Kind kind = inferKind(context); Kinds.unify(kind, requiredKind); } public abstract boolean containsMetaVars(); public abstract int getClassId(); public boolean isMinimal() { return true; } public boolean isMaximal() { return true; } public abstract void addPolarity(Polarity polarity); public void collectConcreteEffects(ArrayList concreteEffects) { } public abstract Type head(); /** * Creates an independent copy of the type, but replaces all effects by metavars */ public abstract Type copySkeleton(THashMap metaVarMap); public abstract boolean equalsCanonical(Type other); public Type canonical() { return this; } public abstract Kind getKind(Environment context); }