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.MethodBuilderBase;
import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
-public class CHRCodeGenerator {
+public class CHRRuntimeRulesetCodeGenerator implements CHRCodeGenerationConstants {
- public static final TypeDesc FACT_ID_TYPE = TypeDesc.INT;
- private static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue";
- private static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name);
- private static final String QUEUE = "queue";
-
- public static void generateStore(ModuleBuilder moduleBuilder, CHRRuleset ruleset) {
- ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.storeClassName, "java/lang/Object");
+ 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<>();
+ 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, "p" + i, typeDesc);
+ storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.parameterName(i), typeDesc);
}
- storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);
for(StoreInitialization ini : hashIndexInitializations)
storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);
- storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, QUEUE, FactActivationQueue);
+ for(CHRRule rule : ruleset.rules)
+ storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
// Constructors
continue;
mb.loadThis();
mb.loadLocal(mb.getParameter(i));
- mb.storeField(ruleset.storeClassName, "p" + i, ruleset.parameterTypeDescs[i]);
+ mb.storeField(ruleset.runtimeRulesetName, CHRCodeGenerationConstants.parameterName(i), ruleset.parameterTypeDescs[i]);
}
- mb.loadThis();
- mb.loadConstant(1);
- mb.storeField(storeClassBuilder.getClassName(), "currentId", TypeDesc.INT);
for(StoreInitialization ini : hashIndexInitializations) {
mb.loadThis();
mb.newObject(ini.className);
mb.dup();
mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);
- mb.storeField(ruleset.storeClassName, ini.fieldName, ini.fieldType);
+ 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(FactActivationQueue_name);
+ mb.newObject(rule.containerClassName);
mb.dup();
- mb.loadConstant(ruleset.priorityCount);
- mb.invokeConstructor(FactActivationQueue_name, new TypeDesc[] {TypeDesc.INT});
- mb.storeField(ruleset.storeClassName, QUEUE, FactActivationQueue);
+ mb.loadThis();
+ mb.invokeConstructor(rule.containerClassName, runtimeRulesetTypeDescArray);
+ mb.storeField(ruleset.runtimeRulesetName, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
}
mb.returnVoid();
mb.finish();
}
- // Activate
-
- {
- MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT});
- mb.loadThis();
- mb.loadField(ruleset.storeClassName, QUEUE, FactActivationQueue);
- mb.loadThis();
- mb.loadLocal(mb.getParameter(0));
- mb.invokeVirtual(FactActivationQueue_name, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.INT});
- mb.returnVoid();
- mb.finish();
- }
-
moduleBuilder.addClass(storeClassBuilder);
}
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;
+ }
}