]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TUnion.java
migrated to svn revision 33108
[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 boolean equalsCanonical(Type other) {
190         if(this == other)
191             return true;
192         if(!other.getClass().equals(TUnion.class))
193             return false;
194         TUnion union = (TUnion)other;
195         int length = effects.length;
196         if(length != union.effects.length)
197             return false;
198         if(length == 0)
199             return true;
200         for(int i=0;i<length;++i) {
201             effects[i] = effects[i].canonical();
202             union.effects[i] = union.effects[i].canonical();
203         }
204         if(length == 2) {
205             if(effects[0].equalsCanonical(union.effects[0]))
206                 return effects[1].equalsCanonical(union.effects[1]);
207             else
208                 return effects[0].equalsCanonical(union.effects[1]) &&
209                         effects[1].equalsCanonical(union.effects[0]);
210         }
211         loop: for(int i=0;i<length;++i) {
212             Type effect = effects[i]; 
213             for(int j=i;j<length;++j)
214                 if(effect.equalsCanonical(union.effects[j])) {
215                     if(j > i) {
216                         effect = union.effects[i];
217                         union.effects[i] = union.effects[j];
218                         union.effects[j] = effect;
219                     }
220                     continue loop;
221                 }
222             return false;
223         }
224         return true;
225     }
226     
227     @Override
228     public Kind getKind(Environment context) {
229         return Kinds.EFFECT;
230     }
231 }