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