(refs #7375) Replaced collectFreeVariables method by a visitor
[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.printing.ExpressionToStringVisitor;
15 import org.simantics.scl.compiler.errors.Locations;
16 import org.simantics.scl.compiler.internal.parsing.Symbol;
17 import org.simantics.scl.compiler.types.Types;
18 import org.simantics.scl.compiler.types.kinds.Kinds;
19
20 import gnu.trove.map.hash.TObjectIntHashMap;
21 import gnu.trove.set.hash.TIntHashSet;
22
23 public class CHRRule extends Symbol {
24     public CHRRuleset parentRuleset;
25     public int priority;
26     public CHRQuery head;
27     public CHRQuery body;
28     public Variable[] existentialVariables;
29     
30     // Analysis
31     //public int firstPriorityExecuted;
32     public int lastPriorityExecuted;
33     
34     // Plans
35     public ArrayList<CHRSearchPlan> plans = new ArrayList<CHRSearchPlan>();
36     
37     // Code generation, move to CHRPriority
38     public String containerClassName;
39     
40     public CHRRule(long location, CHRQuery head, CHRQuery body, Variable[] existentialVariables) {
41         this.location = location;
42         this.head = head;
43         this.body = body;
44         this.existentialVariables = existentialVariables;
45     }
46     
47     public CHRRule(long location, CHRQuery head, CHRQuery body) {
48         this(location, head, body, null);
49     }
50
51     public void resolve(TranslationContext context) {
52         context.pushExistentialFrame();
53         head.resolve(context);
54         context.disallowNewExistentials();
55         body.resolve(context);
56         existentialVariables = context.popExistentialFrame();
57     }
58
59     public void checkType(TypingContext context) {
60         for(Variable variable : existentialVariables)
61             variable.setType(Types.metaVar(Kinds.STAR));
62         head.checkType(context);
63         body.checkType(context);
64     }
65     
66     public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
67         head.collectVars(allVars, vars);
68         body.collectVars(allVars, vars);
69     }
70
71     public void setLocationDeep(long loc) {
72         if(location == Locations.NO_LOCATION) {
73             this.location = loc;
74             head.setLocationDeep(loc);
75             body.setLocationDeep(loc);
76         }
77     }
78     
79     public void simplify(SimplificationContext context) {
80         head.simplify(context);
81         body.simplify(context);
82     }
83
84     public void compile(CompilationContext compilationContext, CHRConstraint initConstraint) {
85         boolean hasLocalActiveLiteral = false;
86         for(int i=0;i<head.literals.length;++i) {
87             CHRLiteral literal = head.literals[i];
88             if(literal.passive)
89                 continue;
90             CHRConstraint constraint = (CHRConstraint)literal.relation;
91             
92             Variable activeFact = new Variable("activeFact", constraint.factType);
93             QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
94             if(!head.createQueryPlan(context, new EVariable(activeFact), i, initConstraint))
95                 return;
96             body.createEnforcePlan(context, priority);
97             addPlan(new CHRSearchPlan(constraint, activeFact, context.getPlanOps()));
98             
99             if(constraint.parentRuleset == parentRuleset)
100                 hasLocalActiveLiteral = true;
101         }
102         if(!hasLocalActiveLiteral) {
103             Variable activeFact = new Variable("activeFact", initConstraint.factType);
104             QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
105             if(!head.createQueryPlan(context, new EVariable(activeFact), -1, initConstraint))
106                 return;
107             body.createEnforcePlan(context, priority);
108             /*System.out.println(this);
109             for(PlanOp planOp : context.getPlanOps())
110                 System.out.println("    " + planOp);*/
111             addPlan(new CHRSearchPlan(initConstraint, activeFact, context.getPlanOps()));
112         }
113     }
114     
115     private void addPlan(CHRSearchPlan plan) {
116         plans.add(plan);
117     }
118
119     public String toString() {
120         StringBuilder b = new StringBuilder();
121         ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
122         visitor.visit(this);
123         return b.toString();
124     }
125     
126 }