]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRHashIndexCodeGenerator.java
(refs #7250) Refactoring CHR implementation
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / chr / CHRHashIndexCodeGenerator.java
1 package org.simantics.scl.compiler.internal.codegen.chr;
2
3 import org.cojen.classfile.TypeDesc;
4 import org.objectweb.asm.Label;
5 import org.objectweb.asm.Opcodes;
6 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
7 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo;
8 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
9 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
10 import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;
11 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
12 import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
13 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
14 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
15
16 public class CHRHashIndexCodeGenerator implements CHRCodeGenerationConstants {
17     
18     public static ClassBuilder generateHashIndex(ClassBuilder storeClassBuilder, CHRConstraint constraint, IndexInfo indexInfo, TypeDesc factClassTypeDesc, String factClassName) {
19         // new CHRHashIndex() {
20         //     @Override
21         //     protected boolean keyEquals(Object a, Object b) {
22         //         return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
23         //     }
24         //     @Override
25         //     protected int keyHashCode(Object key) {
26         //         return ((ExampleFact)key).c0;
27         //     }
28         // }
29
30         ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder();
31         JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator();
32
33         String hashIndexClassName = factClassName + "$" + indexInfo.indexName; 
34         ClassBuilder hashIndexClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, hashIndexClassName, "org/simantics/scl/runtime/chr/CHRHashIndex");
35
36         // Method: keyEquals
37
38         {
39
40             // @Override
41             // protected boolean keyEquals(Object a, Object b) {
42             //     return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
43             // }
44
45             MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyEquals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);
46             mb.loadLocal(mb.getParameter(0));
47             mb.checkCast(factClassTypeDesc);
48             LocalVariable aVar = mb.createLocalVariable("a", factClassTypeDesc);
49             mb.storeLocal(aVar);
50
51             mb.loadLocal(mb.getParameter(1));
52             mb.checkCast(factClassTypeDesc);
53             LocalVariable bVar = mb.createLocalVariable("b", factClassTypeDesc);
54             mb.storeLocal(bVar);
55
56             Label failure = mb.createLabel();
57
58             int curMask = indexInfo.indexMask;
59             for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
60                 if((curMask&1) == 1) {
61                     TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
62                     if(fieldTypeDesc.equals(TypeDesc.VOID))
63                         continue;
64                     mb.loadLocal(aVar);
65                     mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
66
67                     mb.loadLocal(bVar);
68                     mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
69
70                     CodeBuilderUtils.equals(mb, fieldTypeDesc, failure);
71                 }
72             mb.loadConstant(true);
73             mb.returnValue(TypeDesc.BOOLEAN);
74
75             mb.setLocation(failure);
76             mb.loadConstant(false);
77             mb.returnValue(TypeDesc.BOOLEAN);
78             mb.finish();
79         }
80
81         // Method: keyHashCode
82
83         {
84             // @Override
85             // protected int keyHashCode(Object key) {
86             //     return (0x811C9DC5^((ExampleFact)key).c0)*16777619;
87             // }
88
89             MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyHashCode", TypeDesc.INT, Constants.OBJECTS[1]);
90             mb.loadLocal(mb.getParameter(0));
91             mb.checkCast(factClassTypeDesc);
92             LocalVariable factVar = mb.createLocalVariable("fact", factClassTypeDesc);
93             mb.storeLocal(factVar);
94
95             mb.loadConstant(0x811C9DC5);
96
97             int curMask = indexInfo.indexMask;
98             for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
99                 if((curMask&1) == 1) {
100                     TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
101                     if(fieldTypeDesc.equals(TypeDesc.VOID))
102                         continue;
103                     mb.loadLocal(factVar);
104                     mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
105                     CodeBuilderUtils.hashCode(mb, fieldTypeDesc);
106                     mb.math(Opcodes.IXOR);
107                     mb.loadConstant(16777619);
108                     mb.math(Opcodes.IMUL);
109
110                 }
111             mb.returnValue(TypeDesc.INT);
112             mb.finish();
113         }
114
115         hashIndexClassBuilder.addDefaultConstructor();
116
117         return hashIndexClassBuilder;
118     }
119
120 }