]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRHashIndexCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRHashIndexCodeGenerator.java
new file mode 100644 (file)
index 0000000..bafd83e
--- /dev/null
@@ -0,0 +1,120 @@
+package org.simantics.scl.compiler.internal.codegen.chr;
+
+import org.cojen.classfile.TypeDesc;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo;
+import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
+import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
+import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;
+import org.simantics.scl.compiler.internal.codegen.utils.Constants;
+import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
+import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
+
+public class CHRHashIndexCodeGenerator implements CHRCodeGenerationConstants {
+    
+    public static ClassBuilder generateHashIndex(ClassBuilder storeClassBuilder, CHRConstraint constraint, IndexInfo indexInfo, TypeDesc factClassTypeDesc, String factClassName) {
+        // new CHRHashIndex() {
+        //     @Override
+        //     protected boolean keyEquals(Object a, Object b) {
+        //         return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
+        //     }
+        //     @Override
+        //     protected int keyHashCode(Object key) {
+        //         return ((ExampleFact)key).c0;
+        //     }
+        // }
+
+        ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder();
+        JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator();
+
+        String hashIndexClassName = factClassName + "$" + indexInfo.indexName; 
+        ClassBuilder hashIndexClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, hashIndexClassName, "org/simantics/scl/runtime/chr/CHRHashIndex");
+
+        // Method: keyEquals
+
+        {
+
+            // @Override
+            // protected boolean keyEquals(Object a, Object b) {
+            //     return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
+            // }
+
+            MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyEquals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);
+            mb.loadLocal(mb.getParameter(0));
+            mb.checkCast(factClassTypeDesc);
+            LocalVariable aVar = mb.createLocalVariable("a", factClassTypeDesc);
+            mb.storeLocal(aVar);
+
+            mb.loadLocal(mb.getParameter(1));
+            mb.checkCast(factClassTypeDesc);
+            LocalVariable bVar = mb.createLocalVariable("b", factClassTypeDesc);
+            mb.storeLocal(bVar);
+
+            Label failure = mb.createLabel();
+
+            int curMask = indexInfo.indexMask;
+            for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
+                if((curMask&1) == 1) {
+                    TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
+                    if(fieldTypeDesc.equals(TypeDesc.VOID))
+                        continue;
+                    mb.loadLocal(aVar);
+                    mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
+
+                    mb.loadLocal(bVar);
+                    mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
+
+                    CodeBuilderUtils.equals(mb, fieldTypeDesc, failure);
+                }
+            mb.loadConstant(true);
+            mb.returnValue(TypeDesc.BOOLEAN);
+
+            mb.setLocation(failure);
+            mb.loadConstant(false);
+            mb.returnValue(TypeDesc.BOOLEAN);
+            mb.finish();
+        }
+
+        // Method: keyHashCode
+
+        {
+            // @Override
+            // protected int keyHashCode(Object key) {
+            //     return (0x811C9DC5^((ExampleFact)key).c0)*16777619;
+            // }
+
+            MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyHashCode", TypeDesc.INT, Constants.OBJECTS[1]);
+            mb.loadLocal(mb.getParameter(0));
+            mb.checkCast(factClassTypeDesc);
+            LocalVariable factVar = mb.createLocalVariable("fact", factClassTypeDesc);
+            mb.storeLocal(factVar);
+
+            mb.loadConstant(0x811C9DC5);
+
+            int curMask = indexInfo.indexMask;
+            for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
+                if((curMask&1) == 1) {
+                    TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
+                    if(fieldTypeDesc.equals(TypeDesc.VOID))
+                        continue;
+                    mb.loadLocal(factVar);
+                    mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
+                    CodeBuilderUtils.hashCode(mb, fieldTypeDesc);
+                    mb.math(Opcodes.IXOR);
+                    mb.loadConstant(16777619);
+                    mb.math(Opcodes.IMUL);
+
+                }
+            mb.returnValue(TypeDesc.INT);
+            mb.finish();
+        }
+
+        hashIndexClassBuilder.addDefaultConstructor();
+
+        return hashIndexClassBuilder;
+    }
+
+}