-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.elaboration.chr.plan.PrioritizedPlan;
+import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;
+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;
+
+public class CHRConstraint extends Symbol implements CHRRelation {
+ public final String name;
+ public final Type[] parameterTypes;
+
+ 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 Constant isAlive;
+
+ public TIntObjectHashMap<IndexInfo> indices;
+
+ // Query plans
+ public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();
+
+ 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 initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
+ JavaTypeTranslator jtt = context.javaTypeTranslator;
+
+ this.parentRuleset = parentRuleset;
+ this.factClassName = parentRuleset.storeClassName + "$" + name;
+ TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.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(factClassName, "id", CHRCodeGenerator.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, CHRCodeGenerator.fieldName(i), jtt.toTypeDesc(parameterTypes[i])), null);
+ }
+ this.addProcedure = 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, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
+ 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));
+ }
+
+ @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.storeType);
+ 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.storeType},
+ null, new FieldRef(parentRuleset.storeClassName, 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);
+ }
+ 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 IVal fetchFromIndex(CompilationContext context, int boundMask) {
+ IndexInfo indexInfo = indices.get(boundMask);
+ if(indexInfo == null) {
+ indexInfo = createIndexInfo(context, boundMask);
+ indices.put(boundMask, indexInfo);
+ }
+ return indexInfo.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 indexInfo.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.storeType, factType},
+ new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
+ new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
+ 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;
+ }
+
+ 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);
+ }
+}