1 package org.simantics.scl.compiler.elaboration.chr.planning.items;
\r
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
\r
4 import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
\r
5 import org.simantics.scl.compiler.elaboration.chr.CHRRelation;
\r
6 import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp;
\r
7 import org.simantics.scl.compiler.elaboration.chr.plan.IterateConstraintOp;
\r
8 import org.simantics.scl.compiler.elaboration.chr.plan.IterateRelationOp;
\r
9 import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem;
\r
10 import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
\r
11 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
\r
12 import org.simantics.scl.compiler.elaboration.chr.relations.ExternalCHRRelation;
\r
13 import org.simantics.scl.compiler.elaboration.expressions.EApply;
\r
14 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
\r
15 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
\r
16 import org.simantics.scl.compiler.elaboration.expressions.Expression;
\r
17 import org.simantics.scl.compiler.elaboration.expressions.Variable;
\r
18 import org.simantics.scl.compiler.elaboration.java.Builtins;
\r
19 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
\r
21 import gnu.trove.set.hash.THashSet;
\r
22 import gnu.trove.set.hash.TIntHashSet;
\r
24 public class GenericPrePlanItem extends PrePlanItem {
\r
25 public CHRLiteral literal;
\r
26 public CHRRelation relation;
\r
27 public Expression[] expressions;
\r
28 public TIntHashSet[] variableSets;
\r
29 TIntHashSet allVars;
\r
31 public GenericPrePlanItem(CHRLiteral literal, CHRRelation relation, Expression[] expressions,
\r
32 TIntHashSet[] variableSets, int secondaryPriority) {
\r
33 super(secondaryPriority);
\r
34 this.literal = literal;
\r
35 this.relation = relation;
\r
36 this.expressions = expressions;
\r
37 this.variableSets = variableSets;
\r
38 allVars = new TIntHashSet();
\r
39 for(TIntHashSet variableSet : variableSets)
\r
40 allVars.addAll(variableSet);
\r
41 updatePrimaryPriority();
\r
44 private void updatePrimaryPriority() {
\r
47 for(int i=0;i<variableSets.length;++i)
\r
48 if(variableSets[i].isEmpty()) {
\r
50 boundMask |= 1 << i;
\r
52 if(boundCount == variableSets.length)
\r
53 primaryPriority = 0;
\r
55 if(relation instanceof ExternalCHRRelation) {
\r
56 SCLRelation sclRelation = ((ExternalCHRRelation)relation).relation;
\r
57 double selectivity = sclRelation.getSelectivity(boundMask);
\r
58 if(selectivity == Double.POSITIVE_INFINITY)
\r
59 primaryPriority = Double.POSITIVE_INFINITY;
\r
60 else if(selectivity < 1.0)
\r
61 primaryPriority = 0.0;
\r
62 else if(selectivity == 1.0)
\r
63 primaryPriority = 1.0;
\r
65 primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;
\r
68 primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;
\r
73 public void initializeListeners(QueryPlanningContext context) {
\r
74 context.listen(allVars, this);
\r
78 public void variableSolved(QueryPlanningContext context, int variableId) {
\r
79 for(TIntHashSet variableSet : variableSets)
\r
80 variableSet.remove(variableId);
\r
81 allVars.remove(variableId);
\r
82 updatePrimaryPriority();
\r
83 context.priorityQueue.adjust(this);
\r
87 public void generate(QueryPlanningContext context) {
\r
89 Expression[] boundExpressions = new Expression[expressions.length];
\r
90 Variable[] freeVariables = new Variable[expressions.length];
\r
91 int freeVariableCount = 0;
\r
92 for(int i=0;i<expressions.length;++i)
\r
93 if(variableSets[i].isEmpty()) {
\r
94 boundExpressions[i] = expressions[i];
\r
95 boundMask |= 1 << i;
\r
98 freeVariables[i] = ((EVariable)expressions[i]).getVariable();
\r
99 ++freeVariableCount;
\r
101 if(relation instanceof CHRConstraint)
\r
102 context.addPlanOp(new IterateConstraintOp(location, (CHRConstraint)relation, freeVariables, boundExpressions, boundMask,
\r
103 killAfterMatch(), literal.passive));
\r
104 else if(relation instanceof ExternalCHRRelation)
\r
105 context.addPlanOp(new IterateRelationOp(location, ((ExternalCHRRelation)relation).relation,
\r
106 freeVariables, boundExpressions, boundMask));
\r
108 throw new InternalCompilerError();
\r
109 if(freeVariableCount > 1) {
\r
110 THashSet<Variable> usedVariables = new THashSet<Variable>(freeVariableCount);
\r
111 for(int i=0;i<freeVariables.length;++i) {
\r
112 Variable variable = freeVariables[i];
\r
113 if(variable == null)
\r
115 if(!usedVariables.add(variable)) {
\r
116 Variable auxiliary = new Variable(variable.getName(), variable.getType());
\r
117 freeVariables[i] = auxiliary;
\r
118 context.addPlanOp(new CheckOp(location, new EApply(location, new EConstant(Builtins.EQUALS, variable.getType()), new EVariable(auxiliary), new EVariable(variable))));
\r
122 context.bind(allVars);
\r
125 private boolean killAfterMatch() {
\r
126 return literal.killAfterMatch && relation instanceof CHRConstraint;
\r