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);
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) {
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);
}