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