]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TFun.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / types / TFun.java
1 package org.simantics.scl.compiler.types;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.environment.Environment;
6 import org.simantics.scl.compiler.internal.types.HashCodeUtils;
7 import org.simantics.scl.compiler.internal.types.TypeHashCodeContext;
8 import org.simantics.scl.compiler.internal.types.ast.TEffectAst;
9 import org.simantics.scl.compiler.internal.types.ast.TFunctionAst;
10 import org.simantics.scl.compiler.internal.types.ast.TPredAst;
11 import org.simantics.scl.compiler.internal.types.ast.TypeAst;
12 import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
13 import org.simantics.scl.compiler.types.kinds.Kind;
14 import org.simantics.scl.compiler.types.kinds.Kinds;
15 import org.simantics.scl.compiler.types.util.Polarity;
16 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
17
18 import gnu.trove.map.hash.THashMap;
19 import gnu.trove.set.hash.THashSet;
20
21 public class TFun extends Type {
22     public Type domain;
23     public Type effect;
24     public Type range;
25     
26     TFun(Type domain, Type effect, Type range) {
27         if(domain == null)
28             throw new NullPointerException();
29         if(effect == null)
30             throw new NullPointerException();
31         if(range == null)
32             throw new NullPointerException();
33         /*domain = Types.weakCanonical(domain);
34         range = Types.weakCanonical(range);
35         if(domain instanceof TUnion)
36             throw new RuntimeException();
37         if(range instanceof TUnion)
38             throw new RuntimeException();*/
39         
40         this.domain = domain;
41         this.effect = effect;
42         this.range = range;
43     }
44
45     @Override
46     public Type replace(TVar var, Type replacement) {
47         Type newDomain = domain.replace(var, replacement);
48         Type newEffect = effect.replace(var, replacement);
49         Type newRange = range.replace(var, replacement);
50         if(newDomain == domain && newEffect == effect && newRange == range)
51             return this;
52         else
53             return new TFun(newDomain, newEffect, newRange);
54     }
55     
56     @Override
57     public TypeAst toTypeAst(TypeUnparsingContext context) {
58         TypeAst domainAst = domain.toTypeAst(context);
59         TypeAst rangeAst = range.toTypeAst(context);
60         if(Types.canonical(effect) != Types.NO_EFFECTS)
61             rangeAst = new TEffectAst(effect.toTypeAst(context), rangeAst);
62         Type dom = Types.canonical(domain);
63         if(dom instanceof TPred)
64             return new TPredAst(domainAst, rangeAst);
65         else if(dom == Types.PUNIT) {
66             //if(rangeAst instanceof TEffectAst)
67                 return rangeAst;
68             /*else
69                 return new TEffectAst(Types.NO_EFFECTS, rangeAst);*/
70         }
71         else
72             return new TFunctionAst(domainAst, rangeAst);
73     }
74     
75     @Override
76     public void toName(TypeUnparsingContext context, StringBuilder b) {
77         b.append("FUNC_");
78         domain.toName(context, b);
79         b.append('_');
80         effect.toName(context, b);
81         b.append('_');
82         range.toName(context, b);
83     }
84     
85     @Override
86     public void updateHashCode(TypeHashCodeContext context) {
87         context.append(TypeHashCodeContext.FUN);
88         domain.updateHashCode(context);
89         effect.updateHashCode(context);
90         range.updateHashCode(context);
91     }
92     
93     @Override
94     public void collectFreeVars(ArrayList<TVar> vars) {
95         domain.collectFreeVars(vars);
96         effect.collectFreeVars(vars);
97         range.collectFreeVars(vars);
98     }
99     
100     @Override
101     public void collectMetaVars(ArrayList<TMetaVar> vars) {
102         domain.collectMetaVars(vars);
103         effect.collectMetaVars(vars);
104         range.collectMetaVars(vars);
105     }
106     
107     @Override
108     public void collectMetaVars(THashSet<TMetaVar> vars) {
109         domain.collectMetaVars(vars);
110         effect.collectMetaVars(vars);
111         range.collectMetaVars(vars);
112     }
113     
114     @Override
115     public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
116         domain.collectEffectMetaVars(vars);
117         effect.collectMetaVars(vars);
118         range.collectEffectMetaVars(vars);
119     }
120     
121     @Override
122     public boolean isGround() {
123         return domain.isGround() && effect.isGround() && range.isGround();
124     }
125     
126     @Override
127     public boolean containsMetaVars() {
128         return domain.containsMetaVars() 
129                 || effect.containsMetaVars() 
130                 || range.containsMetaVars();
131     }
132     
133     @Override
134     public boolean contains(TMetaVar other) {
135         return domain.contains(other) 
136                 || effect.contains(other)
137                 || range.contains(other);
138     }
139     
140     @Override
141     public int getClassId() {
142         return FUN_ID;
143     }
144     
145     @Override
146     public Kind inferKind(Environment context)
147             throws KindUnificationException {
148         domain.checkKind(context, Kinds.STAR);
149         range.checkKind(context, Kinds.STAR);
150         return Kinds.STAR;
151     }
152
153     @Override
154     public Type convertMetaVarsToVars() {
155         Type newDomain = domain.convertMetaVarsToVars();
156         Type newEffect = effect.convertMetaVarsToVars();
157         Type newRange = range.convertMetaVarsToVars();
158         if(newDomain == domain && newEffect == effect && newRange == range)
159             return this;
160         else
161             return new TFun(newDomain, newEffect, newRange);
162     }
163     
164     @Override
165     public boolean isMinimal() {
166         return Types.canonical(effect) == Types.NO_EFFECTS &&
167                 range.isMinimal() && domain.isMaximal();
168     }
169     
170     public boolean isMaximal() {
171         return false;
172     }
173
174     @Override
175     public void addPolarity(Polarity polarity) {
176         domain.addPolarity(polarity.flip());
177         effect.addPolarity(polarity);
178         range.addPolarity(polarity);
179     }
180
181     @Override
182     public Type head() {
183         return Types.ARROW;
184     }
185
186     @Override
187     public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
188         Type newDomain = domain.copySkeleton(metaVarMap);
189         Type newEffect = Types.NO_EFFECTS;
190         Type newRange = range.copySkeleton(metaVarMap);
191         return new TFun(newDomain, newEffect, newRange);
192     }
193     
194     @Override
195     public int hashCode(int hash) {
196         hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
197         hash = domain.hashCode(hash);
198         hash = effect.hashCode(hash);
199         hash = range.hashCode(hash);
200         return hash;
201     }
202     
203     @Override
204     public int hashCode(int hash, TVar[] boundVars) {
205         hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
206         hash = domain.hashCode(hash, boundVars);
207         hash = effect.hashCode(hash, boundVars);
208         hash = range.hashCode(hash, boundVars);
209         return hash;
210     }
211     
212     @Override
213     public int skeletonHashCode(int hash) {
214         hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
215         hash = domain.skeletonHashCode(hash);
216         hash = range.skeletonHashCode(hash);
217         return hash;
218     }
219     
220     @Override
221     public int skeletonHashCode(int hash, TVar[] boundVars) {
222         hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
223         hash = domain.skeletonHashCode(hash, boundVars);
224         hash = range.skeletonHashCode(hash, boundVars);
225         return hash;
226     }
227     
228     public Type getCanonicalDomain() {
229         if(domain instanceof TMetaVar)
230             domain = domain.canonical();
231         return domain;
232     }
233     
234     public Type getCanonicalEffect() {
235         if(effect instanceof TMetaVar)
236             effect = effect.canonical();
237         return effect;
238     }
239     
240     public Type getCanonicalRange() {
241         if(range instanceof TMetaVar)
242             range = range.canonical();
243         return range;
244     }
245
246     @Override
247     public boolean equalsCanonical(Type other) {
248         if(this == other)
249             return true;
250         if(!other.getClass().equals(TFun.class))
251             return false;
252         TFun fun = (TFun)other;
253         return getCanonicalDomain().equalsCanonical(fun.getCanonicalDomain())
254                 && getCanonicalEffect().equalsCanonical(fun.getCanonicalEffect())
255                 && getCanonicalRange().equalsCanonical(fun.getCanonicalRange());
256     }
257
258     @Override
259     public Kind getKind(Environment context) {
260         return Kinds.STAR;
261     }
262     
263     @Override
264     public Type[] skeletonCanonicalChildren() {
265         return new Type[] {Skeletons.canonicalSkeleton(domain), Skeletons.canonicalSkeleton(range)};
266     }
267 }