1 package org.simantics.scl.compiler.types;
3 import java.util.ArrayList;
4 import java.util.Arrays;
6 import org.simantics.scl.compiler.environment.Environment;
7 import org.simantics.scl.compiler.internal.types.HashCodeUtils;
8 import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
9 import org.simantics.scl.compiler.internal.types.ast.TForAllAst;
10 import org.simantics.scl.compiler.internal.types.ast.TypeAst;
11 import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
12 import org.simantics.scl.compiler.types.kinds.Kind;
13 import org.simantics.scl.compiler.types.kinds.Kinds;
14 import org.simantics.scl.compiler.types.util.Polarity;
15 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
17 import gnu.trove.map.hash.THashMap;
18 import gnu.trove.map.hash.TObjectIntHashMap;
19 import gnu.trove.set.hash.THashSet;
22 public class TForAll extends Type {
23 public final TVar var;
26 TForAll(TVar var, Type type) {
28 if(var == null || type == null)
29 throw new NullPointerException();
35 private TForAll create(Type type) {
39 return new TForAll(var, type);
43 public TForAll replace(TVar var, Type replacement) {
45 if(replacement instanceof TVar) {
46 return new TForAll((TVar)replacement, type.replace(var, replacement));
49 throw new IllegalStateException("Tried to replace a variable that is not free in the type.");
52 return create(type.replace(var, replacement));
56 public TypeAst toTypeAst(TypeUnparsingContext context) {
57 ArrayList<String> vars = new ArrayList<String>();
58 vars.add(context.getName(var));
59 Type cur = Types.canonical(type);
60 while(cur instanceof TForAll) {
61 TForAll forAll = (TForAll)cur;
62 vars.add(context.getName(forAll.var));
63 cur = Types.canonical(forAll.type);
65 return new TForAllAst(
66 vars.toArray(new String[vars.size()]),
67 cur.toTypeAst(context));
71 public void updateHashCode(TypeHashCodeContext context) {
72 context.append(TypeHashCodeContext.FORALL);
73 TObjectIntHashMap<TVar> varHashCode = context.createVarHashCode();
74 varHashCode.put(var, varHashCode.size());
75 type.updateHashCode(context);
76 varHashCode.remove(var);
80 public void collectFreeVars(ArrayList<TVar> vars) {
81 type.collectFreeVars(vars);
86 public void collectMetaVars(ArrayList<TMetaVar> vars) {
87 type.collectMetaVars(vars);
91 public void collectMetaVars(THashSet<TMetaVar> vars) {
92 type.collectMetaVars(vars);
96 public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
97 type.collectEffectMetaVars(vars);
101 public boolean contains(TMetaVar other) {
102 return type.contains(other);
106 public Type convertMetaVarsToVars() {
107 Type newType = type.convertMetaVarsToVars();
111 return new TForAll(var, type);
115 public boolean isGround() {
116 return false; // The method is usually not called for quantified types
117 // so it is unclear what it should do here.
120 public Kind inferKind(Environment context) throws KindUnificationException {
121 type.checkKind(context, Kinds.STAR);
126 public boolean containsMetaVars() {
127 return type.containsMetaVars();
131 public void toName(TypeUnparsingContext context, StringBuilder b) {
132 type.toName(context, b);
136 public int getClassId() {
141 public void addPolarity(Polarity polarity) {
142 type.addPolarity(polarity);
151 public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
152 // Should never get here
153 return new TMetaVar(Kinds.STAR);
157 public int hashCode(int hash) {
160 Type t = Types.canonical(type);
161 while(t instanceof TForAll) {
162 t = Types.canonical( ((TForAll)t).type );
166 TVar[] boundVars = new TVar[count];
170 for(int i=1;i<count;++i) {
171 t = (TForAll)Types.canonical(t.type);
172 boundVars[i] = t.var;
176 for(int i=0;i<count;++i)
177 hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
178 return t.type.hashCode(hash, boundVars);
182 public int hashCode(int hash, TVar[] oldBoundVars) {
185 Type t = Types.canonical(type);
186 while(t instanceof TForAll) {
187 t = Types.canonical( ((TForAll)t).type );
191 TVar[] boundVars = Arrays.copyOf(oldBoundVars, oldBoundVars.length + count);
192 boundVars[oldBoundVars.length] = var;
195 for(int i=1;i<count;++i) {
196 t = (TForAll)Types.canonical(t.type);
197 boundVars[oldBoundVars.length + i] = t.var;
201 for(int i=0;i<count;++i)
202 hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
203 return t.type.hashCode(hash, boundVars);
206 public Type getCanonicalType() {
207 if(type instanceof TMetaVar)
208 type = type.canonical();
213 public boolean equalsCanonical(Type other) {
216 if(!other.getClass().equals(TForAll.class))
218 TForAll forAll = (TForAll)other;
219 return getCanonicalType().equalsCanonical(forAll.getCanonicalType().replace(forAll.var, var));
223 public Kind getKind(Environment context) {