]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/items/GenericPrePlanItem.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[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;\r
2 \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
20 \r
21 import gnu.trove.set.hash.THashSet;\r
22 import gnu.trove.set.hash.TIntHashSet;\r
23 \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
30 \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
42     }\r
43 \r
44     private void updatePrimaryPriority() {\r
45         int boundCount = 0;\r
46         int boundMask = 0;\r
47         for(int i=0;i<variableSets.length;++i)\r
48             if(variableSets[i].isEmpty()) {\r
49                 ++boundCount;\r
50                 boundMask |= 1 << i;\r
51             }\r
52         if(boundCount == variableSets.length)\r
53             primaryPriority = 0;\r
54         else {\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
64                 else\r
65                     primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;\r
66             }\r
67             else\r
68                 primaryPriority = 3.0 - ((double)boundCount) / variableSets.length;\r
69         }\r
70     }\r
71 \r
72     @Override\r
73     public void initializeListeners(QueryPlanningContext context) {\r
74         context.listen(allVars, this);\r
75     }\r
76 \r
77     @Override\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
84     }\r
85     \r
86     @Override\r
87     public void generate(QueryPlanningContext context) {\r
88         int boundMask = 0;\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
96             }\r
97             else {\r
98                 freeVariables[i] = ((EVariable)expressions[i]).getVariable();\r
99                 ++freeVariableCount;\r
100             }\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
107         else\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
114                     continue;\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
119                 }\r
120             }\r
121         }\r
122         context.bind(allVars);\r
123     }\r
124 \r
125     private boolean killAfterMatch() {\r
126         return literal.killAfterMatch && relation instanceof CHRConstraint;\r
127     }\r
128 }\r