]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / relations / CHRConstraint.java
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
new file mode 100644 (file)
index 0000000..9c21f54
--- /dev/null
@@ -0,0 +1,208 @@
+package org.simantics.scl.compiler.elaboration.chr.relations;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.cojen.classfile.TypeDesc;\r
+import org.simantics.scl.compiler.compilation.CompilationContext;\r
+import org.simantics.scl.compiler.constants.Constant;\r
+import org.simantics.scl.compiler.constants.JavaConstructor;\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.ObjectMethodRef;\r
+import org.simantics.scl.compiler.constants.generic.ParameterStackItem;\r
+import org.simantics.scl.compiler.constants.generic.StackItem;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRelation;\r
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;\r
+import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;\r
+import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;\r
+import org.simantics.scl.compiler.internal.codegen.references.IVal;\r
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;\r
+import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;\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.TIntObjectHashMap;\r
+\r
+public class CHRConstraint extends Symbol implements CHRRelation {\r
+    public final String name;\r
+    public final Type[] parameterTypes;\r
+    \r
+    public boolean implicitlyDeclared;\r
+\r
+    // Analysis\r
+    public int firstPriorityAdded;\r
+    public int lastPriorityAdded;\r
+    public int firstPriorityRemoved;\r
+    public int lastPriorityRemoved;\r
+    \r
+    // Transient info\r
+    public CHRRuleset parentRuleset;\r
+    public String factClassName;\r
+    public Type factType;\r
+    public TypeDesc factTypeDesc;\r
+    \r
+    public TCon typeConstructor;\r
+    public Constant constructor;\r
+    public Constant accessId;\r
+    public Constant[] accessors;\r
+    public Constant addProcedure;\r
+    public Constant removeProcedure;\r
+    public Constant isAlive;\r
+    \r
+    public TIntObjectHashMap<IndexInfo> indices;\r
+    \r
+    // Query plans\r
+    public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();\r
+    \r
+    public static class IndexInfo {\r
+        public final int indexMask;\r
+        public final String indexName;\r
+        public final Constant firstFact;\r
+        public final Constant nextFact;\r
+        \r
+        public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {\r
+            this.indexMask = indexMask;\r
+            this.indexName = indexName;\r
+            this.firstFact = firstFact;\r
+            this.nextFact = nextFact;\r
+        }\r
+    }\r
+    \r
+    public CHRConstraint(long location, String name, Type[] parameterTypes) {\r
+        this.location = location;\r
+        this.name = name;\r
+        this.parameterTypes = parameterTypes;\r
+    }\r
+\r
+    public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {\r
+        JavaTypeTranslator jtt = context.javaTypeTranslator;\r
+        \r
+        this.parentRuleset = parentRuleset;\r
+        this.factClassName = parentRuleset.storeClassName + "$" + name;\r
+        TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + name); \r
+        this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);\r
+        this.factTypeDesc = TypeDesc.forClass(factClassName);\r
+        \r
+        Type[] constructorTypes = new Type[parameterTypes.length+1];\r
+        constructorTypes[0] = Types.INTEGER;\r
+        for(int i=0;i<parameterTypes.length;++i)\r
+            constructorTypes[i+1] = parameterTypes[i];\r
+        this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);\r
+        this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},\r
+                null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null);\r
+        this.accessors = new Constant[parameterTypes.length];\r
+        for(int i=0;i<parameterTypes.length;++i)\r
+            this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},\r
+                    null, new FieldRef(factClassName, "c" + i, jtt.toTypeDesc(parameterTypes[i])), null);\r
+        this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},\r
+                new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},\r
+                new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),\r
+                null);\r
+        \r
+        this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));\r
+        \r
+        if(context.module != null) // for unit testing\r
+            context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));\r
+    }\r
+\r
+    @Override\r
+    public TVar[] getTypeVariables() {\r
+        return TVar.EMPTY_ARRAY;\r
+    }\r
+\r
+    @Override\r
+    public Type[] getParameterTypes() {\r
+        return parameterTypes;\r
+    }\r
+    \r
+    @Override\r
+    public String toString() {\r
+        return name;\r
+    }\r
+    \r
+    public Collection<IndexInfo> getIndices() {\r
+        return indices.valueCollection();\r
+    }\r
+    \r
+    public boolean mayBeRemoved() {\r
+        return removeProcedure != null;\r
+    }\r
+\r
+    private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {\r
+        ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);\r
+        keyTypeList.add(parentRuleset.storeType);\r
+        for(int i=0;i<parameterTypes.length;++i)\r
+            if(((indexMask>>i)&1)==1)\r
+                keyTypeList.add(parameterTypes[i]);\r
+        String indexName = nameOfIndex(indexMask, parameterTypes.length);\r
+        Constant accessIndex;\r
+        if(indexMask == 0) {\r
+            accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType},\r
+                    null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null);\r
+        }\r
+        else {\r
+            Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);\r
+            accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);\r
+        }\r
+        return new IndexInfo(\r
+                indexMask,\r
+                indexName,\r
+                accessIndex,\r
+                new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},\r
+                        null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)\r
+                );\r
+    }\r
+\r
+    public Constant accessComponent(int i) {\r
+        return accessors[i];\r
+    }\r
+    \r
+    public IVal fetchFromIndex(CompilationContext context, int boundMask) {\r
+        IndexInfo indexInfo = indices.get(boundMask);\r
+        if(indexInfo == null) {\r
+            indexInfo = createIndexInfo(context, boundMask);\r
+            indices.put(boundMask, indexInfo);\r
+        }\r
+        return indexInfo.firstFact;\r
+    }\r
+\r
+    public Constant nextElement(CompilationContext context, int boundMask) {\r
+        IndexInfo indexInfo = indices.get(boundMask);\r
+        if(indexInfo == null) {\r
+            indexInfo = createIndexInfo(context, boundMask);\r
+            indices.put(boundMask, indexInfo);\r
+        }\r
+        return indexInfo.nextFact;\r
+    }\r
+\r
+    \r
+    public static String nameOfIndex(int indexMask, int length) {\r
+        char[] chars = new char[length];\r
+        for(int i=0;i<length;++i)\r
+            chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';\r
+        return new String(chars);\r
+    }\r
+\r
+    public void setMayBeRemoved() {\r
+        if(removeProcedure == null) {\r
+            removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},\r
+                    new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},\r
+                    new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),\r
+                    null);\r
+            isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType);\r
+        }\r
+    }\r
+\r
+    public int getMinimumPriority() {\r
+        return plans.get(0).priority;\r
+    }\r
+    \r
+    public boolean isPassive() {\r
+        return plans.isEmpty();\r
+    }\r
+}\r