1 package org.simantics.scl.compiler.elaboration.chr.relations;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Collection;
\r
6 import org.cojen.classfile.TypeDesc;
\r
7 import org.simantics.scl.compiler.compilation.CompilationContext;
\r
8 import org.simantics.scl.compiler.constants.Constant;
\r
9 import org.simantics.scl.compiler.constants.JavaConstructor;
\r
10 import org.simantics.scl.compiler.constants.JavaMethod;
\r
11 import org.simantics.scl.compiler.constants.generic.CallJava;
\r
12 import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
\r
13 import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef;
\r
14 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
\r
15 import org.simantics.scl.compiler.constants.generic.StackItem;
\r
16 import org.simantics.scl.compiler.elaboration.chr.CHRRelation;
\r
17 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
\r
18 import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;
\r
19 import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;
\r
20 import org.simantics.scl.compiler.internal.codegen.references.IVal;
\r
21 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
\r
22 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
\r
23 import org.simantics.scl.compiler.internal.parsing.Symbol;
\r
24 import org.simantics.scl.compiler.types.TCon;
\r
25 import org.simantics.scl.compiler.types.TVar;
\r
26 import org.simantics.scl.compiler.types.Type;
\r
27 import org.simantics.scl.compiler.types.Types;
\r
29 import gnu.trove.map.hash.TIntObjectHashMap;
\r
31 public class CHRConstraint extends Symbol implements CHRRelation {
\r
32 public final String name;
\r
33 public final Type[] parameterTypes;
\r
35 public boolean implicitlyDeclared;
\r
38 public int firstPriorityAdded;
\r
39 public int lastPriorityAdded;
\r
40 public int firstPriorityRemoved;
\r
41 public int lastPriorityRemoved;
\r
44 public CHRRuleset parentRuleset;
\r
45 public String factClassName;
\r
46 public Type factType;
\r
47 public TypeDesc factTypeDesc;
\r
49 public TCon typeConstructor;
\r
50 public Constant constructor;
\r
51 public Constant accessId;
\r
52 public Constant[] accessors;
\r
53 public Constant addProcedure;
\r
54 public Constant removeProcedure;
\r
55 public Constant isAlive;
\r
57 public TIntObjectHashMap<IndexInfo> indices;
\r
60 public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();
\r
62 public static class IndexInfo {
\r
63 public final int indexMask;
\r
64 public final String indexName;
\r
65 public final Constant firstFact;
\r
66 public final Constant nextFact;
\r
68 public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {
\r
69 this.indexMask = indexMask;
\r
70 this.indexName = indexName;
\r
71 this.firstFact = firstFact;
\r
72 this.nextFact = nextFact;
\r
76 public CHRConstraint(long location, String name, Type[] parameterTypes) {
\r
77 this.location = location;
\r
79 this.parameterTypes = parameterTypes;
\r
82 public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
\r
83 JavaTypeTranslator jtt = context.javaTypeTranslator;
\r
85 this.parentRuleset = parentRuleset;
\r
86 this.factClassName = parentRuleset.storeClassName + "$" + name;
\r
87 TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + name);
\r
88 this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);
\r
89 this.factTypeDesc = TypeDesc.forClass(factClassName);
\r
91 Type[] constructorTypes = new Type[parameterTypes.length+1];
\r
92 constructorTypes[0] = Types.INTEGER;
\r
93 for(int i=0;i<parameterTypes.length;++i)
\r
94 constructorTypes[i+1] = parameterTypes[i];
\r
95 this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
\r
96 this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},
\r
97 null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null);
\r
98 this.accessors = new Constant[parameterTypes.length];
\r
99 for(int i=0;i<parameterTypes.length;++i)
\r
100 this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
\r
101 null, new FieldRef(factClassName, "c" + i, jtt.toTypeDesc(parameterTypes[i])), null);
\r
102 this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
\r
103 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
\r
104 new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
\r
107 this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
\r
109 if(context.module != null) // for unit testing
\r
110 context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
\r
114 public TVar[] getTypeVariables() {
\r
115 return TVar.EMPTY_ARRAY;
\r
119 public Type[] getParameterTypes() {
\r
120 return parameterTypes;
\r
124 public String toString() {
\r
128 public Collection<IndexInfo> getIndices() {
\r
129 return indices.valueCollection();
\r
132 public boolean mayBeRemoved() {
\r
133 return removeProcedure != null;
\r
136 private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {
\r
137 ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);
\r
138 keyTypeList.add(parentRuleset.storeType);
\r
139 for(int i=0;i<parameterTypes.length;++i)
\r
140 if(((indexMask>>i)&1)==1)
\r
141 keyTypeList.add(parameterTypes[i]);
\r
142 String indexName = nameOfIndex(indexMask, parameterTypes.length);
\r
143 Constant accessIndex;
\r
144 if(indexMask == 0) {
\r
145 accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType},
\r
146 null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null);
\r
149 Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
\r
150 accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
\r
152 return new IndexInfo(
\r
156 new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},
\r
157 null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
\r
161 public Constant accessComponent(int i) {
\r
162 return accessors[i];
\r
165 public IVal fetchFromIndex(CompilationContext context, int boundMask) {
\r
166 IndexInfo indexInfo = indices.get(boundMask);
\r
167 if(indexInfo == null) {
\r
168 indexInfo = createIndexInfo(context, boundMask);
\r
169 indices.put(boundMask, indexInfo);
\r
171 return indexInfo.firstFact;
\r
174 public Constant nextElement(CompilationContext context, int boundMask) {
\r
175 IndexInfo indexInfo = indices.get(boundMask);
\r
176 if(indexInfo == null) {
\r
177 indexInfo = createIndexInfo(context, boundMask);
\r
178 indices.put(boundMask, indexInfo);
\r
180 return indexInfo.nextFact;
\r
184 public static String nameOfIndex(int indexMask, int length) {
\r
185 char[] chars = new char[length];
\r
186 for(int i=0;i<length;++i)
\r
187 chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';
\r
188 return new String(chars);
\r
191 public void setMayBeRemoved() {
\r
192 if(removeProcedure == null) {
\r
193 removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
\r
194 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
\r
195 new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
\r
197 isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType);
\r
201 public int getMinimumPriority() {
\r
202 return plans.get(0).priority;
\r
205 public boolean isPassive() {
\r
206 return plans.isEmpty();
\r