]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TForAll.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / types / TForAll.java
1 package org.simantics.scl.compiler.types;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5
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;
16
17 import gnu.trove.map.hash.THashMap;
18 import gnu.trove.map.hash.TObjectIntHashMap;
19 import gnu.trove.set.hash.THashSet;
20
21
22 public class TForAll extends Type {
23     public final TVar var;
24     public Type type;
25     
26     TForAll(TVar var, Type type) {
27         if(NULL_CHECKS) {
28             if(var == null || type == null)
29                 throw new NullPointerException();
30         }
31         this.var = var;
32         this.type = type;
33     }
34     
35     private TForAll create(Type type) {
36         if(type == this.type)
37             return this;
38         else
39             return new TForAll(var, type);
40     }
41
42     @Override
43     public TForAll replace(TVar var, Type replacement) {
44         if(var == this.var) {
45             if(replacement instanceof TVar) {
46                return new TForAll((TVar)replacement, type.replace(var, replacement));
47             }
48             else
49                 throw new IllegalStateException("Tried to replace a variable that is not free in the type.");
50         }
51         else
52             return create(type.replace(var, replacement));
53     }
54
55     @Override
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);
64         }
65         return new TForAllAst(
66                 vars.toArray(new String[vars.size()]), 
67                 cur.toTypeAst(context));
68     }
69     
70     @Override
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);
77     }
78
79     @Override
80     public void collectFreeVars(ArrayList<TVar> vars) {
81         type.collectFreeVars(vars);
82         vars.remove(var);
83     }
84     
85     @Override
86     public void collectMetaVars(ArrayList<TMetaVar> vars) {
87         type.collectMetaVars(vars);
88     }
89     
90     @Override
91     public void collectMetaVars(THashSet<TMetaVar> vars) {
92         type.collectMetaVars(vars);
93     }
94     
95     @Override
96     public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
97         type.collectEffectMetaVars(vars);
98     }
99     
100     @Override
101     public boolean contains(TMetaVar other) {
102         return type.contains(other);
103     }
104     
105     @Override
106     public Type convertMetaVarsToVars() {
107         Type newType = type.convertMetaVarsToVars();
108         if(newType == type)
109             return this;
110         else
111             return new TForAll(var, type);
112     }
113
114     @Override
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.
118     }
119
120         public Kind inferKind(Environment context) throws KindUnificationException {
121         type.checkKind(context, Kinds.STAR);
122         return Kinds.STAR;
123     }
124
125     @Override
126     public boolean containsMetaVars() {
127         return type.containsMetaVars();
128     }
129
130     @Override
131     public void toName(TypeUnparsingContext context, StringBuilder b) {
132         type.toName(context, b);
133     }
134     
135     @Override
136     public int getClassId() {
137         return FORALL_ID;
138     }
139
140     @Override
141     public void addPolarity(Polarity polarity) {
142         type.addPolarity(polarity);
143     }
144
145     @Override
146     public Type head() {
147         return this;
148     }
149
150     @Override
151     public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
152         // Should never get here
153         return new TMetaVar(Kinds.STAR);
154     }
155     
156     @Override
157     public int hashCode(int hash) {
158         int count=1;
159         {
160             Type t = Types.canonical(type);
161             while(t instanceof TForAll) {
162                 t = Types.canonical( ((TForAll)t).type );
163                 ++count;
164             }
165         }
166         TVar[] boundVars = new TVar[count];
167         boundVars[0] = var;
168         TForAll t = this;
169         {
170             for(int i=1;i<count;++i) {
171                 t = (TForAll)Types.canonical(t.type);
172                 boundVars[i] = t.var;
173             }
174         }
175         
176         for(int i=0;i<count;++i)
177             hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
178         return t.type.hashCode(hash, boundVars);
179     }
180     
181     @Override
182     public int hashCode(int hash, TVar[] oldBoundVars) {
183         int count=1;
184         {
185             Type t = Types.canonical(type);
186             while(t instanceof TForAll) {
187                 t = Types.canonical( ((TForAll)t).type );
188                 ++count;
189             }
190         }
191         TVar[] boundVars = Arrays.copyOf(oldBoundVars, oldBoundVars.length + count);
192         boundVars[oldBoundVars.length] = var;
193         TForAll t = this;
194         {
195             for(int i=1;i<count;++i) {
196                 t = (TForAll)Types.canonical(t.type);
197                 boundVars[oldBoundVars.length + i] = t.var;
198             }
199         }
200         
201         for(int i=0;i<count;++i)
202             hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
203         return t.type.hashCode(hash, boundVars);
204     }
205     
206     @Override
207     public int skeletonHashCode(int hash) {
208         int count=1;
209         {
210             Type t = Types.canonical(type);
211             while(t instanceof TForAll) {
212                 t = Types.canonical( ((TForAll)t).type );
213                 ++count;
214             }
215         }
216         TVar[] boundVars = new TVar[count];
217         boundVars[0] = var;
218         TForAll t = this;
219         {
220             for(int i=1;i<count;++i) {
221                 t = (TForAll)Types.canonical(t.type);
222                 boundVars[i] = t.var;
223             }
224         }
225         
226         for(int i=0;i<count;++i)
227             hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
228         return t.type.skeletonHashCode(hash, boundVars);
229     }
230     
231     @Override
232     public int skeletonHashCode(int hash, TVar[] oldBoundVars) {
233         int count=1;
234         {
235             Type t = Types.canonical(type);
236             while(t instanceof TForAll) {
237                 t = Types.canonical( ((TForAll)t).type );
238                 ++count;
239             }
240         }
241         TVar[] boundVars = Arrays.copyOf(oldBoundVars, oldBoundVars.length + count);
242         boundVars[oldBoundVars.length] = var;
243         TForAll t = this;
244         {
245             for(int i=1;i<count;++i) {
246                 t = (TForAll)Types.canonical(t.type);
247                 boundVars[oldBoundVars.length + i] = t.var;
248             }
249         }
250         
251         for(int i=0;i<count;++i)
252             hash = HashCodeUtils.updateWithPreprocessedValue(hash, FORALL_HASH);
253         return t.type.skeletonHashCode(hash, boundVars);
254     }
255     
256     public Type getCanonicalType() {
257         if(type instanceof TMetaVar)
258             type = type.canonical();
259         return type;
260     }
261
262     @Override
263     public boolean equalsCanonical(Type other) {
264         if(this == other)
265             return true;
266         if(!other.getClass().equals(TForAll.class))
267             return false;
268         TForAll forAll = (TForAll)other;
269         return getCanonicalType().equalsCanonical(forAll.getCanonicalType().replace(forAll.var, var));
270     }
271
272     @Override
273     public Kind getKind(Environment context) {
274         return Kinds.STAR;
275     }
276
277     @Override
278     public Type[] skeletonCanonicalChildren() {
279         return new Type[] { Skeletons.canonicalSkeleton(type) };
280     } 
281     
282 }