X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fchr%2FCHRRuleset.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Felaboration%2Fchr%2FCHRRuleset.java;h=a2b5c2196df7ca02c4529994c8689eccf6a474a6;hp=0000000000000000000000000000000000000000;hb=a8758de5bc19e5adb3f618d3038743a164f09912;hpb=12d9af17384d960b75d58c3935d2b7b46d93e87b diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java new file mode 100644 index 000000000..a2b5c2196 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java @@ -0,0 +1,197 @@ +package org.simantics.scl.compiler.elaboration.chr; + +import java.util.ArrayList; + +import org.cojen.classfile.TypeDesc; +import org.simantics.scl.compiler.compilation.CompilationContext; +import org.simantics.scl.compiler.constants.BooleanConstant; +import org.simantics.scl.compiler.constants.Constant; +import org.simantics.scl.compiler.constants.IntegerConstant; +import org.simantics.scl.compiler.constants.JavaMethod; +import org.simantics.scl.compiler.constants.generic.CallJava; +import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef; +import org.simantics.scl.compiler.constants.generic.MethodRef.SetFieldRef; +import org.simantics.scl.compiler.elaboration.chr.analysis.UsageAnalysis; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp; +import org.simantics.scl.compiler.elaboration.chr.plan.PlanRealizer; +import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; +import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; +import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; +import org.simantics.scl.compiler.elaboration.contexts.TypingContext; +import org.simantics.scl.compiler.elaboration.expressions.Variable; +import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure; +import org.simantics.scl.compiler.errors.Locations; +import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator; +import org.simantics.scl.compiler.internal.codegen.references.BoundVar; +import org.simantics.scl.compiler.internal.codegen.references.IVal; +import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor; +import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter; +import org.simantics.scl.compiler.internal.parsing.Symbol; +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.compiler.types.TVar; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; + +import gnu.trove.map.hash.TObjectIntHashMap; +import gnu.trove.set.hash.THashSet; +import gnu.trove.set.hash.TIntHashSet; + +public class CHRRuleset extends Symbol { + + public static final String INIT_CONSTRAINT = "__INIT__"; + + public ArrayList constraints = new ArrayList(); + public ArrayList rules = new ArrayList(); + + public CHRConstraint initConstraint; + public int priorityCount; + + public String storeClassName; + public TCon storeType; + public BoundVar storeVariable; + public TypeDesc storeTypeDesc; + public Constant activateProcedure; + public Constant readCurrentId; + public Constant writeCurrentId; + + // FIXME remove and change the parameter of Expression.toVal + private CompilationContext cachedContext; + + // For code generation + public BoundVar this_; + public BoundVar[] parameters; + public TypeDesc[] parameterTypeDescs; + + public CHRRuleset() { + initConstraint = new CHRConstraint(Locations.NO_LOCATION, INIT_CONSTRAINT, Type.EMPTY_ARRAY); + constraints.add(initConstraint); + } + + public void resolve(TranslationContext context) { + for(CHRConstraint constraint : constraints) + context.newCHRConstraint(constraint.name, constraint); + priorityCount = 0; + for(CHRRule rule : rules) { + rule.resolve(context); + rule.priority = priorityCount++; + } + /*for(CHRConstraint constraint : constraints) { + Variable newVariable = context.newVariable("claim" + constraint.factClassName); + }*/ + } + + public void collectRefs(TObjectIntHashMap allRefs, TIntHashSet refs) { + for(CHRRule rule : rules) + rule.collectRefs(allRefs, refs); + } + + public void checkType(TypingContext context) { + for(CHRRule rule : rules) + rule.checkType(context); + } + + public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { + for(CHRRule rule : rules) + rule.collectVars(allVars, vars); + } + + public void forVariables(VariableProcedure procedure) { + for(CHRRule rule : rules) + rule.forVariables(procedure); + } + + public void collectFreeVariables(THashSet vars) { + for(CHRRule rule : rules) + rule.collectFreeVariables(vars); + } + + public void setLocationDeep(long loc) { + if(location == Locations.NO_LOCATION) { + this.location = loc; + for(CHRRule rule : rules) + rule.setLocationDeep(loc); + } + } + + public void compile(SimplificationContext context) { + initializeCodeGeneration(context.getCompilationContext()); + UsageAnalysis.analyzeUsage(this); + for(CHRRule rule : rules) + rule.compile(context.getCompilationContext(), initConstraint); + // remove init constraint if it is not useful + if(initConstraint.plans.isEmpty()) { + constraints.remove(0); + initConstraint = null; + } + for(CHRConstraint constraint : constraints) { + constraint.plans.sort((PrioritizedPlan a, PrioritizedPlan b) -> { + return Integer.compare(a.priority, b.priority); + }); + /*System.out.println(constraint.name); + for(PrioritizedPlan plan : constraint.plans) { + System.out.println(" priority " + plan.priority); + for(PlanOp op : plan.ops) + System.out.println(" " + op); + }*/ + } + } + + public void simplify(SimplificationContext context) { + for(CHRRule rule : rules) + rule.simplify(context); + } + + public void initializeCodeGeneration(CompilationContext context) { + cachedContext = context; // FIXME remove + + String suffix = context.namingPolicy.getFreshClosureClassNameSuffix(); + storeType = Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix); + storeClassName = context.namingPolicy.getModuleClassName() + suffix; + storeTypeDesc = TypeDesc.forClass(storeClassName); + storeVariable = new BoundVar(storeType); + for(CHRConstraint constraint : constraints) + constraint.initializeCodeGeneration(context, this); + activateProcedure = new JavaMethod(true, storeClassName, "activate", Types.PROC, Types.UNIT, storeType, Types.INTEGER); + readCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {storeType}, + null, new FieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null); + writeCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {storeType, Types.INTEGER}, + null, new SetFieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null); + if(context.module != null) // for unit testing + context.module.addTypeDescriptor(storeType.name, new StandardTypeConstructor(storeType, TVar.EMPTY_ARRAY, storeTypeDesc)); + } + + public void generateCode(CodeWriter w) { + CHRRulesetObject object = new CHRRulesetObject(storeVariable, this); + w.defineObject(object); + for(CHRConstraint constraint : constraints) { + //System.out.println(constraint); + for(PrioritizedPlan plan : constraint.plans) { + /*System.out.println(" plan " + plan.priority); + for(PlanOp planOp : plan.ops) + System.out.println(" " + planOp);*/ + PlanRealizer realizer = new PlanRealizer(cachedContext, this, storeVariable, plan.ops); + CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.BOOLEAN, new Type[] {constraint.factType}); + plan.implementation = methodWriter.getFunction(); + plan.activeFact.setVal(methodWriter.getParameters()[0]); + realizer.nextOp(methodWriter); + if(methodWriter.isUnfinished()) + methodWriter.return_(BooleanConstant.TRUE); + } + } + if(initConstraint != null) { + IVal initFact = w.apply(location, initConstraint.constructor, IntegerConstant.ZERO); + w.apply(location, initConstraint.addProcedure, storeVariable, initFact); + w.apply(location, activateProcedure, storeVariable, new IntegerConstant(Integer.MAX_VALUE)); + } + } + + public void collectEffects(THashSet effects) { + for(CHRRule rule : rules) { + for(CHRLiteral literal : rule.head.literals) + literal.collectQueryEffects(effects); + for(CHRLiteral literal : rule.head.literals) + literal.collectEnforceEffects(effects); + } + } +}