1 package org.simantics.scl.compiler.types;
3 import java.util.ArrayList;
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;
18 import gnu.trove.map.hash.THashMap;
19 import gnu.trove.set.hash.THashSet;
21 public class TFun extends Type {
26 TFun(Type domain, Type effect, Type range) {
28 throw new NullPointerException();
30 throw new NullPointerException();
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();*/
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)
53 return new TFun(newDomain, newEffect, newRange);
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)
69 return new TEffectAst(Types.NO_EFFECTS, rangeAst);*/
72 return new TFunctionAst(domainAst, rangeAst);
76 public void toName(TypeUnparsingContext context, StringBuilder b) {
78 domain.toName(context, b);
80 effect.toName(context, b);
82 range.toName(context, b);
86 public void updateHashCode(TypeHashCodeContext context) {
87 context.append(TypeHashCodeContext.FUN);
88 domain.updateHashCode(context);
89 effect.updateHashCode(context);
90 range.updateHashCode(context);
94 public void collectFreeVars(ArrayList<TVar> vars) {
95 domain.collectFreeVars(vars);
96 effect.collectFreeVars(vars);
97 range.collectFreeVars(vars);
101 public void collectMetaVars(ArrayList<TMetaVar> vars) {
102 domain.collectMetaVars(vars);
103 effect.collectMetaVars(vars);
104 range.collectMetaVars(vars);
108 public void collectMetaVars(THashSet<TMetaVar> vars) {
109 domain.collectMetaVars(vars);
110 effect.collectMetaVars(vars);
111 range.collectMetaVars(vars);
115 public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
116 domain.collectEffectMetaVars(vars);
117 effect.collectMetaVars(vars);
118 range.collectEffectMetaVars(vars);
122 public boolean isGround() {
123 return domain.isGround() && effect.isGround() && range.isGround();
127 public boolean containsMetaVars() {
128 return domain.containsMetaVars()
129 || effect.containsMetaVars()
130 || range.containsMetaVars();
134 public boolean contains(TMetaVar other) {
135 return domain.contains(other)
136 || effect.contains(other)
137 || range.contains(other);
141 public int getClassId() {
146 public Kind inferKind(Environment context)
147 throws KindUnificationException {
148 domain.checkKind(context, Kinds.STAR);
149 range.checkKind(context, Kinds.STAR);
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)
161 return new TFun(newDomain, newEffect, newRange);
165 public boolean isMinimal() {
166 return Types.canonical(effect) == Types.NO_EFFECTS &&
167 range.isMinimal() && domain.isMaximal();
170 public boolean isMaximal() {
175 public void addPolarity(Polarity polarity) {
176 domain.addPolarity(polarity.flip());
177 effect.addPolarity(polarity);
178 range.addPolarity(polarity);
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);
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);
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);
213 public int skeletonHashCode(int hash) {
214 hash = HashCodeUtils.updateWithPreprocessedValue(hash, FUN_HASH);
215 hash = domain.skeletonHashCode(hash);
216 hash = range.skeletonHashCode(hash);
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);
228 public Type getCanonicalDomain() {
229 if(domain instanceof TMetaVar)
230 domain = domain.canonical();
234 public Type getCanonicalEffect() {
235 if(effect instanceof TMetaVar)
236 effect = effect.canonical();
240 public Type getCanonicalRange() {
241 if(range instanceof TMetaVar)
242 range = range.canonical();
247 public boolean equalsCanonical(Type other) {
250 if(!other.getClass().equals(TFun.class))
252 TFun fun = (TFun)other;
253 return getCanonicalDomain().equalsCanonical(fun.getCanonicalDomain())
254 && getCanonicalEffect().equalsCanonical(fun.getCanonicalEffect())
255 && getCanonicalRange().equalsCanonical(fun.getCanonicalRange());
259 public Kind getKind(Environment context) {
264 public Type[] skeletonCanonicalChildren() {
265 return new Type[] {Skeletons.canonicalSkeleton(domain), Skeletons.canonicalSkeleton(range)};