--- /dev/null
+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;
+ }
+
+}