]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/planning/QueryPlanningContext.java
(refs #7365) Fixed the bug in the test CHR11.scl
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / planning / QueryPlanningContext.java
index c083b8fc9693a41b25ba3165bb2df6f5096c65ea..61503458cd541ef4d84d2aabe0b06220b13d0813 100644 (file)
-package org.simantics.scl.compiler.elaboration.chr.planning;\r
-\r
-import java.util.ArrayList;\r
-\r
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
-import org.simantics.scl.compiler.compilation.CompilationContext;\r
-import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;\r
-import org.simantics.scl.compiler.elaboration.chr.plan.AccessFactOp;\r
-import org.simantics.scl.compiler.elaboration.chr.plan.ClaimOp;\r
-import org.simantics.scl.compiler.elaboration.chr.plan.ExecuteOp;\r
-import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;\r
-import org.simantics.scl.compiler.elaboration.chr.planning.items.CheckPrePlanItem;\r
-import org.simantics.scl.compiler.elaboration.chr.planning.items.EqualsPrePlanItem;\r
-import org.simantics.scl.compiler.elaboration.chr.planning.items.GenericPrePlanItem;\r
-import org.simantics.scl.compiler.elaboration.chr.planning.items.MemberPrePlanItem;\r
-import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;\r
-import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;\r
-import org.simantics.scl.compiler.elaboration.expressions.EApplyType;\r
-import org.simantics.scl.compiler.elaboration.expressions.EConstant;\r
-import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;\r
-import org.simantics.scl.compiler.elaboration.expressions.ELiteral;\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
-\r
-import gnu.trove.impl.Constants;\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.procedure.TIntProcedure;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class QueryPlanningContext {\r
-    CompilationContext compilationContext;\r
-    public PlanPriorityQueue priorityQueue = new PlanPriorityQueue();\r
-    ArrayList<Variable> variables;\r
-    TObjectIntHashMap<Variable> variableMap;\r
-    ArrayList<ArrayList<PrePlanItem>> itemsContainingVariable;\r
-    ArrayList<PlanOp> planOps = new ArrayList<PlanOp>(); \r
-    \r
-    public QueryPlanningContext(CompilationContext compilationContext, Variable[] variables) {\r
-        this.compilationContext = compilationContext;\r
-        this.variables = new ArrayList<Variable>(variables.length*2);\r
-        this.variableMap = new TObjectIntHashMap<Variable>(variables.length, Constants.DEFAULT_LOAD_FACTOR, -1);\r
-        itemsContainingVariable = new ArrayList<ArrayList<PrePlanItem>>(variables.length*2);\r
-        for(Variable variable : variables)\r
-            addVariable(variable);\r
-    }\r
-    \r
-    private void addVariable(Variable variable) {\r
-        int id = variables.size();\r
-        variables.add(variable);\r
-        variableMap.put(variable, id);\r
-        itemsContainingVariable.add(new ArrayList<PrePlanItem>(2));\r
-    }\r
-\r
-    public void add(CHRLiteral literal, int secondaryPriority) {\r
-        if(literal.relation instanceof SpecialCHRRelation) {\r
-            switch((SpecialCHRRelation)literal.relation) {\r
-            case CHECK:\r
-                addCheck(literal.location, literal.parameters[0], secondaryPriority);\r
-                return;\r
-            case EQUALS:\r
-                addGenericEquals(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority);\r
-                return;\r
-            case MEMBER:\r
-                addMember(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority);\r
-                return;\r
-            case EXECUTE:\r
-                throw new InternalCompilerError(literal.location, "EXECUTE constraint is not allowed in query compilation.");\r
-            }\r
-        }\r
-        \r
-        addGenericConstraint(literal, secondaryPriority);\r
-    }\r
-    \r
-    private TIntHashSet getVars(Expression expression, int initialCapacity) {\r
-        TIntHashSet variableSet = new TIntHashSet(initialCapacity);\r
-        expression.collectVars(variableMap, variableSet);\r
-        return variableSet;\r
-    }\r
-    \r
-    private TIntHashSet[] getVars(Expression[] expressions, int initialCapacity) {\r
-        TIntHashSet[] variableSets = new TIntHashSet[expressions.length];\r
-        for(int i=0;i<expressions.length;++i)\r
-            variableSets[i] = getVars(expressions[i], initialCapacity);\r
-        return variableSets;\r
-    }\r
-    \r
-    /**\r
-     * Returns true, if the expression is so simple, it does not involve any computation.\r
-     */\r
-    private static boolean isSimpleExpression(Expression expression) {\r
-        while(expression instanceof EApplyType)\r
-            expression = ((EApplyType)expression).getExpression();\r
-        return expression instanceof EVariable \r
-                || expression instanceof EConstant\r
-                || expression instanceof ELiteral\r
-                || expression instanceof EExternalConstant;\r
-    }\r
-    \r
-    private Expression toSimpleExpression(Expression expression, int secondaryPriority) {\r
-        if(isSimpleExpression(expression))        \r
-            return expression;\r
-        else {\r
-            Variable temp = new Variable("temp", expression.getType());\r
-            addVariable(temp);\r
-            addOneSidedEquals(expression.location, new EVariable(temp), expression, secondaryPriority);\r
-            return new EVariable(temp);\r
-        }\r
-    }\r
-    \r
-    private Expression[] toSimpleExpressions(Expression[] expressions, int secondaryPriority) {\r
-        Expression[] result = new Expression[expressions.length];\r
-        for(int i=0;i<expressions.length;++i)\r
-            result[i] = toSimpleExpression(expressions[i], secondaryPriority);\r
-        return result;\r
-    }\r
-\r
-    private void addGenericConstraint(CHRLiteral literal, int secondaryPriority) {\r
-        if(literal.killAfterMatch)\r
-            ((CHRConstraint)literal.relation).setMayBeRemoved();\r
-        Expression[] parameters = toSimpleExpressions(literal.parameters, secondaryPriority);\r
-        add(literal.location, new GenericPrePlanItem(literal, literal.relation, parameters, getVars(parameters, 1), secondaryPriority));\r
-    }\r
-\r
-    private void addMember(long location, Expression p1, Expression p2, int secondaryPriority) {\r
-        Expression expression1 = toSimpleExpression(p1, secondaryPriority);\r
-        Expression expression2 = toSimpleExpression(p2, secondaryPriority);\r
-        add(location, new MemberPrePlanItem(expression1, expression2,\r
-                getVars(expression1, 1), getVars(expression2, 1), secondaryPriority));\r
-    }\r
-    \r
-    private void addOneSidedEquals(long location, Expression expression1, Expression expression2, int secondaryPriority) {\r
-        add(location, new EqualsPrePlanItem(expression1, expression2,\r
-                getVars(expression1, 1), getVars(expression2, 4), secondaryPriority));\r
-    }\r
-\r
-    private void addGenericEquals(long location, Expression p1, Expression p2, int secondaryPriority) {\r
-        if(isSimpleExpression(p1))\r
-            addOneSidedEquals(location, p1, p2, secondaryPriority);\r
-        else if(isSimpleExpression(p2))\r
-            addOneSidedEquals(location, p2, p1, secondaryPriority);\r
-        else {\r
-            Variable temp = new Variable("temp", p1.getType());\r
-            addVariable(temp);\r
-            addOneSidedEquals(p1.location, new EVariable(temp), p1, secondaryPriority);\r
-            addOneSidedEquals(p2.location, new EVariable(temp), p2, secondaryPriority);\r
-        }\r
-    }\r
-\r
-    private void addCheck(long location, Expression condition, int secondaryPriority) {\r
-        TIntHashSet variableSet = new TIntHashSet(4);\r
-        condition.collectVars(variableMap, variableSet);\r
-        add(location, new CheckPrePlanItem(condition, variableSet, secondaryPriority));\r
-    }\r
-\r
-    private void add(long location, PrePlanItem item) {\r
-        priorityQueue.add(item);\r
-        item.initializeListeners(this);\r
-        item.location = location;\r
-    }\r
-\r
-    public void listen(TIntHashSet variableSet, PrePlanItem item) {\r
-        variableSet.forEach(new TIntProcedure() {\r
-            @Override\r
-            public boolean execute(int variableId) {\r
-                listen(variableId, item);\r
-                return true;\r
-            }\r
-        });\r
-    }\r
-\r
-    public void listen(int variableId, PrePlanItem item) {\r
-        itemsContainingVariable.get(variableId).add(item);\r
-    }\r
-\r
-    public void createQueryPlan() {\r
-        while(!priorityQueue.isEmpty()) {\r
-            PrePlanItem head = priorityQueue.head();\r
-            priorityQueue.pop();\r
-            head.generate(this);\r
-        }\r
-    }\r
-    \r
-    public ArrayList<PlanOp> getPlanOps() {\r
-        return planOps;\r
-    }\r
-    \r
-    private final TIntProcedure BIND_PROCEDURE = new TIntProcedure() {\r
-        @Override\r
-        public boolean execute(int variableId) {\r
-            ArrayList<PrePlanItem> l = itemsContainingVariable.get(variableId);\r
-            for(PrePlanItem item : l)\r
-                item.variableSolved(QueryPlanningContext.this, variableId);\r
-            l.clear();\r
-            return true;\r
-        }\r
-    };\r
-\r
-    public void bind(TIntHashSet variableSet) {\r
-        variableSet.forEach(BIND_PROCEDURE);\r
-    }\r
-\r
-    public void addPlanOp(PlanOp planOp) {\r
-        planOps.add(planOp);\r
-    }\r
-\r
-    public CompilationContext getCompilationContext() {\r
-        return compilationContext;\r
-    }\r
-\r
-    public void activate(CHRLiteral literal, Expression inputFact, int secondaryPriority) {\r
-        Variable[] variables = new Variable[literal.parameters.length];\r
-        for(int i=0;i<literal.parameters.length;++i)\r
-            variables[i] = new Variable("activeFactComponent" + i, literal.parameters[i].getType());\r
-        if(literal.killAfterMatch)\r
-            ((CHRConstraint)literal.relation).setMayBeRemoved();\r
-        planOps.add(new AccessFactOp(literal.location, inputFact, (CHRConstraint)literal.relation, variables, literal.killAfterMatch));\r
-        for(int i=0;i<literal.parameters.length;++i)\r
-            addOneSidedEquals(literal.parameters[i].location, new EVariable(variables[i]), literal.parameters[i], secondaryPriority);\r
-    }\r
-\r
-    public void claim(QueryPlanningContext context, CHRLiteral literal) {\r
-        if(literal.relation instanceof CHRConstraint) {\r
-            CHRConstraint constraint = (CHRConstraint)literal.relation;\r
-            addPlanOp(new ClaimOp(literal.location, constraint, literal.parameters));\r
-        }\r
-        else if(literal.relation instanceof SpecialCHRRelation) {\r
-            switch((SpecialCHRRelation)literal.relation) {\r
-            case EXECUTE:\r
-                addPlanOp(new ExecuteOp(literal.location, literal.parameters[0]));\r
-                break;\r
-            default:\r
-                context.getCompilationContext().errorLog.log(\r
-                        literal.location,\r
-                        "Cannot enforce this constraint.");\r
-            }\r
-        }\r
-    }\r
-\r
-}\r
+package org.simantics.scl.compiler.elaboration.chr.planning;
+
+import java.util.ArrayList;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
+import org.simantics.scl.compiler.elaboration.chr.plan.AccessFactOp;
+import org.simantics.scl.compiler.elaboration.chr.plan.ClaimOp;
+import org.simantics.scl.compiler.elaboration.chr.plan.ExecuteOp;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;
+import org.simantics.scl.compiler.elaboration.chr.planning.items.CheckPrePlanItem;
+import org.simantics.scl.compiler.elaboration.chr.planning.items.EqualsPrePlanItem;
+import org.simantics.scl.compiler.elaboration.chr.planning.items.GenericPrePlanItem;
+import org.simantics.scl.compiler.elaboration.chr.planning.items.MemberPrePlanItem;
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
+import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
+import org.simantics.scl.compiler.elaboration.expressions.EApplyType;
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;
+import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.errors.Locations;
+
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class QueryPlanningContext {
+    CompilationContext compilationContext;
+    public PlanPriorityQueue priorityQueue = new PlanPriorityQueue();
+    ArrayList<Variable> variables;
+    TObjectIntHashMap<Variable> variableMap;
+    ArrayList<ArrayList<PrePlanItem>> itemsContainingVariable;
+    ArrayList<PlanOp> planOps = new ArrayList<PlanOp>(); 
+    
+    public QueryPlanningContext(CompilationContext compilationContext, Variable[] variables) {
+        this.compilationContext = compilationContext;
+        this.variables = new ArrayList<Variable>(variables.length*2);
+        this.variableMap = new TObjectIntHashMap<Variable>(variables.length, Constants.DEFAULT_LOAD_FACTOR, -1);
+        itemsContainingVariable = new ArrayList<ArrayList<PrePlanItem>>(variables.length*2);
+        for(Variable variable : variables)
+            addVariable(variable);
+    }
+    
+    private void addVariable(Variable variable) {
+        int id = variables.size();
+        variables.add(variable);
+        variableMap.put(variable, id);
+        itemsContainingVariable.add(new ArrayList<PrePlanItem>(2));
+    }
+
+    public void add(CHRLiteral literal, int secondaryPriority) {
+        if(literal.relation instanceof SpecialCHRRelation) {
+            switch((SpecialCHRRelation)literal.relation) {
+            case CHECK:
+                addCheck(literal.location, literal.parameters[0], secondaryPriority);
+                return;
+            case EQUALS:
+                addGenericEquals(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority);
+                return;
+            case MEMBER:
+                addMember(literal.location, literal.parameters[0], literal.parameters[1], secondaryPriority);
+                return;
+            case EXECUTE:
+                throw new InternalCompilerError(literal.location, "EXECUTE constraint is not allowed in query compilation.");
+            }
+        }
+        
+        addGenericConstraint(literal, secondaryPriority);
+    }
+    
+    private TIntHashSet getVars(Expression expression, int initialCapacity) {
+        TIntHashSet variableSet = new TIntHashSet(initialCapacity);
+        expression.collectVars(variableMap, variableSet);
+        return variableSet;
+    }
+    
+    private TIntHashSet[] getVars(Expression[] expressions, int initialCapacity) {
+        TIntHashSet[] variableSets = new TIntHashSet[expressions.length];
+        for(int i=0;i<expressions.length;++i)
+            variableSets[i] = getVars(expressions[i], initialCapacity);
+        return variableSets;
+    }
+    
+    /**
+     * Returns true, if the expression is so simple, it does not involve any computation.
+     */
+    private static boolean isSimpleExpression(Expression expression) {
+        while(expression instanceof EApplyType)
+            expression = ((EApplyType)expression).getExpression();
+        return expression instanceof EVariable 
+                || expression instanceof EConstant
+                || expression instanceof ELiteral
+                || expression instanceof EExternalConstant;
+    }
+    
+    private Expression toSimpleExpression(Expression expression, int secondaryPriority) {
+        if(isSimpleExpression(expression))        
+            return expression;
+        else {
+            Variable temp = new Variable("temp", expression.getType());
+            addVariable(temp);
+            addOneSidedEquals(expression.location, new EVariable(temp), expression, secondaryPriority);
+            return new EVariable(temp);
+        }
+    }
+    
+    private Expression[] toSimpleExpressions(Expression[] expressions, int secondaryPriority) {
+        Expression[] result = new Expression[expressions.length];
+        for(int i=0;i<expressions.length;++i)
+            result[i] = toSimpleExpression(expressions[i], secondaryPriority);
+        return result;
+    }
+
+    private void addGenericConstraint(CHRLiteral literal, int secondaryPriority) {
+        if(literal.killAfterMatch)
+            ((CHRConstraint)literal.relation).setMayBeRemoved();
+        Expression[] parameters = toSimpleExpressions(literal.parameters, secondaryPriority);
+        add(literal.location, new GenericPrePlanItem(literal, literal.relation, parameters, getVars(parameters, 1), secondaryPriority));
+    }
+
+    private void addMember(long location, Expression p1, Expression p2, int secondaryPriority) {
+        Expression expression1 = toSimpleExpression(p1, secondaryPriority);
+        Expression expression2 = toSimpleExpression(p2, secondaryPriority);
+        add(location, new MemberPrePlanItem(expression1, expression2,
+                getVars(expression1, 1), getVars(expression2, 1), secondaryPriority));
+    }
+    
+    private void addOneSidedEquals(long location, Expression expression1, Expression expression2, int secondaryPriority) {
+        add(location, new EqualsPrePlanItem(expression1, expression2,
+                getVars(expression1, 1), getVars(expression2, 4), secondaryPriority));
+    }
+
+    private void addGenericEquals(long location, Expression p1, Expression p2, int secondaryPriority) {
+        if(isSimpleExpression(p1))
+            addOneSidedEquals(location, p1, p2, secondaryPriority);
+        else if(isSimpleExpression(p2))
+            addOneSidedEquals(location, p2, p1, secondaryPriority);
+        else {
+            Variable temp = new Variable("temp", p1.getType());
+            addVariable(temp);
+            addOneSidedEquals(p1.location, new EVariable(temp), p1, secondaryPriority);
+            addOneSidedEquals(p2.location, new EVariable(temp), p2, secondaryPriority);
+        }
+    }
+
+    private void addCheck(long location, Expression condition, int secondaryPriority) {
+        TIntHashSet variableSet = new TIntHashSet(4);
+        condition.collectVars(variableMap, variableSet);
+        add(location, new CheckPrePlanItem(condition, variableSet, secondaryPriority));
+    }
+
+    private void add(long location, PrePlanItem item) {
+        priorityQueue.add(item);
+        item.initializeListeners(this);
+        item.location = location;
+    }
+
+    public void listen(TIntHashSet variableSet, PrePlanItem item) {
+        variableSet.forEach(new TIntProcedure() {
+            @Override
+            public boolean execute(int variableId) {
+                listen(variableId, item);
+                return true;
+            }
+        });
+    }
+
+    public void listen(int variableId, PrePlanItem item) {
+        itemsContainingVariable.get(variableId).add(item);
+    }
+
+    public boolean createQueryPlan() {
+        while(!priorityQueue.isEmpty()) {
+            PrePlanItem head = priorityQueue.head();
+            if(head.primaryPriority == Double.POSITIVE_INFINITY) {
+                compilationContext.errorLog.log(head.location, "Cannot solve the query.");
+                return false;
+            }
+            priorityQueue.pop();
+            head.generate(this);
+        }
+        return true;
+    }
+    
+    public ArrayList<PlanOp> getPlanOps() {
+        return planOps;
+    }
+    
+    private final TIntProcedure BIND_PROCEDURE = new TIntProcedure() {
+        @Override
+        public boolean execute(int variableId) {
+            ArrayList<PrePlanItem> l = itemsContainingVariable.get(variableId);
+            for(PrePlanItem item : l)
+                item.variableSolved(QueryPlanningContext.this, variableId);
+            l.clear();
+            return true;
+        }
+    };
+
+    public void bind(TIntHashSet variableSet) {
+        variableSet.forEach(BIND_PROCEDURE);
+    }
+
+    public void addPlanOp(PlanOp planOp) {
+        planOps.add(planOp);
+    }
+
+    public CompilationContext getCompilationContext() {
+        return compilationContext;
+    }
+
+    public void activate(CHRLiteral literal, Expression inputFact, int secondaryPriority) {
+        Variable[] variables = new Variable[literal.parameters.length];
+        for(int i=0;i<literal.parameters.length;++i)
+            variables[i] = new Variable("activeFactComponent" + i, literal.parameters[i].getType());
+        if(literal.killAfterMatch)
+            ((CHRConstraint)literal.relation).setMayBeRemoved();
+        planOps.add(new AccessFactOp(literal.location, inputFact, (CHRConstraint)literal.relation, variables, literal.killAfterMatch));
+        for(int i=0;i<literal.parameters.length;++i)
+            addOneSidedEquals(literal.parameters[i].location, new EVariable(variables[i]), literal.parameters[i], secondaryPriority);
+    }
+    
+    public void addInitFact(CHRConstraint initConstraint, Expression inputFact) {
+        planOps.add(new AccessFactOp(Locations.NO_LOCATION, inputFact, initConstraint, Variable.EMPTY_ARRAY, false));
+    }
+
+    public void claim(QueryPlanningContext context, CHRLiteral literal) {
+        if(literal.relation instanceof CHRConstraint) {
+            CHRConstraint constraint = (CHRConstraint)literal.relation;
+            addPlanOp(new ClaimOp(literal.location, constraint, literal.parameters));
+        }
+        else if(literal.relation instanceof SpecialCHRRelation) {
+            switch((SpecialCHRRelation)literal.relation) {
+            case EXECUTE:
+                addPlanOp(new ExecuteOp(literal.location, literal.parameters[0]));
+                break;
+            default:
+                context.getCompilationContext().errorLog.log(
+                        literal.location,
+                        "Cannot enforce this constraint.");
+            }
+        }
+    }
+
+}