--- /dev/null
+package org.simantics.scl.compiler.elaboration.java;
+
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.query.compilation.QueryCompilationContext;
+import org.simantics.scl.compiler.elaboration.relations.AbstractRelation;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+public class OptionalRelation extends AbstractRelation {
+ public static final OptionalRelation INSTANCE = new OptionalRelation();
+
+ private OptionalRelation() {}
+
+ private static final TVar A = Types.var(Kinds.STAR);
+
+ private static final TVar[] TYPE_VARIABLES = new TVar[] {A};
+
+ @Override
+ public TVar[] getTypeVariables() {
+ return TYPE_VARIABLES;
+ }
+
+ private static final Type[] PARAMETER_TYPES = new Type[] {A, Types.apply(Types.MAYBE, A)};
+
+ @Override
+ public Type[] getParameterTypes() {
+ return PARAMETER_TYPES;
+ }
+
+ @Override
+ public int getPhase() {
+ return 0;
+ }
+
+ @Override
+ public double getSelectivity(int boundVariables) {
+ switch(boundVariables) {
+ case FF:
+ case BF: return Double.POSITIVE_INFINITY;
+ case FB: return 0.95;
+ case BB: return 0.5;
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public int getRequiredVariablesMask() {
+ return FB;
+ }
+
+ @Override
+ public void generate(long location,
+ QueryCompilationContext context,
+ Type[] typeParameters, Variable[] parameters, int boundVariables) {
+ switch(boundVariables) {
+ case FB:
+ context.iterateMaybe(parameters[0], new EVariable(parameters[1]));
+ break;
+ case BB:
+ context.condition(
+ new EApply(
+ context.getConstant(Name.create("Prelude", "elemMaybe"), typeParameters),
+ new Expression[] {
+ context.getEvidence(location, Types.pred(Types.EQ, typeParameters[0])),
+ new EVariable(parameters[0]),
+ new EVariable(parameters[1])
+ }
+ ));
+ break;
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Optional";
+ }
+}