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;
33 import gnu.trove.set.hash.THashSet;
35 public class CHRConstraint extends Symbol implements CHRRelation {
36 public final String name;
37 public final Type[] parameterTypes;
38 public String[] fieldNames;
40 public boolean implicitlyDeclared;
43 //public int firstPriorityAdded;
44 public int lastPriorityAdded;
45 //public int firstPriorityRemoved;
46 public int lastPriorityRemoved;
49 public CHRRuleset parentRuleset;
50 public String factClassName;
52 public TypeDesc factTypeDesc;
54 public TCon typeConstructor;
55 public Constant constructor;
56 public Constant accessId;
57 public Constant[] accessors;
58 public Constant addProcedure;
59 public Constant removeProcedure;
61 public String nextContainerFieldName;
63 public TIntObjectHashMap<IndexInfo> indices;
65 public static class IndexInfo {
66 public final int indexMask;
67 public final String indexName;
68 public final Constant firstFact;
69 public final Constant nextFact;
71 public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {
72 this.indexMask = indexMask;
73 this.indexName = indexName;
74 this.firstFact = firstFact;
75 this.nextFact = nextFact;
79 public CHRConstraint(long location, String name, Type[] parameterTypes) {
80 this.location = location;
82 this.parameterTypes = parameterTypes;
85 public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
86 JavaTypeTranslator jtt = context.javaTypeTranslator;
88 this.parentRuleset = parentRuleset;
89 this.factClassName = parentRuleset.runtimeRulesetClassName + "$" + name;
90 TCon factTypeConstructor = Types.con(parentRuleset.runtimeRulesetType.module, parentRuleset.runtimeRulesetType.name + "$" + name);
91 this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);
92 this.factTypeDesc = TypeDesc.forClass(factClassName);
94 Type[] constructorTypes = new Type[parameterTypes.length+1];
95 constructorTypes[0] = Types.INTEGER;
96 ArrayList<StackItem> stackItems = new ArrayList<StackItem>(constructorTypes.length);
97 stackItems.add(new ParameterStackItem(0, Types.INTEGER));
98 for(int i=0;i<parameterTypes.length;++i) {
99 Type parameterType = parameterTypes[i];
100 constructorTypes[i+1] = parameterType;
101 if(!parameterType.equals(Types.UNIT))
102 stackItems.add(new ParameterStackItem(stackItems.size(), parameterType));
104 TypeDesc[] constructorTypeDescs = JavaTypeTranslator.filterVoid(jtt.toTypeDescs(constructorTypes));
105 this.constructor = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, constructorTypes,
106 stackItems.toArray(new StackItem[stackItems.size()]),
107 new ConstructorRef(factClassName, constructorTypeDescs),
109 //this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
110 this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},
111 null, new FieldRef(CHRCodeGenerationConstants.CHRFact_name, "id", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null);
112 this.accessors = new Constant[parameterTypes.length];
113 for(int i=0;i<parameterTypes.length;++i) {
114 TypeDesc typeDesc = jtt.toTypeDesc(parameterTypes[i]);
115 if(typeDesc.equals(TypeDesc.VOID))
117 this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
118 null, new FieldRef(factClassName, CHRCodeGenerationConstants.fieldName(i), jtt.toTypeDesc(parameterTypes[i])), null);
120 this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, Types.CHRContext, factType},
121 new StackItem[] {new ParameterStackItem(2, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType), new ParameterStackItem(1, Types.CHRContext)},
122 new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc, CHRCodeGenerationConstants.CHRContext}),
125 this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
127 if(context.module != null) // for unit testing
128 context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
131 if(parentRuleset.extensible) {
132 nextContainerFieldName = CHRCodeGenerationConstants.nextContainerName(name);
137 public TVar[] getTypeVariables() {
138 return TVar.EMPTY_ARRAY;
142 public Type[] getParameterTypes() {
143 return parameterTypes;
147 public String toString() {
151 public Collection<IndexInfo> getIndices() {
152 return indices.valueCollection();
155 public boolean mayBeRemoved() {
156 return removeProcedure != null;
159 private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {
160 ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);
161 keyTypeList.add(parentRuleset.runtimeRulesetType);
162 for(int i=0;i<parameterTypes.length;++i)
163 if(((indexMask>>i)&1)==1)
164 keyTypeList.add(parameterTypes[i]);
165 String indexName = nameOfIndex(indexMask, parameterTypes.length);
166 Constant accessIndex;
168 accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.runtimeRulesetType},
169 null, new FieldRef(parentRuleset.runtimeRulesetClassName, name + "$" + indexName, factTypeDesc), null);
172 Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
173 accessIndex = new JavaMethod(true, parentRuleset.runtimeRulesetClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
175 return new IndexInfo(
179 new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},
180 null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
184 public IndexInfo getOrCreateIndex(CompilationContext context, int boundMask) {
185 IndexInfo indexInfo = indices.get(boundMask);
186 if(indexInfo == null) {
187 indexInfo = createIndexInfo(context, boundMask);
188 indices.put(boundMask, indexInfo);
193 public IVal fetchFromIndex(CompilationContext context, int boundMask) {
194 return getOrCreateIndex(context, boundMask).firstFact;
197 public Constant nextElement(CompilationContext context, int boundMask) {
198 IndexInfo indexInfo = indices.get(boundMask);
199 if(indexInfo == null) {
200 indexInfo = createIndexInfo(context, boundMask);
201 indices.put(boundMask, indexInfo);
203 return getOrCreateIndex(context, boundMask).nextFact;
207 public static String nameOfIndex(int indexMask, int length) {
208 char[] chars = new char[length];
209 for(int i=0;i<length;++i)
210 chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';
211 return new String(chars);
214 public void setMayBeRemoved() {
215 if(removeProcedure == null) {
216 removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, factType},
217 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType)},
218 new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc}),
223 public TPred[] getTypeConstraints() {
224 return TPred.EMPTY_ARRAY;
227 public IVal accessComponent(long location, CodeWriter w, IVal fact, int i) {
228 Constant accessor = accessors[i];
230 return NoRepConstant.UNIT;
232 return w.apply(location, accessor, fact);
236 public String[] getFieldNames() {
241 public void collectEnforceEffects(THashSet<Type> effects) {
242 effects.add(Types.PROC);
246 public void collectQueryEffects(THashSet<Type> effects) {
247 effects.add(Types.PROC);