]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerator.java
(refs #7250) Cleaning up CHR code generation
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / chr / CHRCodeGenerator.java
1 package org.simantics.scl.compiler.internal.codegen.chr;
2
3 import java.util.ArrayList;
4
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;
14
15 public class CHRCodeGenerator {
16
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";
21
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); 
27
28         ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<>();
29         for(CHRConstraint constraint : ruleset.constraints)
30             generateFact(storeClassBuilder, constraint, hashIndexInitializations);
31
32         // Fields
33         for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
34             TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
35             if(typeDesc.equals(TypeDesc.VOID))
36                 continue;
37             storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "p" + i, typeDesc);
38         }
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);
43
44         // Constructors
45
46         {
47             MethodBuilderBase mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, ruleset.parameterTypeDescs);
48             mb.loadThis();
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))
53                     continue;
54                 mb.loadThis();
55                 mb.loadLocal(mb.getParameter(i));
56                 mb.storeField(ruleset.storeClassName, "p" + i, ruleset.parameterTypeDescs[i]);
57             }
58             mb.loadThis();
59             mb.loadConstant(1);
60             mb.storeField(storeClassBuilder.getClassName(), "currentId", TypeDesc.INT);
61             for(StoreInitialization ini : hashIndexInitializations) {
62                 mb.loadThis();
63                 mb.newObject(ini.className);
64                 mb.dup();
65                 mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);
66                 mb.storeField(ruleset.storeClassName, ini.fieldName, ini.fieldType);
67             }
68             {
69                 mb.loadThis();
70                 mb.newObject(FactActivationQueue_name);
71                 mb.dup();
72                 mb.loadConstant(ruleset.priorityCount);
73                 mb.invokeConstructor(FactActivationQueue_name, new TypeDesc[] {TypeDesc.INT});
74                 mb.storeField(ruleset.storeClassName, QUEUE, FactActivationQueue);
75             }
76             mb.returnVoid();
77             mb.finish();
78         }
79
80         // Activate
81
82         {
83             MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT});
84             mb.loadThis();
85             mb.loadField(ruleset.storeClassName, QUEUE, FactActivationQueue);
86             mb.loadThis();
87             mb.loadLocal(mb.getParameter(0));
88             mb.invokeVirtual(FactActivationQueue_name, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.INT});
89             mb.returnVoid();
90             mb.finish();
91         }
92
93         moduleBuilder.addClass(storeClassBuilder);
94     }
95
96     private static void generateFact(ClassBuilder storeClassBuilder, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
97         CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, constraint);
98         generator.generate(hashIndexInitializations);
99     }
100 }