]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/query/compilation/QueryCompilationContext.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / query / compilation / QueryCompilationContext.java
1 package org.simantics.scl.compiler.elaboration.query.compilation;
2
3 import static org.simantics.scl.compiler.elaboration.expressions.Expressions.Just;
4 import static org.simantics.scl.compiler.elaboration.expressions.Expressions.Nothing;
5 import static org.simantics.scl.compiler.elaboration.expressions.Expressions.apply;
6 import static org.simantics.scl.compiler.elaboration.expressions.Expressions.lambda;
7 import static org.simantics.scl.compiler.elaboration.expressions.Expressions.var;
8
9 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
10 import org.simantics.scl.compiler.common.names.Name;
11 import org.simantics.scl.compiler.common.names.Names;
12 import org.simantics.scl.compiler.compilation.CompilationContext;
13 import org.simantics.scl.compiler.constants.BooleanConstant;
14 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
15 import org.simantics.scl.compiler.elaboration.expressions.Case;
16 import org.simantics.scl.compiler.elaboration.expressions.EApply;
17 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
18 import org.simantics.scl.compiler.elaboration.expressions.EIf;
19 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
20 import org.simantics.scl.compiler.elaboration.expressions.EMatch;
21 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;
22 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;
23 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
24 import org.simantics.scl.compiler.elaboration.expressions.Expression;
25 import org.simantics.scl.compiler.elaboration.expressions.Variable;
26 import org.simantics.scl.compiler.elaboration.java.Builtins;
27 import org.simantics.scl.compiler.errors.Locations;
28 import org.simantics.scl.compiler.types.TPred;
29 import org.simantics.scl.compiler.types.Type;
30 import org.simantics.scl.compiler.types.Types;
31 import org.simantics.scl.compiler.types.exceptions.MatchException;
32
33 public class QueryCompilationContext {    
34     TypingContext context;
35     QueryCompilationMode mode;
36     Type resultType;
37     Expression continuation;
38     double branching = 1.0;
39     double cost = 0.0;
40     
41     public QueryCompilationContext(
42             TypingContext context,
43             QueryCompilationMode mode,
44             Type resultType,
45             Expression continuation) {
46         this.context = context;
47         this.mode = mode;
48         this.resultType = resultType;
49         this.continuation = continuation;
50     }
51
52     public Expression failure() {
53         switch(mode) {
54         case ITERATE: return new EConstant(Builtins.TUPLE_CONSTRUCTORS[0]);
55         case GET_FIRST: return new EConstant(Builtins.Nothing, resultType);
56         case GET_ALL: return new EConstant(Builtins.LIST_CONSTRUCTORS[0], resultType);
57         case CHECK: return new ELiteral(new BooleanConstant(false));
58         default: throw new InternalCompilerError();
59         }
60     }
61     
62     public Expression disjunction(Expression a, Expression b) {
63         switch(mode) {
64         case ITERATE: return new ESimpleLet(new Variable("_", Types.UNIT), a, b);
65         case GET_FIRST: {
66             Variable var = new Variable("temp", a.getType());
67             return new EMatch(a,
68                 new Case(new EConstant(Builtins.Nothing), b), 
69                 new Case(new EVariable(var), new EVariable(var)));
70         }
71         case GET_ALL: {
72             try {
73                 return new EApply(context.getCompilationContext().getConstant(Names.Prelude_appendList, 
74                         Types.matchApply(Types.LIST, a.getType())), a, b);
75             } catch (MatchException e) {
76                 throw new InternalCompilerError();
77             }
78         }
79         case CHECK: return new EIf(a, new ELiteral(new BooleanConstant(true)), b);
80         default: throw new InternalCompilerError();
81         }
82     }
83     
84     public Expression condition(Expression condition, Expression continuation) {
85         return new EIf(condition, continuation, failure());
86     }
87     
88     public void condition(Expression condition) {
89         continuation = condition(condition, continuation);
90     }
91     
92     public void equalityCondition(long location, Expression a, Expression b) {
93         Type type = a.getType();
94         condition(new EApply(
95                 location,
96                 Types.PROC,
97                 context.getCompilationContext().getConstant(Names.Builtin_equals, type),
98                 new Expression[] {
99                     a,
100                     b
101                 }
102                 ));
103     }
104     
105     public void let(Variable variable, Expression value) {
106         continuation = new ESimpleLet(variable, value, continuation);
107     }
108     
109     public void iterateMaybe(Variable variable, Expression value) {
110         continuation = new EMatch(value,
111                 new Case(Nothing(variable.getType()), failure()),
112                 new Case(Just(var(variable)), continuation));
113     }
114     
115     public void match(Expression pattern, Expression value, boolean mayFail) {
116         if(mayFail)
117             continuation = new EMatch(value,
118                     new Case(pattern, continuation),
119                     new Case(new EVariable(new Variable("_", pattern.getType())), failure()));
120         else
121             continuation = new EMatch(value,
122                     new Case(pattern, continuation));
123     }
124     
125     public void iterateList(Variable variable, Expression list) {
126         try {
127             switch(mode) {
128             case ITERATE:
129                 continuation = new EApply(
130                         Locations.NO_LOCATION,
131                         Types.PROC,
132                         context.getCompilationContext().getConstant(Names.Prelude_iterList, variable.getType(), Types.PROC, Types.tupleConstructor(0)),
133                         new Expression[] {
134                             new ESimpleLambda(Types.PROC, variable, continuation), 
135                             list
136                         }
137                         );
138                 break;
139             case CHECK:
140                 continuation = new EApply(
141                         Locations.NO_LOCATION,
142                         Types.PROC,
143                         context.getCompilationContext().getConstant(Names.Prelude_any, variable.getType(), Types.PROC),
144                         new Expression[] {
145                             new ESimpleLambda(Types.PROC, variable, continuation), 
146                             list
147                         }
148                         );
149                 break;
150             case GET_ALL:
151                 continuation = new EApply(
152                         Locations.NO_LOCATION,
153                         Types.PROC,
154                         context.getCompilationContext().getConstant(Names.Prelude_concatMap, variable.getType(), Types.PROC, 
155                                 Types.matchApply(Types.LIST, continuation.getType())),
156                         new Expression[] {
157                             new ESimpleLambda(Types.PROC, variable, continuation), 
158                             list
159                         }
160                         );
161                 break;
162             case GET_FIRST:
163                 continuation = new EApply(
164                         Locations.NO_LOCATION,
165                         Types.PROC,
166                         context.getCompilationContext().getConstant(Names.Prelude_mapFirst, variable.getType(), Types.PROC,
167                                 Types.matchApply(Types.MAYBE, continuation.getType())),
168                         new Expression[] {
169                             new ESimpleLambda(Types.PROC, variable, continuation), 
170                             list
171                         }
172                         );
173                 break;
174             default: throw new InternalCompilerError("iterateList could not handle mode " + mode);
175             }
176         } catch(MatchException e) {
177             throw new InternalCompilerError(e);
178         }
179     }
180     
181     public void iterateVector(Variable variable, Expression vector) {
182         try {
183             switch(mode) {
184             case ITERATE:
185                 continuation = new EApply(
186                         Locations.NO_LOCATION,
187                         Types.PROC,
188                         context.getCompilationContext().getConstant(Names.Vector_iterVector, variable.getType(), Types.PROC, continuation.getType()),
189                         new Expression[] {
190                             new ESimpleLambda(Types.PROC, variable, continuation), 
191                             vector
192                         }
193                         );
194                 break;
195             case CHECK:
196                 continuation = new EApply(
197                         Locations.NO_LOCATION,
198                         Types.PROC,
199                         context.getCompilationContext().getConstant(Names.Vector_anyVector, variable.getType(), Types.PROC),
200                         new Expression[] {
201                             new ESimpleLambda(Types.PROC, variable, continuation), 
202                             vector
203                         }
204                         );
205                 break;
206             case GET_ALL:
207                 continuation = new EApply(
208                         Locations.NO_LOCATION,
209                         Types.PROC,
210                         context.getCompilationContext().getConstant(Names.Vector_concatMapVector, variable.getType(), Types.PROC,
211                                 Types.matchApply(Types.LIST, continuation.getType())),
212                         new Expression[] {
213                             new ESimpleLambda(Types.PROC, variable, continuation), 
214                             vector
215                         }
216                         );
217                 break;
218             case GET_FIRST:
219                 continuation = new EApply(
220                         Locations.NO_LOCATION,
221                         Types.PROC,
222                         context.getCompilationContext().getConstant(Names.Vector_mapFirstVector, variable.getType(), Types.PROC, 
223                                 Types.matchApply(Types.MAYBE, continuation.getType())),
224                         new Expression[] {
225                             new ESimpleLambda(Types.PROC, variable, continuation), 
226                             vector
227                         }
228                         );
229                 break;
230             default: throw new InternalCompilerError("iterateVector could not handle mode " + mode);
231             }
232         } catch(MatchException e) {
233             throw new InternalCompilerError(e);
234         }
235     }
236     
237     public void iterateMSet(Variable variable, Expression set) {
238         try {
239             switch(mode) {
240             case ITERATE:
241                 continuation = apply(context.getCompilationContext(), Types.PROC, Names.MSet_iter, variable.getType(), Types.PROC, continuation.getType(),
242                         lambda(Types.PROC, variable, continuation), 
243                         set
244                         );
245                 break;
246             case GET_FIRST:
247                 continuation = apply(context.getCompilationContext(), Types.PROC, Names.MSet_mapFirst, variable.getType(), Types.PROC, 
248                         Types.matchApply(Types.MAYBE, continuation.getType()),
249                         lambda(Types.PROC, variable, continuation), 
250                         set
251                         );
252                 break;
253             default: throw new InternalCompilerError("iterateMSet could not handle mode " + mode);
254             }
255         } catch(MatchException e) {
256             throw new InternalCompilerError(e);
257         }
258     }
259
260     public void updateCost(double localBranching, double localCost) {
261         branching *= localBranching;
262         cost *= localBranching;
263         cost += localCost;
264     }
265     
266     public Expression getConstant(Name name, Type[] typeParameters) {
267         return context.getCompilationContext().getConstant(name, typeParameters);
268     }
269     
270     public QueryCompilationContext createCheckContext() {
271         return new QueryCompilationContext(context, QueryCompilationMode.CHECK,
272                 null, new ELiteral(new BooleanConstant(true)));
273     }
274     
275     public double getBranching() {
276         return branching;
277     }
278     
279     public double getCost() {
280         return cost;
281     }
282
283     public QueryCompilationContext createSubcontext(Expression innerExpression) {
284         return new QueryCompilationContext(context, mode, resultType, innerExpression);
285     }
286     
287     public void setContinuation(Expression continuation) {
288         this.continuation = continuation;
289     }
290     
291     public Expression getContinuation() {
292         return continuation;
293     }
294
295     public Expression disjunction(Expression[] disjuncts) {
296         Expression result = failure();
297         for(int i=disjuncts.length-1;i>=0;--i)
298             result = disjunction(disjuncts[i], result);
299         return result;
300     }
301     
302     public TypingContext getTypingContext() {
303         return context;
304     }
305
306     public EVariable getEvidence(long location, TPred pred) {
307         EVariable evidence = new EVariable(location, null);
308         evidence.setType(pred);
309         context.addConstraintDemand(evidence);
310         return evidence;
311     }
312
313     public CompilationContext getCompilationContext() {
314         return context.getCompilationContext();
315     }
316 }