]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java
Refactoring CHR handling code
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / relations / CHRConstraint.java
index 9c21f541bef61a50a06f8a890d61e4bd38ae68f9..839f0930e23cc276d1538a57e25217555739b130 100644 (file)
-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
+package org.simantics.scl.compiler.elaboration.chr.relations;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.constants.JavaMethod;
+import org.simantics.scl.compiler.constants.NoRepConstant;
+import org.simantics.scl.compiler.constants.generic.CallJava;
+import org.simantics.scl.compiler.constants.generic.MethodRef.ConstructorRef;
+import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
+import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef;
+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.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;
+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.TPred;
+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.TIntObjectHashMap;
+import gnu.trove.set.hash.THashSet;
+
+public class CHRConstraint extends Symbol implements CHRRelation {
+    public final String name;
+    public final Type[] parameterTypes;
+    public String[] fieldNames;
+    
+    public boolean implicitlyDeclared;
+
+    // Analysis
+    //public int firstPriorityAdded;
+    public int lastPriorityAdded;
+    //public int firstPriorityRemoved;
+    public int lastPriorityRemoved;
+    
+    // Transient info
+    public CHRRuleset parentRuleset;
+    public String factClassName;
+    public Type factType;
+    public TypeDesc factTypeDesc;
+    
+    public TCon typeConstructor;
+    public Constant constructor;
+    public Constant accessId;
+    public Constant[] accessors;
+    public Constant addProcedure;
+    public Constant removeProcedure;
+    
+    public String nextContainerFieldName;
+    
+    public TIntObjectHashMap<IndexInfo> indices;
+    
+    public static class IndexInfo {
+        public final int indexMask;
+        public final String indexName;
+        public final Constant firstFact;
+        public final Constant nextFact;
+        
+        public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {
+            this.indexMask = indexMask;
+            this.indexName = indexName;
+            this.firstFact = firstFact;
+            this.nextFact = nextFact;
+        }
+    }
+    
+    public CHRConstraint(long location, String name, Type[] parameterTypes) {
+        this.location = location;
+        this.name = name;
+        this.parameterTypes = parameterTypes;
+    }
+    
+    public void setParent(CHRRuleset parentRuleset) {
+        this.parentRuleset = parentRuleset;
+    }
+
+    public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
+        JavaTypeTranslator jtt = context.javaTypeTranslator;
+        
+        this.factClassName = parentRuleset.runtimeRulesetClassName + "$" + 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);
+        
+        Type[] constructorTypes = new Type[parameterTypes.length+1];
+        constructorTypes[0] = Types.INTEGER;
+        ArrayList<StackItem> stackItems = new ArrayList<StackItem>(constructorTypes.length);
+        stackItems.add(new ParameterStackItem(0, Types.INTEGER));
+        for(int i=0;i<parameterTypes.length;++i) {
+            Type parameterType = parameterTypes[i];
+            constructorTypes[i+1] = parameterType;
+            if(!parameterType.equals(Types.UNIT))
+                stackItems.add(new ParameterStackItem(stackItems.size(), parameterType));
+        }
+        TypeDesc[] constructorTypeDescs = JavaTypeTranslator.filterVoid(jtt.toTypeDescs(constructorTypes));
+        this.constructor = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, constructorTypes,
+                stackItems.toArray(new StackItem[stackItems.size()]),
+                new ConstructorRef(factClassName, constructorTypeDescs),
+                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(CHRCodeGenerationConstants.CHRFact_name, "id", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null);
+        this.accessors = new Constant[parameterTypes.length];
+        for(int i=0;i<parameterTypes.length;++i) {
+            TypeDesc typeDesc = jtt.toTypeDesc(parameterTypes[i]);
+            if(typeDesc.equals(TypeDesc.VOID))
+                continue;
+            this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
+                    null, new FieldRef(factClassName, CHRCodeGenerationConstants.fieldName(i), jtt.toTypeDesc(parameterTypes[i])), null);
+        }
+        this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, Types.CHRContext, factType},
+                new StackItem[] {new ParameterStackItem(2, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType), new ParameterStackItem(1, Types.CHRContext)},
+                new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc, CHRCodeGenerationConstants.CHRContext}),
+                null);
+        
+        this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
+        
+        if(context.module != null) // for unit testing
+            context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
+        
+        // next container
+        if(parentRuleset.extensible) {
+            nextContainerFieldName = CHRCodeGenerationConstants.nextContainerName(name);
+        }
+    }
+
+    @Override
+    public TVar[] getTypeVariables() {
+        return TVar.EMPTY_ARRAY;
+    }
+
+    @Override
+    public Type[] getParameterTypes() {
+        return parameterTypes;
+    }
+    
+    @Override
+    public String toString() {
+        return name;
+    }
+    
+    public Collection<IndexInfo> getIndices() {
+        return indices.valueCollection();
+    }
+    
+    public boolean mayBeRemoved() {
+        return removeProcedure != null;
+    }
+
+    private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {
+        ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);
+        keyTypeList.add(parentRuleset.runtimeRulesetType);
+        for(int i=0;i<parameterTypes.length;++i)
+            if(((indexMask>>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.runtimeRulesetType},
+                    null, new FieldRef(parentRuleset.runtimeRulesetClassName, name + "$" + indexName, factTypeDesc), null);
+        }
+        else {
+            Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
+            accessIndex = new JavaMethod(true, parentRuleset.runtimeRulesetClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
+        }
+        return new IndexInfo(
+                indexMask,
+                indexName,
+                accessIndex,
+                new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},
+                        null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
+                );
+    }
+    
+    public IndexInfo getOrCreateIndex(CompilationContext context, int boundMask) {
+        IndexInfo indexInfo = indices.get(boundMask);
+        if(indexInfo == null) {
+            indexInfo = createIndexInfo(context, boundMask);
+            indices.put(boundMask, indexInfo);
+        }
+        return indexInfo;
+    }
+    
+    public IVal fetchFromIndex(CompilationContext context, int boundMask) {
+        return getOrCreateIndex(context, boundMask).firstFact;
+    }
+
+    public Constant nextElement(CompilationContext context, int boundMask) {
+        IndexInfo indexInfo = indices.get(boundMask);
+        if(indexInfo == null) {
+            indexInfo = createIndexInfo(context, boundMask);
+            indices.put(boundMask, indexInfo);
+        }
+        return getOrCreateIndex(context, boundMask).nextFact;
+    }
+
+    
+    public static String nameOfIndex(int indexMask, int length) {
+        char[] chars = new char[length];
+        for(int i=0;i<length;++i)
+            chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';
+        return new String(chars);
+    }
+
+    public void setMayBeRemoved() {
+        if(removeProcedure == null) {
+            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);
+        }
+    }
+
+    public TPred[] getTypeConstraints() {
+        return TPred.EMPTY_ARRAY;
+    }
+
+    public IVal accessComponent(long location, CodeWriter w, IVal fact, int i) {
+        Constant accessor = accessors[i];
+        if(accessor == null)
+            return NoRepConstant.UNIT;
+        else
+            return w.apply(location, accessor, fact);
+    }
+    
+    @Override
+    public String[] getFieldNames() {
+        return fieldNames;
+    }
+
+    @Override
+    public void collectEnforceEffects(THashSet<Type> effects) {
+        effects.add(Types.PROC);
+    }
+
+    @Override
+    public void collectQueryEffects(THashSet<Type> effects) {
+        effects.add(Types.PROC);
+    }
+}