package org.simantics.scl.compiler.internal.codegen.chr; import java.util.ArrayList; import org.cojen.classfile.TypeDesc; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan; 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.references.BoundVar; 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.MethodBuilder; import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase; import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder; import gnu.trove.list.array.TIntArrayList; import gnu.trove.set.hash.THashSet; public class CHRFactCodeGenerator { private static final TypeDesc FACT_ID_TYPE = TypeDesc.INT; private static final String CHRHashIndex_name = "org/simantics/scl/runtime/chr/CHRHashIndex"; private static final TypeDesc CHRHashIndex = TypeDesc.forClass(CHRHashIndex_name); private static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue"; private static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name); private static final String Fact_name = "org/simantics/scl/runtime/chr/Fact"; private static final TypeDesc Fact = TypeDesc.forClass(Fact_name); private static final String QUEUE = "queue"; private ModuleBuilder moduleBuilder; private JavaTypeTranslator jtt; private CHRRuleset ruleset; private ClassBuilder storeClassBuilder; private CHRConstraint constraint; private String factClassName; private TypeDesc factTypeDesc; private ClassBuilder factClassBuilder; private TypeDesc storeTypeDesc; private TypeDesc[] storeTypeDescArray; private TypeDesc[] parameterTypeDescs; private boolean supportsRemoval; CHRFactCodeGenerator(ClassBuilder storeClassBuilder, CHRConstraint constraint) { this.storeClassBuilder = storeClassBuilder; this.constraint = constraint; this.ruleset = constraint.parentRuleset; this.moduleBuilder = storeClassBuilder.getModuleBuilder(); this.jtt = moduleBuilder.getJavaTypeTranslator(); this.storeTypeDesc = storeClassBuilder.getType(); this.storeTypeDescArray = new TypeDesc[] { storeTypeDesc }; this.factClassName = storeClassBuilder.getClassName() + "$" + constraint.name; this.factTypeDesc = TypeDesc.forClass(factClassName); this.factClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, factClassName, "java/lang/Object", Fact_name); this.parameterTypeDescs = jtt.toTypeDescs(constraint.parameterTypes); this.supportsRemoval = constraint.mayBeRemoved(); } public void generate(ArrayList hashIndexInitializations) { generateFields(hashIndexInitializations); hashIndexInitializations.add(new StoreInitialization(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, constraint.name + "$temp", factTypeDesc, factClassName)); generateIndices(); generateAdd(); if(supportsRemoval) generateRemove(); generateIsAlive(); for(int i=0;i getParameterTypeDescs = new ArrayList(constraint.parameterTypes.length); for(int i=0;i>i)&1)==1) getParameterTypeDescs.add(parameterTypeDescs[i]); MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, constraint.name + "$" + indexInfo.indexName, factTypeDesc, getParameterTypeDescs.toArray(new TypeDesc[getParameterTypeDescs.size()])); // ExampleFact$temp.c0 = c0; mb.loadThis(); mb.loadField(storeClassBuilder.getClassName(), constraint.name + "$temp", factTypeDesc); LocalVariable tempFactVar = mb.createLocalVariable("temp", factTypeDesc); mb.storeLocal(tempFactVar); int parameterId=0; for(int i=0;i>i)&1)==1) { TypeDesc typeDesc = parameterTypeDescs[i]; if(!typeDesc.equals(TypeDesc.VOID)) { mb.loadLocal(tempFactVar); mb.loadLocal(mb.getParameter(parameterId)); mb.storeField(factClassName, fieldName(i), typeDesc); } ++parameterId; } // return (ExampleFact)ExampleFact_bfIndex.getEqual(ExampleFact$temp); mb.loadThis(); mb.loadField(storeClassBuilder.getClassName(), constraint.name + "$" + indexInfo.indexName, CHRHashIndex); mb.loadLocal(tempFactVar); mb.invokeVirtual(CHRHashIndex_name, supportsRemoval ? "getEqual" : "getEqualNoRemovals", TypeDesc.OBJECT, Constants.OBJECTS[1]); mb.checkCast(factTypeDesc); mb.returnValue(factTypeDesc); mb.finish(); } } } private THashSet usedParameters = new THashSet(); private void generateActivateI(int i) { PrioritizedPlan plan = constraint.plans.get(i); MethodBuilder mb = factClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "activate" + i, TypeDesc.BOOLEAN, storeTypeDescArray); LocalVariable storeVar = mb.getParameter(0); LocalVariable factVar = new LocalVariable(0, factTypeDesc); mb.setLocalVariable(ruleset.this_, storeVar); mb.setLocalVariable(plan.implementation.getParameters()[0], factVar); // Set closure parameters usedParameters.clear(); plan.implementation.forValRefs(valRef -> { if(valRef.getBinding() instanceof BoundVar) usedParameters.add((BoundVar)valRef.getBinding()); }); for(int j=0;j labels = new ArrayList