package org.simantics.scl.compiler.elaboration.java; import org.simantics.scl.compiler.common.names.Names; 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(Names.Prelude_elemMaybe, typeParameters), new Expression[] { new EVariable(parameters[0]), new EVariable(parameters[1]) } )); break; default: throw new IllegalArgumentException(); } } @Override public String toString() { return "Optional"; } }