bb5491ad17111c79aa7fc30ee2742cd2ef782149
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / CHRRuleset.java
1 package org.simantics.scl.compiler.elaboration.chr;
2
3 import java.util.ArrayList;
4
5 import org.cojen.classfile.TypeDesc;
6 import org.simantics.scl.compiler.compilation.CompilationContext;
7 import org.simantics.scl.compiler.constants.BooleanConstant;
8 import org.simantics.scl.compiler.constants.Constant;
9 import org.simantics.scl.compiler.constants.IntegerConstant;
10 import org.simantics.scl.compiler.constants.JavaMethod;
11 import org.simantics.scl.compiler.constants.generic.CallJava;
12 import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
13 import org.simantics.scl.compiler.constants.generic.MethodRef.SetFieldRef;
14 import org.simantics.scl.compiler.elaboration.chr.analysis.UsageAnalysis;
15 import org.simantics.scl.compiler.elaboration.chr.plan.PlanRealizer;
16 import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;
17 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
18 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
19 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
20 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
21 import org.simantics.scl.compiler.elaboration.expressions.Variable;
22 import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
23 import org.simantics.scl.compiler.errors.Locations;
24 import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;
25 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
26 import org.simantics.scl.compiler.internal.codegen.references.IVal;
27 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
28 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
29 import org.simantics.scl.compiler.internal.parsing.Symbol;
30 import org.simantics.scl.compiler.types.TCon;
31 import org.simantics.scl.compiler.types.TVar;
32 import org.simantics.scl.compiler.types.Type;
33 import org.simantics.scl.compiler.types.Types;
34
35 import gnu.trove.map.hash.TObjectIntHashMap;
36 import gnu.trove.set.hash.THashSet;
37 import gnu.trove.set.hash.TIntHashSet;
38
39 public class CHRRuleset extends Symbol {
40     
41     public static final String INIT_CONSTRAINT = "__INIT__";
42     
43     public ArrayList<CHRConstraint> constraints = new ArrayList<CHRConstraint>();
44     public ArrayList<CHRRule> rules = new ArrayList<CHRRule>();
45     
46     public CHRConstraint initConstraint;
47     public int priorityCount;
48     
49     public String storeClassName;
50     public TCon storeType;
51     public BoundVar storeVariable;
52     public TypeDesc storeTypeDesc;
53     public Constant activateProcedure;
54     public Constant readCurrentId;
55     public Constant writeCurrentId;
56     
57     // FIXME remove and change the parameter of Expression.toVal
58     private CompilationContext cachedContext;
59     
60     // For code generation
61     public BoundVar this_;
62     public BoundVar[] parameters;
63     public TypeDesc[] parameterTypeDescs;
64     
65     public CHRRuleset() {
66         initConstraint = new CHRConstraint(Locations.NO_LOCATION, INIT_CONSTRAINT, Type.EMPTY_ARRAY);
67         constraints.add(initConstraint);
68     }
69     
70     public void resolve(TranslationContext context) {
71         for(CHRConstraint constraint : constraints)
72             context.newCHRConstraint(constraint.name, constraint);
73         priorityCount = 0;
74         for(CHRRule rule : rules) {
75             rule.resolve(context);
76             rule.priority = priorityCount++;
77         }
78         /*for(CHRConstraint constraint : constraints) {
79             Variable newVariable = context.newVariable("claim" + constraint.factClassName);
80         }*/
81     }
82
83     public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
84         for(CHRRule rule : rules)
85             rule.collectRefs(allRefs, refs);
86     }
87
88     public void checkType(TypingContext context) {
89         for(CHRRule rule : rules)
90             rule.checkType(context);
91     }
92
93     public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
94         for(CHRRule rule : rules)
95             rule.collectVars(allVars, vars);
96     }
97
98     public void forVariables(VariableProcedure procedure) {
99         for(CHRRule rule : rules)
100             rule.forVariables(procedure);
101     }
102
103     public void collectFreeVariables(THashSet<Variable> vars) {
104         for(CHRRule rule : rules)
105             rule.collectFreeVariables(vars);
106     }
107
108     public void setLocationDeep(long loc) {
109         if(location == Locations.NO_LOCATION) {
110             this.location = loc;
111             for(CHRRule rule : rules)
112                 rule.setLocationDeep(loc);
113         }
114     }
115
116     public void compile(SimplificationContext context) {
117         initializeCodeGeneration(context.getCompilationContext());
118         UsageAnalysis.analyzeUsage(this);
119         for(CHRRule rule : rules)
120             rule.compile(context.getCompilationContext(), initConstraint);
121         // remove init constraint if it is not useful
122         if(initConstraint.plans.isEmpty()) {
123             constraints.remove(0);
124             initConstraint = null;
125         }
126         for(CHRConstraint constraint : constraints) {
127             constraint.plans.sort((PrioritizedPlan a, PrioritizedPlan b) -> {
128                 return Integer.compare(a.priority, b.priority);
129             });
130             /*System.out.println(constraint.name);
131             for(PrioritizedPlan plan : constraint.plans) {
132                 System.out.println("  priority " + plan.priority);
133                 for(PlanOp op : plan.ops)
134                     System.out.println("    " + op);
135             }*/
136         }
137     }
138
139     public void simplify(SimplificationContext context) {
140         for(CHRRule rule : rules)
141             rule.simplify(context);
142     }
143     
144     public void initializeCodeGeneration(CompilationContext context) {
145         cachedContext = context; // FIXME remove
146         
147         String suffix = context.namingPolicy.getFreshClosureClassNameSuffix();
148         storeType = Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix);
149         storeClassName = context.namingPolicy.getModuleClassName() + suffix;
150         storeTypeDesc = TypeDesc.forClass(storeClassName);
151         storeVariable = new BoundVar(storeType); 
152         for(CHRConstraint constraint : constraints)
153             constraint.initializeCodeGeneration(context, this);
154         activateProcedure = new JavaMethod(true, storeClassName, "activate", Types.PROC, Types.UNIT, storeType, Types.INTEGER);
155         readCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {storeType},
156                 null, new FieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null);
157         writeCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {storeType, Types.INTEGER},
158                 null, new SetFieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null);
159         if(context.module != null) // for unit testing
160             context.module.addTypeDescriptor(storeType.name, new StandardTypeConstructor(storeType, TVar.EMPTY_ARRAY, storeTypeDesc));
161     }
162     
163     public void generateCode(CodeWriter w) {
164         CHRRulesetObject object = new CHRRulesetObject(storeVariable, this);
165         w.defineObject(object);
166         for(CHRConstraint constraint : constraints) {
167             //System.out.println(constraint);
168             for(PrioritizedPlan plan : constraint.plans) {
169                 /*System.out.println("    plan " + plan.priority);
170                 for(PlanOp planOp : plan.ops)
171                     System.out.println("        " + planOp);*/
172                 PlanRealizer realizer = new PlanRealizer(cachedContext, this, storeVariable, plan.ops);
173                 CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.BOOLEAN, new Type[] {constraint.factType});
174                 plan.implementation = methodWriter.getFunction();
175                 plan.activeFact.setVal(methodWriter.getParameters()[0]);
176                 realizer.nextOp(methodWriter);
177                 if(methodWriter.isUnfinished())
178                     methodWriter.return_(BooleanConstant.TRUE);
179             }
180         }
181         if(initConstraint != null) {
182             IVal initFact = w.apply(location, initConstraint.constructor, IntegerConstant.ZERO);
183             w.apply(location, initConstraint.addProcedure, storeVariable, initFact);
184             w.apply(location, activateProcedure, storeVariable, new IntegerConstant(Integer.MAX_VALUE));
185         }
186     }
187
188     public void collectEffects(THashSet<Type> effects) {
189         for(CHRRule rule : rules) {
190             for(CHRLiteral literal : rule.head.literals)
191                 literal.collectQueryEffects(effects);
192             for(CHRLiteral literal : rule.head.literals)
193                 literal.collectEnforceEffects(effects);
194         }
195     }
196 }