--- /dev/null
+package org.simantics.scl.compiler.types;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
+import org.simantics.scl.compiler.internal.types.ast.TForAllAst;
+import org.simantics.scl.compiler.internal.types.ast.TypeAst;
+import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
+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;
+
+
+public class TForAll extends Type {
+ public final TVar var;
+ public final Type type;
+
+ TForAll(TVar var, Type type) {
+ if(NULL_CHECKS) {
+ if(var == null || type == null)
+ throw new NullPointerException();
+ }
+ this.var = var;
+ this.type = type;
+ }
+
+ private TForAll create(Type type) {
+ if(type == this.type)
+ return this;
+ else
+ return new TForAll(var, type);
+ }
+
+ @Override
+ public TForAll replace(TVar var, Type replacement) {
+ if(var == this.var) {
+ if(replacement instanceof TVar) {
+ return new TForAll((TVar)replacement, type.replace(var, replacement));
+ }
+ else
+ throw new IllegalStateException("Tried to replace a variable that is not free in the type.");
+ }
+ else
+ return create(type.replace(var, replacement));
+ }
+
+ @Override
+ public TypeAst toTypeAst(TypeUnparsingContext context) {
+ ArrayList<String> vars = new ArrayList<String>();
+ vars.add(context.getName(var));
+ Type cur = Types.canonical(type);
+ while(cur instanceof TForAll) {
+ TForAll forAll = (TForAll)cur;
+ vars.add(context.getName(forAll.var));
+ cur = Types.canonical(forAll.type);
+ }
+ return new TForAllAst(
+ vars.toArray(new String[vars.size()]),
+ cur.toTypeAst(context));
+ }
+
+ @Override
+ public void updateHashCode(TypeHashCodeContext context) {
+ context.append(TypeHashCodeContext.FORALL);
+ TObjectIntHashMap<TVar> varHashCode = context.createVarHashCode();
+ varHashCode.put(var, varHashCode.size());
+ type.updateHashCode(context);
+ varHashCode.remove(var);
+ }
+
+ @Override
+ public void collectFreeVars(ArrayList<TVar> vars) {
+ type.collectFreeVars(vars);
+ vars.remove(var);
+ }
+
+ @Override
+ public void collectMetaVars(ArrayList<TMetaVar> vars) {
+ type.collectMetaVars(vars);
+ }
+
+ @Override
+ public void collectMetaVars(THashSet<TMetaVar> vars) {
+ type.collectMetaVars(vars);
+ }
+
+ @Override
+ public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
+ type.collectEffectMetaVars(vars);
+ }
+
+ @Override
+ public boolean contains(TMetaVar other) {
+ return type.contains(other);
+ }
+
+ @Override
+ public Type convertMetaVarsToVars() {
+ Type newType = type.convertMetaVarsToVars();
+ if(newType == type)
+ return this;
+ else
+ return new TForAll(var, type);
+ }
+
+ @Override
+ public boolean isGround() {
+ return false; // The method is usually not called for quantified types
+ // so it is unclear what it should do here.
+ }
+
+ public Kind inferKind(Environment context) throws KindUnificationException {
+ type.checkKind(context, Kinds.STAR);
+ return Kinds.STAR;
+ }
+
+ @Override
+ public boolean containsMetaVars() {
+ return type.containsMetaVars();
+ }
+
+ @Override
+ public void toName(TypeUnparsingContext context, StringBuilder b) {
+ type.toName(context, b);
+ }
+
+ @Override
+ public int getClassId() {
+ return FORALL_ID;
+ }
+
+ @Override
+ public void addPolarity(Polarity polarity) {
+ type.addPolarity(polarity);
+ }
+
+ @Override
+ public Type head() {
+ return this;
+ }
+
+ @Override
+ public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
+ // Should never get here
+ return new TMetaVar(Kinds.STAR);
+ }
+}