-package org.simantics.scl.compiler.elaboration.chr;\r
-\r
-import org.simantics.scl.compiler.elaboration.chr.plan.PostCommitOp;\r
-import org.simantics.scl.compiler.elaboration.chr.plan.PreCommitOp;\r
-import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\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.expressions.VariableProcedure;\r
-import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.parsing.Symbol;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class CHRQuery extends Symbol {\r
- public CHRLiteral[] literals;\r
-\r
- public CHRQuery(CHRLiteral[] literals) {\r
- this.literals = literals;\r
- }\r
-\r
- public void resolve(TranslationContext context) {\r
- for(CHRLiteral literal : literals)\r
- literal.resolve(context);\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- for(CHRLiteral literal : literals)\r
- literal.collectRefs(allRefs, refs);\r
- }\r
-\r
- public void checkType(TypingContext context) {\r
- for(CHRLiteral literal : literals)\r
- literal.checkType(context);\r
- }\r
- \r
- public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
- for(CHRLiteral literal : literals)\r
- literal.collectVars(allVars, vars);\r
- }\r
-\r
- public void forVariables(VariableProcedure procedure) {\r
- for(CHRLiteral literal : literals)\r
- literal.forVariables(procedure);\r
- }\r
-\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- for(CHRLiteral literal : literals)\r
- literal.collectFreeVariables(vars);\r
- }\r
-\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- this.location = loc;\r
- for(CHRLiteral literal : literals)\r
- literal.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- public void createQueryPlan(QueryPlanningContext context, Expression inputFact, int activeLiteralId) {\r
- for(int i=0;i<literals.length;++i) {\r
- CHRLiteral literal = literals[i];\r
- if(i == activeLiteralId)\r
- context.activate(literal, inputFact, i);\r
- else\r
- context.add(literal, i);\r
- }\r
- context.createQueryPlan();\r
- }\r
- \r
- public void simplify(SimplificationContext context) {\r
- for(CHRLiteral literal : literals)\r
- literal.simplify(context);\r
- }\r
-\r
- public void createEnforcePlan(QueryPlanningContext context, int priority) {\r
- context.addPlanOp(new PreCommitOp(location));\r
- for(CHRLiteral literal : literals)\r
- context.claim(context, literal);\r
- context.addPlanOp(new PostCommitOp(location, priority));\r
- }\r
- \r
- public String toString() {\r
- StringBuilder b = new StringBuilder();\r
- ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
- visitor.visit(this);\r
- return b.toString();\r
- }\r
-}\r
+package org.simantics.scl.compiler.elaboration.chr;
+
+import org.simantics.scl.compiler.elaboration.chr.plan.PostCommitOp;
+import org.simantics.scl.compiler.elaboration.chr.plan.PreCommitOp;
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class CHRQuery extends Symbol {
+ public CHRLiteral[] literals;
+
+ public CHRQuery(CHRLiteral[] literals) {
+ this.literals = literals;
+ }
+
+ public void resolve(TranslationContext context) {
+ for(CHRLiteral literal : literals)
+ literal.resolve(context);
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ for(CHRLiteral literal : literals)
+ literal.collectRefs(allRefs, refs);
+ }
+
+ public void checkType(TypingContext context) {
+ for(CHRLiteral literal : literals)
+ literal.checkType(context);
+ }
+
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+ for(CHRLiteral literal : literals)
+ literal.collectVars(allVars, vars);
+ }
+
+ public void forVariables(VariableProcedure procedure) {
+ for(CHRLiteral literal : literals)
+ literal.forVariables(procedure);
+ }
+
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ for(CHRLiteral literal : literals)
+ literal.collectFreeVariables(vars);
+ }
+
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ this.location = loc;
+ for(CHRLiteral literal : literals)
+ literal.setLocationDeep(loc);
+ }
+ }
+
+ public boolean createQueryPlan(QueryPlanningContext context, Expression inputFact, int activeLiteralId) {
+ for(int i=0;i<literals.length;++i) {
+ CHRLiteral literal = literals[i];
+ if(i == activeLiteralId)
+ context.activate(literal, inputFact, i);
+ else
+ context.add(literal, i);
+ }
+ return context.createQueryPlan();
+ }
+
+ public void simplify(SimplificationContext context) {
+ for(CHRLiteral literal : literals)
+ literal.simplify(context);
+ }
+
+ public void createEnforcePlan(QueryPlanningContext context, int priority) {
+ context.addPlanOp(new PreCommitOp(location));
+ for(CHRLiteral literal : literals)
+ context.claim(context, literal);
+ context.addPlanOp(new PostCommitOp(location, priority));
+ }
+
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
+ visitor.visit(this);
+ return b.toString();
+ }
+}
-package org.simantics.scl.compiler.elaboration.chr;\r
-\r
-import org.simantics.scl.compiler.compilation.CompilationContext;\r
-import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;\r
-import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;\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.contexts.SimplificationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
-import org.simantics.scl.compiler.elaboration.expressions.EVariable;\r
-import org.simantics.scl.compiler.elaboration.expressions.Variable;\r
-import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;\r
-import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.parsing.Symbol;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.kinds.Kinds;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class CHRRule extends Symbol {\r
- public int priority;\r
- public CHRQuery head;\r
- public CHRQuery body;\r
- public Variable[] existentialVariables;\r
- \r
- // Analysis\r
- public int firstPriorityExecuted;\r
- public int lastPriorityExecuted;\r
- \r
- public CHRRule(long location, CHRQuery head, CHRQuery body, Variable[] existentialVariables) {\r
- this.location = location;\r
- this.head = head;\r
- this.body = body;\r
- this.existentialVariables = existentialVariables;\r
- }\r
-\r
- public void resolve(TranslationContext context) {\r
- context.pushExistentialFrame();\r
- head.resolve(context);\r
- body.resolve(context);\r
- existentialVariables = context.popExistentialFrame();\r
- }\r
-\r
- public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {\r
- head.collectRefs(allRefs, refs);\r
- body.collectRefs(allRefs, refs);\r
- }\r
-\r
- public void checkType(TypingContext context) {\r
- for(Variable variable : existentialVariables)\r
- variable.setType(Types.metaVar(Kinds.STAR));\r
- head.checkType(context);\r
- body.checkType(context);\r
- }\r
- \r
- public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {\r
- head.collectVars(allVars, vars);\r
- body.collectVars(allVars, vars);\r
- }\r
-\r
- public void forVariables(VariableProcedure procedure) {\r
- head.forVariables(procedure);\r
- body.forVariables(procedure);\r
- }\r
-\r
- public void collectFreeVariables(THashSet<Variable> vars) {\r
- head.collectFreeVariables(vars);\r
- body.collectFreeVariables(vars);\r
- }\r
-\r
- public void setLocationDeep(long loc) {\r
- if(location == Locations.NO_LOCATION) {\r
- this.location = loc;\r
- head.setLocationDeep(loc);\r
- body.setLocationDeep(loc);\r
- }\r
- }\r
- \r
- public void simplify(SimplificationContext context) {\r
- head.simplify(context);\r
- body.simplify(context);\r
- }\r
-\r
- public void compile(CompilationContext compilationContext, CHRConstraint initConstraint) {\r
- boolean hasActiveLiteral = false;\r
- for(int i=0;i<head.literals.length;++i) {\r
- CHRLiteral literal = head.literals[i];\r
- if(literal.passive)\r
- continue;\r
- CHRConstraint constraint = (CHRConstraint)literal.relation;\r
- \r
- Variable activeFact = new Variable("activeFact", constraint.factType);\r
- QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);\r
- head.createQueryPlan(context, new EVariable(activeFact), i);\r
- body.createEnforcePlan(context, priority);\r
- constraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));\r
- \r
- hasActiveLiteral = true;\r
- }\r
- if(!hasActiveLiteral) {\r
- Variable activeFact = new Variable("activeFact", initConstraint.factType);\r
- QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);\r
- head.createQueryPlan(context, null, -1);\r
- body.createEnforcePlan(context, priority);\r
- /*System.out.println(this);\r
- for(PlanOp planOp : context.getPlanOps())\r
- System.out.println(" " + planOp);*/\r
- initConstraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));\r
- }\r
- }\r
- \r
- public String toString() {\r
- StringBuilder b = new StringBuilder();\r
- ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);\r
- visitor.visit(this);\r
- return b.toString();\r
- }\r
- \r
-}\r
+package org.simantics.scl.compiler.elaboration.chr;
+
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp;
+import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;
+import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
+import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class CHRRule extends Symbol {
+ public int priority;
+ public CHRQuery head;
+ public CHRQuery body;
+ public Variable[] existentialVariables;
+
+ // Analysis
+ public int firstPriorityExecuted;
+ public int lastPriorityExecuted;
+
+ public CHRRule(long location, CHRQuery head, CHRQuery body, Variable[] existentialVariables) {
+ this.location = location;
+ this.head = head;
+ this.body = body;
+ this.existentialVariables = existentialVariables;
+ }
+
+ public void resolve(TranslationContext context) {
+ context.pushExistentialFrame();
+ head.resolve(context);
+ body.resolve(context);
+ existentialVariables = context.popExistentialFrame();
+ }
+
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ head.collectRefs(allRefs, refs);
+ body.collectRefs(allRefs, refs);
+ }
+
+ public void checkType(TypingContext context) {
+ for(Variable variable : existentialVariables)
+ variable.setType(Types.metaVar(Kinds.STAR));
+ head.checkType(context);
+ body.checkType(context);
+ }
+
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+ head.collectVars(allVars, vars);
+ body.collectVars(allVars, vars);
+ }
+
+ public void forVariables(VariableProcedure procedure) {
+ head.forVariables(procedure);
+ body.forVariables(procedure);
+ }
+
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ head.collectFreeVariables(vars);
+ body.collectFreeVariables(vars);
+ }
+
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ this.location = loc;
+ head.setLocationDeep(loc);
+ body.setLocationDeep(loc);
+ }
+ }
+
+ public void simplify(SimplificationContext context) {
+ head.simplify(context);
+ body.simplify(context);
+ }
+
+ public void compile(CompilationContext compilationContext, CHRConstraint initConstraint) {
+ boolean hasActiveLiteral = false;
+ for(int i=0;i<head.literals.length;++i) {
+ CHRLiteral literal = head.literals[i];
+ if(literal.passive)
+ continue;
+ CHRConstraint constraint = (CHRConstraint)literal.relation;
+
+ Variable activeFact = new Variable("activeFact", constraint.factType);
+ QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
+ if(!head.createQueryPlan(context, new EVariable(activeFact), i))
+ return;
+ body.createEnforcePlan(context, priority);
+ constraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));
+
+ hasActiveLiteral = true;
+ }
+ if(!hasActiveLiteral) {
+ Variable activeFact = new Variable("activeFact", initConstraint.factType);
+ QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
+ if(!head.createQueryPlan(context, null, -1))
+ return;
+ body.createEnforcePlan(context, priority);
+ /*System.out.println(this);
+ for(PlanOp planOp : context.getPlanOps())
+ System.out.println(" " + planOp);*/
+ initConstraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));
+ }
+ }
+
+ public String toString() {
+ StringBuilder b = new StringBuilder();
+ ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
+ visitor.visit(this);
+ return b.toString();
+ }
+
+}
-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 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 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.");
+ }
+ }
+ }
+
+}