package org.simantics.scl.compiler.elaboration.chr;
+import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.constants.JavaConstructor;
import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator;
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject;
+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.ModuleBuilder;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
public class CHRRulesetObject extends SSAObject {
CHRRuleset ruleset;
+ public BoundVar this_;
+ public BoundVar[] parameters;
+ public TObjectIntHashMap<BoundVar> parameterIndexMap;
+ public TypeDesc[] parameterTypeDescs;
+
public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) {
super(ruleset.runtimeRulesetType);
this.setTarget(target);
@Override
public Constant liftClosure(BoundVar newTarget, BoundVar[] parameters) {
- ruleset.this_ = newTarget;
- ruleset.parameters = parameters;
- return new JavaConstructor(ruleset.runtimeRulesetName, Types.PROC, ruleset.runtimeRulesetType, Types.getTypes(parameters));
+ ruleset.rulesetObject = this;
+ this.this_ = newTarget;
+ this.parameters = parameters;
+ this.parameterIndexMap = new TObjectIntHashMap<>(parameters.length);
+ for(int i=0;i<parameters.length;++i)
+ this.parameterIndexMap.put(parameters[i], i);
+ return new JavaConstructor(ruleset.runtimeRulesetClassName, Types.PROC, ruleset.runtimeRulesetType, Types.getTypes(parameters));
}
@Override
public void generateCode(ModuleBuilder moduleBuilder) {
CHRRuntimeRulesetCodeGenerator.generateRuntimeRuleset(moduleBuilder, ruleset);
}
+
+ @FunctionalInterface
+ public interface ParameterDefiner {
+ public void defineParameter(int index, BoundVar var);
+ }
+
+ public void realizeMethod(MethodBuilder mb, ParameterDefiner loader, SSAFunction function, LocalVariable this_, LocalVariable ... callParameters) {
+ mb.setLocalVariable(this.this_, this_);
+ BoundVar[] functionParameters = function.getParameters();
+ if(functionParameters.length != callParameters.length)
+ throw new InternalCompilerError();
+ for(int i=0;i<callParameters.length;++i)
+ mb.setLocalVariable(functionParameters[i], callParameters[i]);
+
+ // Set closure parameters
+ TIntHashSet usedParameterIndices = new TIntHashSet(parameters.length);
+ function.forValRefs(valRef -> {
+ Val binding = valRef.getBinding();
+ if(parameterIndexMap.containsKey(binding))
+ usedParameterIndices.add(parameterIndexMap.get((BoundVar)binding));
+ });
+ usedParameterIndices.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int i) {
+ loader.defineParameter(i, parameters[i]);
+ return true;
+ }
+ });
+
+ // Generate code
+ function.markGenerateOnFly();
+ function.generateCodeWithAlreadyPreparedParameters(mb);
+ }
}