--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.planning.items;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.IterateConstraintOp;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.IterateRelationOp;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem;\r
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
+import org.simantics.scl.compiler.elaboration.chr.relations.ExternalCHRRelation;\r
+import org.simantics.scl.compiler.elaboration.expressions.EApply;\r
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
+import org.simantics.scl.compiler.elaboration.expressions.Expression;\r
+import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
+import org.simantics.scl.compiler.elaboration.java.Builtins;\r
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;\r
+\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\r
+\r
+public class GenericPrePlanItem extends PrePlanItem {\r
+ public CHRLiteral literal;\r
+ public CHRRelation relation;\r
+ public Expression[] expressions;\r
+ public TIntHashSet[] variableSets;\r
+ TIntHashSet allVars;\r
+\r
+ public GenericPrePlanItem(CHRLiteral literal, CHRRelation relation, Expression[] expressions,\r
+ TIntHashSet[] variableSets, int secondaryPriority) {\r
+ super(secondaryPriority);\r
+ this.literal = literal;\r
+ this.relation = relation;\r
+ this.expressions = expressions;\r
+ this.variableSets = variableSets;\r
+ allVars = new TIntHashSet();\r
+ for(TIntHashSet variableSet : variableSets)\r
+ allVars.addAll(variableSet);\r
+ updatePrimaryPriority();\r
+ }\r
+\r
+ private void updatePrimaryPriority() {\r
+ int boundCount = 0;\r
+ int boundMask = 0;\r
+ for(int i=0;i<variableSets.length;++i)\r
+ if(variableSets[i].isEmpty()) {\r
+ ++boundCount;\r
+ boundMask |= 1 << i;\r
+ }\r
+ if(boundCount == variableSets.length)\r
+ primaryPriority = 0;\r
+ else {\r
+ if(relation instanceof ExternalCHRRelation) {\r
+ SCLRelation sclRelation = ((ExternalCHRRelation)relation).relation;\r
+ double selectivity = sclRelation.getSelectivity(boundMask);\r
+ if(selectivity == Double.POSITIVE_INFINITY)\r
+ primaryPriority = Double.POSITIVE_INFINITY;\r
+ else if(selectivity < 1.0)\r
+ primaryPriority = 0.0;\r
+ else if(selectivity == 1.0)\r
+ primaryPriority = 1.0;\r
+ else\r
+ primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;\r
+ }\r
+ else\r
+ primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void initializeListeners(QueryPlanningContext context) {\r
+ context.listen(allVars, this);\r
+ }\r
+\r
+ @Override\r
+ public void variableSolved(QueryPlanningContext context, int variableId) {\r
+ for(TIntHashSet variableSet : variableSets)\r
+ variableSet.remove(variableId);\r
+ allVars.remove(variableId);\r
+ updatePrimaryPriority();\r
+ context.priorityQueue.adjust(this);\r
+ }\r
+ \r
+ @Override\r
+ public void generate(QueryPlanningContext context) {\r
+ int boundMask = 0;\r
+ Expression[] boundExpressions = new Expression[expressions.length];\r
+ Variable[] freeVariables = new Variable[expressions.length];\r
+ int freeVariableCount = 0;\r
+ for(int i=0;i<expressions.length;++i)\r
+ if(variableSets[i].isEmpty()) {\r
+ boundExpressions[i] = expressions[i];\r
+ boundMask |= 1 << i;\r
+ }\r
+ else {\r
+ freeVariables[i] = ((EVariable)expressions[i]).getVariable();\r
+ ++freeVariableCount;\r
+ }\r
+ if(relation instanceof CHRConstraint)\r
+ context.addPlanOp(new IterateConstraintOp(location, (CHRConstraint)relation, freeVariables, boundExpressions, boundMask,\r
+ killAfterMatch(), literal.passive));\r
+ else if(relation instanceof ExternalCHRRelation)\r
+ context.addPlanOp(new IterateRelationOp(location, ((ExternalCHRRelation)relation).relation,\r
+ freeVariables, boundExpressions, boundMask));\r
+ else\r
+ throw new InternalCompilerError();\r
+ if(freeVariableCount > 1) {\r
+ THashSet<Variable> usedVariables = new THashSet<Variable>(freeVariableCount);\r
+ for(int i=0;i<freeVariables.length;++i) {\r
+ Variable variable = freeVariables[i];\r
+ if(variable == null)\r
+ continue;\r
+ if(!usedVariables.add(variable)) {\r
+ Variable auxiliary = new Variable(variable.getName(), variable.getType());\r
+ freeVariables[i] = auxiliary;\r
+ context.addPlanOp(new CheckOp(location, new EApply(location, new EConstant(Builtins.EQUALS, variable.getType()), new EVariable(auxiliary), new EVariable(variable))));\r
+ }\r
+ }\r
+ }\r
+ context.bind(allVars);\r
+ }\r
+\r
+ private boolean killAfterMatch() {\r
+ return literal.killAfterMatch && relation instanceof CHRConstraint;\r
+ }\r
+}\r