]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java
(refs #7365) Fixed the bug in the test CHR11.scl
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / chr / CHRRulesetObject.java
index f14cb0c6b10b4771f410fc0d1f8c45d5176fea49..96e86aed1df99760e52a6f6184665c0f50364238 100644 (file)
@@ -1,31 +1,83 @@
-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);
+    }
+}