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