From: Hannu Niemistö Date: Thu, 1 Jun 2017 10:04:26 +0000 (+0300) Subject: (refs #7250) CHR rules modularization (first working version) X-Git-Tag: v1.31.0~339^2~4 X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F85%2F585%2F5;p=simantics%2Fplatform.git (refs #7250) CHR rules modularization (first working version) This change adds a complete implementation of CHR modularization. New top level declaration ruleset allows to define rulesets that can be included into other rulesets (see CHR{5,6}.scl). Change-Id: I3a188d788602fa27f863e16969f956d79c9684a9 --- diff --git a/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java b/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java index acf2bb18d..5843b89e3 100644 --- a/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java +++ b/bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java @@ -885,4 +885,11 @@ public abstract class TypeDesc extends Descriptor { } } } + + 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; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/commands/CommandSession.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/commands/CommandSession.java index 1cf6d0de9..a8f3d2045 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/commands/CommandSession.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/commands/CommandSession.java @@ -423,10 +423,9 @@ public class CommandSession { void finishBlock() { if(currentBlock != null) { checkInterrupted(); - LinkedList 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; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/exceptions/InternalCompilerError.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/exceptions/InternalCompilerError.java index ae3bdd87c..71b619301 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/exceptions/InternalCompilerError.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/exceptions/InternalCompilerError.java @@ -31,5 +31,10 @@ public class InternalCompilerError extends RuntimeException { super(cause); this.location = Locations.NO_LOCATION; } + + public InternalCompilerError(long location, Throwable cause) { + super(cause); + this.location = location; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java index 9c7c77470..a8dca8c11 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java @@ -183,7 +183,7 @@ public class CodeGeneration { } 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); } @@ -199,7 +199,7 @@ public class CodeGeneration { 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); } @@ -211,7 +211,7 @@ public class CodeGeneration { } 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); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java index 652adf93e..4bf5d847e 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java @@ -23,9 +23,9 @@ import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst; 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; @@ -39,7 +39,6 @@ import org.simantics.scl.compiler.module.ImportDeclaration; import gnu.trove.map.hash.THashMap; public class DeclarationClassification { - DModuleHeader moduleHeader; ArrayList importsAst = new ArrayList(); ArrayList dataTypesAst = new ArrayList(); ArrayList typeAliasesAst = new ArrayList(); @@ -53,6 +52,7 @@ public class DeclarationClassification { ArrayList effectsAst = new ArrayList(); ArrayList rulesAst = new ArrayList(); ArrayList mappingRelationsAst = new ArrayList(); + ArrayList rulesetsAst = new ArrayList(); THashMap valueDocumentation = new THashMap(); THashMap relationDocumentation = new THashMap(); @@ -108,8 +108,8 @@ public class DeclarationClassification { 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()); } @@ -346,11 +346,19 @@ public class DeclarationClassification { } } + 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) { @@ -384,10 +392,6 @@ public class DeclarationClassification { 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) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java index 1cba44207..6499ab4fe 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java @@ -6,6 +6,7 @@ import java.util.List; 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; @@ -31,6 +32,7 @@ import org.simantics.scl.compiler.elaboration.expressions.EGetConstraint; 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; @@ -47,6 +49,7 @@ import org.simantics.scl.compiler.elaboration.modules.TypeAlias; 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; @@ -84,6 +87,7 @@ 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.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; @@ -211,7 +215,8 @@ public class Elaboration { public void addTypesToEnvironment( ArrayList dataTypesAst, ArrayList typeAliasesAst, - ArrayList effectsAst) { + ArrayList effectsAst, + ArrayList rulesetsAst) { for(DDataAst dataType : dataTypesAst) { dataType.parameterKinds = new Kind[dataType.parameters.length]; Kind constructorKind = Kinds.STAR; @@ -226,8 +231,7 @@ public class Elaboration { 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; } @@ -235,9 +239,7 @@ public class Elaboration { 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) { @@ -248,11 +250,24 @@ public class Elaboration { 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]; @@ -702,6 +717,18 @@ public class Elaboration { } } + public void processRulesets(ArrayList 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. diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java index 77e6e96df..8621283b7 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java @@ -3,6 +3,7 @@ package org.simantics.scl.compiler.compilation; 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; @@ -72,6 +73,14 @@ public class NamespaceOfModule implements Namespace { 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 { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java index 643513d67..cd43b76e1 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java @@ -44,6 +44,7 @@ public class SCLCompiler { try { SCLParserImpl parser = new SCLParserImpl(sourceReader); parser.setParserOptions(SCLParserOptions.MODULE_DEFAULT); + parser.setCompilationContext(compilationContext); if(!parser.isEmpty()) for(DeclarationAst declaration : (ArrayList)parser.parseModule()) declarations.handle(declaration); @@ -70,7 +71,6 @@ public class SCLCompiler { String moduleName) { try { if(hasErrors()) return; - compilationContext.header = ModuleHeader.process(compilationContext.errorLog, declarations.moduleHeader); Elaboration elaboration = new Elaboration(compilationContext, timer, localEnvironmentFactory, @@ -87,7 +87,8 @@ public class SCLCompiler { elaboration.addTypesToEnvironment( declarations.dataTypesAst, declarations.typeAliasesAst, - declarations.effectsAst); + declarations.effectsAst, + declarations.rulesetsAst); if(hasErrors()) return; elaboration.processTypeAliases(declarations.typeAliasesAst); if(hasErrors()) return; @@ -101,6 +102,8 @@ public class SCLCompiler { 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); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FunctionValue.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FunctionValue.java index d37b75089..dcef289f0 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FunctionValue.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FunctionValue.java @@ -151,7 +151,7 @@ public abstract class FunctionValue extends Constant { // 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}); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java index 9846ebd48..b30021c1c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.elaboration.chr; 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; @@ -29,7 +30,7 @@ public class CHRRule extends Symbol { public Variable[] existentialVariables; // Analysis - public int firstPriorityExecuted; + //public int firstPriorityExecuted; public int lastPriorityExecuted; // Plans @@ -124,7 +125,6 @@ public class CHRRule extends Symbol { private void addPlan(CHRSearchPlan plan) { plans.add(plan); - plan.constraint.minimumPriority = Math.min(plan.constraint.minimumPriority, priority); } public String toString() { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java index 7b5ceec83..d5f619654 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java @@ -9,9 +9,11 @@ import org.simantics.scl.compiler.constants.Constant; 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; @@ -21,11 +23,14 @@ import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; 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; @@ -33,7 +38,9 @@ import org.simantics.scl.compiler.types.TCon; 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; @@ -44,11 +51,19 @@ public class CHRRuleset extends Symbol { public ArrayList constraints = new ArrayList(); public ArrayList rules = new ArrayList(); + public ArrayList includes = new ArrayList(); + public THashMap constraintSourceMap = new THashMap(); + public THashMap activeConstraintGGInfo = new THashMap(); // contains also imported constraints + public THashMap> inverseActiveConstraintSourceMap = new THashMap>(); + + 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; @@ -59,9 +74,9 @@ public class CHRRuleset extends Symbol { 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); @@ -69,6 +84,27 @@ public class CHRRuleset extends Symbol { } 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; @@ -82,26 +118,36 @@ public class CHRRuleset extends Symbol { } public void collectRefs(TObjectIntHashMap 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 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 vars) { + for(IncludeStatement include : includes) + include.value.collectFreeVariables(vars); for(CHRRule rule : rules) rule.collectFreeVariables(vars); } @@ -113,31 +159,91 @@ public class CHRRuleset extends Symbol { 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 list = inverseActiveConstraintSourceMap.get(include); + if(list == null) { + list = new ArrayList(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 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); @@ -145,14 +251,18 @@ public class CHRRuleset extends Symbol { 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) { @@ -170,12 +280,45 @@ public class CHRRuleset extends Symbol { 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 effects) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java index a15e30e42..96e86aed1 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java @@ -1,16 +1,31 @@ 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 parameterIndexMap; + public TypeDesc[] parameterTypeDescs; + public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) { super(ruleset.runtimeRulesetType); this.setTarget(target); @@ -19,13 +34,50 @@ public class CHRRulesetObject extends SSAObject { @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 { + 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); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/CHRConstraintGGInfo.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/CHRConstraintGGInfo.java new file mode 100644 index 000000000..dbe33d6eb --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/CHRConstraintGGInfo.java @@ -0,0 +1,10 @@ +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; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java index 3d5e0246b..a738c1f42 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java @@ -12,13 +12,14 @@ import gnu.trove.map.hash.THashMap; public class UsageAnalysis { public static void analyzeUsage(CHRRuleset ruleset) { THashMap> 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> headConstraintMap) { for(CHRRule rule : ruleset.rules) @@ -39,15 +40,14 @@ public class UsageAnalysis { 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) { @@ -60,15 +60,17 @@ public class UsageAnalysis { 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> 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; } @@ -85,9 +87,8 @@ public class UsageAnalysis { 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) { @@ -121,7 +122,7 @@ public class UsageAnalysis { 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 + "]"); @@ -135,7 +136,7 @@ public class UsageAnalysis { System.out.print(" [" + rule.firstPriorityExecuted + ".." + rule.lastPriorityExecuted + "] "); System.out.println(rule); } - } + }*/ private static void determinePassiveLiterals(CHRRule rule) { for(CHRLiteral literal : rule.head.literals) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java index e4484a933..5b7f81664 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java @@ -31,7 +31,7 @@ public class ClaimOp extends PlanOp { for(int i=0;i parameters = new ArrayList(expressions.length+1); - parameters.add(planContext.storeVar); + parameters.add(planContext.getStoreVar(constraint)); for(int i=0;i>i)&1)==1) parameters.add(expressions[i].toVal(context.environment, w)); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java index 0ed3f8975..bc6b7da58 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java @@ -10,7 +10,9 @@ import org.simantics.scl.compiler.constants.singletons.JustConstant; 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; @@ -22,15 +24,15 @@ import org.simantics.scl.compiler.types.Types; public abstract class PlanContext { public CompilationContext context; public CHRRuleset ruleset; - public IVal storeVar; + public IVal mainStoreVar; public IVal contextVar; public ArrayList partnerFacts = new ArrayList(); 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; } @@ -116,4 +118,12 @@ public abstract class PlanContext { w.continueAs(end); } + + public IVal getStoreVar(CHRConstraint constraint) { + IncludeStatement includeStatement = ruleset.constraintSourceMap.get(constraint); + if(includeStatement != null) + return includeStatement.storeVar; + else + return mainStoreVar; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java index de00093cf..5b3057dd9 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java @@ -27,7 +27,7 @@ public class PostCommitOp extends PlanOp { 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) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PreCommitOp.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PreCommitOp.java index 95e865be3..c4629f6d0 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PreCommitOp.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PreCommitOp.java @@ -17,7 +17,7 @@ public class PreCommitOp extends PlanOp { 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); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java index 8612fd766..c0f439288 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java @@ -38,9 +38,9 @@ public class CHRConstraint extends Symbol implements CHRRelation { public boolean implicitlyDeclared; // Analysis - public int firstPriorityAdded; + //public int firstPriorityAdded; public int lastPriorityAdded; - public int firstPriorityRemoved; + //public int firstPriorityRemoved; public int lastPriorityRemoved; // Transient info @@ -56,11 +56,9 @@ public class CHRConstraint extends Symbol implements CHRRelation { public Constant addProcedure; public Constant removeProcedure; - public TIntObjectHashMap indices; + public String nextContainerFieldName; - // Query plans - public int minimumPriority = Integer.MAX_VALUE; - public int nextPriority = Integer.MAX_VALUE; // used in code generation + public TIntObjectHashMap indices; public static class IndexInfo { public final int indexMask; @@ -86,7 +84,7 @@ public class CHRConstraint extends Symbol implements CHRRelation { 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); @@ -126,6 +124,11 @@ public class CHRConstraint extends Symbol implements CHRRelation { 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 @@ -161,11 +164,11 @@ public class CHRConstraint extends Symbol implements CHRRelation { 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, @@ -176,13 +179,17 @@ public class CHRConstraint extends Symbol implements CHRRelation { ); } - 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) { @@ -191,7 +198,7 @@ public class CHRConstraint extends Symbol implements CHRRelation { indexInfo = createIndexInfo(context, boundMask); indices.put(boundMask, indexInfo); } - return indexInfo.nextFact; + return getOrCreateIndex(context, boundMask).nextFact; } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java index 203bd81d2..d9746bb04 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java @@ -8,6 +8,7 @@ import org.simantics.scl.compiler.common.names.Names; 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; @@ -521,4 +522,8 @@ public class TranslationContext extends TypeTranslationContext implements Enviro public SCLValue getValue(Name name) { return environment.getValue(name); } + + public CHRRuleset resolveRuleset(String name) throws AmbiguousNameException { + return Environments.getRuleset(environment, name); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java index 927720611..1eea959fd 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java @@ -126,4 +126,8 @@ public class TypeTranslationContext { errorLog.log(loc, "Expected a type with kind " + expectedKind + " but got " + provided + "."); } } + + public CompilationContext getCompilationContext() { + return compilationContext; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java index c5f30417e..157efb360 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java @@ -1,7 +1,6 @@ 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; @@ -11,6 +10,7 @@ import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; 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; @@ -19,7 +19,7 @@ import org.simantics.scl.compiler.errors.Locations; public class EBlock extends ASTExpression { - LinkedList statements = new LinkedList(); + ArrayList statements = new ArrayList(); boolean monadic; public EBlock() { @@ -33,9 +33,17 @@ public class EBlock extends ASTExpression { this.monadic = monadic; } - public LinkedList getStatements() { + public ArrayList 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) { @@ -66,7 +74,7 @@ public class EBlock extends ASTExpression { in = extractRules(i, endId, in); break; case CHR: - in = extractCHRRules(context, i, endId, in); + in = new ECHRRuleset(extractCHRRules(context, i, endId), in); break; } } @@ -78,7 +86,7 @@ public class EBlock extends ASTExpression { 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)(List)statements.subList(begin, end), in); @@ -123,7 +137,7 @@ public class EBlock extends ASTExpression { 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(); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRulesetConstructor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRulesetConstructor.java new file mode 100644 index 000000000..e8a5cb81b --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRulesetConstructor.java @@ -0,0 +1,105 @@ +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 allRefs, TIntHashSet refs) { + ruleset.collectRefs(allRefs, refs); + } + @Override + public void collectVars(TObjectIntHashMap 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 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 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(); + } + +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreCHRRulesetConstructor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreCHRRulesetConstructor.java new file mode 100644 index 000000000..500c80573 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreCHRRulesetConstructor.java @@ -0,0 +1,41 @@ +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; + } +} diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java index 8d54d5063..4cf513c54 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java @@ -10,6 +10,7 @@ public interface ExpressionTransformer { 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); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java index 62e21f204..ad32098ba 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java @@ -8,7 +8,8 @@ public interface ExpressionVisitor { 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); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java index 5d1d2eb95..ac61eb486 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java @@ -2,6 +2,7 @@ package org.simantics.scl.compiler.elaboration.expressions; 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; @@ -9,6 +10,7 @@ import org.simantics.scl.compiler.elaboration.equation.EquationVisitor; 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; @@ -118,9 +120,12 @@ EquationVisitor { } @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 consumer) { } + + @Override + public CHRRuleset getRuleset(String name) throws AmbiguousNameException { + return null; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java index df86c1130..3be214d2d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java @@ -7,6 +7,7 @@ import java.util.function.Consumer; 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; @@ -107,6 +108,10 @@ public class Environments { 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. @@ -332,6 +337,13 @@ public class Environments { return ns.getTypeClass(name); } }; + + private static final NamespaceValueAccessor getRuleset = new NamespaceValueAccessor() { + @Override + public CHRRuleset get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getRuleset(name); + } + }; private static T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor accessor) throws AmbiguousNameException { Namespace namespace = environment.getLocalNamespace(); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java index 9b4712c84..e5af69204 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java @@ -1,9 +1,8 @@ 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; @@ -70,6 +69,8 @@ public interface Namespace { */ 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 diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java index 0c97d308a..214749bcb 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java @@ -1,10 +1,9 @@ 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; @@ -268,6 +267,33 @@ public class NamespaceImpl implements Namespace { return result; } + @Override + public CHRRuleset getRuleset(String name) throws AmbiguousNameException { + CHRRuleset result = null, temp; + Module resultModule = null; + ArrayList 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(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 proc) { for(ModuleImport moduleImport : moduleImports) diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java index 3f95fa507..37f1202e3 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java @@ -1,6 +1,7 @@ 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 { @@ -34,4 +35,12 @@ 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"; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java index e68ed2bae..865ab22e6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java @@ -5,6 +5,7 @@ import java.util.ArrayList; 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; @@ -20,6 +21,7 @@ public class CHRFactCodeGenerator implements CHRCodeGenerationConstants { private JavaTypeTranslator jtt; private ClassBuilder storeClassBuilder; + private CHRRuleset ruleset; private CHRConstraint constraint; private String factClassName; @@ -32,8 +34,9 @@ public class CHRFactCodeGenerator implements CHRCodeGenerationConstants { 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(); @@ -123,7 +126,7 @@ public class CHRFactCodeGenerator implements CHRCodeGenerationConstants { 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(); @@ -205,13 +208,30 @@ public class CHRFactCodeGenerator implements CHRCodeGenerationConstants { } // 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(); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRPriorityFactContainerCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRPriorityFactContainerCodeGenerator.java index 7ee11f05e..496a33b36 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRPriorityFactContainerCodeGenerator.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRPriorityFactContainerCodeGenerator.java @@ -6,20 +6,18 @@ import java.util.concurrent.atomic.AtomicReference; 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; @@ -73,9 +71,9 @@ public class CHRPriorityFactContainerCodeGenerator implements CHRCodeGenerationC } 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)); @@ -102,8 +100,7 @@ public class CHRPriorityFactContainerCodeGenerator implements CHRCodeGenerationC planMap.forEachEntry(new TObjectObjectProcedure>() { @Override public boolean execute(CHRConstraint constraint, ArrayList plans) { - int nextPriority = constraint.nextPriority; - constraint.nextPriority = rule.priority; + int nextPriority = ruleset.getAndUpdateNextPriority(constraint, rule.priority); Label next = nextLabel.get(); if(next != null) @@ -132,6 +129,21 @@ public class CHRPriorityFactContainerCodeGenerator implements CHRCodeGenerationC 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; @@ -148,8 +160,6 @@ public class CHRPriorityFactContainerCodeGenerator implements CHRCodeGenerationC mb.finish(); } - private THashSet usedParameters = new THashSet(); - // protected abstract void activate(CHRContext context, CHRFact fact); private void generateActivate(CHRConstraint constraint, CHRSearchPlan plan, int id) { @@ -159,31 +169,11 @@ public class CHRPriorityFactContainerCodeGenerator implements CHRCodeGenerationC 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 { 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(); } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java index 003086704..9ff56eda4 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java @@ -7,30 +7,33 @@ import org.objectweb.asm.Opcodes; import org.simantics.scl.compiler.elaboration.chr.CHRRule; import org.simantics.scl.compiler.elaboration.chr.CHRRuleset; import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint; +import org.simantics.scl.compiler.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 hashIndexInitializations = new ArrayList(); 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 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 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 hashIndexInitializations) { - CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, constraint); + private static void generateFact(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRConstraint constraint, ArrayList hashIndexInitializations) { + CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, ruleset, constraint); generator.generate(hashIndexInitializations); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java index aaab03e1a..ba9d62d27 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java @@ -530,7 +530,7 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder { public void markGenerateOnFly() { for(SSAStatement stat = firstStatement; stat != null; stat = stat.next) - stat.markGenerateOnFly(); + stat.markGenerateOnFly(); } public SSABlock copy(CopyContext context) { diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAClosure.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAClosure.java index 17c695e51..57748b284 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAClosure.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAClosure.java @@ -19,7 +19,7 @@ import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor; 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; diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java index b8b7def59..6d139a4d6 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java @@ -77,7 +77,7 @@ public class LetApply extends LetStatement implements ValRefBinder { @Override public void toString(PrintingContext context) { - if(determineGenerateOnFly()) + if(/*target.getLabel() == null &&*/ determineGenerateOnFly()) context.addInlineExpression(target, this); else toStringAux(context); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java index cf46899f6..9f6fe9f01 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java @@ -164,6 +164,7 @@ public class LetFunctions extends SSAStatement implements ClosureBinder { 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); @@ -211,7 +212,7 @@ public class LetFunctions extends SSAStatement implements ClosureBinder { 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()); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/StandardTypeConstructor.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/StandardTypeConstructor.java index bbcd370bb..6af3bd310 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/StandardTypeConstructor.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/StandardTypeConstructor.java @@ -9,7 +9,7 @@ import org.simantics.scl.compiler.types.kinds.Kind; 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); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java index 0fe185e61..5316b861d 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java @@ -28,7 +28,8 @@ public class ClassBuilder { 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); @@ -96,9 +97,13 @@ public class ClassBuilder { methodVisitor.visitEnd(); } - public MethodBuilderBase addConstructor(int access, TypeDesc[] params) { + public MethodBuilderBase addConstructorBase(int access, TypeDesc[] params) { return addMethodBase(access, "", TypeDesc.VOID, params); } + + public MethodBuilder addConstructor(int access, TypeDesc[] params) { + return addMethod(access, "", TypeDesc.VOID, params); + } public MethodBuilder addInitializer() { return addMethod(Opcodes.ACC_PUBLIC, "", TypeDesc.VOID, Constants.EMPTY_TYPEDESC_ARRAY); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/CodeBuilderUtils.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/CodeBuilderUtils.java index 81f7b117a..71ce63e5c 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/CodeBuilderUtils.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/CodeBuilderUtils.java @@ -27,7 +27,7 @@ public class CodeBuilderUtils { 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(); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java index 843659d6c..bd1a911a1 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java @@ -25,6 +25,10 @@ public class MethodBuilderBase { } methodVisitor.visitCode(); } + + public LocalVariable getThis(TypeDesc type) { + return new LocalVariable(0, type); + } public void loadConstant(boolean value) { if(value) diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ModuleBuilder.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ModuleBuilder.java index 8db288a89..32d428339 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ModuleBuilder.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ModuleBuilder.java @@ -124,7 +124,7 @@ public class ModuleBuilder { // 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 }); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java index 33a88ffba..80acf17c5 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java @@ -6,17 +6,18 @@ import org.simantics.scl.compiler.elaboration.expressions.EVar; 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 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) @@ -52,16 +53,21 @@ public class ModuleHeader { 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; } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DModuleHeader.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DModuleHeader.java deleted file mode 100644 index 25d14e2d2..000000000 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DModuleHeader.java +++ /dev/null @@ -1,36 +0,0 @@ -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;iJFlex 1.6.1 - * from the specification file C:/GamsGui/git/platform/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex + * from the specification file C:/Simugawa.git/git/platform/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex */ public class SCLLexer { @@ -589,6 +590,7 @@ 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()); @@ -596,6 +598,12 @@ public class SCLLexer { 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; + } /** @@ -1196,7 +1204,7 @@ public class SCLLexer { } case 157: break; case 63: - { return sym(SCLTerminals.RULE); + { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.RULE); } case 158: break; case 64: @@ -1276,7 +1284,7 @@ public class SCLLexer { } case 177: break; case 83: - { return sym(SCLTerminals.RULESET); + { return sym(supportCHR() ? SCLTerminals.RULESET : SCLTerminals.ID); } case 178: break; case 84: @@ -1316,7 +1324,7 @@ public class SCLLexer { } case 187: break; case 93: - { return sym(SCLTerminals.TRANSFORMATION); + { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.TRANSFORMATION); } case 188: break; case 94: diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java index 08e6a4f2d..09fc79e0f 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java @@ -8,6 +8,7 @@ import java.util.List; 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; @@ -53,6 +54,7 @@ import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement; 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; @@ -73,6 +75,7 @@ import org.simantics.scl.compiler.elaboration.query.pre.QPreBinds; 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; @@ -86,9 +89,9 @@ import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst; 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; @@ -113,9 +116,15 @@ public class SCLParserImpl extends SCLParser { 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) { @@ -158,7 +167,7 @@ public class SCLParserImpl extends SCLParser { for(int i=0;i> typeClassInstances = new THashMap>(); THashMap values = new THashMap(); THashMap> fieldAccessors = new THashMap>(); - THashMap relations = new THashMap(); - THashMap entityTypes = new THashMap(); - THashMap rules = new THashMap(); - THashMap mappingRelations = new THashMap(); + THashMap relations = new THashMap(2); + THashMap entityTypes = new THashMap(2); + THashMap rules = new THashMap(2); + THashMap mappingRelations = new THashMap(2); + THashMap rulesets = new THashMap(2); ArrayList dependencies = new ArrayList(); THashMap branchPoints; CompilationError[] warnings = CompilationError.EMPTY_ARRAY; @@ -191,6 +193,11 @@ public class ConcreteModule implements Module { return effectConstructors.get(name); } + @Override + public CHRRuleset getRuleset(String name) { + return rulesets.get(name); + } + public Collection getTypeClasses() { return typeClasses.values(); } @@ -315,4 +322,8 @@ public class ConcreteModule implements Module { } list.add(accessor); } + + public void addRuleset(String name, CHRRuleset ruleset) { + rulesets.put(name, ruleset); + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java index a53a90b91..61d2c2928 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java @@ -5,6 +5,7 @@ import java.util.Collections; 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; @@ -146,4 +147,9 @@ public abstract class LazyModule implements Module { public CompilationError[] getWarnings() { return CompilationError.EMPTY_ARRAY; } + + @Override + public CHRRuleset getRuleset(String name) { + return null; + } } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java index 51d39e103..ee90b5e1a 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java @@ -5,6 +5,7 @@ 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.Documentation; import org.simantics.scl.compiler.elaboration.modules.SCLValue; import org.simantics.scl.compiler.elaboration.modules.TypeClass; @@ -40,6 +41,7 @@ public interface Module { Collection getInstances(TCon typeClass); MappingRelation getMappingRelation(String name); TransformationRule getRule(String name); + CHRRuleset getRuleset(String name); Collection getRules(); void findValuesForPrefix(String prefix, NamespaceFilter filter, TObjectProcedure proc); diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java index 4ed45005b..5ae73c412 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java @@ -117,7 +117,7 @@ public class RuntimeModule { 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); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java index 2b42bc7ba..a5b9a6541 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java @@ -236,7 +236,7 @@ public class ExpressionEvaluator { ArrayList lvTypes = new ArrayList(); if(expression instanceof EBlock) { EBlock block = (EBlock)expression; - if(localStorage != null && !(block.getStatements().getLast() instanceof GuardStatement)) { + if(localStorage != null && !(block.getLast() instanceof GuardStatement)) { THashSet localVariables = new THashSet(); ListIterator it = block.getStatements().listIterator(); while(it.hasNext()) { @@ -264,7 +264,7 @@ public class ExpressionEvaluator { 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]))); } diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/SCLCompilerConfiguration.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/SCLCompilerConfiguration.java index 57f7102cb..1331530dd 100644 --- a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/SCLCompilerConfiguration.java +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/SCLCompilerConfiguration.java @@ -33,5 +33,9 @@ public interface SCLCompilerConfiguration { 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; + } } diff --git a/bundles/org.simantics.scl.runtime/scl/TestCHR.scl b/bundles/org.simantics.scl.runtime/scl/TestCHR.scl deleted file mode 100644 index 7958317c1..000000000 --- a/bundles/org.simantics.scl.runtime/scl/TestCHR.scl +++ /dev/null @@ -1,15 +0,0 @@ -import "StandardLibrary" - -topologicalSort :: Show a => [(a,a)] -> [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)] diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/info/SCLInfo.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/info/SCLInfo.java index 63b2338f4..33b5fc7e9 100644 --- a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/info/SCLInfo.java +++ b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/info/SCLInfo.java @@ -3,6 +3,8 @@ package org.simantics.scl.ui.info; public class SCLInfo { public static String[] RESERVED_WORDS = new String[] { + "module", + "data", "type", "effect", @@ -33,6 +35,7 @@ public class SCLInfo { "as", "forall", "rule", + "ruleset", "extends", "by", "select", diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ActiveTests.java b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ActiveTests.java index de215c092..fe18da61d 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ActiveTests.java +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ActiveTests.java @@ -1,7 +1,5 @@ package org.simantics.scl.compiler.tests; -import org.junit.Test; - public class ActiveTests extends TestBase { public ActiveTests() { super("scl"); } @@ -20,6 +18,4 @@ public class ActiveTests extends TestBase { //@Test public void Bug6989() { test(); } - @Test public void CHR5() { test(); } - } diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java index f50056e8d..1c0100425 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java @@ -26,6 +26,8 @@ public class ModuleRegressionTests extends TestBase { @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(); } diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl index e3c8b8c27..00ca32bec 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl @@ -1,16 +1,34 @@ +module { + export = [main], + chr +} + import "StandardLibrary" -topologicalSort :: Show a => [(a,a)] -> [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 -> () +addSet set newElement = () + where + include IntegerSet set + True => Element newElement -main = topologicalSort [(2,4),(3,7),(7,2),(1,3)] +printSet :: IntegerSet -> () +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 +() diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR6.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR6.scl new file mode 100644 index 000000000..c18a13a5a --- /dev/null +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR6.scl @@ -0,0 +1,23 @@ +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 +-- +() diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/unit/TestCHRCodeGenerator.java b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/unit/TestCHRCodeGenerator.java index 5a04ed6f3..2ec8ad5d6 100644 --- a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/unit/TestCHRCodeGenerator.java +++ b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/unit/TestCHRCodeGenerator.java @@ -56,7 +56,7 @@ public class TestCHRCodeGenerator { 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);