1 package org.simantics.scl.compiler.elaboration.chr.relations;
3 import java.util.ArrayList;
4 import java.util.Collection;
6 import org.cojen.classfile.TypeDesc;
7 import org.simantics.scl.compiler.compilation.CompilationContext;
8 import org.simantics.scl.compiler.constants.Constant;
9 import org.simantics.scl.compiler.constants.JavaConstructor;
10 import org.simantics.scl.compiler.constants.JavaMethod;
11 import org.simantics.scl.compiler.constants.generic.CallJava;
12 import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
13 import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef;
14 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
15 import org.simantics.scl.compiler.constants.generic.StackItem;
16 import org.simantics.scl.compiler.elaboration.chr.CHRRelation;
17 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
18 import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;
19 import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;
20 import org.simantics.scl.compiler.internal.codegen.references.IVal;
21 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
22 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
23 import org.simantics.scl.compiler.internal.parsing.Symbol;
24 import org.simantics.scl.compiler.types.TCon;
25 import org.simantics.scl.compiler.types.TPred;
26 import org.simantics.scl.compiler.types.TVar;
27 import org.simantics.scl.compiler.types.Type;
28 import org.simantics.scl.compiler.types.Types;
30 import gnu.trove.map.hash.TIntObjectHashMap;
32 public class CHRConstraint extends Symbol implements CHRRelation {
33 public final String name;
34 public final Type[] parameterTypes;
36 public boolean implicitlyDeclared;
39 public int firstPriorityAdded;
40 public int lastPriorityAdded;
41 public int firstPriorityRemoved;
42 public int lastPriorityRemoved;
45 public CHRRuleset parentRuleset;
46 public String factClassName;
48 public TypeDesc factTypeDesc;
50 public TCon typeConstructor;
51 public Constant constructor;
52 public Constant accessId;
53 public Constant[] accessors;
54 public Constant addProcedure;
55 public Constant removeProcedure;
56 public Constant isAlive;
58 public TIntObjectHashMap<IndexInfo> indices;
61 public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();
63 public static class IndexInfo {
64 public final int indexMask;
65 public final String indexName;
66 public final Constant firstFact;
67 public final Constant nextFact;
69 public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {
70 this.indexMask = indexMask;
71 this.indexName = indexName;
72 this.firstFact = firstFact;
73 this.nextFact = nextFact;
77 public CHRConstraint(long location, String name, Type[] parameterTypes) {
78 this.location = location;
80 this.parameterTypes = parameterTypes;
83 public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
84 JavaTypeTranslator jtt = context.javaTypeTranslator;
86 this.parentRuleset = parentRuleset;
87 this.factClassName = parentRuleset.storeClassName + "$" + name;
88 TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + name);
89 this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);
90 this.factTypeDesc = TypeDesc.forClass(factClassName);
92 Type[] constructorTypes = new Type[parameterTypes.length+1];
93 constructorTypes[0] = Types.INTEGER;
94 for(int i=0;i<parameterTypes.length;++i)
95 constructorTypes[i+1] = parameterTypes[i];
96 this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
97 this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},
98 null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null);
99 this.accessors = new Constant[parameterTypes.length];
100 for(int i=0;i<parameterTypes.length;++i)
101 this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
102 null, new FieldRef(factClassName, "c" + i, jtt.toTypeDesc(parameterTypes[i])), null);
103 this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
104 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
105 new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
108 this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
110 if(context.module != null) // for unit testing
111 context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
115 public TVar[] getTypeVariables() {
116 return TVar.EMPTY_ARRAY;
120 public Type[] getParameterTypes() {
121 return parameterTypes;
125 public String toString() {
129 public Collection<IndexInfo> getIndices() {
130 return indices.valueCollection();
133 public boolean mayBeRemoved() {
134 return removeProcedure != null;
137 private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {
138 ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);
139 keyTypeList.add(parentRuleset.storeType);
140 for(int i=0;i<parameterTypes.length;++i)
141 if(((indexMask>>i)&1)==1)
142 keyTypeList.add(parameterTypes[i]);
143 String indexName = nameOfIndex(indexMask, parameterTypes.length);
144 Constant accessIndex;
146 accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType},
147 null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null);
150 Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
151 accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
153 return new IndexInfo(
157 new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},
158 null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
162 public Constant accessComponent(int i) {
166 public IVal fetchFromIndex(CompilationContext context, int boundMask) {
167 IndexInfo indexInfo = indices.get(boundMask);
168 if(indexInfo == null) {
169 indexInfo = createIndexInfo(context, boundMask);
170 indices.put(boundMask, indexInfo);
172 return indexInfo.firstFact;
175 public Constant nextElement(CompilationContext context, int boundMask) {
176 IndexInfo indexInfo = indices.get(boundMask);
177 if(indexInfo == null) {
178 indexInfo = createIndexInfo(context, boundMask);
179 indices.put(boundMask, indexInfo);
181 return indexInfo.nextFact;
185 public static String nameOfIndex(int indexMask, int length) {
186 char[] chars = new char[length];
187 for(int i=0;i<length;++i)
188 chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';
189 return new String(chars);
192 public void setMayBeRemoved() {
193 if(removeProcedure == null) {
194 removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
195 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
196 new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
198 isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType);
202 public int getMinimumPriority() {
203 return plans.get(0).priority;
206 public boolean isPassive() {
207 return plans.isEmpty();
210 public TPred[] getTypeConstraints() {
211 return TPred.EMPTY_ARRAY;