1 package org.simantics.scl.compiler.internal.codegen.chr;
3 import java.util.ArrayList;
5 import org.cojen.classfile.TypeDesc;
6 import org.objectweb.asm.Opcodes;
7 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
8 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
9 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
10 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
11 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
12 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
13 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
15 public class CHRCodeGenerator {
17 public static final TypeDesc FACT_ID_TYPE = TypeDesc.INT;
18 private static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue";
19 private static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name);
20 private static final String QUEUE = "queue";
22 public static void generateStore(ModuleBuilder moduleBuilder, CHRRuleset ruleset) {
23 ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.storeClassName, "java/lang/Object");
24 if(ruleset.parameters == null)
25 ruleset.parameters = new BoundVar[0];
26 ruleset.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.parameters);
28 ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<>();
29 for(CHRConstraint constraint : ruleset.constraints)
30 generateFact(storeClassBuilder, constraint, hashIndexInitializations);
33 for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
34 TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
35 if(typeDesc.equals(TypeDesc.VOID))
37 storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "p" + i, typeDesc);
39 storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);
40 for(StoreInitialization ini : hashIndexInitializations)
41 storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);
42 storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, QUEUE, FactActivationQueue);
47 MethodBuilderBase mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, ruleset.parameterTypeDescs);
49 mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
50 for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
51 TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
52 if(typeDesc.equals(TypeDesc.VOID))
55 mb.loadLocal(mb.getParameter(i));
56 mb.storeField(ruleset.storeClassName, "p" + i, ruleset.parameterTypeDescs[i]);
60 mb.storeField(storeClassBuilder.getClassName(), "currentId", TypeDesc.INT);
61 for(StoreInitialization ini : hashIndexInitializations) {
63 mb.newObject(ini.className);
65 mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);
66 mb.storeField(ruleset.storeClassName, ini.fieldName, ini.fieldType);
70 mb.newObject(FactActivationQueue_name);
72 mb.loadConstant(ruleset.priorityCount);
73 mb.invokeConstructor(FactActivationQueue_name, new TypeDesc[] {TypeDesc.INT});
74 mb.storeField(ruleset.storeClassName, QUEUE, FactActivationQueue);
83 MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT});
85 mb.loadField(ruleset.storeClassName, QUEUE, FactActivationQueue);
87 mb.loadLocal(mb.getParameter(0));
88 mb.invokeVirtual(FactActivationQueue_name, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.INT});
93 moduleBuilder.addClass(storeClassBuilder);
96 private static void generateFact(ClassBuilder storeClassBuilder, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
97 CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, constraint);
98 generator.generate(hashIndexInitializations);