]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/items/GenericPrePlanItem.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / planning / items / GenericPrePlanItem.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/items/GenericPrePlanItem.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/items/GenericPrePlanItem.java
new file mode 100644 (file)
index 0000000..fcf42ee
--- /dev/null
@@ -0,0 +1,128 @@
+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