1 package org.simantics.scl.compiler.elaboration.query.compilation;
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;
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;
33 public class QueryCompilationContext implements EnvironmentalContext {
34 private static final Name EQUALS = Name.create("Prelude", "==");
36 TypingContext context;
37 QueryCompilationMode mode;
39 Expression continuation;
40 double branching = 1.0;
43 public QueryCompilationContext(
44 TypingContext context,
45 QueryCompilationMode mode,
47 Expression continuation) {
48 this.context = context;
50 this.resultType = resultType;
51 this.continuation = continuation;
54 public Expression failure() {
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();
64 public Expression disjunction(Expression a, Expression b) {
66 case ITERATE: return new ESimpleLet(new Variable("_", Types.UNIT), a, b);
68 Variable var = new Variable("temp", a.getType());
70 new Case(new EConstant(Builtins.Nothing), b),
71 new Case(new EVariable(var), new EVariable(var)));
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();
81 case CHECK: return new EIf(a, new ELiteral(new BooleanConstant(true)), b);
82 default: throw new InternalCompilerError();
86 public Expression condition(Expression condition, Expression continuation) {
87 return new EIf(condition, continuation, failure());
90 public void condition(Expression condition) {
91 continuation = condition(condition, continuation);
94 public void equalityCondition(long location, Expression a, Expression b) {
95 Type type = a.getType();
99 context.getConstant(EQUALS, type),
101 getEvidence(location, Types.pred(Types.EQ, type)),
108 public void let(Variable variable, Expression value) {
109 continuation = new ESimpleLet(variable, value, continuation);
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));
118 public void match(Expression pattern, Expression value, boolean mayFail) {
120 continuation = new EMatch(value,
121 new Case(pattern, continuation),
122 new Case(new EVariable(new Variable("_", pattern.getType())), failure()));
124 continuation = new EMatch(value,
125 new Case(pattern, continuation));
128 public void iterateList(Variable variable, Expression list) {
132 continuation = new EApply(
133 Locations.NO_LOCATION,
135 context.getConstant(Name.create("Prelude", "iterList"), variable.getType(), Types.PROC, Types.tupleConstructor(0)),
137 new ESimpleLambda(Types.PROC, variable, continuation),
143 continuation = new EApply(
144 Locations.NO_LOCATION,
146 context.getConstant(Name.create("Prelude", "any"), variable.getType(), Types.PROC),
148 new ESimpleLambda(Types.PROC, variable, continuation),
154 continuation = new EApply(
155 Locations.NO_LOCATION,
157 context.getConstant(Name.create("Prelude", "concatMap"), variable.getType(), Types.PROC,
158 Types.matchApply(Types.LIST, continuation.getType())),
160 new ESimpleLambda(Types.PROC, variable, continuation),
166 continuation = new EApply(
167 Locations.NO_LOCATION,
169 context.getConstant(Name.create("Prelude", "mapFirst"), variable.getType(), Types.PROC,
170 Types.matchApply(Types.MAYBE, continuation.getType())),
172 new ESimpleLambda(Types.PROC, variable, continuation),
177 default: throw new InternalCompilerError("iterateList could not handle mode " + mode);
179 } catch(MatchException e) {
180 throw new InternalCompilerError(e);
184 public void iterateVector(Variable variable, Expression vector) {
188 continuation = new EApply(
189 Locations.NO_LOCATION,
191 context.getConstant(Name.create("Vector", "iterVector"), variable.getType(), Types.PROC, continuation.getType()),
193 new ESimpleLambda(Types.PROC, variable, continuation),
199 continuation = new EApply(
200 Locations.NO_LOCATION,
202 context.getConstant(Name.create("Vector", "anyVector"), variable.getType(), Types.PROC),
204 new ESimpleLambda(Types.PROC, variable, continuation),
210 continuation = new EApply(
211 Locations.NO_LOCATION,
213 context.getConstant(Name.create("Vector", "concatMapVector"), variable.getType(), Types.PROC,
214 Types.matchApply(Types.LIST, continuation.getType())),
216 new ESimpleLambda(Types.PROC, variable, continuation),
222 continuation = new EApply(
223 Locations.NO_LOCATION,
225 context.getConstant(Name.create("Vector", "mapFirstVector"), variable.getType(), Types.PROC,
226 Types.matchApply(Types.MAYBE, continuation.getType())),
228 new ESimpleLambda(Types.PROC, variable, continuation),
233 default: throw new InternalCompilerError("iterateVector could not handle mode " + mode);
235 } catch(MatchException e) {
236 throw new InternalCompilerError(e);
240 private static final Name MSet_iter = Name.create("MSet", "iter");
241 private static final Name MSet_mapFirst = Name.create("MSet", "mapFirst");
243 public void iterateMSet(Variable variable, Expression set) {
247 continuation = apply(context, Types.PROC, MSet_iter, variable.getType(), Types.PROC, continuation.getType(),
248 lambda(Types.PROC, variable, continuation),
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),
259 default: throw new InternalCompilerError("iterateMSet could not handle mode " + mode);
261 } catch(MatchException e) {
262 throw new InternalCompilerError(e);
266 public void updateCost(double localBranching, double localCost) {
267 branching *= localBranching;
268 cost *= localBranching;
272 public Expression getConstant(Name name, Type[] typeParameters) {
273 return context.getConstant(name, typeParameters);
276 public QueryCompilationContext createCheckContext() {
277 return new QueryCompilationContext(context, QueryCompilationMode.CHECK,
278 null, new ELiteral(new BooleanConstant(true)));
281 public double getBranching() {
285 public double getCost() {
289 public QueryCompilationContext createSubcontext(Expression innerExpression) {
290 return new QueryCompilationContext(context, mode, resultType, innerExpression);
293 public void setContinuation(Expression continuation) {
294 this.continuation = continuation;
297 public Expression getContinuation() {
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);
308 public TypingContext getTypingContext() {
312 public EVariable getEvidence(long location, TPred pred) {
313 EVariable evidence = new EVariable(location, null);
314 evidence.setType(pred);
315 context.addConstraintDemand(evidence);
320 public SCLValue getValue(Name name) {
321 return context.getValue(name);