]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java
(refs #7250) Refactoring CHR implementation
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / chr / CHRRuntimeRulesetCodeGenerator.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java
new file mode 100644 (file)
index 0000000..0030867
--- /dev/null
@@ -0,0 +1,90 @@
+package org.simantics.scl.compiler.internal.codegen.chr;
+
+import java.util.ArrayList;
+
+import org.cojen.classfile.TypeDesc;
+import org.objectweb.asm.Opcodes;
+import org.simantics.scl.compiler.elaboration.chr.CHRRule;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
+import org.simantics.scl.compiler.internal.codegen.utils.Constants;
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
+import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
+
+public class CHRRuntimeRulesetCodeGenerator implements CHRCodeGenerationConstants {
+
+    public static void generateRuntimeRuleset(ModuleBuilder moduleBuilder, CHRRuleset ruleset) {
+        ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.runtimeRulesetName, CHRRuntimeRuleset_name);
+        if(ruleset.parameters == null)
+            ruleset.parameters = new BoundVar[0];
+        ruleset.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.parameters); 
+
+        ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<StoreInitialization>();
+        for(CHRConstraint constraint : ruleset.constraints)
+            generateFact(storeClassBuilder, constraint, hashIndexInitializations);
+        
+        for(int i=ruleset.rules.size()-1;i>=0;--i)
+            generateFactContainer(storeClassBuilder, ruleset, ruleset.rules.get(i));
+
+        // Fields
+        for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
+            TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
+            if(typeDesc.equals(TypeDesc.VOID))
+                continue;
+            storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.parameterName(i), typeDesc);
+        }
+        for(StoreInitialization ini : hashIndexInitializations)
+            storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);
+        for(CHRRule rule : ruleset.rules)
+            storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
+
+        // Constructors
+
+        {
+            MethodBuilderBase mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, ruleset.parameterTypeDescs);
+            mb.loadThis();
+            mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
+            for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
+                TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
+                if(typeDesc.equals(TypeDesc.VOID))
+                    continue;
+                mb.loadThis();
+                mb.loadLocal(mb.getParameter(i));
+                mb.storeField(ruleset.runtimeRulesetName, CHRCodeGenerationConstants.parameterName(i), ruleset.parameterTypeDescs[i]);
+            }
+            for(StoreInitialization ini : hashIndexInitializations) {
+                mb.loadThis();
+                mb.newObject(ini.className);
+                mb.dup();
+                mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);
+                mb.storeField(ruleset.runtimeRulesetName, ini.fieldName, ini.fieldType);
+            }
+            TypeDesc[] runtimeRulesetTypeDescArray = new TypeDesc[] {TypeDesc.forClass(storeClassBuilder.getClassName())};
+            for(CHRRule rule : ruleset.rules) {
+                mb.loadThis();
+                mb.newObject(rule.containerClassName);
+                mb.dup();
+                mb.loadThis();
+                mb.invokeConstructor(rule.containerClassName, runtimeRulesetTypeDescArray);
+                mb.storeField(ruleset.runtimeRulesetName, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
+            }
+            mb.returnVoid();
+            mb.finish();
+        }
+
+        moduleBuilder.addClass(storeClassBuilder);
+    }
+
+    private static void generateFact(ClassBuilder storeClassBuilder, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
+        CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, constraint);
+        generator.generate(hashIndexInitializations);
+    }
+
+    private static void generateFactContainer(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRRule rule) {
+        CHRPriorityFactContainerCodeGenerator generator = new CHRPriorityFactContainerCodeGenerator(storeClassBuilder, ruleset, rule); 
+        generator.generate();
+        rule.containerClassName = generator.containerClassName;
+    }
+}