]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java
Merge "Implemented GraphPropertyRelation with the new CHR implementation"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / relations / CHRConstraint.java
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.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;
29
30 import gnu.trove.map.hash.TIntObjectHashMap;
31
32 public class CHRConstraint extends Symbol implements CHRRelation {
33     public final String name;
34     public final Type[] parameterTypes;
35     
36     public boolean implicitlyDeclared;
37
38     // Analysis
39     public int firstPriorityAdded;
40     public int lastPriorityAdded;
41     public int firstPriorityRemoved;
42     public int lastPriorityRemoved;
43     
44     // Transient info
45     public CHRRuleset parentRuleset;
46     public String factClassName;
47     public Type factType;
48     public TypeDesc factTypeDesc;
49     
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;
57     
58     public TIntObjectHashMap<IndexInfo> indices;
59     
60     // Query plans
61     public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();
62     
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;
68         
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;
74         }
75     }
76     
77     public CHRConstraint(long location, String name, Type[] parameterTypes) {
78         this.location = location;
79         this.name = name;
80         this.parameterTypes = parameterTypes;
81     }
82
83     public void initializeCodeGeneration(CompilationContext context, CHRRuleset parentRuleset) {
84         JavaTypeTranslator jtt = context.javaTypeTranslator;
85         
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);
91         
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}),
106                 null);
107         
108         this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
109         
110         if(context.module != null) // for unit testing
111             context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
112     }
113
114     @Override
115     public TVar[] getTypeVariables() {
116         return TVar.EMPTY_ARRAY;
117     }
118
119     @Override
120     public Type[] getParameterTypes() {
121         return parameterTypes;
122     }
123     
124     @Override
125     public String toString() {
126         return name;
127     }
128     
129     public Collection<IndexInfo> getIndices() {
130         return indices.valueCollection();
131     }
132     
133     public boolean mayBeRemoved() {
134         return removeProcedure != null;
135     }
136
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;
145         if(indexMask == 0) {
146             accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType},
147                     null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null);
148         }
149         else {
150             Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
151             accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
152         }
153         return new IndexInfo(
154                 indexMask,
155                 indexName,
156                 accessIndex,
157                 new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {factType},
158                         null, new FieldRef(factClassName, indexName + "Next", factTypeDesc), null)
159                 );
160     }
161
162     public Constant accessComponent(int i) {
163         return accessors[i];
164     }
165     
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);
171         }
172         return indexInfo.firstFact;
173     }
174
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);
180         }
181         return indexInfo.nextFact;
182     }
183
184     
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);
190     }
191
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}),
197                     null);
198             isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType);
199         }
200     }
201
202     public int getMinimumPriority() {
203         return plans.get(0).priority;
204     }
205     
206     public boolean isPassive() {
207         return plans.isEmpty();
208     }
209     
210     public TPred[] getTypeConstraints() {
211         return TPred.EMPTY_ARRAY;
212     }
213
214 }