From a2df536f7fc878982c6c960a79ed49f350cddc6f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Hannu=20Niemist=C3=B6?= Date: Tue, 30 May 2017 10:49:26 +0300 Subject: [PATCH] (refs #7250) Refactoring CHR implementation This change is preparation for the modularization of the CHR rule systems. The main change is moving the major rule execution code from fact classes to priority level classes. Change-Id: Idd63339d8c2cf81e2af07660f0f81cae273c1d62 --- .../scl/compiler/common/names/Names.java | 1 + .../scl/compiler/elaboration/chr/CHRRule.java | 20 +- .../compiler/elaboration/chr/CHRRuleset.java | 69 ++-- .../elaboration/chr/CHRRulesetObject.java | 8 +- ...rioritizedPlan.java => CHRSearchPlan.java} | 9 +- .../elaboration/chr/plan/ClaimOp.java | 2 +- .../chr/plan/IterateConstraintOp.java | 1 - .../elaboration/chr/plan/PlanContext.java | 8 +- .../elaboration/chr/plan/PlanRealizer.java | 4 +- .../elaboration/chr/plan/PostCommitOp.java | 7 +- .../chr/relations/CHRConstraint.java | 46 ++- .../compiler/elaboration/java/Builtins.java | 6 + .../chr/CHRCodeGenerationConstants.java | 37 +++ .../codegen/chr/CHRFactCodeGenerator.java | 295 ++---------------- .../chr/CHRHashIndexCodeGenerator.java | 120 +++++++ ...CHRPriorityFactContainerCodeGenerator.java | 189 +++++++++++ ...va => CHRRuntimeRulesetCodeGenerator.java} | 60 ++-- .../internal/codegen/chr/ExampleStore.java | 21 +- .../simantics/scl/compiler/types/Types.java | 5 +- .../org.simantics.scl.runtime/scl/TestCHR.scl | 15 + .../simantics/scl/runtime/chr/CHRContext.java | 17 + .../simantics/scl/runtime/chr/CHRFact.java | 5 + .../scl/runtime/chr/CHRPriority.java | 78 +++++ .../runtime/chr/CHRPriorityFactContainer.java | 59 ++++ .../scl/runtime/chr/CHRRuntimeRuleset.java | 5 + .../org/simantics/scl/runtime/chr/Fact.java | 11 - .../scl/runtime/chr/FactActivationQueue.java | 120 ------- .../scl/runtime/chr/PriorityContainer.java | 42 --- .../tests/TestFactActivationQueue.java | 58 ---- .../scl/compiler/tests/ActiveTests.java | 3 +- .../simantics/scl/compiler/tests/scl/CHR5.scl | 16 + .../tests/unit/TestCHRCodeGenerator.java | 8 +- 32 files changed, 700 insertions(+), 645 deletions(-) rename bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/{PrioritizedPlan.java => CHRSearchPlan.java} (59%) create mode 100644 bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java create mode 100644 bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRHashIndexCodeGenerator.java create mode 100644 bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRPriorityFactContainerCodeGenerator.java rename bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/{CHRCodeGenerator.java => CHRRuntimeRulesetCodeGenerator.java} (60%) create mode 100644 bundles/org.simantics.scl.runtime/scl/TestCHR.scl create mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRContext.java create mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRFact.java create mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriority.java create mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriorityFactContainer.java create mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRRuntimeRuleset.java delete mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/Fact.java delete mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java delete mode 100644 bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/PriorityContainer.java delete mode 100644 bundles/org.simantics.scl.runtime/tests/org/simantics/scl/runtime/tests/TestFactActivationQueue.java create mode 100644 tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java index 1c4255b46..50729430d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java @@ -12,6 +12,7 @@ public class Names { public static final Name Builtin_equals = Name.create(Types.BUILTIN, "=="); public static final Name Builtin_fail = Name.create(Types.BUILTIN, "fail"); public static final Name Builtin_runProc = Name.create(Types.BUILTIN, "runProc"); + public static final Name Builtin_createCHRContext = Name.create(Types.BUILTIN, "createCHRContext"); public static final Name Data_XML_createElement = Name.create("Data/XML", "createElement"); public static final Type Data_XML_Element = Types.con("Data/XML", "Element"); public static final TCon Expressions_Context_Context = Types.con("Expressions/Context", "Context"); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java index 48aefbdac..9846ebd48 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java @@ -1,8 +1,9 @@ package org.simantics.scl.compiler.elaboration.chr; +import java.util.ArrayList; + import org.simantics.scl.compiler.compilation.CompilationContext; -import org.simantics.scl.compiler.elaboration.chr.plan.PlanOp; -import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan; +import org.simantics.scl.compiler.elaboration.chr.plan.CHRSearchPlan; import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; @@ -31,6 +32,12 @@ public class CHRRule extends Symbol { public int firstPriorityExecuted; public int lastPriorityExecuted; + // Plans + public ArrayList plans = new ArrayList(); + + // Code generation, move to CHRPriority + public String containerClassName; + public CHRRule(long location, CHRQuery head, CHRQuery body, Variable[] existentialVariables) { this.location = location; this.head = head; @@ -98,7 +105,7 @@ public class CHRRule extends Symbol { if(!head.createQueryPlan(context, new EVariable(activeFact), i)) return; body.createEnforcePlan(context, priority); - constraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps())); + addPlan(new CHRSearchPlan(constraint, activeFact, context.getPlanOps())); hasActiveLiteral = true; } @@ -111,10 +118,15 @@ public class CHRRule extends Symbol { /*System.out.println(this); for(PlanOp planOp : context.getPlanOps()) System.out.println(" " + planOp);*/ - initConstraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps())); + addPlan(new CHRSearchPlan(initConstraint, activeFact, context.getPlanOps())); } } + private void addPlan(CHRSearchPlan plan) { + plans.add(plan); + plan.constraint.minimumPriority = Math.min(plan.constraint.minimumPriority, priority); + } + public String toString() { StringBuilder b = new StringBuilder(); ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b); 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 index bb5491ad1..7b5ceec83 100644 --- 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 @@ -7,13 +7,14 @@ 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.JavaConstructor; 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.CHRSearchPlan; 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; @@ -21,7 +22,8 @@ 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.chr.CHRCodeGenerationConstants; +import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator; 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; @@ -46,11 +48,10 @@ public class CHRRuleset extends Symbol { public CHRConstraint initConstraint; public int priorityCount; - public String storeClassName; - public TCon storeType; - public BoundVar storeVariable; - public TypeDesc storeTypeDesc; - public Constant activateProcedure; + public String runtimeRulesetName; + public TCon runtimeRulesetType; + public BoundVar runtimeRulesetVariable; + public TypeDesc runtimeRulesetTypeDesc; public Constant readCurrentId; public Constant writeCurrentId; @@ -119,21 +120,10 @@ public class CHRRuleset extends Symbol { for(CHRRule rule : rules) rule.compile(context.getCompilationContext(), initConstraint); // remove init constraint if it is not useful - if(initConstraint.plans.isEmpty()) { + if(initConstraint.minimumPriority == Integer.MAX_VALUE) { 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) { @@ -145,43 +135,46 @@ public class CHRRuleset extends Symbol { 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); + runtimeRulesetType = Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix); + runtimeRulesetName = context.namingPolicy.getModuleClassName() + suffix; + runtimeRulesetTypeDesc = TypeDesc.forClass(runtimeRulesetName); + runtimeRulesetVariable = new BoundVar(runtimeRulesetType); 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); + readCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {Types.CHRContext}, + null, new FieldRef(CHRCodeGenerationConstants.CHRContext_name, "currentId", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null); + writeCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {Types.CHRContext, Types.INTEGER}, + null, new SetFieldRef(CHRCodeGenerationConstants.CHRContext_name, "currentId", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null); if(context.module != null) // for unit testing - context.module.addTypeDescriptor(storeType.name, new StandardTypeConstructor(storeType, TVar.EMPTY_ARRAY, storeTypeDesc)); + context.module.addTypeDescriptor(runtimeRulesetType.name, new StandardTypeConstructor(runtimeRulesetType, TVar.EMPTY_ARRAY, runtimeRulesetTypeDesc)); } + + public static final Constant ACTIVATE = new JavaMethod(true, CHRCodeGenerationConstants.CHRContext_name, "activate", Types.PROC, Types.UNIT, Types.CHRContext, Types.INTEGER); + private static final Constant CREATE_CHR_CONTEXT = new JavaConstructor("org/simantics/scl/runtime/chr/CHRContext", Types.PROC, Types.CHRContext); public void generateCode(CodeWriter w) { - CHRRulesetObject object = new CHRRulesetObject(storeVariable, this); + CHRRulesetObject object = new CHRRulesetObject(runtimeRulesetVariable, this); w.defineObject(object); - for(CHRConstraint constraint : constraints) { - //System.out.println(constraint); - for(PrioritizedPlan plan : constraint.plans) { + for(CHRRule rule : rules) { + for(CHRSearchPlan plan : rule.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}); + CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.BOOLEAN, new Type[] {Types.CHRContext, plan.constraint.factType}); plan.implementation = methodWriter.getFunction(); - plan.activeFact.setVal(methodWriter.getParameters()[0]); + IVal[] implementationParameters = methodWriter.getParameters(); + plan.activeFact.setVal(implementationParameters[1]); + PlanRealizer realizer = new PlanRealizer(cachedContext, this, runtimeRulesetVariable, implementationParameters[0], plan.ops); realizer.nextOp(methodWriter); if(methodWriter.isUnfinished()) methodWriter.return_(BooleanConstant.TRUE); } } if(initConstraint != null) { + IVal chrContext = w.apply(location, CREATE_CHR_CONTEXT); 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)); + w.apply(location, initConstraint.addProcedure, runtimeRulesetVariable, chrContext, initFact); + w.apply(location, ACTIVATE, chrContext, new IntegerConstant(Integer.MAX_VALUE)); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java index 73ba8ea1a..a15e30e42 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java @@ -2,7 +2,7 @@ package org.simantics.scl.compiler.elaboration.chr; import org.simantics.scl.compiler.constants.Constant; import org.simantics.scl.compiler.constants.JavaConstructor; -import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator; +import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator; import org.simantics.scl.compiler.internal.codegen.references.BoundVar; import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject; import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; @@ -12,7 +12,7 @@ public class CHRRulesetObject extends SSAObject { CHRRuleset ruleset; public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) { - super(ruleset.storeType); + super(ruleset.runtimeRulesetType); this.setTarget(target); this.ruleset = ruleset; } @@ -21,11 +21,11 @@ public class CHRRulesetObject extends SSAObject { public Constant liftClosure(BoundVar newTarget, BoundVar[] parameters) { ruleset.this_ = newTarget; ruleset.parameters = parameters; - return new JavaConstructor(ruleset.storeClassName, Types.PROC, ruleset.storeType, Types.getTypes(parameters)); + return new JavaConstructor(ruleset.runtimeRulesetName, Types.PROC, ruleset.runtimeRulesetType, Types.getTypes(parameters)); } @Override public void generateCode(ModuleBuilder moduleBuilder) { - CHRCodeGenerator.generateStore(moduleBuilder, ruleset); + CHRRuntimeRulesetCodeGenerator.generateRuntimeRuleset(moduleBuilder, ruleset); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PrioritizedPlan.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/CHRSearchPlan.java similarity index 59% rename from bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PrioritizedPlan.java rename to bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/CHRSearchPlan.java index f7a072e5d..f958e459b 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PrioritizedPlan.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/CHRSearchPlan.java @@ -2,17 +2,18 @@ package org.simantics.scl.compiler.elaboration.chr.plan; import java.util.List; +import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction; -public class PrioritizedPlan { - public int priority; +public class CHRSearchPlan { + public CHRConstraint constraint; public Variable activeFact; public List ops; public SSAFunction implementation; - public PrioritizedPlan(int priority, Variable activeFact, List ops) { - this.priority = priority; + public CHRSearchPlan(CHRConstraint constraint, Variable activeFact, List ops) { + this.constraint = constraint; this.activeFact = activeFact; this.ops = ops; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java index ad6129aad..e4484a933 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java @@ -31,7 +31,7 @@ public class ClaimOp extends PlanOp { for(int i=0;i partnerFacts = new ArrayList(); public IVal currentId; - public PlanContext(CompilationContext context, CHRRuleset ruleset, IVal storeVar) { + public PlanContext(CompilationContext context, CHRRuleset ruleset, IVal storeVar, IVal contextVar) { this.context = context; this.ruleset = ruleset; this.storeVar = storeVar; + this.contextVar = contextVar; } public abstract void nextOp(CodeWriter w); public IVal generateNewId(long location, CodeWriter w) { if(currentId == null) - currentId = w.apply(location, ruleset.readCurrentId, storeVar); + currentId = w.apply(location, ruleset.readCurrentId, contextVar); IVal result = currentId; currentId = w.apply(location, IncreaseByOne.INSTANCE, currentId); return result; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanRealizer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanRealizer.java index 0fbbcfba4..43fedf765 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanRealizer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanRealizer.java @@ -11,8 +11,8 @@ public class PlanRealizer extends PlanContext { List ops; int id = 0; - public PlanRealizer(CompilationContext context, CHRRuleset ruleset, IVal storeVar, List ops) { - super(context, ruleset, storeVar); + public PlanRealizer(CompilationContext context, CHRRuleset ruleset, IVal storeVar, IVal contextVar, List ops) { + super(context, ruleset, storeVar, contextVar); this.ops = ops; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java index af41f932b..de00093cf 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java @@ -3,6 +3,7 @@ package org.simantics.scl.compiler.elaboration.chr.plan; import org.simantics.scl.compiler.compilation.CompilationContext; import org.simantics.scl.compiler.constants.IntegerConstant; import org.simantics.scl.compiler.constants.singletons.NullCheck; +import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import org.simantics.scl.compiler.internal.codegen.continuations.ICont; import org.simantics.scl.compiler.internal.codegen.references.IVal; @@ -24,9 +25,9 @@ public class PostCommitOp extends PlanOp { @Override public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) { if(planContext.currentId != null) { - w.apply(location, planContext.ruleset.writeCurrentId, planContext.storeVar, planContext.currentId); + w.apply(location, planContext.ruleset.writeCurrentId, planContext.contextVar, planContext.currentId); planContext.currentId = null; - w.apply(location, planContext.ruleset.activateProcedure, planContext.storeVar, new IntegerConstant(priority)); + w.apply(location, CHRRuleset.ACTIVATE, planContext.contextVar, new IntegerConstant(priority)); } for(PartnerFact activeFact : planContext.partnerFacts) { if(activeFact.killAfterMatch) { @@ -35,7 +36,7 @@ public class PostCommitOp extends PlanOp { else { CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType); w.jump(iterateAlive.getContinuation(), w.apply(location, activeFact.nextFact, activeFact.factVar)); - iterateUntilLiveFactFound(iterateAlive, activeFact); + iterateUntilLiveFactFound(iterateAlive, activeFact); } break; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java index 868d70a6f..8612fd766 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java @@ -16,9 +16,8 @@ import org.simantics.scl.compiler.constants.generic.ParameterStackItem; import org.simantics.scl.compiler.constants.generic.StackItem; import org.simantics.scl.compiler.elaboration.chr.CHRRelation; import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; -import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan; -import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator; -import org.simantics.scl.compiler.internal.codegen.chr.CHRFactCodeGenerator; +import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerationConstants; +import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator; import org.simantics.scl.compiler.internal.codegen.references.IVal; import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator; import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor; @@ -56,12 +55,12 @@ public class CHRConstraint extends Symbol implements CHRRelation { public Constant[] accessors; public Constant addProcedure; public Constant removeProcedure; - public Constant isAlive; public TIntObjectHashMap indices; // Query plans - public ArrayList plans = new ArrayList(); + public int minimumPriority = Integer.MAX_VALUE; + public int nextPriority = Integer.MAX_VALUE; // used in code generation public static class IndexInfo { public final int indexMask; @@ -87,8 +86,8 @@ public class CHRConstraint extends Symbol implements CHRRelation { JavaTypeTranslator jtt = context.javaTypeTranslator; this.parentRuleset = parentRuleset; - this.factClassName = parentRuleset.storeClassName + "$" + name; - TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + name); + this.factClassName = parentRuleset.runtimeRulesetName + "$" + name; + TCon factTypeConstructor = Types.con(parentRuleset.runtimeRulesetType.module, parentRuleset.runtimeRulesetType.name + "$" + name); this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY); this.factTypeDesc = TypeDesc.forClass(factClassName); @@ -109,18 +108,18 @@ public class CHRConstraint extends Symbol implements CHRRelation { null); //this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes); this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType}, - null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null); + null, new FieldRef(CHRCodeGenerationConstants.CHRFact_name, "id", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null); this.accessors = new Constant[parameterTypes.length]; for(int i=0;i(Math.min(10, 1 << parameterTypes.length)); @@ -154,19 +153,19 @@ public class CHRConstraint extends Symbol implements CHRRelation { private IndexInfo createIndexInfo(CompilationContext context, int indexMask) { ArrayList keyTypeList = new ArrayList(parameterTypes.length+1); - keyTypeList.add(parentRuleset.storeType); + keyTypeList.add(parentRuleset.runtimeRulesetType); for(int i=0;i>i)&1)==1) keyTypeList.add(parameterTypes[i]); String indexName = nameOfIndex(indexMask, parameterTypes.length); Constant accessIndex; if(indexMask == 0) { - accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType}, - null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null); + accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.runtimeRulesetType}, + null, new FieldRef(parentRuleset.runtimeRulesetName, name + "$" + indexName, factTypeDesc), null); } else { Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]); - accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes); + accessIndex = new JavaMethod(true, parentRuleset.runtimeRulesetName, name + "$" + indexName, Types.PROC, factType, keyTypes); } return new IndexInfo( indexMask, @@ -205,22 +204,13 @@ public class CHRConstraint extends Symbol implements CHRRelation { public void setMayBeRemoved() { if(removeProcedure == null) { - removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType}, - new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)}, - new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}), + removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, factType}, + new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType)}, + new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc}), null); - isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType); } } - public int getMinimumPriority() { - return plans.get(0).priority; - } - - public boolean isPassive() { - return plans.isEmpty(); - } - public TPred[] getTypeConstraints() { return TPred.EMPTY_ARRAY; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java index 14808c820..334cb4560 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java @@ -9,6 +9,7 @@ import org.simantics.scl.compiler.common.precedence.Associativity; import org.simantics.scl.compiler.common.precedence.Precedence; import org.simantics.scl.compiler.constants.BooleanConstant; import org.simantics.scl.compiler.constants.Constant; +import org.simantics.scl.compiler.constants.JavaConstructor; import org.simantics.scl.compiler.constants.JavaStaticField; import org.simantics.scl.compiler.constants.JavaStaticMethod; import org.simantics.scl.compiler.constants.NoRepConstant; @@ -47,6 +48,7 @@ import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.kinds.Kind; import org.simantics.scl.compiler.types.kinds.Kinds; +import org.simantics.scl.runtime.chr.CHRContext; import org.simantics.scl.runtime.profiling.BranchPoint; public class Builtins extends ConcreteModule { @@ -350,6 +352,10 @@ public class Builtins extends ConcreteModule { } setParentClassLoader(getClass().getClassLoader()); + + // CHR + + addTypeDescriptor("CHRContext", new StandardTypeConstructor(Types.CHRContext, Kinds.STAR, TypeDesc.forClass(CHRContext.class))); } @Override diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java new file mode 100644 index 000000000..3f95fa507 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java @@ -0,0 +1,37 @@ +package org.simantics.scl.compiler.internal.codegen.chr; + +import org.cojen.classfile.TypeDesc; + +public interface CHRCodeGenerationConstants { + + public static final TypeDesc FACT_ID_TYPE = TypeDesc.INT; + + public static final String CHRHashIndex_name = "org/simantics/scl/runtime/chr/CHRHashIndex"; + public static final TypeDesc CHRHashIndex = TypeDesc.forClass(CHRHashIndex_name); + + public static final String CHRFact_name = "org/simantics/scl/runtime/chr/CHRFact"; + public static final TypeDesc CHRFact = TypeDesc.forClass(CHRFact_name); + + public static final String CHRPriority_name = "org/simantics/scl/runtime/chr/CHRPriority"; + + public static final String CHRPriorityFactContainer_name = "org/simantics/scl/runtime/chr/CHRPriorityFactContainer"; + public static final TypeDesc CHRPriorityFactContainer = TypeDesc.forClass(CHRPriorityFactContainer_name); + + public static final String CHRContext_name = "org/simantics/scl/runtime/chr/CHRContext"; + public static final TypeDesc CHRContext = TypeDesc.forClass(CHRContext_name); + + public static final String CHRRuntimeRuleset_name = "org/simantics/scl/runtime/chr/CHRRuntimeRuleset"; + public static final TypeDesc CHRRuntimeRuleset = TypeDesc.forClass(CHRRuntimeRuleset_name); + + public static String priorityName(int priority) { + return "l" + priority; + } + + public static String fieldName(int id) { + return "c" + id; + } + + public static String parameterName(int i) { + return "p" + i; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java index 06725ec2b..e68ed2bae 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java @@ -5,43 +5,26 @@ import java.util.ArrayList; import org.cojen.classfile.TypeDesc; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; -import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; -import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo; -import org.simantics.scl.compiler.internal.codegen.references.BoundVar; import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator; import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder; -import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils; import org.simantics.scl.compiler.internal.codegen.utils.Constants; import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable; -import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase; import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; -import gnu.trove.list.array.TIntArrayList; -import gnu.trove.set.hash.THashSet; - -public class CHRFactCodeGenerator { - private static final TypeDesc FACT_ID_TYPE = TypeDesc.INT; - private static final String CHRHashIndex_name = "org/simantics/scl/runtime/chr/CHRHashIndex"; - private static final TypeDesc CHRHashIndex = TypeDesc.forClass(CHRHashIndex_name); - private static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue"; - private static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name); - private static final String Fact_name = "org/simantics/scl/runtime/chr/Fact"; - private static final TypeDesc Fact = TypeDesc.forClass(Fact_name); - private static final String QUEUE = "queue"; +public class CHRFactCodeGenerator implements CHRCodeGenerationConstants { private ModuleBuilder moduleBuilder; private JavaTypeTranslator jtt; - private CHRRuleset ruleset; private ClassBuilder storeClassBuilder; private CHRConstraint constraint; private String factClassName; private TypeDesc factTypeDesc; - private ClassBuilder factClassBuilder; + private ClassBuilder classBuilder; private TypeDesc storeTypeDesc; private TypeDesc[] storeTypeDescArray; @@ -52,7 +35,6 @@ public class CHRFactCodeGenerator { CHRFactCodeGenerator(ClassBuilder storeClassBuilder, CHRConstraint constraint) { this.storeClassBuilder = storeClassBuilder; this.constraint = constraint; - this.ruleset = constraint.parentRuleset; this.moduleBuilder = storeClassBuilder.getModuleBuilder(); this.jtt = moduleBuilder.getJavaTypeTranslator(); @@ -61,7 +43,7 @@ public class CHRFactCodeGenerator { this.factClassName = storeClassBuilder.getClassName() + "$" + constraint.name; this.factTypeDesc = TypeDesc.forClass(factClassName); - this.factClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, factClassName, "java/lang/Object", Fact_name); + this.classBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, factClassName, CHRFact_name); this.parameterTypeDescs = jtt.toTypeDescs(constraint.parameterTypes); this.supportsRemoval = constraint.mayBeRemoved(); @@ -77,16 +59,10 @@ public class CHRFactCodeGenerator { if(supportsRemoval) generateRemove(); - generateIsAlive(); - - for(int i=0;i usedParameters = new THashSet(); - - private void generateActivateI(int i) { - PrioritizedPlan plan = constraint.plans.get(i); - MethodBuilder mb = factClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "activate" + i, TypeDesc.BOOLEAN, storeTypeDescArray); - LocalVariable storeVar = mb.getParameter(0); - LocalVariable factVar = new LocalVariable(0, factTypeDesc); - mb.setLocalVariable(ruleset.this_, storeVar); - mb.setLocalVariable(plan.implementation.getParameters()[0], factVar); - - // Set closure parameters - usedParameters.clear(); - plan.implementation.forValRefs(valRef -> { - if(valRef.getBinding() instanceof BoundVar) - usedParameters.add((BoundVar)valRef.getBinding()); - }); - for(int j=0;j labels = new ArrayList