+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.TVarAst;
+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;
+
+
+public class TVar extends Type {
+ public static final TVar[] EMPTY_ARRAY = new TVar[0];
+
+ private Kind kind;
+
+ TVar(Kind kind) {
+ this.kind = kind;
+ }
+
+ public Kind getKind() {
+ if(kind instanceof KMetaVar)
+ kind = Kinds.canonical(kind);
+ return kind;
+ }
+
+ @Override
+ public Type replace(TVar var, Type replacement) {
+ if(this == var)
+ return replacement;
+ else
+ return this;
+ }
+
+ @Override
+ public TypeAst toTypeAst(TypeUnparsingContext context) {
+ return new TVarAst(context.getName(this));
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ while(obj instanceof TMetaVar) {
+ TMetaVar metaVar = (TMetaVar)obj;
+ if(metaVar.ref == null)
+ return false;
+ else
+ obj = metaVar.ref;
+ }
+ return this == obj;
+ }
+
+ @Override
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+
+ @Override
+ public void updateHashCode(TypeHashCodeContext context) {
+ TObjectIntHashMap<TVar> varHashCode = context.getVarHashCode();
+ if(varHashCode != null && varHashCode.containsKey(this))
+ context.append(varHashCode.get(this));
+ else
+ context.append(System.identityHashCode(this));
+ }
+
+ @Override
+ public void collectFreeVars(ArrayList<TVar> vars) {
+ if(!vars.contains(this))
+ vars.add(this);
+ }
+
+ @Override
+ public void collectMetaVars(ArrayList<TMetaVar> vars) {
+ }
+
+ @Override
+ public void collectMetaVars(THashSet<TMetaVar> vars) {
+ }
+
+ @Override
+ public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
+ }
+
+ @Override
+ public boolean isGround() {
+ return false;
+ }
+
+ public Kind inferKind(Environment context) throws KindUnificationException {
+ if(kind == null)
+ kind = Kinds.metaVar();
+ return kind;
+ }
+
+ @Override
+ public boolean containsMetaVars() {
+ return false;
+ }
+
+ @Override
+ public void toName(TypeUnparsingContext context, StringBuilder b) {
+ b.append(context.getName(this));
+ }
+
+ @Override
+ public int getClassId() {
+ return VAR_ID;
+ }
+
+ @Override
+ public boolean contains(TMetaVar other) {
+ return false;
+ }
+
+ @Override
+ public Type convertMetaVarsToVars() {
+ return this;
+ }
+
+ @Override
+ public void addPolarity(Polarity polarity) {
+ }
+
+ @Override
+ public Type head() {
+ return this;
+ }
+
+ @Override
+ public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
+ return this;
+ }
+}