}
}
}
+
+ public static TypeDesc[] concat(TypeDesc[] a, TypeDesc[] b) {
+ TypeDesc[] result = new TypeDesc[a.length + b.length];
+ System.arraycopy(a, 0, result, 0, a.length);
+ System.arraycopy(b, 0, result, a.length, b.length);
+ return result;
+ }
}
void finishBlock() {
if(currentBlock != null) {
checkInterrupted();
- LinkedList<Statement> statements = currentBlock.getStatements();
currentBlock.location = Locations.combine(
- statements.getFirst().location,
- statements.getLast().location);
+ currentBlock.getFirst().location,
+ currentBlock.getLast().location);
execute(reader, currentBlock, handler);
currentBlock = null;
}
super(cause);
this.location = Locations.NO_LOCATION;
}
+
+ public InternalCompilerError(long location, Throwable cause) {
+ super(cause);
+ this.location = location;
+ }
}
}
public void optimizeSSA() {
- if(SCLCompilerConfiguration.SHOW_SSA_BEFORE_OPTIMIZATION) {
+ if(SCLCompilerConfiguration.SHOW_SSA_BEFORE_OPTIMIZATION && SCLCompilerConfiguration.debugFilter(module.getName())) {
System.out.println("=== SSA before optimization ====================================");
System.out.println(ssaModule);
}
if(phase == 0)
ssaModule.saveInlinableDefinitions();
}
- if(SCLCompilerConfiguration.SHOW_SSA_BEFORE_LAMBDA_LIFTING) {
+ if(SCLCompilerConfiguration.SHOW_SSA_BEFORE_LAMBDA_LIFTING && SCLCompilerConfiguration.debugFilter(module.getName())) {
System.out.println("=== SSA before lambda lifting ==================================");
System.out.println(ssaModule);
}
}
public void generateCode() {
- if(SCLCompilerConfiguration.SHOW_FINAL_SSA) {
+ if(SCLCompilerConfiguration.SHOW_FINAL_SSA && SCLCompilerConfiguration.debugFilter(module.getName())) {
System.out.println("=== Final SSA ==================================================");
System.out.println(ssaModule);
}
import org.simantics.scl.compiler.internal.parsing.declarations.DImportJavaAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
-import org.simantics.scl.compiler.internal.parsing.declarations.DModuleHeader;
import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DRulesetAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
import gnu.trove.map.hash.THashMap;
public class DeclarationClassification {
- DModuleHeader moduleHeader;
ArrayList<ImportDeclaration> importsAst = new ArrayList<ImportDeclaration>();
ArrayList<DDataAst> dataTypesAst = new ArrayList<DDataAst>();
ArrayList<DTypeAst> typeAliasesAst = new ArrayList<DTypeAst>();
ArrayList<DEffectAst> effectsAst = new ArrayList<DEffectAst>();
ArrayList<DRuleAst> rulesAst = new ArrayList<DRuleAst>();
ArrayList<DMappingRelationAst> mappingRelationsAst = new ArrayList<DMappingRelationAst>();
+ ArrayList<DRulesetAst> rulesetsAst = new ArrayList<DRulesetAst>();
THashMap<String, DDocumentationAst> valueDocumentation = new THashMap<String, DDocumentationAst>();
THashMap<String, DDocumentationAst> relationDocumentation = new THashMap<String, DDocumentationAst>();
handle((DMappingRelationAst)declaration);
else if(declaration instanceof DRelationAst)
handle((DRelationAst)declaration);
- else if(declaration instanceof DModuleHeader)
- handle((DModuleHeader)declaration);
+ else if(declaration instanceof DRulesetAst)
+ handle((DRulesetAst)declaration);
else
throw new InternalCompilerError("Unknown declaration " + declaration.getClass().getSimpleName());
}
}
}
+ public void handle(DRulesetAst declaration) {
+ if(documentation != null) {
+ declaration.documentation = documentation;
+ documentation = null;
+ }
+ rulesetsAst.add(declaration);
+ }
+
public void handle(DDocumentationAst declaration) {
if(documentation != null) {
errorLog.log(documentation.location, "Invalid documentation string. It precedes another documentation string.");
}
- documentation = declaration;
+ documentation = declaration;
}
public void handle(DAnnotationAst declaration) {
mappingRelationsAst.add(declaration);
}
- public void handle(DModuleHeader declaration) {
- moduleHeader = declaration;
- }
-
public void addValueDocumentation(String valueName, DDocumentationAst documentation) {
DDocumentationAst oldDoc = valueDocumentation.put(valueName, documentation);
if(oldDoc != null) {
import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.common.datatypes.Constructor;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.constants.JavaTypeInstanceConstructor;
import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EPreCHRRulesetConstructor;
import org.simantics.scl.compiler.elaboration.expressions.EVar;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
import org.simantics.scl.compiler.elaboration.modules.TypeClassMethod;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.query.Query;
import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
import org.simantics.scl.compiler.elaboration.relations.ConcreteRelation;
import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DRulesetAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
public void addTypesToEnvironment(
ArrayList<DDataAst> dataTypesAst,
ArrayList<DTypeAst> typeAliasesAst,
- ArrayList<DEffectAst> effectsAst) {
+ ArrayList<DEffectAst> effectsAst,
+ ArrayList<DRulesetAst> rulesetsAst) {
for(DDataAst dataType : dataTypesAst) {
dataType.parameterKinds = new Kind[dataType.parameters.length];
Kind constructorKind = Kinds.STAR;
NameExistenceChecks.checkIfTypeExists(errorLog,
dataType.location, importedEnvironment, dataType.name);
- if(module.addTypeDescriptor(dataType.name, typeConstructor))
- errorLog.log(dataType.location, "Type "+dataType.name+" has already been defined in this module.");
+ addTypeDescriptor(dataType.location, dataType.name, typeConstructor);
dataType.typeConstructor = typeConstructor;
}
TypeAlias alias = new TypeAlias(Types.con(moduleName, typeAlias.name), typeAlias.parameters.length);
NameExistenceChecks.checkIfTypeExists(errorLog,
typeAlias.location, importedEnvironment, typeAlias.name);
- if(module.addTypeDescriptor(typeAlias.name, alias)) {
- errorLog.log(typeAlias.location, "Type alias "+typeAlias.name+" has already been defined in this module.");
- }
+ addTypeDescriptor(typeAlias.location, typeAlias.name, alias);
}
for(DEffectAst effect : effectsAst) {
TypeDesc.forClass(effect.threadLocalType)
));
if(module.addEffectConstructor(effect.name, effectConstructor))
- errorLog.log(effect.location, "Type "+effect.name+" has already been defined in this module.");
- }
+ errorLog.log(effect.location, "Effect "+effect.name+" has already been defined in this module.");
+ }
+ for(DRulesetAst ruleset : rulesetsAst) {
+ ruleset.type = Types.con(moduleName, ruleset.name);
+ ruleset.className = compilationContext.namingPolicy.getDataTypeClassName(ruleset.name);
+ StandardTypeConstructor typeConstructor = new StandardTypeConstructor(ruleset.type, Kinds.STAR,
+ TypeDesc.forClass(ruleset.className), ruleset.documentation == null ? null : ruleset.documentation.documentation);
+ typeConstructor.external = true;
+ addTypeDescriptor(ruleset.location, ruleset.name, typeConstructor);
+ }
javaTypeTranslator = new JavaTypeTranslator(compilationContext.environment);
compilationContext.javaTypeTranslator = javaTypeTranslator;
}
+
+ private void addTypeDescriptor(long location, String name, TypeDescriptor typeDescriptor) {
+ if(module.addTypeDescriptor(name, typeDescriptor))
+ errorLog.log(location, "Type "+name+" has already been defined in this module.");
+ }
private static final int[] EMPTY_INT_ARRAY = new int[0];
}
}
+ public void processRulesets(ArrayList<DRulesetAst> rulesetsAst) {
+ for(DRulesetAst ruleset : rulesetsAst) {
+ String constructorName = "create" + ruleset.name;
+ supplementedTypeAnnotations.add(new SupplementedValueType(ruleset.location, constructorName, Types.functionE(Types.PUNIT, Types.PROC, ruleset.type)));
+ try {
+ valueDefinitionsAst.add(new DValueAst(new EVar(constructorName), new EPreCHRRulesetConstructor(ruleset)));
+ } catch (NotPatternException e) {
+ throw new InternalCompilerError(ruleset.location, e);
+ }
+ }
+ }
+
/**
* Convert a java class method into a {@link CallJava} instance.
* Compilation errors are logged for failures in finding the named class or in accessing the method.
import java.util.Arrays;
import java.util.function.Consumer;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
return base.getRelation(name);
}
+ @Override
+ public CHRRuleset getRuleset(String name) throws AmbiguousNameException {
+ CHRRuleset ruleset = module.getRuleset(name);
+ if(ruleset != null)
+ return ruleset;
+ return base.getRuleset(name);
+ }
+
@Override
public SCLEntityType getEntityType(String name)
throws AmbiguousNameException {
try {
SCLParserImpl parser = new SCLParserImpl(sourceReader);
parser.setParserOptions(SCLParserOptions.MODULE_DEFAULT);
+ parser.setCompilationContext(compilationContext);
if(!parser.isEmpty())
for(DeclarationAst declaration : (ArrayList<DeclarationAst>)parser.parseModule())
declarations.handle(declaration);
String moduleName) {
try {
if(hasErrors()) return;
- compilationContext.header = ModuleHeader.process(compilationContext.errorLog, declarations.moduleHeader);
Elaboration elaboration = new Elaboration(compilationContext,
timer,
localEnvironmentFactory,
elaboration.addTypesToEnvironment(
declarations.dataTypesAst,
declarations.typeAliasesAst,
- declarations.effectsAst);
+ declarations.effectsAst,
+ declarations.rulesetsAst);
if(hasErrors()) return;
elaboration.processTypeAliases(declarations.typeAliasesAst);
if(hasErrors()) return;
if(hasErrors()) return;
elaboration.processJavaMethods(declarations.javaMethodDeclarations);
if(hasErrors()) return;
+ elaboration.processRulesets(declarations.rulesetsAst);
+ if(hasErrors()) return;
elaboration.addDataTypesToEnvironment();
elaboration.addTypeClassesToEnvironment();
elaboration.preprocessValueDefinitions(declarations.typeAnnotationsAst);
// Constructor
{
- MethodBuilderBase mb = classFile.addConstructor(Opcodes.ACC_PUBLIC, Constants.EMPTY_TYPEDESC_ARRAY);
+ MethodBuilderBase mb = classFile.addConstructorBase(Opcodes.ACC_PUBLIC, Constants.EMPTY_TYPEDESC_ARRAY);
mb.loadThis();
mb.loadConstant(arity);
mb.invokeConstructor(MethodBuilderBase.getClassName(Constants.FUNCTION_N_IMPL), new TypeDesc[] {TypeDesc.INT});
import java.util.ArrayList;
+import org.junit.runners.ParentRunner;
import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.elaboration.chr.plan.CHRSearchPlan;
import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
public Variable[] existentialVariables;
// Analysis
- public int firstPriorityExecuted;
+ //public int firstPriorityExecuted;
public int lastPriorityExecuted;
// Plans
private void addPlan(CHRSearchPlan plan) {
plans.add(plan);
- plan.constraint.minimumPriority = Math.min(plan.constraint.minimumPriority, priority);
}
public String toString() {
import org.simantics.scl.compiler.constants.IntegerConstant;
import org.simantics.scl.compiler.constants.JavaConstructor;
import org.simantics.scl.compiler.constants.JavaMethod;
+import org.simantics.scl.compiler.constants.NoRepConstant;
import org.simantics.scl.compiler.constants.generic.CallJava;
import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
import org.simantics.scl.compiler.constants.generic.MethodRef.SetFieldRef;
+import org.simantics.scl.compiler.elaboration.chr.analysis.CHRConstraintGGInfo;
import org.simantics.scl.compiler.elaboration.chr.analysis.UsageAnalysis;
import org.simantics.scl.compiler.elaboration.chr.plan.CHRSearchPlan;
import org.simantics.scl.compiler.elaboration.chr.plan.PlanRealizer;
import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
+import org.simantics.scl.compiler.environment.AmbiguousNameException;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerationConstants;
import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator;
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
import org.simantics.scl.compiler.internal.parsing.Symbol;
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.runtime.chr.CHRContext;
+import gnu.trove.map.hash.THashMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import gnu.trove.set.hash.THashSet;
import gnu.trove.set.hash.TIntHashSet;
public ArrayList<CHRConstraint> constraints = new ArrayList<CHRConstraint>();
public ArrayList<CHRRule> rules = new ArrayList<CHRRule>();
+ public ArrayList<IncludeStatement> includes = new ArrayList<IncludeStatement>();
+ public THashMap<CHRConstraint, IncludeStatement> constraintSourceMap = new THashMap<CHRConstraint, IncludeStatement>();
+ public THashMap<CHRConstraint, CHRConstraintGGInfo> activeConstraintGGInfo = new THashMap<CHRConstraint, CHRConstraintGGInfo>(); // contains also imported constraints
+ public THashMap<IncludeStatement, ArrayList<CHRConstraint>> inverseActiveConstraintSourceMap = new THashMap<IncludeStatement, ArrayList<CHRConstraint>>();
+
+ public boolean extensible;
public CHRConstraint initConstraint;
public int priorityCount;
- public String runtimeRulesetName;
+ public int initialPriorityNumber = 0;
+
+ public String runtimeRulesetClassName;
public TCon runtimeRulesetType;
public BoundVar runtimeRulesetVariable;
public TypeDesc runtimeRulesetTypeDesc;
private CompilationContext cachedContext;
// For code generation
- public BoundVar this_;
- public BoundVar[] parameters;
- public TypeDesc[] parameterTypeDescs;
+ public CHRRulesetObject rulesetObject;
+ public SSAFunction initializer;
+ public SSAFunction deinitializer;
public CHRRuleset() {
initConstraint = new CHRConstraint(Locations.NO_LOCATION, INIT_CONSTRAINT, Type.EMPTY_ARRAY);
}
public void resolve(TranslationContext context) {
+ boolean failedIncludes = false;
+ for(IncludeStatement include : includes) {
+ try {
+ include.ruleset = context.resolveRuleset(include.name.text);
+ if(include.ruleset == null) {
+ failedIncludes = true;
+ context.getErrorLog().log(include.name.location, "Couldn't resolve ruleset " + include.name + ".");
+ continue;
+ }
+ include.value = include.value.resolve(context);
+ for(CHRConstraint constraint : include.ruleset.constraints) {
+ context.newCHRConstraint(constraint.name, constraint);
+ constraintSourceMap.put(constraint, include);
+ }
+ } catch (AmbiguousNameException e) {
+ failedIncludes = true;
+ context.getErrorLog().log(include.name.location, e.getMessage());
+ }
+ }
+ if(failedIncludes)
+ return;
for(CHRConstraint constraint : constraints)
context.newCHRConstraint(constraint.name, constraint);
priorityCount = 0;
}
public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ for(IncludeStatement include : includes)
+ include.value.collectRefs(allRefs, refs);
for(CHRRule rule : rules)
rule.collectRefs(allRefs, refs);
}
public void checkType(TypingContext context) {
+ for(IncludeStatement include : includes)
+ include.value = include.value.checkType(context, include.ruleset.runtimeRulesetType);
for(CHRRule rule : rules)
rule.checkType(context);
}
public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+ for(IncludeStatement include : includes)
+ include.value.collectVars(allVars, vars);
for(CHRRule rule : rules)
rule.collectVars(allVars, vars);
}
public void forVariables(VariableProcedure procedure) {
+ for(IncludeStatement include : includes)
+ include.value.forVariables(procedure);
for(CHRRule rule : rules)
rule.forVariables(procedure);
}
public void collectFreeVariables(THashSet<Variable> vars) {
+ for(IncludeStatement include : includes)
+ include.value.collectFreeVariables(vars);
for(CHRRule rule : rules)
rule.collectFreeVariables(vars);
}
rule.setLocationDeep(loc);
}
}
+
+ public int getMinimumPriority(CHRConstraint constraint) {
+ CHRConstraintGGInfo info = activeConstraintGGInfo.get(constraint);
+ if(info == null)
+ return Integer.MAX_VALUE;
+ else
+ return info.minimumPriority;
+ }
+
+ public int getAndUpdateNextPriority(CHRConstraint constraint, int nextPriority) {
+ CHRConstraintGGInfo info = activeConstraintGGInfo.get(constraint);
+ if(info == null)
+ return Integer.MAX_VALUE;
+ else {
+ int result = info.nextPriority;
+ info.nextPriority = nextPriority;
+ return result;
+ }
+ }
public void compile(SimplificationContext context) {
initializeCodeGeneration(context.getCompilationContext());
+ if(extensible)
+ applyExtensibleDefaults();
UsageAnalysis.analyzeUsage(this);
- for(CHRRule rule : rules)
+ for(CHRRule rule : rules) {
rule.compile(context.getCompilationContext(), initConstraint);
+ for(CHRSearchPlan plan : rule.plans) {
+ CHRConstraint constraint = plan.constraint;
+ if(!activeConstraintGGInfo.containsKey(constraint)) {
+ activeConstraintGGInfo.put(constraint, new CHRConstraintGGInfo(rule.priority));
+ IncludeStatement include = constraintSourceMap.get(constraint);
+ if(include != null) {
+ ArrayList<CHRConstraint> list = inverseActiveConstraintSourceMap.get(include);
+ if(list == null) {
+ list = new ArrayList<CHRConstraint>(4);
+ inverseActiveConstraintSourceMap.put(include, list);
+ }
+ list.add(constraint);
+ }
+ }
+ }
+ }
// remove init constraint if it is not useful
- if(initConstraint.minimumPriority == Integer.MAX_VALUE) {
+ if(getMinimumPriority(initConstraint) == Integer.MAX_VALUE) {
constraints.remove(0);
initConstraint = null;
}
}
+ private void applyExtensibleDefaults() {
+ for(CHRConstraint constraint : constraints) {
+ // FIXME Too much indexing!!!
+ int max = 1 << constraint.parameterTypes.length;
+ for(int i=0;i<max;++i)
+ constraint.getOrCreateIndex(cachedContext, i);
+ /*
+ constraint.getOrCreateIndex(cachedContext, 0);
+ if(constraint.parameterTypes.length > 0)
+ constraint.getOrCreateIndex(cachedContext, 1);*/
+ }
+ }
+
public void simplify(SimplificationContext context) {
+ for(IncludeStatement include : includes)
+ include.value = include.value.simplify(context);
for(CHRRule rule : rules)
rule.simplify(context);
}
+ public void setRulesetType(TCon type, String className) {
+ this.runtimeRulesetType = type;
+ this.runtimeRulesetClassName = className;
+ }
+
public void initializeCodeGeneration(CompilationContext context) {
cachedContext = context; // FIXME remove
- String suffix = context.namingPolicy.getFreshClosureClassNameSuffix();
- runtimeRulesetType = Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix);
- runtimeRulesetName = context.namingPolicy.getModuleClassName() + suffix;
- runtimeRulesetTypeDesc = TypeDesc.forClass(runtimeRulesetName);
+ boolean createTypeDesc = false;
+ if(runtimeRulesetType == null) {
+ String suffix = context.namingPolicy.getFreshClosureClassNameSuffix();
+ setRulesetType(Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix), context.namingPolicy.getModuleClassName() + suffix);
+ createTypeDesc = true;
+ }
+ runtimeRulesetTypeDesc = TypeDesc.forClass(runtimeRulesetClassName);
runtimeRulesetVariable = new BoundVar(runtimeRulesetType);
for(CHRConstraint constraint : constraints)
constraint.initializeCodeGeneration(context, this);
null, new FieldRef(CHRCodeGenerationConstants.CHRContext_name, "currentId", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null);
writeCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {Types.CHRContext, Types.INTEGER},
null, new SetFieldRef(CHRCodeGenerationConstants.CHRContext_name, "currentId", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null);
- if(context.module != null) // for unit testing
+ if(createTypeDesc && context.module != null) // for unit testing
context.module.addTypeDescriptor(runtimeRulesetType.name, new StandardTypeConstructor(runtimeRulesetType, TVar.EMPTY_ARRAY, runtimeRulesetTypeDesc));
}
public static final Constant ACTIVATE = new JavaMethod(true, CHRCodeGenerationConstants.CHRContext_name, "activate", Types.PROC, Types.UNIT, Types.CHRContext, Types.INTEGER);
private static final Constant CREATE_CHR_CONTEXT = new JavaConstructor("org/simantics/scl/runtime/chr/CHRContext", Types.PROC, Types.CHRContext);
- public void generateCode(CodeWriter w) {
+ public IVal generateCode(CodeWriter w) {
+ for(IncludeStatement include : includes) {
+ include.storeVar = include.value.toVal(cachedContext.environment, w);
+ initialPriorityNumber = Math.max(initialPriorityNumber, include.ruleset.initialPriorityNumber + include.ruleset.priorityCount);
+ }
CHRRulesetObject object = new CHRRulesetObject(runtimeRulesetVariable, this);
w.defineObject(object);
for(CHRRule rule : rules) {
methodWriter.return_(BooleanConstant.TRUE);
}
}
+ if(!includes.isEmpty()) {
+ {
+ CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {Types.CHRContext});
+ initializer = methodWriter.getFunction();
+ for(IncludeStatement include : includes) {
+ methodWriter.apply(include.location,
+ new JavaMethod(true, runtimeRulesetClassName, "register", Types.PROC, Types.UNIT, new Type[] {runtimeRulesetType, Types.CHRContext, include.ruleset.runtimeRulesetType}),
+ object.getTarget(), methodWriter.getParameters()[0], include.storeVar);
+ }
+ methodWriter.return_(NoRepConstant.UNIT);
+ }
+ {
+ CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {Types.CHRContext});
+ deinitializer = methodWriter.getFunction();
+ for(IncludeStatement include : includes) {
+ methodWriter.apply(include.location,
+ new JavaMethod(true, runtimeRulesetClassName, "unregister", Types.PROC, Types.UNIT, new Type[] {runtimeRulesetType, Types.CHRContext, include.ruleset.runtimeRulesetType}),
+ object.getTarget(), methodWriter.getParameters()[0], include.storeVar);
+ }
+ methodWriter.return_(NoRepConstant.UNIT);
+ }
+ }
if(initConstraint != null) {
IVal chrContext = w.apply(location, CREATE_CHR_CONTEXT);
+ if(initializer != null) {
+ w.apply(location,
+ new JavaMethod(true, runtimeRulesetClassName, "initialize", Types.PROC, Types.UNIT, new Type[] {runtimeRulesetType, Types.CHRContext}),
+ object.getTarget(), chrContext);
+ }
IVal initFact = w.apply(location, initConstraint.constructor, IntegerConstant.ZERO);
w.apply(location, initConstraint.addProcedure, runtimeRulesetVariable, chrContext, initFact);
w.apply(location, ACTIVATE, chrContext, new IntegerConstant(Integer.MAX_VALUE));
+ if(deinitializer != null) {
+ w.apply(location,
+ new JavaMethod(true, runtimeRulesetClassName, "deinitialize", Types.PROC, Types.UNIT, new Type[] {runtimeRulesetType, Types.CHRContext}),
+ object.getTarget(), chrContext);
+ }
}
+ return runtimeRulesetVariable;
}
public void collectEffects(THashSet<Type> effects) {
package org.simantics.scl.compiler.elaboration.chr;
+import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.constants.JavaConstructor;
import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator;
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject;
+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.ModuleBuilder;
import org.simantics.scl.compiler.types.Types;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
public class CHRRulesetObject extends SSAObject {
CHRRuleset ruleset;
+ public BoundVar this_;
+ public BoundVar[] parameters;
+ public TObjectIntHashMap<BoundVar> parameterIndexMap;
+ public TypeDesc[] parameterTypeDescs;
+
public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) {
super(ruleset.runtimeRulesetType);
this.setTarget(target);
@Override
public Constant liftClosure(BoundVar newTarget, BoundVar[] parameters) {
- ruleset.this_ = newTarget;
- ruleset.parameters = parameters;
- return new JavaConstructor(ruleset.runtimeRulesetName, Types.PROC, ruleset.runtimeRulesetType, Types.getTypes(parameters));
+ ruleset.rulesetObject = this;
+ this.this_ = newTarget;
+ this.parameters = parameters;
+ this.parameterIndexMap = new TObjectIntHashMap<>(parameters.length);
+ for(int i=0;i<parameters.length;++i)
+ this.parameterIndexMap.put(parameters[i], i);
+ return new JavaConstructor(ruleset.runtimeRulesetClassName, Types.PROC, ruleset.runtimeRulesetType, Types.getTypes(parameters));
}
@Override
public void generateCode(ModuleBuilder moduleBuilder) {
CHRRuntimeRulesetCodeGenerator.generateRuntimeRuleset(moduleBuilder, ruleset);
}
+
+ @FunctionalInterface
+ public interface ParameterDefiner {
+ public void defineParameter(int index, BoundVar var);
+ }
+
+ public void realizeMethod(MethodBuilder mb, ParameterDefiner loader, SSAFunction function, LocalVariable this_, LocalVariable ... callParameters) {
+ mb.setLocalVariable(this.this_, this_);
+ BoundVar[] functionParameters = function.getParameters();
+ if(functionParameters.length != callParameters.length)
+ throw new InternalCompilerError();
+ for(int i=0;i<callParameters.length;++i)
+ mb.setLocalVariable(functionParameters[i], callParameters[i]);
+
+ // Set closure parameters
+ TIntHashSet usedParameterIndices = new TIntHashSet(parameters.length);
+ function.forValRefs(valRef -> {
+ Val binding = valRef.getBinding();
+ if(parameterIndexMap.containsKey(binding))
+ usedParameterIndices.add(parameterIndexMap.get((BoundVar)binding));
+ });
+ usedParameterIndices.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int i) {
+ loader.defineParameter(i, parameters[i]);
+ return true;
+ }
+ });
+
+ // Generate code
+ function.markGenerateOnFly();
+ function.generateCodeWithAlreadyPreparedParameters(mb);
+ }
}
--- /dev/null
+package org.simantics.scl.compiler.elaboration.chr.analysis;
+
+public class CHRConstraintGGInfo {
+ public int minimumPriority;
+ public int nextPriority = Integer.MAX_VALUE;
+
+ public CHRConstraintGGInfo(int minimumPriority) {
+ this.minimumPriority = minimumPriority;
+ }
+}
public class UsageAnalysis {
public static void analyzeUsage(CHRRuleset ruleset) {
THashMap<CHRConstraint,ArrayList<CHRRule>> headConstraintMap = createHeadConstraintMap(ruleset);
- calculateFirstPriorities(ruleset, headConstraintMap);
+ //calculateFirstPriorities(ruleset, headConstraintMap);
calculateLastPriorities(ruleset, headConstraintMap);
- for(CHRRule rule : ruleset.rules)
- determinePassiveLiterals(rule);
+ if(!ruleset.extensible)
+ for(CHRRule rule : ruleset.rules)
+ determinePassiveLiterals(rule);
//printPriorities(ruleset);
}
-
+ /*
private static void calculateFirstPriorities(CHRRuleset ruleset,
THashMap<CHRConstraint, ArrayList<CHRRule>> headConstraintMap) {
for(CHRRule rule : ruleset.rules)
int constraintPriority = constraint.firstPriorityAdded;
if(constraintPriority == Integer.MAX_VALUE)
return;
- result = Math.max(result, constraint.firstPriorityAdded);
+ result = Math.max(result, constraintPriority);
}
rule.firstPriorityExecuted = result;
for(CHRLiteral literal : rule.head.literals)
if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) {
CHRConstraint constraint = (CHRConstraint)literal.relation;
- if(constraint.firstPriorityRemoved != Integer.MAX_VALUE)
- continue;
- constraint.firstPriorityRemoved = result;
+ if(constraint.firstPriorityRemoved == Integer.MAX_VALUE)
+ constraint.firstPriorityRemoved = result;
}
for(CHRLiteral literal : rule.body.literals)
if(literal.relation instanceof CHRConstraint) {
continue;
for(CHRRule lowerPriorityRule : list)
if(lowerPriorityRule.priority < rule.priority)
+ // We know here that previous call to lowerPriorityRule "failed",
+ // because constraint.firstPriorityAdded was previously Integer.MAX_VALUE
calculateFirstPriority(headConstraintMap, lowerPriorityRule);
}
}
-
+ */
private static void calculateLastPriorities(CHRRuleset ruleset,
THashMap<CHRConstraint, ArrayList<CHRRule>> headConstraintMap) {
for(CHRRule rule : ruleset.rules)
rule.lastPriorityExecuted = Integer.MIN_VALUE;
- for(CHRConstraint constraint : ruleset.constraints) {
+ for(CHRConstraint constraint : headConstraintMap.keySet()) {
constraint.lastPriorityAdded = Integer.MIN_VALUE;
constraint.lastPriorityRemoved = Integer.MIN_VALUE;
}
for(CHRLiteral literal : rule.head.literals)
if(literal.killAfterMatch && literal.relation instanceof CHRConstraint) {
CHRConstraint constraint = (CHRConstraint)literal.relation;
- if(constraint.lastPriorityRemoved != Integer.MIN_VALUE)
- continue;
- constraint.lastPriorityRemoved = priority;
+ if(constraint.lastPriorityRemoved == Integer.MIN_VALUE)
+ constraint.lastPriorityRemoved = priority;
}
for(CHRLiteral literal : rule.body.literals)
if(literal.relation instanceof CHRConstraint) {
return map;
}
- private static void printPriorities(CHRRuleset ruleset) {
+ /*private static void printPriorities(CHRRuleset ruleset) {
System.out.println("-------------------------------");
for(CHRConstraint constraint : ruleset.constraints) {
System.out.print(" [" + constraint.firstPriorityAdded + ".." + constraint.lastPriorityAdded + "]");
System.out.print(" [" + rule.firstPriorityExecuted + ".." + rule.lastPriorityExecuted + "] ");
System.out.println(rule);
}
- }
+ }*/
private static void determinePassiveLiterals(CHRRule rule) {
for(CHRLiteral literal : rule.head.literals) {
for(int i=0;i<parameters.length;++i)
parameterVars[i+1] = parameters[i].toVal(context.environment, w);
IVal newFact = w.apply(location, constraint.constructor, parameterVars);
- w.apply(location, constraint.addProcedure, planContext.storeVar, planContext.contextVar, newFact);
+ w.apply(location, constraint.addProcedure, planContext.getStoreVar(constraint), planContext.contextVar, newFact);
planContext.nextOp(w);
}
IVal fact = body.getParameters()[0];
ArrayList<IVal> parameters = new ArrayList<IVal>(expressions.length+1);
- parameters.add(planContext.storeVar);
+ parameters.add(planContext.getStoreVar(constraint));
for(int i=0;i<expressions.length;++i)
if(((boundMask>>i)&1)==1)
parameters.add(expressions[i].toVal(context.environment, w));
import org.simantics.scl.compiler.constants.singletons.ListElement;
import org.simantics.scl.compiler.constants.singletons.ListLength;
import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
import org.simantics.scl.compiler.elaboration.java.EqualsFunction;
import org.simantics.scl.compiler.internal.codegen.continuations.Branch;
import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
public abstract class PlanContext {
public CompilationContext context;
public CHRRuleset ruleset;
- public IVal storeVar;
+ public IVal mainStoreVar;
public IVal contextVar;
public ArrayList<PartnerFact> partnerFacts = new ArrayList<PartnerFact>();
public IVal currentId;
- public PlanContext(CompilationContext context, CHRRuleset ruleset, IVal storeVar, IVal contextVar) {
+ public PlanContext(CompilationContext context, CHRRuleset ruleset, IVal mainStoreVar, IVal contextVar) {
this.context = context;
this.ruleset = ruleset;
- this.storeVar = storeVar;
+ this.mainStoreVar = mainStoreVar;
this.contextVar = contextVar;
}
w.continueAs(end);
}
+
+ public IVal getStoreVar(CHRConstraint constraint) {
+ IncludeStatement includeStatement = ruleset.constraintSourceMap.get(constraint);
+ if(includeStatement != null)
+ return includeStatement.storeVar;
+ else
+ return mainStoreVar;
+ }
}
if(planContext.currentId != null) {
w.apply(location, planContext.ruleset.writeCurrentId, planContext.contextVar, planContext.currentId);
planContext.currentId = null;
- w.apply(location, CHRRuleset.ACTIVATE, planContext.contextVar, new IntegerConstant(priority));
+ w.apply(location, CHRRuleset.ACTIVATE, planContext.contextVar, new IntegerConstant(priority+planContext.ruleset.initialPriorityNumber));
}
for(PartnerFact activeFact : planContext.partnerFacts) {
if(activeFact.killAfterMatch) {
public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {
for(PartnerFact activeFact : planContext.partnerFacts) {
if(activeFact.killAfterMatch)
- w.apply(location, activeFact.constraint.removeProcedure, planContext.storeVar, activeFact.factVar);
+ w.apply(location, activeFact.constraint.removeProcedure, planContext.getStoreVar(activeFact.constraint), activeFact.factVar);
}
planContext.nextOp(w);
}
public boolean implicitlyDeclared;
// Analysis
- public int firstPriorityAdded;
+ //public int firstPriorityAdded;
public int lastPriorityAdded;
- public int firstPriorityRemoved;
+ //public int firstPriorityRemoved;
public int lastPriorityRemoved;
// Transient info
public Constant addProcedure;
public Constant removeProcedure;
- public TIntObjectHashMap<IndexInfo> indices;
+ public String nextContainerFieldName;
- // Query plans
- public int minimumPriority = Integer.MAX_VALUE;
- public int nextPriority = Integer.MAX_VALUE; // used in code generation
+ public TIntObjectHashMap<IndexInfo> indices;
public static class IndexInfo {
public final int indexMask;
JavaTypeTranslator jtt = context.javaTypeTranslator;
this.parentRuleset = parentRuleset;
- this.factClassName = parentRuleset.runtimeRulesetName + "$" + name;
+ this.factClassName = parentRuleset.runtimeRulesetClassName + "$" + name;
TCon factTypeConstructor = Types.con(parentRuleset.runtimeRulesetType.module, parentRuleset.runtimeRulesetType.name + "$" + name);
this.factType = Types.apply(factTypeConstructor, TVar.EMPTY_ARRAY);
this.factTypeDesc = TypeDesc.forClass(factClassName);
if(context.module != null) // for unit testing
context.module.addTypeDescriptor(factTypeConstructor.name, new StandardTypeConstructor(factTypeConstructor, TVar.EMPTY_ARRAY, factTypeDesc));
+
+ // next container
+ if(parentRuleset.extensible) {
+ nextContainerFieldName = CHRCodeGenerationConstants.nextContainerName(name);
+ }
}
@Override
Constant accessIndex;
if(indexMask == 0) {
accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.runtimeRulesetType},
- null, new FieldRef(parentRuleset.runtimeRulesetName, name + "$" + indexName, factTypeDesc), null);
+ null, new FieldRef(parentRuleset.runtimeRulesetClassName, name + "$" + indexName, factTypeDesc), null);
}
else {
Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
- accessIndex = new JavaMethod(true, parentRuleset.runtimeRulesetName, name + "$" + indexName, Types.PROC, factType, keyTypes);
+ accessIndex = new JavaMethod(true, parentRuleset.runtimeRulesetClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
}
return new IndexInfo(
indexMask,
);
}
- public IVal fetchFromIndex(CompilationContext context, int boundMask) {
+ public IndexInfo getOrCreateIndex(CompilationContext context, int boundMask) {
IndexInfo indexInfo = indices.get(boundMask);
if(indexInfo == null) {
indexInfo = createIndexInfo(context, boundMask);
indices.put(boundMask, indexInfo);
}
- return indexInfo.firstFact;
+ return indexInfo;
+ }
+
+ public IVal fetchFromIndex(CompilationContext context, int boundMask) {
+ return getOrCreateIndex(context, boundMask).firstFact;
}
public Constant nextElement(CompilationContext context, int boundMask) {
indexInfo = createIndexInfo(context, boundMask);
indices.put(boundMask, indexInfo);
}
- return indexInfo.nextFact;
+ return getOrCreateIndex(context, boundMask).nextFact;
}
import org.simantics.scl.compiler.common.precedence.Associativity;
import org.simantics.scl.compiler.common.precedence.Precedence;
import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
import org.simantics.scl.compiler.elaboration.expressions.Case;
import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous;
public SCLValue getValue(Name name) {
return environment.getValue(name);
}
+
+ public CHRRuleset resolveRuleset(String name) throws AmbiguousNameException {
+ return Environments.getRuleset(environment, name);
+ }
}
errorLog.log(loc, "Expected a type with kind " + expectedKind + " but got " + provided + ".");
}
}
+
+ public CompilationContext getCompilationContext() {
+ return compilationContext;
+ }
}
package org.simantics.scl.compiler.elaboration.expressions;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
public class EBlock extends ASTExpression {
- LinkedList<Statement> statements = new LinkedList<Statement>();
+ ArrayList<Statement> statements = new ArrayList<Statement>();
boolean monadic;
public EBlock() {
this.monadic = monadic;
}
- public LinkedList<Statement> getStatements() {
+ public ArrayList<Statement> getStatements() {
return statements;
}
+
+ public Statement getFirst() {
+ return statements.get(0);
+ }
+
+ public Statement getLast() {
+ return statements.get(statements.size()-1);
+ }
@Override
public Expression resolve(TranslationContext context) {
in = extractRules(i, endId, in);
break;
case CHR:
- in = extractCHRRules(context, i, endId, in);
+ in = new ECHRRuleset(extractCHRRules(context, i, endId), in);
break;
}
}
return new EPreRuleset(statements.subList(begin, end).toArray(new RuleStatement[end-begin]), in);
}
- private Expression extractCHRRules(TranslationContext context, int begin, int end, Expression in) {
+ private CHRRuleset extractCHRRules(TranslationContext context, int begin, int end) {
CHRRuleset ruleset = new CHRRuleset();
ruleset.location = Locations.combine(statements.get(begin).location, statements.get(end-1).location);
for(int i=begin;i<end;++i) {
ruleset.rules.add(CHRTranslation.convertCHRStatement(context, (CHRStatement)statement));
else if(statement instanceof ConstraintStatement)
ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
+ else if(statement instanceof IncludeStatement)
+ ruleset.includes.add((IncludeStatement)statement);
else
- throw new InternalCompilerError("Invalid CHR statement.");
+ context.getErrorLog().log(statement.location, "Invalid CHR statement.");
}
- return new ECHRRuleset(ruleset, in);
+ return ruleset;
}
+ public CHRRuleset extractCHRRules(TranslationContext context) {
+ return extractCHRRules(context, 0, statements.size());
+ }
+
@SuppressWarnings("unchecked")
private Expression extractLet(int begin, int end, Expression in) {
return new EPreLet((List<LetStatement>)(List<?>)statements.subList(begin, end), in);
public int getSyntacticFunctionArity() {
if(monadic)
return 0;
- Statement lastStatement = statements.getLast();
+ Statement lastStatement = statements.get(statements.size()-1);
if(!(lastStatement instanceof GuardStatement))
return 0;
return ((GuardStatement)lastStatement).value.getSyntacticFunctionArity();
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
+import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.interpreted.IExpression;
+import org.simantics.scl.compiler.top.ExpressionInterpretationContext;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class ECHRRulesetConstructor extends Expression {
+ CHRRuleset ruleset;
+
+ public ECHRRulesetConstructor(CHRRuleset ruleset) {
+ this.ruleset = ruleset;
+ }
+
+ @Override
+ public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+ ruleset.collectRefs(allRefs, refs);
+ }
+ @Override
+ public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+ ruleset.collectVars(allVars, vars);
+ }
+ @Override
+ public void forVariables(VariableProcedure procedure) {
+ ruleset.forVariables(procedure);
+ }
+ @Override
+ protected void updateType() throws MatchException {
+ throw new InternalCompilerError("Type of ECHRRulesetConstructor should be already given.");
+ }
+ @Override
+ public IVal toVal(Environment env, CodeWriter w) {
+ return ruleset.generateCode(w);
+ }
+ @Override
+ public void collectFreeVariables(THashSet<Variable> vars) {
+ ruleset.collectFreeVariables(vars);
+ }
+ @Override
+ public Expression resolve(TranslationContext context) {
+ context.pushFrame();
+ context.pushCHRConstraintFrame();
+ ruleset.resolve(context);
+ context.popCHRConstraintFrame(ruleset.constraints);
+ context.popFrame();
+ return this;
+ }
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ this.location = loc;
+ ruleset.setLocationDeep(loc);
+ }
+ }
+ @Override
+ public Expression decorate(ExpressionDecorator decorator) {
+ return this;
+ }
+ @Override
+ public void collectEffects(THashSet<Type> effects) {
+ ruleset.collectEffects(effects);
+ }
+ @Override
+ public void accept(ExpressionVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public Expression inferType(TypingContext context) {
+ ruleset.checkType(context);
+ return this;
+ }
+
+ @Override
+ public Expression simplify(SimplificationContext context) {
+ ruleset.simplify(context);
+ ruleset.compile(context);
+ return this;
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return transformer.transform(this);
+ }
+
+ @Override
+ public IExpression toIExpression(ExpressionInterpretationContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+}
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions;
+
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.parsing.declarations.DRulesetAst;
+
+public class EPreCHRRulesetConstructor extends ASTExpression {
+ DRulesetAst rulesetAst;
+
+ public EPreCHRRulesetConstructor(DRulesetAst rulesetAst) {
+ this.rulesetAst = rulesetAst;
+ this.location = rulesetAst.location;
+ }
+
+ @Override
+ public Expression resolve(TranslationContext context) {
+ CHRRuleset ruleset = rulesetAst.block.extractCHRRules(context);
+ ruleset.setLocationDeep(rulesetAst.location);
+ ruleset.setRulesetType(rulesetAst.type, rulesetAst.className);
+ ruleset.extensible = true;
+ context.getCompilationContext().module.addRuleset(rulesetAst.name, ruleset);
+ ECHRRulesetConstructor result = new ECHRRulesetConstructor(ruleset);
+ result.resolve(context);
+ result.setType(rulesetAst.type);
+ return result;
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ rulesetAst.block.setLocationDeep(loc);
+ location = loc;
+ }
+ }
+
+ @Override
+ public Expression accept(ExpressionTransformer transformer) {
+ return this;
+ }
+}
Expression transform(EBind expression);
Expression transform(EBlock expression);
Expression transform(ECHRRuleset expression);
+ Expression transform(ECHRRulesetConstructor expression);
Expression transform(EConstant expression);
Expression transform(ECoveringBranchPoint expression);
Expression transform(EEnforce expression);
void visit(EBinary expression);
void visit(EBind expression);
void visit(EBlock expression);
- void visit(ECHRRuleset echrRuleset);
+ void visit(ECHRRuleset expression);
+ void visit(ECHRRulesetConstructor expression);
void visit(EConstant expression);
void visit(ECoveringBranchPoint expression);
void visit(EEnforce expression);
import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
import org.simantics.scl.compiler.elaboration.chr.CHRRule;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.equation.EqBasic;
import org.simantics.scl.compiler.elaboration.equation.EqGuard;
import org.simantics.scl.compiler.elaboration.equation.Equation;
import org.simantics.scl.compiler.elaboration.expressions.accessor.ExpressionAccessor;
import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
}
@Override
- public Expression transform(ECHRRuleset expression) {
- expression.in = expression.in.accept(this);
- for(CHRRule rule : expression.ruleset.rules) {
+ public void visit(IncludeStatement statement) {
+ statement.value = statement.value.accept(this);
+ }
+
+ public void transform(CHRRuleset ruleset) {
+ for(CHRRule rule : ruleset.rules) {
for(CHRLiteral lit : rule.head.literals)
for(int i=0;i<lit.parameters.length;++i)
lit.parameters[i] = lit.parameters[i].accept(this);
for(int i=0;i<lit.parameters.length;++i)
lit.parameters[i] = lit.parameters[i].accept(this);
}
+ }
+
+ @Override
+ public Expression transform(ECHRRuleset expression) {
+ expression.in = expression.in.accept(this);
+ transform(expression.ruleset);
+ return expression;
+ }
+
+ @Override
+ public Expression transform(ECHRRulesetConstructor expression) {
+ transform(expression.ruleset);
return expression;
}
import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
import org.simantics.scl.compiler.elaboration.chr.CHRRule;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.equation.EqBasic;
import org.simantics.scl.compiler.elaboration.equation.EqGuard;
import org.simantics.scl.compiler.elaboration.equation.Equation;
import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor;
import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
for(Equation equation : expression.equations)
equation.accept(this);
}
-
- @Override
- public void visit(ECHRRuleset ruleset) {
- for(CHRRule rule : ruleset.ruleset.rules) {
+
+ public void visit(CHRRuleset ruleset) {
+ for(CHRRule rule : ruleset.rules) {
for(CHRLiteral literal : rule.head.literals)
for(Expression parameter : literal.parameters)
parameter.accept(this);
for(Expression parameter : literal.parameters)
parameter.accept(this);
}
- ruleset.in.accept(this);
+ }
+
+ @Override
+ public void visit(ECHRRuleset expression) {
+ visit(expression.ruleset);
+ expression.in.accept(this);
+ }
+
+ @Override
+ public void visit(ECHRRulesetConstructor expression) {
+ visit(expression.ruleset);
}
@Override
statement.body.accept(this);
}
+ @Override
+ public void visit(IncludeStatement statement) {
+ statement.value.accept(this);
+ }
}
--- /dev/null
+package org.simantics.scl.compiler.elaboration.expressions.block;
+
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;
+import org.simantics.scl.compiler.internal.parsing.Token;
+import org.simantics.scl.compiler.types.Type;
+
+public class IncludeStatement extends Statement implements ValRefBinder {
+ public Token name;
+ public Expression value;
+
+ public CHRRuleset ruleset;
+ public IVal storeVar;
+
+ public IncludeStatement(Token name, Expression value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ @Override
+ public void setLocationDeep(long loc) {
+ if(location == Locations.NO_LOCATION) {
+ location = loc;
+ value.setLocationDeep(loc);
+ }
+ }
+
+ @Override
+ public StatementGroup getStatementGroup() {
+ return StatementGroup.CHR;
+ }
+
+ @Override
+ public Expression toExpression(EnvironmentalContext context, boolean monadic, Expression in) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void resolvePattern(TranslationContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean mayBeRecursive() {
+ return true;
+ }
+
+ @Override
+ public void accept(StatementVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public SSAFunction getParentFunction() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void replaceByApply(ValRef valRef, Val function, Type[] typeParameters, Val[] parameters2) {
+ throw new UnsupportedOperationException();
+ }
+
+}
\ No newline at end of file
void visit(GuardStatement statement);
void visit(LetStatement statement);
void visit(RuleStatement statement);
+ void visit(IncludeStatement statement);
}
import org.simantics.scl.compiler.elaboration.expressions.EBind;
import org.simantics.scl.compiler.elaboration.expressions.EBlock;
import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset;
+import org.simantics.scl.compiler.elaboration.expressions.ECHRRulesetConstructor;
import org.simantics.scl.compiler.elaboration.expressions.EConstant;
import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;
import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
}
@Override
- public void visit(EEquations eEquations) {
+ public void visit(EEquations expression) {
b.append("eq");
}
@Override
- public void visit(ECHRRuleset echrRuleset) {
- b.append("CHRRuleset");
+ public void visit(ECHRRuleset expression) {
+ b.append("ECHRRuleset");
+ }
+
+ @Override
+ public void visit(ECHRRulesetConstructor expression) {
+ b.append("ECHRRulesetConstructor");
}
public void visit(CHRRule rule) {
import java.util.function.Consumer;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
@Override
public void findTypesForPrefix(String prefix, NamespaceFilter filter, Consumer<TCon> consumer) {
}
+
+ @Override
+ public CHRRuleset getRuleset(String name) throws AmbiguousNameException {
+ return null;
+ }
}
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.compilation.CompilationContext;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
return getEnvironmentEntry(environment, localName, getTypeClass);
}
+ public static CHRRuleset getRuleset(Environment environment, String localName) throws AmbiguousNameException {
+ return getEnvironmentEntry(environment, localName, getRuleset);
+ }
+
/**
* Get the Name object representing an SCL value defined in a given environment.
* The name can be a local name or a fully scoped name with modules separated by periods.
return ns.getTypeClass(name);
}
};
+
+ private static final NamespaceValueAccessor<CHRRuleset> getRuleset = new NamespaceValueAccessor<CHRRuleset>() {
+ @Override
+ public CHRRuleset get(Namespace ns, String name) throws AmbiguousNameException {
+ return ns.getRuleset(name);
+ }
+ };
private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
Namespace namespace = environment.getLocalNamespace();
package org.simantics.scl.compiler.environment;
-import java.util.List;
import java.util.function.Consumer;
-import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
*/
EffectConstructor getEffectConstructor(String name) throws AmbiguousNameException;
+ CHRRuleset getRuleset(String name) throws AmbiguousNameException;
+
/**
* Get a TypeClass for a given name. The same instance is returned on each call.
* @param name the name of a defined entity type
package org.simantics.scl.compiler.environment;
import java.util.ArrayList;
-import java.util.List;
import java.util.function.Consumer;
-import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
return result;
}
+ @Override
+ public CHRRuleset getRuleset(String name) throws AmbiguousNameException {
+ CHRRuleset result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getRuleset(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
@Override
public void findValuesForPrefix(String prefix, NamespaceFilter filter, TObjectProcedure<SCLValue> proc) {
for(ModuleImport moduleImport : moduleImports)
package org.simantics.scl.compiler.internal.codegen.chr;
import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
public interface CHRCodeGenerationConstants {
public static String parameterName(int i) {
return "p" + i;
}
+
+ public static String includedName(IncludeStatement include) {
+ return "included" + include.name.text;
+ }
+
+ public static String nextContainerName(String name) {
+ return name + "$nextContainer";
+ }
}
import org.cojen.classfile.TypeDesc;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo;
import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
private JavaTypeTranslator jtt;
private ClassBuilder storeClassBuilder;
+ private CHRRuleset ruleset;
private CHRConstraint constraint;
private String factClassName;
private TypeDesc[] parameterTypeDescs;
private boolean supportsRemoval;
- CHRFactCodeGenerator(ClassBuilder storeClassBuilder, CHRConstraint constraint) {
+ CHRFactCodeGenerator(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRConstraint constraint) {
this.storeClassBuilder = storeClassBuilder;
+ this.ruleset = ruleset;
this.constraint = constraint;
this.moduleBuilder = storeClassBuilder.getModuleBuilder();
continue;
constructorParameters.add(typeDesc);
}
- MethodBuilderBase mb = classBuilder.addConstructor(Opcodes.ACC_PUBLIC, constructorParameters.toArray(new TypeDesc[constructorParameters.size()]));
+ MethodBuilderBase mb = classBuilder.addConstructorBase(Opcodes.ACC_PUBLIC, constructorParameters.toArray(new TypeDesc[constructorParameters.size()]));
mb.loadThis();
mb.invokeConstructor(classBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
mb.loadThis();
}
// Add fact to priority queue
- if(constraint.minimumPriority != Integer.MAX_VALUE) {
+ int minimumPriority = ruleset.getMinimumPriority(constraint);
+ if(minimumPriority != Integer.MAX_VALUE) {
mb.loadLocal(storeParameter);
- mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.priorityName(constraint.minimumPriority), CHRPriorityFactContainer);
+ mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.priorityName(minimumPriority), CHRPriorityFactContainer);
mb.loadLocal(mb.getParameter(1));
mb.loadThis();
mb.invokeVirtual(CHRPriorityFactContainer_name, "addFact", TypeDesc.VOID, new TypeDesc[] {CHRContext, CHRFact});
}
+ else if(constraint.nextContainerFieldName != null) {
+ mb.loadLocal(storeParameter);
+ mb.loadField(storeClassBuilder.getClassName(), constraint.nextContainerFieldName, CHRPriorityFactContainer);
+ LocalVariable containerVar = mb.createLocalVariable("container", CHRPriorityFactContainer);
+ mb.storeLocal(containerVar);
+
+ mb.loadLocal(containerVar);
+ Label finishLabel = mb.createLabel();
+ mb.ifNullBranch(finishLabel, true);
+
+ mb.loadLocal(containerVar);
+ mb.loadLocal(mb.getParameter(1));
+ mb.loadThis();
+ mb.invokeVirtual(CHRPriorityFactContainer_name, "addFact", TypeDesc.VOID, new TypeDesc[] {CHRContext, CHRFact});
+ mb.setLocation(finishLabel);
+ }
mb.returnVoid();
mb.finish();
}
import org.cojen.classfile.TypeDesc;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.elaboration.chr.CHRRule;
import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.chr.plan.CHRSearchPlan;
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.ClassBuilder;
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 gnu.trove.impl.PrimeFinder;
import gnu.trove.map.hash.THashMap;
import gnu.trove.procedure.TObjectObjectProcedure;
-import gnu.trove.set.hash.THashSet;
public class CHRPriorityFactContainerCodeGenerator implements CHRCodeGenerationConstants {
ClassBuilder storeClassBuilder;
}
private void generateContructor() {
- MethodBuilderBase mb = classBuilder.addConstructor(Opcodes.ACC_PUBLIC, new TypeDesc[] {storeTypeDesc});
+ MethodBuilderBase mb = classBuilder.addConstructorBase(Opcodes.ACC_PUBLIC, new TypeDesc[] {storeTypeDesc});
mb.loadThis();
- mb.loadConstant(rule.priority);
+ mb.loadConstant(rule.priority + ruleset.initialPriorityNumber);
mb.invokeSuperConstructor(new TypeDesc[] {TypeDesc.INT});
mb.loadThis();
mb.loadLocal(mb.getParameter(0));
planMap.forEachEntry(new TObjectObjectProcedure<CHRConstraint, ArrayList<CHRSearchPlan>>() {
@Override
public boolean execute(CHRConstraint constraint, ArrayList<CHRSearchPlan> plans) {
- int nextPriority = constraint.nextPriority;
- constraint.nextPriority = rule.priority;
+ int nextPriority = ruleset.getAndUpdateNextPriority(constraint, rule.priority);
Label next = nextLabel.get();
if(next != null)
mb.loadLocal(mb.getParameter(1));
mb.invokeVirtual(CHRPriorityFactContainer_name, "addFact", TypeDesc.VOID, new TypeDesc[] {CHRContext, CHRFact});
}
+ else if(constraint.nextContainerFieldName != null && !ruleset.constraintSourceMap.containsKey(constraint)) {
+ mb.loadThis();
+ mb.loadField(containerClassName, "parent", storeTypeDesc);
+ mb.loadField(storeClassBuilder.getClassName(), constraint.nextContainerFieldName, CHRPriorityFactContainer);
+ LocalVariable containerVar = mb.createLocalVariable("container", CHRPriorityFactContainer);
+ mb.storeLocal(containerVar);
+
+ mb.loadLocal(containerVar);
+ mb.ifNullBranch(finishLabel, true);
+
+ mb.loadLocal(containerVar);
+ mb.loadLocal(mb.getParameter(0));
+ mb.loadLocal(mb.getParameter(1));
+ mb.invokeVirtual(CHRPriorityFactContainer_name, "addFact", TypeDesc.VOID, new TypeDesc[] {CHRContext, CHRFact});
+ }
mb.branch(finishLabel);
return true;
mb.finish();
}
- private THashSet<BoundVar> usedParameters = new THashSet<BoundVar>();
-
// protected abstract void activate(CHRContext context, CHRFact fact);
private void generateActivate(CHRConstraint constraint, CHRSearchPlan plan, int id) {
mb.loadField(containerClassName, "parent", storeTypeDesc);
LocalVariable parent = mb.createLocalVariable("parent", storeTypeDesc);
mb.storeLocal(parent);
- BoundVar[] implementationParameters = plan.implementation.getParameters();
- mb.setLocalVariable(ruleset.this_, parent);
- mb.setLocalVariable(implementationParameters[0], mb.getParameter(0));
- mb.setLocalVariable(implementationParameters[1], mb.getParameter(1));
-
- // Set closure parameters
- usedParameters.clear();
- plan.implementation.forValRefs(valRef -> {
- if(valRef.getBinding() instanceof BoundVar)
- usedParameters.add((BoundVar)valRef.getBinding());
- });
- for(int j=0;j<ruleset.parameters.length;++j) {
- BoundVar parameter = ruleset.parameters[j];
- if(!usedParameters.contains(parameter))
- continue;
+ ruleset.rulesetObject.realizeMethod(mb, (i, target) -> {
mb.loadLocal(parent);
- mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.parameterName(j), ruleset.parameterTypeDescs[j]);
- mb.store(parameter);
- }
-
- // Generate code
- //System.out.println("=== activate" + i + " ==========================================================");
- //System.out.println(plan.implementation);
- plan.implementation.markGenerateOnFly();
- plan.implementation.generateCodeWithAlreadyPreparedParameters(mb);
+ mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.parameterName(i), ruleset.rulesetObject.parameterTypeDescs[i]);
+ mb.store(target);
+ }, plan.implementation, parent, mb.getParameter(0), mb.getParameter(1));
mb.finish();
}
}
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(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.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);
}
public void markGenerateOnFly() {
for(SSAStatement stat = firstStatement; stat != null; stat = stat.next)
- stat.markGenerateOnFly();
+ stat.markGenerateOnFly();
}
public SSABlock copy(CopyContext context) {
import org.simantics.scl.compiler.types.TVar;
import org.simantics.scl.compiler.types.Type;
-public abstract class SSAClosure implements Printable, BoundVarBinder{
+public abstract class SSAClosure implements Printable, BoundVarBinder {
Val target;
ClosureBinder parent;
@Override
public void toString(PrintingContext context) {
- if(determineGenerateOnFly())
+ if(/*target.getLabel() == null &&*/ determineGenerateOnFly())
context.addInlineExpression(target, this);
else
toStringAux(context);
BoundVar newVar = varMap.get(var);
if(newVar == null) {
newVar = new BoundVar(var.getType());
+ newVar.setLabel(var.getLabel());
oldVarsList.add(var);
newVarsList.add(newVar);
varMap.put(var, newVar);
inVarsMap.put(closure, inVars);
varMap.put(closure, map);
- closure.parametrize(inVars);
+ closure.parametrize(inVars);
SCLConstant functionConstant = new SCLConstant(context.createName(), closure.getType());
context.addConstant(functionConstant);
oldTargets.put(closure, (BoundVar)closure.getTarget());
public class StandardTypeConstructor extends TypeConstructor {
private TypeDesc typeDesc; // null, if trivial data type (one constructor with one parameter)
- public boolean external;
+ public boolean external; // this means that the class don't need to be generated
public StandardTypeConstructor(TCon con, Kind kind) {
super(con, kind);
this.className = className;
this.superClassName = superClassName;
this.classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- this.classVisitor = SCLCompilerConfiguration.SHOW_COMPILED_BYTECODE
+ this.classVisitor = SCLCompilerConfiguration.SHOW_COMPILED_BYTECODE
+ && SCLCompilerConfiguration.debugFilter(moduleBuilder.namingPolicy.getModuleName())
? new TraceClassVisitor(classWriter, new PrintWriter(System.out))
: classWriter;
classVisitor.visit(Opcodes.V1_5, access, className, null, superClassName, interfaces);
methodVisitor.visitEnd();
}
- public MethodBuilderBase addConstructor(int access, TypeDesc[] params) {
+ public MethodBuilderBase addConstructorBase(int access, TypeDesc[] params) {
return addMethodBase(access, "<init>", TypeDesc.VOID, params);
}
+
+ public MethodBuilder addConstructor(int access, TypeDesc[] params) {
+ return addMethod(access, "<init>", TypeDesc.VOID, params);
+ }
public MethodBuilder addInitializer() {
return addMethod(Opcodes.ACC_PUBLIC, "<clinit>", TypeDesc.VOID, Constants.EMPTY_TYPEDESC_ARRAY);
classBuilder.addField(fieldModifiers, fieldNamePrefix+i, types[i]);
// Create constructor
- MethodBuilderBase mb = classBuilder.addConstructor(
+ MethodBuilderBase mb = classBuilder.addConstructorBase(
types.length == 0 ? Opcodes.ACC_PRIVATE : Opcodes.ACC_PUBLIC,
JavaTypeTranslator.filterVoid(types));
mb.loadThis();
}
methodVisitor.visitCode();
}
+
+ public LocalVariable getThis(TypeDesc type) {
+ return new LocalVariable(0, type);
+ }
public void loadConstant(boolean value) {
if(value)
// Create constructor
{
- MethodBuilderBase mb = classBuilder.addConstructor(Opcodes.ACC_PUBLIC, Arrays.copyOf(parameterTypes, knownParametersCount));
+ MethodBuilderBase mb = classBuilder.addConstructorBase(Opcodes.ACC_PUBLIC, Arrays.copyOf(parameterTypes, knownParametersCount));
mb.loadThis();
mb.loadConstant(remainingArity);
mb.invokeConstructor(MethodBuilderBase.getClassName(Constants.FUNCTION_N_IMPL), new TypeDesc[] { TypeDesc.INT });
import org.simantics.scl.compiler.elaboration.expressions.annotations.AnnotationUtils;
import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
import org.simantics.scl.compiler.errors.ErrorLog;
-import org.simantics.scl.compiler.internal.parsing.declarations.DModuleHeader;
public class ModuleHeader {
public String classLoader;
public long classLoaderLocation;
public String defaultLocalName;
- public boolean fields;
public List<EVar> export;
+ // Features
+ public boolean chr;
+ public boolean fields;
- private void read(ErrorLog errorLog, DModuleHeader header) {
- for(FieldAssignment assignment : header.fields)
+ private void read(ErrorLog errorLog, FieldAssignment[] fields) {
+ for(FieldAssignment assignment : fields)
switch(assignment.name) {
case "bundle":
if(assignment.value == null)
errorLog.log(assignment.location, "No value expected for property fields.");
this.fields = true;
break;
+ case "chr":
+ if(assignment.value != null)
+ errorLog.log(assignment.location, "No value expected for property chr.");
+ this.chr = true;
+ break;
default:
errorLog.logWarning(assignment.location, "Unknown module header field was skipped.");
}
}
- public static ModuleHeader process(ErrorLog errorLog, DModuleHeader header) {
- if(header == null)
+ public static ModuleHeader process(ErrorLog errorLog, FieldAssignment[] fields) {
+ if(fields == null)
return null;
ModuleHeader result = new ModuleHeader();
- result.read(errorLog, header);
+ result.read(errorLog, fields);
return result;
}
}
+++ /dev/null
-package org.simantics.scl.compiler.internal.parsing.declarations;
-
-import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
-import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
-
-
-
-public class DModuleHeader extends DeclarationAst {
- public final FieldAssignment[] fields;
-
- public DModuleHeader(FieldAssignment[] fields) {
- this.fields = fields;
- }
-
- @Override
- public void toString(int indentation, StringBuilder b) {
- for(int i=0;i<indentation;++i) b.append(" ");
- b.append("module {");
- ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
- boolean first = true;
- for(FieldAssignment field : fields) {
- if(first)
- first = false;
- else
- b.append(',');
- b.append('\n');
- for(int i=0;i<=indentation;++i) b.append(" ");
- b.append(field.name);
- b.append(" = ");
- field.value.accept(visitor);
- }
- b.append('\n');
- for(int i=0;i<indentation;++i) b.append(" ");
- b.append('}');
- }
-}
--- /dev/null
+package org.simantics.scl.compiler.internal.parsing.declarations;
+
+import org.simantics.scl.compiler.elaboration.expressions.EBlock;
+import org.simantics.scl.compiler.types.TCon;
+
+public class DRulesetAst extends DeclarationAst {
+ public final String name;
+ public final EBlock block;
+ public DDocumentationAst documentation;
+
+ public TCon type;
+ public String className;
+
+ public DRulesetAst(String name, EBlock block) {
+ this.name = name;
+ this.block = block;
+ }
+}
package org.simantics.scl.compiler.internal.parsing.parser;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.internal.parsing.Token;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
TIntArrayList stateStack = new TIntArrayList(2);
StringBuffer string = new StringBuffer();
+ CompilationContext context;
private Token sym(int id) {
return new Token(id, yychar, yychar+yylength(), yytext());
private Token sym(int id, String text) {
return new Token(id, yychar, yychar+yylength(), text);
}
+ public void setCompilationContext(CompilationContext context) {
+ this.context = context;
+ }
+ public boolean supportCHR() {
+ return context.header == null ? false : context.header.chr;
+ }
%}
letter = [a-zA-Z_]
else { return sym(SCLTerminals.ELSE); }
where { return sym(SCLTerminals.WHERE); }
when { return sym(SCLTerminals.WHEN); }
- ruleset { return sym(SCLTerminals.RULESET); }
- rule { return sym(SCLTerminals.RULE); }
+ ruleset { return sym(supportCHR() ? SCLTerminals.RULESET : SCLTerminals.ID); }
+ rule { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.RULE); }
abstract{whitespace}rule { return sym(SCLTerminals.ABSTRACT_RULE); }
extends { return sym(SCLTerminals.EXTENDS); }
mapping{whitespace}relation { return sym(SCLTerminals.MAPPING_RELATION); }
- transformation { return sym(SCLTerminals.TRANSFORMATION); }
+ transformation { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.TRANSFORMATION); }
select{whitespace}first { return sym(SCLTerminals.SELECT_FIRST); }
select{whitespace}distinct { return sym(SCLTerminals.SELECT_DISTINCT); }
select { return sym(SCLTerminals.SELECT); }
package org.simantics.scl.compiler.internal.parsing.parser;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.internal.parsing.Token;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.6.1
- * from the specification file <tt>C:/GamsGui/git/platform/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex</tt>
+ * from the specification file <tt>C:/Simugawa.git/git/platform/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex</tt>
*/
public class SCLLexer {
TIntArrayList stateStack = new TIntArrayList(2);
StringBuffer string = new StringBuffer();
+ CompilationContext context;
private Token sym(int id) {
return new Token(id, yychar, yychar+yylength(), yytext());
private Token sym(int id, String text) {
return new Token(id, yychar, yychar+yylength(), text);
}
+ public void setCompilationContext(CompilationContext context) {
+ this.context = context;
+ }
+ public boolean supportCHR() {
+ return context.header == null ? false : context.header.chr;
+ }
/**
}
case 157: break;
case 63:
- { return sym(SCLTerminals.RULE);
+ { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.RULE);
}
case 158: break;
case 64:
}
case 177: break;
case 83:
- { return sym(SCLTerminals.RULESET);
+ { return sym(supportCHR() ? SCLTerminals.RULESET : SCLTerminals.ID);
}
case 178: break;
case 84:
}
case 187: break;
case 93:
- { return sym(SCLTerminals.TRANSFORMATION);
+ { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.TRANSFORMATION);
}
case 188: break;
case 94:
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.common.precedence.Associativity;
import org.simantics.scl.compiler.common.precedence.Precedence;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.constants.CharacterConstant;
import org.simantics.scl.compiler.constants.StringConstant;
import org.simantics.scl.compiler.elaboration.equation.EqBasic;
import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
import org.simantics.scl.compiler.elaboration.query.pre.QPreEquals;
import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.header.ModuleHeader;
import org.simantics.scl.compiler.internal.parsing.Symbol;
import org.simantics.scl.compiler.internal.parsing.Token;
import org.simantics.scl.compiler.internal.parsing.declarations.ConstructorAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DImportJavaAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
-import org.simantics.scl.compiler.internal.parsing.declarations.DModuleHeader;
import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DRulesetAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
private final SCLPostLexer lexer;
private SCLParserOptions options;
+ private CompilationContext context;
public SCLParserImpl(Reader reader) {
- lexer = new SCLPostLexer(reader);
+ this.lexer = new SCLPostLexer(reader);
+ }
+
+ public void setCompilationContext(CompilationContext context) {
+ this.context = context;
+ lexer.setCompilationContext(context);
}
public void setParserOptions(SCLParserOptions options) {
for(int i=0;i<length();i+=2) {
DeclarationAst declaration = (DeclarationAst)get(i);
if(declaration == null)
- throw new NullPointerException();
+ continue;
declarations.add(declaration);
}
return declarations;
FieldAssignment[] fields = new FieldAssignment[length()/2-1];
for(int i=0;i<fields.length;++i)
fields[i] = (FieldAssignment)get(2+i*2);
- return new DModuleHeader(fields);
+ context.header = ModuleHeader.process(context.errorLog, fields);
+ return null;
}
@Override
@Override
protected Object reduceRulesetDefinition() {
- // TODO Auto-generated method stub
- return null;
+ Token name = (Token)get(1);
+ EBlock block = (EBlock)get(3);
+ return new DRulesetAst(name.text, block);
}
@Override
protected Object reduceLocalInclude() {
- // TODO Auto-generated method stub
- return null;
+ Token name = (Token)get(1);
+ Expression value = (Expression)get(2);
+ return new IncludeStatement(name, value);
}
}
import java.io.IOException;
import java.util.Arrays;
+import org.simantics.scl.compiler.compilation.CompilationContext;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.parsing.Token;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
* @author Hannu Niemistö
*/
public class SCLPostLexer {
+
+ private static final int PATCH_SIZE = 16;
+ private static final int INITIAL_QUEUE_SIZE = 32;
public static TIntHashSet INDENTABLE = new TIntHashSet();
public static TIntHashSet NO_SEMICOLON_BEFORE = new TIntHashSet();
}
SCLLexer lexer;
- Token[] queue = new Token[16];
+ Token[] queue = new Token[INITIAL_QUEUE_SIZE];
int queuePos=0, queueSize=0;
TIntArrayList indentations = new TIntArrayList();
TIntArrayList indentationTokens = new TIntArrayList();
boolean firstTokenOfLine = true;
private SCLParserOptions options;
private boolean isFirstToken = true;
+ private CompilationContext context;
+
+ /**
+ * We are parsing a module header and therefore should process tokens one by one and not by patches.
+ */
+ private boolean isInsideModule = false;
{
indentations.add(0);
public SCLPostLexer(java.io.Reader in) {
this(new SCLLexer(in));
}
+
+ public void setCompilationContext(CompilationContext context) {
+ lexer.setCompilationContext(context);
+ this.context = context;
+ }
public Token nextToken() throws Exception {
while(queuePos == queueSize)
queuePos = 0;
queueSize = 0;
- for(int i=0;i<8;++i)
+ for(int i=0;i<PATCH_SIZE;++i) {
handleToken(lexer.nextToken());
+ if(isInsideModule) {
+ if(context.header == null)
+ break;
+ else
+ isInsideModule = false;
+ }
+ }
}
private SCLSyntaxErrorException error(int start, int end, String description) {
isFirstToken = false;
if(symbol.id == SCLTerminals.ID && symbol.text.equals("module") && options != null && options.isModule) {
push(new Token(SCLTerminals.MODULE, symbol.location, symbol.text));
+ isInsideModule = true;
return;
}
}
import org.simantics.scl.compiler.common.names.Name;
import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.modules.Documentation;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
THashMap<TCon, ArrayList<TypeClassInstance>> typeClassInstances = new THashMap<TCon, ArrayList<TypeClassInstance>>();
THashMap<String, SCLValue> values = new THashMap<String, SCLValue>();
THashMap<String, List<Constant>> fieldAccessors = new THashMap<String, List<Constant>>();
- THashMap<String, SCLRelation> relations = new THashMap<String, SCLRelation>();
- THashMap<String, SCLEntityType> entityTypes = new THashMap<String, SCLEntityType>();
- THashMap<String, TransformationRule> rules = new THashMap<String, TransformationRule>();
- THashMap<String, MappingRelation> mappingRelations = new THashMap<String, MappingRelation>();
+ THashMap<String, SCLRelation> relations = new THashMap<String, SCLRelation>(2);
+ THashMap<String, SCLEntityType> entityTypes = new THashMap<String, SCLEntityType>(2);
+ THashMap<String, TransformationRule> rules = new THashMap<String, TransformationRule>(2);
+ THashMap<String, MappingRelation> mappingRelations = new THashMap<String, MappingRelation>(2);
+ THashMap<String, CHRRuleset> rulesets = new THashMap<String, CHRRuleset>(2);
ArrayList<ImportDeclaration> dependencies = new ArrayList<ImportDeclaration>();
THashMap<String, BranchPoint[]> branchPoints;
CompilationError[] warnings = CompilationError.EMPTY_ARRAY;
return effectConstructors.get(name);
}
+ @Override
+ public CHRRuleset getRuleset(String name) {
+ return rulesets.get(name);
+ }
+
public Collection<TypeClass> getTypeClasses() {
return typeClasses.values();
}
}
list.add(accessor);
}
+
+ public void addRuleset(String name, CHRRuleset ruleset) {
+ rulesets.put(name, ruleset);
+ }
}
import java.util.List;
import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.modules.Documentation;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
public CompilationError[] getWarnings() {
return CompilationError.EMPTY_ARRAY;
}
+
+ @Override
+ public CHRRuleset getRuleset(String name) {
+ return null;
+ }
}
import java.util.function.Consumer;
import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
import org.simantics.scl.compiler.elaboration.modules.Documentation;
import org.simantics.scl.compiler.elaboration.modules.SCLValue;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
Collection<TypeClassInstance> getInstances(TCon typeClass);
MappingRelation getMappingRelation(String name);
TransformationRule getRule(String name);
+ CHRRuleset getRuleset(String name);
Collection<TransformationRule> getRules();
void findValuesForPrefix(String prefix, NamespaceFilter filter, TObjectProcedure<SCLValue> proc);
if(bytes == null)
throw new ClassNotFoundException(name);
}
- if(SCLCompilerConfiguration.SHOW_DECOMPILED_BYTECODE)
+ if(SCLCompilerConfiguration.SHOW_DECOMPILED_BYTECODE && SCLCompilerConfiguration.debugFilter(moduleName))
showDecompiledBytecode(internalName);
return defineClass(name, bytes, 0, bytes.length);
}
ArrayList<Type> lvTypes = new ArrayList<Type>();
if(expression instanceof EBlock) {
EBlock block = (EBlock)expression;
- if(localStorage != null && !(block.getStatements().getLast() instanceof GuardStatement)) {
+ if(localStorage != null && !(block.getLast() instanceof GuardStatement)) {
THashSet<String> localVariables = new THashSet<String>();
ListIterator<Statement> it = block.getStatements().listIterator();
while(it.hasNext()) {
localStorage.store(variableName, null, type);
}
}
- if(!(block.getStatements().getLast() instanceof GuardStatement))
+ if(!(block.getLast() instanceof GuardStatement))
block.addStatement(new GuardStatement(new EConstant(Builtins.TUPLE_CONSTRUCTORS[0])));
}
public static final boolean EVERY_DATALOG_STRATUM_IN_SEPARATE_METHOD = true;
public static final boolean ALLOW_OVERLOADING = true;
+
+ public static boolean debugFilter(String name) {
+ return true;
+ }
}
+++ /dev/null
-import "StandardLibrary"
-
-topologicalSort :: Show a => [(a,a)] -> <Proc> [a]
-topologicalSort dependencies = MList.freeze answer
- where
- answer = MList.create ()
-
- (?x,?y) <- dependencies => print "RULE 1, x=\(?x), y=\(?y)", Dep ?x ?y, InDegree ?x 0, InDegree ?y 1
- InDegree ?x ?a => print "pre InDegree \(?x) \(?a)"
- -InDegree ?x ?a, -InDegree ?x ?b => print "RULE 2, x=\(?x), a=\(?a), b=\(?b)", InDegree ?x (?a + ?b)
- InDegree ?x ?a => print "InDegree \(?x) \(?a)"
- InDegree ?x 0 => print "RULE 3, x=\(?x)", AdjustInDegrees ?x, MList.add answer ?x
- AdjustInDegrees ?x, Dep ?x ?y => print "RULE 4, x=\(?x), y=\(?y)", InDegree ?y (-1)
-
-main = topologicalSort [(2,4),(3,7),(7,2),(1,3)]
public class SCLInfo {
public static String[] RESERVED_WORDS = new String[] {
+ "module",
+
"data",
"type",
"effect",
"as",
"forall",
"rule",
+ "ruleset",
"extends",
"by",
"select",
package org.simantics.scl.compiler.tests;
-import org.junit.Test;
-
public class ActiveTests extends TestBase {
public ActiveTests() { super("scl"); }
//@Test public void Bug6989() { test(); }
- @Test public void CHR5() { test(); }
-
}
@Test public void CHR2() { test(); }
@Test public void CHR3() { test(); }
@Test public void CHR4() { test(); }
+ @Test public void CHR5() { test(); }
+ @Test public void CHR6() { test(); }
@Test public void ClosureRecursion() { test(); }
@Test public void Collaz() { test(); }
@Test public void Compose() { test(); }
+module {
+ export = [main],
+ chr
+}
+
import "StandardLibrary"
-topologicalSort :: Show a => [(a,a)] -> <Proc> [a]
-topologicalSort dependencies = MList.freeze answer
- where
- answer = MList.create ()
+ruleset IntegerSet where
+ constraint Element Integer
+ // Set may not contain duplicates
+ Element ?x => print "added \(?x)"
+ -Element ?x, Element ?x => print "removed duplicate \(?x)"
- (?x,?y) <- dependencies => print "RULE 1, x=\(?x), y=\(?y)", Dep ?x ?y, InDegree ?x 0, InDegree ?y 1
- -InDegree ?x ?a, -InDegree ?x ?b => print "RULE 2, x=\(?x), a=\(?a), b=\(?b)", InDegree ?x (?a + ?b)
- InDegree ?x ?a => print "InDegree \(?x) \(?a)"
- InDegree ?x 0 => print "RULE 3, x=\(?x)", AdjustInDegrees ?x, MList.add answer ?x
- AdjustInDegrees ?x, Dep ?x ?y => print "RULE 4, x=\(?x), y=\(?y)", InDegree ?y (-1)
+addSet :: IntegerSet -> Integer -> <Proc> ()
+addSet set newElement = ()
+ where
+ include IntegerSet set
+ True => Element newElement
-main = topologicalSort [(2,4),(3,7),(7,2),(1,3)]
+printSet :: IntegerSet -> <Proc> ()
+printSet set = ()
+ where
+ include IntegerSet set
+ Element ?x => print "printing \(?x)"
+
+main = ()
+ where
+ set = createIntegerSet
+ addSet set 1
+ addSet set 2
+ addSet set 1
+ printSet set
--
-[1, 3, 7, 2, 4]
\ No newline at end of file
+()
--- /dev/null
+module {
+ export = [main],
+ chr
+}
+
+import "StandardLibrary"
+
+ruleset RS where
+ constraint X Integer
+ -X ?value, X ?value => True
+ X ?value => print "A \(?value)"
+
+main :: ()
+main = ()
+ where
+ rs = createRS
+ include RS rs
+ X ?value => print "B \(?value)"
+ True => X 1
+ True => X 2
+ True => X 1
+--
+()
MutableClassLoader classLoader = environment.getMutableClassLoader();
classLoader.addClasses(moduleBuilder.getClasses());
- String storeClassName = ruleset.runtimeRulesetName.replace('/', '.');
+ String storeClassName = ruleset.runtimeRulesetClassName.replace('/', '.');
Class<?> storeClass = classLoader.loadClass(storeClassName);
Class<?> factClass = classLoader.loadClass(storeClassName+"$ExampleFact");
Constructor<?> factConstructor = factClass.getConstructor(int.class, int.class, int.class);