-package org.simantics.scl.compiler.elaboration.chr;\r
-\r
-import org.simantics.scl.compiler.constants.Constant;\r
-import org.simantics.scl.compiler.constants.JavaConstructor;\r
-import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;\r
-import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject;\r
-import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;\r
-import org.simantics.scl.compiler.types.Types;\r
-\r
-public class CHRRulesetObject extends SSAObject {\r
- CHRRuleset ruleset;\r
-\r
- public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) {\r
- super(ruleset.storeType);\r
- this.setTarget(target);\r
- this.ruleset = ruleset;\r
- }\r
- \r
- @Override\r
- public Constant liftClosure(BoundVar newTarget, BoundVar[] parameters) {\r
- ruleset.this_ = newTarget;\r
- ruleset.parameters = parameters;\r
- return new JavaConstructor(ruleset.storeClassName, Types.PROC, ruleset.storeType, Types.getTypes(parameters));\r
- }\r
- \r
- @Override\r
- public void generateCode(ModuleBuilder moduleBuilder) {\r
- CHRCodeGenerator.generateStore(moduleBuilder, ruleset);\r
- }\r
-}\r
+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);
+ this.ruleset = ruleset;
+ }
+
+ @Override
+ public Constant liftClosure(BoundVar newTarget, BoundVar[] 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);
+ }
+}