]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/items/GenericPrePlanItem.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / planning / items / GenericPrePlanItem.java
1 package org.simantics.scl.compiler.elaboration.chr.planning.items;
2
3 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
4 import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
5 import org.simantics.scl.compiler.elaboration.chr.CHRRelation;
6 import org.simantics.scl.compiler.elaboration.chr.plan.CheckOp;
7 import org.simantics.scl.compiler.elaboration.chr.plan.IterateConstraintOp;
8 import org.simantics.scl.compiler.elaboration.chr.plan.IterateRelationOp;
9 import org.simantics.scl.compiler.elaboration.chr.planning.PrePlanItem;
10 import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
11 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
12 import org.simantics.scl.compiler.elaboration.chr.relations.ExternalCHRRelation;
13 import org.simantics.scl.compiler.elaboration.expressions.EApply;
14 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
15 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
16 import org.simantics.scl.compiler.elaboration.expressions.Expression;
17 import org.simantics.scl.compiler.elaboration.expressions.Variable;
18 import org.simantics.scl.compiler.elaboration.java.Builtins;
19 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
20
21 import gnu.trove.set.hash.THashSet;
22 import gnu.trove.set.hash.TIntHashSet;
23
24 public class GenericPrePlanItem extends PrePlanItem {
25     public CHRLiteral literal;
26     public CHRRelation relation;
27     public Expression[] expressions;
28     public TIntHashSet[] variableSets;
29     TIntHashSet allVars;
30
31     public GenericPrePlanItem(CHRLiteral literal, CHRRelation relation, Expression[] expressions,
32             TIntHashSet[] variableSets, int secondaryPriority) {
33         super(secondaryPriority);
34         this.literal = literal;
35         this.relation = relation;
36         this.expressions = expressions;
37         this.variableSets = variableSets;
38         allVars = new TIntHashSet();
39         for(TIntHashSet variableSet : variableSets)
40             allVars.addAll(variableSet);
41         updatePrimaryPriority();
42     }
43
44     private void updatePrimaryPriority() {
45         int boundCount = 0;
46         int boundMask = 0;
47         for(int i=0;i<variableSets.length;++i)
48             if(variableSets[i].isEmpty()) {
49                 ++boundCount;
50                 boundMask |= 1 << i;
51             }
52         if(boundCount == variableSets.length)
53             primaryPriority = 0;
54         else {
55             if(relation instanceof ExternalCHRRelation) {
56                 SCLRelation sclRelation = ((ExternalCHRRelation)relation).relation;
57                 double selectivity = sclRelation.getSelectivity(boundMask);
58                 if(selectivity == Double.POSITIVE_INFINITY)
59                     primaryPriority = Double.POSITIVE_INFINITY;
60                 else if(selectivity < 1.0)
61                     primaryPriority = 0.0;
62                 else if(selectivity == 1.0)
63                     primaryPriority = 1.0;
64                 else
65                     primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;
66             }
67             else
68                 primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;
69         }
70     }
71
72     @Override
73     public void initializeListeners(QueryPlanningContext context) {
74         context.listen(allVars, this);
75     }
76
77     @Override
78     public void variableSolved(QueryPlanningContext context, int variableId) {
79         for(TIntHashSet variableSet : variableSets)
80             variableSet.remove(variableId);
81         allVars.remove(variableId);
82         updatePrimaryPriority();
83         context.priorityQueue.adjust(this);
84     }
85     
86     @Override
87     public void generate(QueryPlanningContext context) {
88         int boundMask = 0;
89         Expression[] boundExpressions = new Expression[expressions.length];
90         Variable[] freeVariables = new Variable[expressions.length];
91         int freeVariableCount = 0;
92         for(int i=0;i<expressions.length;++i)
93             if(variableSets[i].isEmpty()) {
94                 boundExpressions[i] = expressions[i];
95                 boundMask |= 1 << i;
96             }
97             else {
98                 freeVariables[i] = ((EVariable)expressions[i]).getVariable();
99                 ++freeVariableCount;
100             }
101         if(relation instanceof CHRConstraint)
102             context.addPlanOp(new IterateConstraintOp(location, (CHRConstraint)relation, freeVariables, boundExpressions, boundMask,
103                     killAfterMatch(), literal.passive));
104         else if(relation instanceof ExternalCHRRelation)
105             context.addPlanOp(new IterateRelationOp(location, ((ExternalCHRRelation)relation).relation,
106                     freeVariables, boundExpressions, literal.typeConstraintEvidenceParameters, boundMask));
107         else
108             throw new InternalCompilerError();
109         if(freeVariableCount > 1) {
110             THashSet<Variable> usedVariables = new THashSet<Variable>(freeVariableCount);
111             for(int i=0;i<freeVariables.length;++i) {
112                 Variable variable = freeVariables[i];
113                 if(variable == null)
114                     continue;
115                 if(!usedVariables.add(variable)) {
116                     Variable auxiliary = new Variable(variable.getName(), variable.getType());
117                     freeVariables[i] = auxiliary;
118                     context.addPlanOp(new CheckOp(location, new EApply(location, new EConstant(Builtins.EQUALS, variable.getType()), new EVariable(auxiliary), new EVariable(variable))));
119                 }
120             }
121         }
122         context.bind(allVars);
123     }
124
125     private boolean killAfterMatch() {
126         return literal.killAfterMatch && relation instanceof CHRConstraint;
127     }
128 }