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