]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TUnion.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / types / TUnion.java
1 package org.simantics.scl.compiler.types;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
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.TConAst;
10 import org.simantics.scl.compiler.internal.types.ast.TypeAst;
11 import org.simantics.scl.compiler.types.kinds.Kind;
12 import org.simantics.scl.compiler.types.kinds.Kinds;
13 import org.simantics.scl.compiler.types.util.Polarity;
14 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
15
16 import gnu.trove.map.hash.THashMap;
17 import gnu.trove.set.hash.THashSet;
18
19 public class TUnion extends Type {    
20     public final Type[] effects;
21
22     public TUnion(Type ... effects) {
23         if(NULL_CHECKS) {
24             for(Type effect : effects)
25                 if(effect == null)
26                     throw new InternalCompilerError();
27         }
28         this.effects = effects;
29     }
30
31     @Override
32     public Type replace(TVar var, Type replacement) {
33         for(int i=0;i<effects.length;++i) {
34             Type effect = effects[i];
35             Type newEffect = effect.replace(var, replacement);
36             if(newEffect != effect) {
37                 Type[] newEffects = new Type[effects.length];
38                 for(int j=0;j<i;++j)
39                     newEffects[j] = effects[j];
40                 newEffects[i] = newEffect;
41                 for(int j=i+1;j<effects.length;++j)
42                     newEffects[j] = effects[j].replace(var, replacement);
43                 return new TUnion(newEffects);
44             }
45         }
46         return this;
47     }
48
49     @Override
50     public TypeAst toTypeAst(TypeUnparsingContext context) {
51         StringBuilder b = new StringBuilder();
52         //b.append("#");
53         for(int i=0;i<effects.length;++i) {
54             if(i > 0)
55                 b.append(",");
56             b.append(effects[i].toString(context));
57         }
58         //b.append("#");
59         return new TConAst(b.toString());
60     }
61
62     @Override
63     public void toName(TypeUnparsingContext context, StringBuilder b) {
64         boolean first = true;
65         for(Type effect : effects) {
66             if(first)
67                 first = false;
68             else
69                 b.append('_');
70             effect.toName(context, b);
71         }
72     }
73
74     @Override
75     public void updateHashCode(TypeHashCodeContext context) {
76         context.append(TypeHashCodeContext.UNION);
77         for(Type effect : effects)
78             effect.updateHashCode(context);
79     }
80
81     @Override
82     public void collectFreeVars(ArrayList<TVar> vars) {
83         for(Type effect : effects)
84             effect.collectFreeVars(vars);
85     }
86
87     @Override
88     public void collectMetaVars(ArrayList<TMetaVar> vars) {
89         for(Type effect : effects)
90             effect.collectMetaVars(vars);
91     }
92     
93     @Override
94     public void collectMetaVars(THashSet<TMetaVar> vars) {
95         for(Type effect : effects)
96             effect.collectMetaVars(vars);
97     }
98
99     @Override
100     public boolean isGround() {
101         for(Type effect : effects)
102             if(!effect.isGround())
103                 return false;
104         return true;
105     }
106
107     @Override
108     public boolean containsMetaVars() {
109         for(Type effect : effects)
110             if(effect.containsMetaVars())
111                 return true;
112         return false;
113     }
114
115     @Override
116     public int getClassId() {
117         return UNION_ID;
118     }
119
120     @Override
121     public boolean contains(TMetaVar other) {
122         for(Type type : effects)
123             if(type.contains(other))
124                 return true;
125         return false;
126     }
127
128     @Override
129     public Type convertMetaVarsToVars() {
130         for(int i=0;i<effects.length;++i)
131             effects[i] = effects[i].convertMetaVarsToVars();
132         return this;
133     }
134     
135     @Override
136     public boolean isMinimal() {
137         return effects.length == 0;
138     }
139     
140     @Override
141     public boolean isMaximal() {
142         return false;
143     }
144
145     @Override
146     public void addPolarity(Polarity polarity) {
147         for(Type effect : effects)
148             effect.addPolarity(polarity);
149     }
150
151     @Override
152     public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
153         throw new UnsupportedOperationException();
154     }
155     
156     @Override
157     public void collectConcreteEffects(ArrayList<TCon> concreteEffects) {
158         for(Type effect : effects)
159             effect.collectConcreteEffects(concreteEffects);
160     }
161
162     @Override
163     public Type head() {
164         throw new UnsupportedOperationException();
165     }
166
167     @Override
168     public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
169         return Types.NO_EFFECTS;
170     }
171     
172     @Override
173     public int hashCode(int hash) {
174         int sum = UNION_HASH;
175         for(Type effect : effects)
176             sum += effect.hashCode(HashCodeUtils.SEED);
177         return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
178     }
179     
180     @Override
181     public int hashCode(int hash, TVar[] boundVars) {
182         int sum = UNION_HASH;
183         for(Type effect : effects)
184             sum += effect.hashCode(HashCodeUtils.SEED, boundVars);
185         return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
186     }
187     
188     @Override
189     public int skeletonHashCode(int hash) {
190         int sum = UNION_HASH;
191         for(Type effect : effects)
192             sum += effect.skeletonHashCode(HashCodeUtils.SEED);
193         return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
194     }
195     
196     @Override
197     public int skeletonHashCode(int hash, TVar[] boundVars) {
198         int sum = UNION_HASH;
199         for(Type effect : effects)
200             sum += effect.skeletonHashCode(HashCodeUtils.SEED, boundVars);
201         return HashCodeUtils.updateWithPreprocessedValue(hash, sum);
202     }
203     
204     @Override
205     public boolean equalsCanonical(Type other) {
206         if(this == other)
207             return true;
208         if(!other.getClass().equals(TUnion.class))
209             return false;
210         TUnion union = (TUnion)other;
211         int length = effects.length;
212         if(length != union.effects.length)
213             return false;
214         if(length == 0)
215             return true;
216         for(int i=0;i<length;++i) {
217             effects[i] = effects[i].canonical();
218             union.effects[i] = union.effects[i].canonical();
219         }
220         if(length == 2) {
221             if(effects[0].equalsCanonical(union.effects[0]))
222                 return effects[1].equalsCanonical(union.effects[1]);
223             else
224                 return effects[0].equalsCanonical(union.effects[1]) &&
225                         effects[1].equalsCanonical(union.effects[0]);
226         }
227         loop: for(int i=0;i<length;++i) {
228             Type effect = effects[i]; 
229             for(int j=i;j<length;++j)
230                 if(effect.equalsCanonical(union.effects[j])) {
231                     if(j > i) {
232                         effect = union.effects[i];
233                         union.effects[i] = union.effects[j];
234                         union.effects[j] = effect;
235                     }
236                     continue loop;
237                 }
238             return false;
239         }
240         return true;
241     }
242     
243     @Override
244     public Kind getKind(Environment context) {
245         return Kinds.EFFECT;
246     }
247     
248     @Override
249     public Type[] skeletonCanonicalChildren() {
250         return EMPTY_ARRAY;
251     }
252 }