package org.simantics.scl.compiler.elaboration.chr.planning.items; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.elaboration.chr.plan.AssignOp; import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp; import org.simantics.scl.compiler.elaboration.chr.plan.MatchOp; import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem; import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EConstant; 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.java.Builtins; import gnu.trove.set.hash.TIntHashSet; public class EqualsPrePlanItem extends PrePlanItem { public Expression expression1, expression2; public TIntHashSet variableSet1, variableSet2; public EqualsPrePlanItem(Expression expression1, Expression expression2, TIntHashSet variableSet1, TIntHashSet variableSet2, int secondaryPriority) { super(secondaryPriority); this.expression1 = expression1; this.expression2 = expression2; this.variableSet1 = variableSet1; this.variableSet2 = variableSet2; updatePrimaryPriority(); } private void updatePrimaryPriority() { if(variableSet2.isEmpty()) { if(variableSet1.isEmpty()) primaryPriority = 0; else primaryPriority = 1; } else { if(variableSet1.isEmpty() && expression2.isPattern(0)) primaryPriority = 0.0; } } @Override public void initializeListeners(QueryPlanningContext context) { context.listen(variableSet1, this); context.listen(variableSet2, this); } @Override public void variableSolved(QueryPlanningContext context, int variableId) { variableSet1.remove(variableId); variableSet2.remove(variableId); updatePrimaryPriority(); context.priorityQueue.adjust(this); } @Override public void generate(QueryPlanningContext context) { if(variableSet1.isEmpty() && variableSet2.isEmpty()) { context.addPlanOp(new CheckOp(location, new EApply(location, new EConstant(Builtins.EQUALS, expression1.getType()), expression1, expression2))); } else if(variableSet2.isEmpty()) { Variable variable = ((EVariable)expression1).getVariable(); context.addPlanOp(new AssignOp(location, variable, expression2)); context.bind(variableSet1); } else if(variableSet1.isEmpty()) { if(expression2 instanceof EVariable) { Variable variable = ((EVariable)expression2).getVariable(); context.addPlanOp(new AssignOp(location, variable, expression1)); } else { context.addPlanOp(new MatchOp(location, expression1, expression2)); } context.bind(variableSet2); } else throw new InternalCompilerError("Unsolvable query."); } }