]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java
(refs #7365) Fixed the bug in the test CHR11.scl
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / chr / CHRRuntimeRulesetCodeGenerator.java
index 003086704522773d11ebaa0e43bf4b659e00c28d..341ba34a796b18ebdd7dbd0850e7649b1328f60f 100644 (file)
@@ -7,30 +7,33 @@ 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.elaboration.expressions.block.IncludeStatement;
 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.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;
 
 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); 
+        ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.runtimeRulesetClassName, CHRRuntimeRuleset_name);
+        if(ruleset.rulesetObject.parameters == null)
+            ruleset.rulesetObject.parameters = new BoundVar[0];
+        TypeDesc[] parameterTypeDescs = ruleset.rulesetObject.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.rulesetObject.parameters); 
 
         ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<StoreInitialization>();
         for(CHRConstraint constraint : ruleset.constraints)
-            generateFact(storeClassBuilder, constraint, hashIndexInitializations);
+            generateFact(storeClassBuilder, ruleset, 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];
+        for(int i=0;i<parameterTypeDescs.length;++i) {
+            TypeDesc typeDesc = parameterTypeDescs[i];
             if(typeDesc.equals(TypeDesc.VOID))
                 continue;
             storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.parameterName(i), typeDesc);
@@ -39,27 +42,35 @@ public class CHRRuntimeRulesetCodeGenerator implements CHRCodeGenerationConstant
             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);
-
+        if(ruleset.extensible)
+            for(CHRConstraint constraint : ruleset.constraints)
+                if(constraint.nextContainerFieldName != null)
+                    storeClassBuilder.addField(Opcodes.ACC_PUBLIC, constraint.nextContainerFieldName, CHRPriorityFactContainer);
+        //if(ruleset.extensible)
+        //    storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);
+        
         // Constructors
 
         {
-            MethodBuilderBase mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, ruleset.parameterTypeDescs);
+            MethodBuilder mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, parameterTypeDescs);
+                    //TypeDesc.concat(ruleset.parameterTypeDescs, includeTypeDescs));
             mb.loadThis();
             mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
-            for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
-                TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
+            int p=0;
+            for(int i=0;i<parameterTypeDescs.length;++i) {
+                TypeDesc typeDesc = 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]);
+                mb.loadLocal(mb.getParameter(p++));
+                mb.storeField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), 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);
+                mb.storeField(ruleset.runtimeRulesetClassName, ini.fieldName, ini.fieldType);
             }
             TypeDesc[] runtimeRulesetTypeDescArray = new TypeDesc[] {TypeDesc.forClass(storeClassBuilder.getClassName())};
             for(CHRRule rule : ruleset.rules) {
@@ -68,17 +79,106 @@ public class CHRRuntimeRulesetCodeGenerator implements CHRCodeGenerationConstant
                 mb.dup();
                 mb.loadThis();
                 mb.invokeConstructor(rule.containerClassName, runtimeRulesetTypeDescArray);
-                mb.storeField(ruleset.runtimeRulesetName, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
+                mb.storeField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
             }
             mb.returnVoid();
             mb.finish();
         }
+        
+        // Registration
+        
+        for(IncludeStatement include : ruleset.includes) {
+            {
+                MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "register", TypeDesc.VOID,
+                        new TypeDesc[] {CHRContext, include.ruleset.runtimeRulesetTypeDesc});
+                LocalVariable contextVar = mb.getParameter(0);
+                LocalVariable importedStore = mb.getParameter(1);
+                ArrayList<CHRConstraint> list = ruleset.inverseActiveConstraintSourceMap.get(include);
+                if(list != null)
+                    for(CHRConstraint constraint : list) {
+                        int minimumPriority = ruleset.getMinimumPriority(constraint);
+                        if(minimumPriority == Integer.MAX_VALUE)
+                            continue;
+                        mb.loadLocal(importedStore);
+                        mb.loadThis();
+                        mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.priorityName(minimumPriority), CHRPriorityFactContainer);
+                        mb.storeField(include.ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.nextContainerName(constraint.name), CHRPriorityFactContainer);
+                    }
+                
+                // update context id
+                mb.loadLocal(importedStore);
+                mb.loadLocal(contextVar);
+                mb.invokeVirtual("org/simantics/scl/runtime/chr/CHRRuntimeRuleset", "register", TypeDesc.VOID, new TypeDesc[] {CHRContext});
+                /*mb.loadLocal(contextVar);
+                mb.loadLocal(contextVar);
+                mb.loadField(CHRContext_name, "currentId", FACT_ID_TYPE);
+                mb.loadLocal(importedStore);
+                mb.loadField(include.ruleset.runtimeRulesetClassName, "currentId", FACT_ID_TYPE);
+                mb.invokeStatic("java/lang/Math", "max", FACT_ID_TYPE, new TypeDesc[] {FACT_ID_TYPE, FACT_ID_TYPE});
+                mb.storeField(CHRContext_name, "currentId", FACT_ID_TYPE);*/
+                
+                mb.returnVoid();
+                mb.finish();
+            }
+            
+            {
+                MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "unregister", TypeDesc.VOID,
+                        new TypeDesc[] {CHRContext, include.ruleset.runtimeRulesetTypeDesc});
+                LocalVariable contextVar = mb.getParameter(0);
+                LocalVariable importedStore = mb.getParameter(1);
+                ArrayList<CHRConstraint> list = ruleset.inverseActiveConstraintSourceMap.get(include);
+                if(list != null)
+                    for(CHRConstraint constraint : list) {
+                        int minimumPriority = ruleset.getMinimumPriority(constraint);
+                        if(minimumPriority == Integer.MAX_VALUE)
+                            continue;
+                        mb.loadLocal(importedStore);
+                        mb.loadNull();
+                        mb.storeField(include.ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.nextContainerName(constraint.name), CHRPriorityFactContainer);
+                    }
+                
+                // store context id
+                mb.loadLocal(importedStore);
+                mb.loadLocal(contextVar);
+                mb.invokeVirtual("org/simantics/scl/runtime/chr/CHRRuntimeRuleset", "unregister", TypeDesc.VOID, new TypeDesc[] {CHRContext});
+                /*mb.loadLocal(importedStore);
+                mb.loadLocal(contextVar);
+                mb.loadField(CHRContext_name, "currentId", FACT_ID_TYPE);
+                mb.storeField(include.ruleset.runtimeRulesetClassName, "currentId", FACT_ID_TYPE);*/
+                
+                mb.returnVoid();
+                mb.finish();
+            }
+        }
+        
+        if(ruleset.initializer != null) {
+            MethodBuilder mb = storeClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "initialize", TypeDesc.VOID, new TypeDesc[] {CHRContext});
+            ruleset.rulesetObject.realizeMethod(mb,
+                    (i, target) -> {
+                        mb.loadThis();
+                        mb.loadField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
+                        mb.store(target);
+                    },
+                    ruleset.initializer, mb.getThis(ruleset.runtimeRulesetTypeDesc), mb.getParameter(0));
+            mb.finish();
+        }
+        if(ruleset.deinitializer != null) {
+            MethodBuilder mb = storeClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "deinitialize", TypeDesc.VOID, new TypeDesc[] {CHRContext});
+            ruleset.rulesetObject.realizeMethod(mb,
+                    (i, target) -> {
+                        mb.loadThis();
+                        mb.loadField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
+                        mb.store(target);
+                    },
+                    ruleset.deinitializer, mb.getThis(ruleset.runtimeRulesetTypeDesc), mb.getParameter(0));
+            mb.finish();
+        }
 
         moduleBuilder.addClass(storeClassBuilder);
     }
 
-    private static void generateFact(ClassBuilder storeClassBuilder, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
-        CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, constraint);
+    private static void generateFact(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
+        CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, ruleset, constraint);
         generator.generate(hashIndexInitializations);
     }