1 package org.simantics.scl.compiler.types;
3 import java.util.ArrayList;
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.TApplyAst;
10 import org.simantics.scl.compiler.internal.types.ast.TListAst;
11 import org.simantics.scl.compiler.internal.types.ast.TTupleAst;
12 import org.simantics.scl.compiler.internal.types.ast.TypeAst;
13 import org.simantics.scl.compiler.types.exceptions.KindUnificationException;
14 import org.simantics.scl.compiler.types.kinds.Kind;
15 import org.simantics.scl.compiler.types.kinds.Kinds;
16 import org.simantics.scl.compiler.types.util.Polarity;
17 import org.simantics.scl.compiler.types.util.TMultiApply;
18 import org.simantics.scl.compiler.types.util.TypeUnparsingContext;
20 import gnu.trove.map.hash.THashMap;
21 import gnu.trove.set.hash.THashSet;
27 * @author Hannu Niemistö
29 public class TApply extends Type {
31 public Type parameter;
33 public TApply(Type function, Type parameter) {
36 throw new NullPointerException();
38 throw new NullPointerException();
40 this.function = function;
41 this.parameter = parameter;
44 private TApply create(Type function, Type parameter) {
45 if(function == this.function && parameter == this.parameter)
48 return new TApply(function, parameter);
52 public TApply replace(TVar var, Type replacement) {
54 function.replace(var, replacement),
55 parameter.replace(var, replacement));
59 public TypeAst toTypeAst(TypeUnparsingContext context) {
60 TMultiApply multiApply = Types.toMultiApply(this);
62 Type function = multiApply.function;
63 List<Type> parameters = multiApply.parameters;
68 if(function instanceof TCon) {
69 /*if(function == Types.ARROW && parameters.size() >= 2) {
70 ast = new TFunctionAst(
71 parameters.get(0).toTypeAst(context),
72 parameters.get(1).toTypeAst(context));
75 else*/ if(function == Types.LIST && parameters.size() >= 1) {
77 parameters.get(0).toTypeAst(context));
81 TCon con = (TCon)function;
82 if(con.module == Types.BUILTIN && con.name.charAt(0)=='(') {
83 int tupleLength = con.name.length()-2;
84 if(tupleLength>0) ++tupleLength;
85 if(parameters.size() >= tupleLength) {
86 TypeAst[] components = new TypeAst[tupleLength];
87 for(int i=0;i<tupleLength;++i)
88 components[i] = parameters.get(i).toTypeAst(context);
89 ast = new TTupleAst(components);
90 parameterPos = tupleLength;
96 ast = function.toTypeAst(context);
97 for(;parameterPos < multiApply.parameters.size();++parameterPos)
100 parameters.get(parameterPos).toTypeAst(context));
105 public void updateHashCode(TypeHashCodeContext context) {
106 context.append(TypeHashCodeContext.APPLY);
107 function.updateHashCode(context);
108 parameter.updateHashCode(context);
112 public void collectFreeVars(ArrayList<TVar> vars) {
113 function.collectFreeVars(vars);
114 parameter.collectFreeVars(vars);
118 public void collectMetaVars(ArrayList<TMetaVar> vars) {
119 function.collectMetaVars(vars);
120 parameter.collectMetaVars(vars);
124 public void collectMetaVars(THashSet<TMetaVar> vars) {
125 function.collectMetaVars(vars);
126 parameter.collectMetaVars(vars);
130 public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
131 function.collectEffectMetaVars(vars);
132 parameter.collectEffectMetaVars(vars);
136 public boolean contains(TMetaVar other) {
137 return function.contains(other) || parameter.contains(other);
141 public Type convertMetaVarsToVars() {
142 Type newFunction = function.convertMetaVarsToVars();
143 Type newParameter = parameter.convertMetaVarsToVars();
144 if(newFunction == function && newParameter == parameter)
147 return new TApply(newFunction, newParameter);
151 public boolean isGround() {
152 return function.isGround() && parameter.isGround();
155 public void checkKind(Environment context, Kind requiredKind) throws KindUnificationException {
156 Kind functionKind = function.inferKind(context);
157 Kind parameterKind = parameter.inferKind(context);
158 Kinds.unify(functionKind, Kinds.arrow(parameterKind, requiredKind));
162 public Kind getKind(Environment context) {
163 Kind functionKind = function.getKind(context);
164 return Kinds.rangeOfArrow(functionKind);
168 public boolean containsMetaVars() {
169 return function.containsMetaVars() || parameter.containsMetaVars();
173 public void toName(TypeUnparsingContext context, StringBuilder b) {
174 function.toName(context, b);
176 parameter.toName(context, b);
180 public int getClassId() {
185 public void addPolarity(Polarity polarity) {
186 function.addPolarity(Polarity.BIPOLAR);
187 parameter.addPolarity(Polarity.BIPOLAR);
192 return function.head();
196 public Type copySkeleton(THashMap<TMetaVar, TMetaVar> metaVarMap) {
197 Type newFunction = function.copySkeleton(metaVarMap);
198 Type newParameter = parameter.copySkeleton(metaVarMap);
199 if(newFunction == function && newParameter == parameter)
202 return new TApply(newFunction, newParameter);
206 public int hashCode(int hash) {
207 hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
208 hash = function.hashCode(hash);
209 hash = parameter.hashCode(hash);
214 public int hashCode(int hash, TVar[] boundVars) {
215 hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
216 hash = function.hashCode(hash, boundVars);
217 hash = parameter.hashCode(hash, boundVars);
222 public int skeletonHashCode(int hash) {
223 hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
224 hash = function.skeletonHashCode(hash);
225 hash = parameter.skeletonHashCode(hash);
230 public int skeletonHashCode(int hash, TVar[] boundVars) {
231 hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
232 hash = function.skeletonHashCode(hash, boundVars);
233 hash = parameter.skeletonHashCode(hash, boundVars);
237 public Type getCanonicalFunction() {
238 if(function instanceof TMetaVar)
239 function = function.canonical();
243 public Type getCanonicalParameter() {
244 if(parameter instanceof TMetaVar)
245 parameter = parameter.canonical();
250 public boolean equalsCanonical(Type other) {
253 if(!other.getClass().equals(TApply.class))
255 TApply apply = (TApply)other;
256 return getCanonicalFunction().equalsCanonical(apply.getCanonicalFunction())
257 && getCanonicalParameter().equalsCanonical(apply.getCanonicalParameter());
261 public Type[] skeletonCanonicalChildren() {
262 return new Type[] {Skeletons.canonicalSkeleton(function), Skeletons.canonicalSkeleton(parameter)};