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.CHRRule;
8 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
9 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
10 import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
11 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
12 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
13 import org.simantics.scl.compiler.internal.codegen.utils.Constants;
14 import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
15 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
16 import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilderBase;
17 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
19 public class CHRRuntimeRulesetCodeGenerator implements CHRCodeGenerationConstants {
21 public static void generateRuntimeRuleset(ModuleBuilder moduleBuilder, CHRRuleset ruleset) {
22 ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.runtimeRulesetClassName, CHRRuntimeRuleset_name);
23 if(ruleset.rulesetObject.parameters == null)
24 ruleset.rulesetObject.parameters = new BoundVar[0];
25 TypeDesc[] parameterTypeDescs = ruleset.rulesetObject.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.rulesetObject.parameters);
27 ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<StoreInitialization>();
28 for(CHRConstraint constraint : ruleset.constraints)
29 generateFact(storeClassBuilder, ruleset, constraint, hashIndexInitializations);
31 for(int i=ruleset.rules.size()-1;i>=0;--i)
32 generateFactContainer(storeClassBuilder, ruleset, ruleset.rules.get(i));
35 for(int i=0;i<parameterTypeDescs.length;++i) {
36 TypeDesc typeDesc = parameterTypeDescs[i];
37 if(typeDesc.equals(TypeDesc.VOID))
39 storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.parameterName(i), typeDesc);
41 for(StoreInitialization ini : hashIndexInitializations)
42 storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);
43 for(CHRRule rule : ruleset.rules)
44 storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
45 if(ruleset.extensible)
46 for(CHRConstraint constraint : ruleset.constraints)
47 if(constraint.nextContainerFieldName != null)
48 storeClassBuilder.addField(Opcodes.ACC_PUBLIC, constraint.nextContainerFieldName, CHRPriorityFactContainer);
49 //if(ruleset.extensible)
50 // storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);
55 MethodBuilder mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, parameterTypeDescs);
56 //TypeDesc.concat(ruleset.parameterTypeDescs, includeTypeDescs));
58 mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
60 for(int i=0;i<parameterTypeDescs.length;++i) {
61 TypeDesc typeDesc = parameterTypeDescs[i];
62 if(typeDesc.equals(TypeDesc.VOID))
65 mb.loadLocal(mb.getParameter(p++));
66 mb.storeField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
68 for(StoreInitialization ini : hashIndexInitializations) {
70 mb.newObject(ini.className);
72 mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);
73 mb.storeField(ruleset.runtimeRulesetClassName, ini.fieldName, ini.fieldType);
75 TypeDesc[] runtimeRulesetTypeDescArray = new TypeDesc[] {TypeDesc.forClass(storeClassBuilder.getClassName())};
76 for(CHRRule rule : ruleset.rules) {
78 mb.newObject(rule.containerClassName);
81 mb.invokeConstructor(rule.containerClassName, runtimeRulesetTypeDescArray);
82 mb.storeField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
90 for(IncludeStatement include : ruleset.includes) {
92 MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "register", TypeDesc.VOID,
93 new TypeDesc[] {CHRContext, include.ruleset.runtimeRulesetTypeDesc});
94 LocalVariable contextVar = mb.getParameter(0);
95 LocalVariable importedStore = mb.getParameter(1);
96 ArrayList<CHRConstraint> list = ruleset.inverseActiveConstraintSourceMap.get(include);
98 for(CHRConstraint constraint : list) {
99 int minimumPriority = ruleset.getMinimumPriority(constraint);
100 if(minimumPriority == Integer.MAX_VALUE)
102 mb.loadLocal(importedStore);
104 mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.priorityName(minimumPriority), CHRPriorityFactContainer);
105 mb.storeField(include.ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.nextContainerName(constraint.name), CHRPriorityFactContainer);
109 mb.loadLocal(importedStore);
110 mb.loadLocal(contextVar);
111 mb.invokeVirtual("org/simantics/scl/runtime/chr/CHRRuntimeRuleset", "register", TypeDesc.VOID, new TypeDesc[] {CHRContext});
112 /*mb.loadLocal(contextVar);
113 mb.loadLocal(contextVar);
114 mb.loadField(CHRContext_name, "currentId", FACT_ID_TYPE);
115 mb.loadLocal(importedStore);
116 mb.loadField(include.ruleset.runtimeRulesetClassName, "currentId", FACT_ID_TYPE);
117 mb.invokeStatic("java/lang/Math", "max", FACT_ID_TYPE, new TypeDesc[] {FACT_ID_TYPE, FACT_ID_TYPE});
118 mb.storeField(CHRContext_name, "currentId", FACT_ID_TYPE);*/
125 MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "unregister", TypeDesc.VOID,
126 new TypeDesc[] {CHRContext, include.ruleset.runtimeRulesetTypeDesc});
127 LocalVariable contextVar = mb.getParameter(0);
128 LocalVariable importedStore = mb.getParameter(1);
129 ArrayList<CHRConstraint> list = ruleset.inverseActiveConstraintSourceMap.get(include);
131 for(CHRConstraint constraint : list) {
132 int minimumPriority = ruleset.getMinimumPriority(constraint);
133 if(minimumPriority == Integer.MAX_VALUE)
135 mb.loadLocal(importedStore);
137 mb.storeField(include.ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.nextContainerName(constraint.name), CHRPriorityFactContainer);
141 mb.loadLocal(importedStore);
142 mb.loadLocal(contextVar);
143 mb.invokeVirtual("org/simantics/scl/runtime/chr/CHRRuntimeRuleset", "unregister", TypeDesc.VOID, new TypeDesc[] {CHRContext});
144 /*mb.loadLocal(importedStore);
145 mb.loadLocal(contextVar);
146 mb.loadField(CHRContext_name, "currentId", FACT_ID_TYPE);
147 mb.storeField(include.ruleset.runtimeRulesetClassName, "currentId", FACT_ID_TYPE);*/
154 if(ruleset.initializer != null) {
155 MethodBuilder mb = storeClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "initialize", TypeDesc.VOID, new TypeDesc[] {CHRContext});
156 ruleset.rulesetObject.realizeMethod(mb,
159 mb.loadField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
162 ruleset.initializer, mb.getThis(ruleset.runtimeRulesetTypeDesc), mb.getParameter(0));
165 if(ruleset.deinitializer != null) {
166 MethodBuilder mb = storeClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "deinitialize", TypeDesc.VOID, new TypeDesc[] {CHRContext});
167 ruleset.rulesetObject.realizeMethod(mb,
170 mb.loadField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
173 ruleset.deinitializer, mb.getThis(ruleset.runtimeRulesetTypeDesc), mb.getParameter(0));
177 moduleBuilder.addClass(storeClassBuilder);
180 private static void generateFact(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
181 CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, ruleset, constraint);
182 generator.generate(hashIndexInitializations);
185 private static void generateFactContainer(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRRule rule) {
186 CHRPriorityFactContainerCodeGenerator generator = new CHRPriorityFactContainerCodeGenerator(storeClassBuilder, ruleset, rule);
187 generator.generate();
188 rule.containerClassName = generator.containerClassName;