(refs #7250) Refactoring CHR implementation
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / CHRRule.java
1 package org.simantics.scl.compiler.elaboration.chr;
2
3 import java.util.ArrayList;
4
5 import org.simantics.scl.compiler.compilation.CompilationContext;
6 import org.simantics.scl.compiler.elaboration.chr.plan.CHRSearchPlan;
7 import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
8 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
9 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
10 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
11 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
12 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
13 import org.simantics.scl.compiler.elaboration.expressions.Variable;
14 import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
15 import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
16 import org.simantics.scl.compiler.errors.Locations;
17 import org.simantics.scl.compiler.internal.parsing.Symbol;
18 import org.simantics.scl.compiler.types.Types;
19 import org.simantics.scl.compiler.types.kinds.Kinds;
20
21 import gnu.trove.map.hash.TObjectIntHashMap;
22 import gnu.trove.set.hash.THashSet;
23 import gnu.trove.set.hash.TIntHashSet;
24
25 public class CHRRule extends Symbol {
26     public int priority;
27     public CHRQuery head;
28     public CHRQuery body;
29     public Variable[] existentialVariables;
30     
31     // Analysis
32     public int firstPriorityExecuted;
33     public int lastPriorityExecuted;
34     
35     // Plans
36     public ArrayList<CHRSearchPlan> plans = new ArrayList<CHRSearchPlan>();
37     
38     // Code generation, move to CHRPriority
39     public String containerClassName;
40     
41     public CHRRule(long location, CHRQuery head, CHRQuery body, Variable[] existentialVariables) {
42         this.location = location;
43         this.head = head;
44         this.body = body;
45         this.existentialVariables = existentialVariables;
46     }
47
48     public void resolve(TranslationContext context) {
49         context.pushExistentialFrame();
50         head.resolve(context);
51         body.resolve(context);
52         existentialVariables = context.popExistentialFrame();
53     }
54
55     public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
56         head.collectRefs(allRefs, refs);
57         body.collectRefs(allRefs, refs);
58     }
59
60     public void checkType(TypingContext context) {
61         for(Variable variable : existentialVariables)
62             variable.setType(Types.metaVar(Kinds.STAR));
63         head.checkType(context);
64         body.checkType(context);
65     }
66     
67     public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
68         head.collectVars(allVars, vars);
69         body.collectVars(allVars, vars);
70     }
71
72     public void forVariables(VariableProcedure procedure) {
73         head.forVariables(procedure);
74         body.forVariables(procedure);
75     }
76
77     public void collectFreeVariables(THashSet<Variable> vars) {
78         head.collectFreeVariables(vars);
79         body.collectFreeVariables(vars);
80     }
81
82     public void setLocationDeep(long loc) {
83         if(location == Locations.NO_LOCATION) {
84             this.location = loc;
85             head.setLocationDeep(loc);
86             body.setLocationDeep(loc);
87         }
88     }
89     
90     public void simplify(SimplificationContext context) {
91         head.simplify(context);
92         body.simplify(context);
93     }
94
95     public void compile(CompilationContext compilationContext, CHRConstraint initConstraint) {
96         boolean hasActiveLiteral = false;
97         for(int i=0;i<head.literals.length;++i) {
98             CHRLiteral literal = head.literals[i];
99             if(literal.passive)
100                 continue;
101             CHRConstraint constraint = (CHRConstraint)literal.relation;
102             
103             Variable activeFact = new Variable("activeFact", constraint.factType);
104             QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
105             if(!head.createQueryPlan(context, new EVariable(activeFact), i))
106                 return;
107             body.createEnforcePlan(context, priority);
108             addPlan(new CHRSearchPlan(constraint, activeFact, context.getPlanOps()));
109             
110             hasActiveLiteral = true;
111         }
112         if(!hasActiveLiteral) {
113             Variable activeFact = new Variable("activeFact", initConstraint.factType);
114             QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
115             if(!head.createQueryPlan(context, null, -1))
116                 return;
117             body.createEnforcePlan(context, priority);
118             /*System.out.println(this);
119             for(PlanOp planOp : context.getPlanOps())
120                 System.out.println("    " + planOp);*/
121             addPlan(new CHRSearchPlan(initConstraint, activeFact, context.getPlanOps()));
122         }
123     }
124     
125     private void addPlan(CHRSearchPlan plan) {
126         plans.add(plan);
127         plan.constraint.minimumPriority = Math.min(plan.constraint.minimumPriority, priority);
128     }
129
130     public String toString() {
131         StringBuilder b = new StringBuilder();
132         ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
133         visitor.visit(this);
134         return b.toString();
135     }
136     
137 }