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