]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/TApply.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / types / TApply.java
1 package org.simantics.scl.compiler.types;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
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;
19
20 import gnu.trove.map.hash.THashMap;
21 import gnu.trove.set.hash.THashSet;
22
23
24
25 /**
26  * Type application.
27  * @author Hannu Niemistö
28  */
29 public class TApply extends Type {
30     public Type function;
31     public Type parameter;
32     
33     public TApply(Type function, Type parameter) {
34         if(NULL_CHECKS) {
35             if(function == null)
36                 throw new NullPointerException();
37             if(parameter == null)
38                 throw new NullPointerException();
39         }
40         this.function = function;
41         this.parameter = parameter;
42     }
43     
44     private TApply create(Type function, Type parameter) {
45         if(function == this.function && parameter == this.parameter)
46             return this;
47         else
48             return new TApply(function, parameter);
49     }
50
51     @Override
52     public TApply replace(TVar var, Type replacement) {
53         return create(
54                 function.replace(var, replacement), 
55                 parameter.replace(var, replacement));
56     }
57
58     @Override
59     public TypeAst toTypeAst(TypeUnparsingContext context) {
60         TMultiApply multiApply = Types.toMultiApply(this);
61         
62         Type function = multiApply.function;
63         List<Type> parameters = multiApply.parameters;
64         
65         TypeAst ast = null;
66         int parameterPos = 0;
67
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));
73                 parameterPos = 2;
74             }
75             else*/ if(function == Types.LIST && parameters.size() >= 1) {
76                 ast = new TListAst(
77                         parameters.get(0).toTypeAst(context));
78                 parameterPos = 1;
79             }
80             else {
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;
91                     }
92                 }                                
93             }
94         }
95         if(ast == null)
96             ast = function.toTypeAst(context);
97         for(;parameterPos < multiApply.parameters.size();++parameterPos)
98             ast = new TApplyAst(
99                     ast, 
100                     parameters.get(parameterPos).toTypeAst(context));
101         return ast;
102     }
103
104     @Override
105     public void updateHashCode(TypeHashCodeContext context) {
106         context.append(TypeHashCodeContext.APPLY);
107         function.updateHashCode(context);
108         parameter.updateHashCode(context);
109     }
110
111     @Override
112     public void collectFreeVars(ArrayList<TVar> vars) {
113         function.collectFreeVars(vars);
114         parameter.collectFreeVars(vars);
115     }
116
117     @Override
118     public void collectMetaVars(ArrayList<TMetaVar> vars) {
119         function.collectMetaVars(vars);
120         parameter.collectMetaVars(vars);
121     }
122     
123     @Override
124     public void collectMetaVars(THashSet<TMetaVar> vars) {
125         function.collectMetaVars(vars);
126         parameter.collectMetaVars(vars);
127     }
128     
129     @Override
130     public void collectEffectMetaVars(ArrayList<TMetaVar> vars) {
131         function.collectEffectMetaVars(vars);
132         parameter.collectEffectMetaVars(vars);
133     }
134     
135     @Override
136     public boolean contains(TMetaVar other) {
137         return function.contains(other) || parameter.contains(other);
138     }
139     
140     @Override
141     public Type convertMetaVarsToVars() {
142         Type newFunction = function.convertMetaVarsToVars();
143         Type newParameter = parameter.convertMetaVarsToVars();
144         if(newFunction == function && newParameter == parameter)
145             return this;
146         else
147             return new TApply(newFunction, newParameter);
148     }
149
150     @Override
151     public boolean isGround() {
152         return function.isGround() && parameter.isGround();
153     }
154
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));
159     }
160         
161         @Override
162         public Kind getKind(Environment context) {
163             Kind functionKind = function.getKind(context);
164             return Kinds.rangeOfArrow(functionKind);
165         }
166
167     @Override
168     public boolean containsMetaVars() {
169         return function.containsMetaVars() || parameter.containsMetaVars();
170     }
171
172     @Override
173     public void toName(TypeUnparsingContext context, StringBuilder b) {
174         function.toName(context, b);
175         b.append('_');
176         parameter.toName(context, b);
177     }
178
179     @Override
180     public int getClassId() {
181         return APPLY_ID;
182     }
183
184     @Override
185     public void addPolarity(Polarity polarity) {
186         function.addPolarity(Polarity.BIPOLAR);
187         parameter.addPolarity(Polarity.BIPOLAR);
188     }
189     
190     @Override
191     public Type head() {
192         return function.head();
193     }
194
195     @Override
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)
200             return this;
201         else
202             return new TApply(newFunction, newParameter);
203     }
204
205     @Override
206     public int hashCode(int hash) {
207         hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
208         hash = function.hashCode(hash);
209         hash = parameter.hashCode(hash);
210         return hash;
211     }
212     
213     @Override
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);
218         return hash;
219     }
220     
221     @Override
222     public int skeletonHashCode(int hash) {
223         hash = HashCodeUtils.updateWithPreprocessedValue(hash, APPLY_HASH);
224         hash = function.skeletonHashCode(hash);
225         hash = parameter.skeletonHashCode(hash);
226         return hash;
227     }
228     
229     @Override
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);
234         return hash;
235     }
236     
237     public Type getCanonicalFunction() {
238         if(function instanceof TMetaVar)
239             function = function.canonical();
240         return function;
241     }
242     
243     public Type getCanonicalParameter() {
244         if(parameter instanceof TMetaVar)
245             parameter = parameter.canonical();
246         return parameter;
247     }
248     
249     @Override
250     public boolean equalsCanonical(Type other) {
251         if(this == other)
252             return true;
253         if(!other.getClass().equals(TApply.class))
254             return false;
255         TApply apply = (TApply)other;
256         return getCanonicalFunction().equalsCanonical(apply.getCanonicalFunction())
257                 && getCanonicalParameter().equalsCanonical(apply.getCanonicalParameter());
258     }
259     
260     @Override
261     public Type[] skeletonCanonicalChildren() {
262         return new Type[] {Skeletons.canonicalSkeleton(function), Skeletons.canonicalSkeleton(parameter)};
263     }
264 }