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.JavaMethod;
10 import org.simantics.scl.compiler.constants.NoRepConstant;
11 import org.simantics.scl.compiler.constants.generic.CallJava;
12 import org.simantics.scl.compiler.constants.generic.MethodRef.ConstructorRef;
13 import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
14 import org.simantics.scl.compiler.constants.generic.MethodRef.ObjectMethodRef;
15 import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
16 import org.simantics.scl.compiler.constants.generic.StackItem;
17 import org.simantics.scl.compiler.elaboration.chr.CHRRelation;
18 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
19 import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerationConstants;
20 import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator;
21 import org.simantics.scl.compiler.internal.codegen.references.IVal;
22 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
23 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
24 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
25 import org.simantics.scl.compiler.internal.parsing.Symbol;
26 import org.simantics.scl.compiler.types.TCon;
27 import org.simantics.scl.compiler.types.TPred;
28 import org.simantics.scl.compiler.types.TVar;
29 import org.simantics.scl.compiler.types.Type;
30 import org.simantics.scl.compiler.types.Types;
32 import gnu.trove.map.hash.TIntObjectHashMap;
34 public class CHRConstraint extends Symbol implements CHRRelation {
35 public final String name;
36 public final Type[] parameterTypes;
37 public String[] fieldNames;
39 public boolean implicitlyDeclared;
42 //public int firstPriorityAdded;
43 public int lastPriorityAdded;
44 //public int firstPriorityRemoved;
45 public int lastPriorityRemoved;
48 public CHRRuleset parentRuleset;
49 public String factClassName;
51 public TypeDesc factTypeDesc;
53 public TCon typeConstructor;
54 public Constant constructor;
55 public Constant accessId;
56 public Constant[] accessors;
57 public Constant addProcedure;
58 public Constant removeProcedure;
60 public String nextContainerFieldName;
62 public TIntObjectHashMap<IndexInfo> indices;
64 public static class IndexInfo {
65 public final int indexMask;
66 public final String indexName;
67 public final Constant firstFact;
68 public final Constant nextFact;
70 public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {
71 this.indexMask = indexMask;
72 this.indexName = indexName;
73 this.firstFact = firstFact;
74 this.nextFact = nextFact;
78 public CHRConstraint(long location, String name, Type[] parameterTypes) {
79 this.location = location;
81 this.parameterTypes = parameterTypes;
84 public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
85 JavaTypeTranslator jtt = context.javaTypeTranslator;
87 this.parentRuleset = parentRuleset;
88 this.factClassName = parentRuleset.runtimeRulesetClassName + "$" + name;
89 TCon factTypeConstructor = Types.con(parentRuleset.runtimeRulesetType.module, parentRuleset.runtimeRulesetType.name + "$" + name);
90 this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);
91 this.factTypeDesc = TypeDesc.forClass(factClassName);
93 Type[] constructorTypes = new Type[parameterTypes.length+1];
94 constructorTypes[0] = Types.INTEGER;
95 ArrayList<StackItem> stackItems = new ArrayList<StackItem>(constructorTypes.length);
96 stackItems.add(new ParameterStackItem(0, Types.INTEGER));
97 for(int i=0;i<parameterTypes.length;++i) {
98 Type parameterType = parameterTypes[i];
99 constructorTypes[i+1] = parameterType;
100 if(!parameterType.equals(Types.UNIT))
101 stackItems.add(new ParameterStackItem(stackItems.size(), parameterType));
103 TypeDesc[] constructorTypeDescs = JavaTypeTranslator.filterVoid(jtt.toTypeDescs(constructorTypes));
104 this.constructor = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, constructorTypes,
105 stackItems.toArray(new StackItem[stackItems.size()]),
106 new ConstructorRef(factClassName, constructorTypeDescs),
108 //this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
109 this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},
110 null, new FieldRef(CHRCodeGenerationConstants.CHRFact_name, "id", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null);
111 this.accessors = new Constant[parameterTypes.length];
112 for(int i=0;i<parameterTypes.length;++i) {
113 TypeDesc typeDesc = jtt.toTypeDesc(parameterTypes[i]);
114 if(typeDesc.equals(TypeDesc.VOID))
116 this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
117 null, new FieldRef(factClassName, CHRCodeGenerationConstants.fieldName(i), jtt.toTypeDesc(parameterTypes[i])), null);
119 this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, Types.CHRContext, factType},
120 new StackItem[] {new ParameterStackItem(2, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType), new ParameterStackItem(1, Types.CHRContext)},
121 new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc, CHRCodeGenerationConstants.CHRContext}),
124 this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
126 if(context.module != null) // for unit testing
127 context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
130 if(parentRuleset.extensible) {
131 nextContainerFieldName = CHRCodeGenerationConstants.nextContainerName(name);
136 public TVar[] getTypeVariables() {
137 return TVar.EMPTY_ARRAY;
141 public Type[] getParameterTypes() {
142 return parameterTypes;
146 public String toString() {
150 public Collection<IndexInfo> getIndices() {
151 return indices.valueCollection();
154 public boolean mayBeRemoved() {
155 return removeProcedure != null;
158 private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {
159 ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);
160 keyTypeList.add(parentRuleset.runtimeRulesetType);
161 for(int i=0;i<parameterTypes.length;++i)
162 if(((indexMask>>i)&1)==1)
163 keyTypeList.add(parameterTypes[i]);
164 String indexName = nameOfIndex(indexMask, parameterTypes.length);
165 Constant accessIndex;
167 accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.runtimeRulesetType},
168 null, new FieldRef(parentRuleset.runtimeRulesetClassName, name + "$" + indexName, factTypeDesc), null);
171 Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
172 accessIndex = new JavaMethod(true, parentRuleset.runtimeRulesetClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
174 return new IndexInfo(
178 new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},
179 null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
183 public IndexInfo getOrCreateIndex(CompilationContext context, int boundMask) {
184 IndexInfo indexInfo = indices.get(boundMask);
185 if(indexInfo == null) {
186 indexInfo = createIndexInfo(context, boundMask);
187 indices.put(boundMask, indexInfo);
192 public IVal fetchFromIndex(CompilationContext context, int boundMask) {
193 return getOrCreateIndex(context, boundMask).firstFact;
196 public Constant nextElement(CompilationContext context, int boundMask) {
197 IndexInfo indexInfo = indices.get(boundMask);
198 if(indexInfo == null) {
199 indexInfo = createIndexInfo(context, boundMask);
200 indices.put(boundMask, indexInfo);
202 return getOrCreateIndex(context, boundMask).nextFact;
206 public static String nameOfIndex(int indexMask, int length) {
207 char[] chars = new char[length];
208 for(int i=0;i<length;++i)
209 chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';
210 return new String(chars);
213 public void setMayBeRemoved() {
214 if(removeProcedure == null) {
215 removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, factType},
216 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType)},
217 new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc}),
222 public TPred[] getTypeConstraints() {
223 return TPred.EMPTY_ARRAY;
226 public IVal accessComponent(long location, CodeWriter w, IVal fact, int i) {
227 Constant accessor = accessors[i];
229 return NoRepConstant.UNIT;
231 return w.apply(location, accessor, fact);
235 public String[] getFieldNames() {