]> gerrit.simantics Code Review - simantics/platform.git/blob
d3d6bdf90ee9f26da83142c76f91344dc66a8f13
[simantics/platform.git] /
1 package org.simantics.scl.compiler.elaboration.chr.relations;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5
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.TVar;
26 import org.simantics.scl.compiler.types.Type;
27 import org.simantics.scl.compiler.types.Types;
28
29 import gnu.trove.map.hash.TIntObjectHashMap;
30
31 public class CHRConstraint extends Symbol implements CHRRelation {
32     public final String name;
33     public final Type[] parameterTypes;
34     
35     public boolean implicitlyDeclared;
36
37     // Analysis
38     public int firstPriorityAdded;
39     public int lastPriorityAdded;
40     public int firstPriorityRemoved;
41     public int lastPriorityRemoved;
42     
43     // Transient info
44     public CHRRuleset parentRuleset;
45     public String factClassName;
46     public Type factType;
47     public TypeDesc factTypeDesc;
48     
49     public TCon typeConstructor;
50     public Constant constructor;
51     public Constant accessId;
52     public Constant[] accessors;
53     public Constant addProcedure;
54     public Constant removeProcedure;
55     public Constant isAlive;
56     
57     public TIntObjectHashMap<IndexInfo> indices;
58     
59     // Query plans
60     public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();
61     
62     public static class IndexInfo {
63         public final int indexMask;
64         public final String indexName;
65         public final Constant firstFact;
66         public final Constant nextFact;
67         
68         public IndexInfo(int indexMask, String indexName, Constant firstFact, Constant nextFact) {
69             this.indexMask = indexMask;
70             this.indexName = indexName;
71             this.firstFact = firstFact;
72             this.nextFact = nextFact;
73         }
74     }
75     
76     public CHRConstraint(long location, String name, Type[] parameterTypes) {
77         this.location = location;
78         this.name = name;
79         this.parameterTypes = parameterTypes;
80     }
81
82     public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
83         JavaTypeTranslator jtt = context.javaTypeTranslator;
84         
85         this.parentRuleset = parentRuleset;
86         this.factClassName = parentRuleset.storeClassName + "$" + name;
87         TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + name); 
88         this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);
89         this.factTypeDesc = TypeDesc.forClass(factClassName);
90         
91         Type[] constructorTypes = new Type[parameterTypes.length+1];
92         constructorTypes[0] = Types.INTEGER;
93         for(int i=0;i<parameterTypes.length;++i)
94             constructorTypes[i+1] = parameterTypes[i];
95         this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
96         this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},
97                 null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null);
98         this.accessors = new Constant[parameterTypes.length];
99         for(int i=0;i<parameterTypes.length;++i)
100             this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
101                     null, new FieldRef(factClassName, "c" + i, jtt.toTypeDesc(parameterTypes[i])), null);
102         this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
103                 new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
104                 new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
105                 null);
106         
107         this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
108         
109         if(context.module != null) // for unit testing
110             context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
111     }
112
113     @Override
114     public TVar[] getTypeVariables() {
115         return TVar.EMPTY_ARRAY;
116     }
117
118     @Override
119     public Type[] getParameterTypes() {
120         return parameterTypes;
121     }
122     
123     @Override
124     public String toString() {
125         return name;
126     }
127     
128     public Collection<IndexInfo> getIndices() {
129         return indices.valueCollection();
130     }
131     
132     public boolean mayBeRemoved() {
133         return removeProcedure != null;
134     }
135
136     private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {
137         ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);
138         keyTypeList.add(parentRuleset.storeType);
139         for(int i=0;i<parameterTypes.length;++i)
140             if(((indexMask>>i)&1)==1)
141                 keyTypeList.add(parameterTypes[i]);
142         String indexName = nameOfIndex(indexMask, parameterTypes.length);
143         Constant accessIndex;
144         if(indexMask == 0) {
145             accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType},
146                     null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null);
147         }
148         else {
149             Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
150             accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
151         }
152         return new IndexInfo(
153                 indexMask,
154                 indexName,
155                 accessIndex,
156                 new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},
157                         null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
158                 );
159     }
160
161     public Constant accessComponent(int i) {
162         return accessors[i];
163     }
164     
165     public IVal fetchFromIndex(CompilationContext context, int boundMask) {
166         IndexInfo indexInfo = indices.get(boundMask);
167         if(indexInfo == null) {
168             indexInfo = createIndexInfo(context, boundMask);
169             indices.put(boundMask, indexInfo);
170         }
171         return indexInfo.firstFact;
172     }
173
174     public Constant nextElement(CompilationContext context, int boundMask) {
175         IndexInfo indexInfo = indices.get(boundMask);
176         if(indexInfo == null) {
177             indexInfo = createIndexInfo(context, boundMask);
178             indices.put(boundMask, indexInfo);
179         }
180         return indexInfo.nextFact;
181     }
182
183     
184     public static String nameOfIndex(int indexMask, int length) {
185         char[] chars = new char[length];
186         for(int i=0;i<length;++i)
187             chars[i] = ((indexMask>>i)&1) == 1 ? 'b' : 'f';
188         return new String(chars);
189     }
190
191     public void setMayBeRemoved() {
192         if(removeProcedure == null) {
193             removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
194                     new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
195                     new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
196                     null);
197             isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType);
198         }
199     }
200
201     public int getMinimumPriority() {
202         return plans.get(0).priority;
203     }
204     
205     public boolean isPassive() {
206         return plans.isEmpty();
207     }
208 }