(refs #7250) Merging master, minor CHR bugfixes 90/590/1
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Fri, 2 Jun 2017 13:39:28 +0000 (16:39 +0300)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Fri, 2 Jun 2017 14:34:55 +0000 (17:34 +0300)
Change-Id: I11c76beee0e73ff78370f72bbfb88fdbdf6c7616

90 files changed:
bundles/org.simantics.scl.compiler/src/org/cojen/classfile/TypeDesc.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/commands/CommandSession.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/exceptions/InternalCompilerError.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/common/names/Names.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/DeclarationClassification.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/Elaboration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/NamespaceOfModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/FunctionValue.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRulesetObject.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/CHRConstraintGGInfo.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/analysis/UsageAnalysis.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/CHRSearchPlan.java [moved from bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PrioritizedPlan.java with 59% similarity]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/ClaimOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateConstraintOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanRealizer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PreCommitOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/relations/CHRConstraint.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TranslationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/contexts/TypeTranslationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EBlock.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ECHRRulesetConstructor.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EPreCHRRulesetConstructor.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionTransformer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ExpressionVisitor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionVisitor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/block/IncludeStatement.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/block/StatementVisitor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/printing/ExpressionToStringVisitor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/EmptyNamespace.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Namespace.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/NamespaceImpl.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerationConstants.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerator.java [deleted file]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRFactCodeGenerator.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRHashIndexCodeGenerator.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRPriorityFactContainerCodeGenerator.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRRuntimeRulesetCodeGenerator.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/ExampleStore.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAClosure.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAFunction.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/types/StandardTypeConstructor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ClassBuilder.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/CodeBuilderUtils.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/ModuleBuilder.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/header/ModuleHeader.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DModuleHeader.java [deleted file]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DRulesetAst.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCL.grammar
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParserImpl.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLPostLexer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLTerminals.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/ConcreteModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/LazyModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/Module.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/SCLCompilerConfiguration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/types/Types.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRContext.java [new file with mode: 0644]
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRFact.java [new file with mode: 0644]
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriority.java [new file with mode: 0644]
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriorityFactContainer.java [new file with mode: 0644]
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRRuntimeRuleset.java [new file with mode: 0644]
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/Fact.java [deleted file]
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java [deleted file]
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/PriorityContainer.java [deleted file]
bundles/org.simantics.scl.runtime/tests/org/simantics/scl/runtime/tests/TestFactActivationQueue.java [deleted file]
bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/info/SCLInfo.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ActiveTests.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/ModuleRegressionTests.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR6.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/unit/TestCHRCodeGenerator.java

index acf2bb18d643ae4f40c1d3a6d1896d9782787f63..5843b89e32eae40bb25d84a9e28fee05b017a9ad 100644 (file)
@@ -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;
+    }
 }
index 1cf6d0de9c5f0786fe4df80072602e22670f514e..a8f3d2045efb105928e18c951d1322410bd13a0f 100644 (file)
@@ -423,10 +423,9 @@ public class CommandSession {
         void finishBlock() {
             if(currentBlock != null) {
                 checkInterrupted();
-                LinkedList<Statement> statements = currentBlock.getStatements();
                 currentBlock.location = Locations.combine(
-                        statements.getFirst().location,
-                        statements.getLast().location);
+                        currentBlock.getFirst().location,
+                        currentBlock.getLast().location);
                 execute(reader, currentBlock, handler);
                 currentBlock = null;
             }
index ae3bdd87ca368ed06cddf8c42f209ea339c63b1f..71b6193015b1b4aafb8d9e0cc226131a0f7f928b 100644 (file)
@@ -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;
+    }
    
 }
index 1c4255b46c14ae83b9455fba3afb450a9d5e432e..50729430db70e2a07f7cfa894424b82cfdc058b4 100644 (file)
@@ -12,6 +12,7 @@ public class Names {
     public static final Name Builtin_equals = Name.create(Types.BUILTIN, "==");
     public static final Name Builtin_fail = Name.create(Types.BUILTIN, "fail");
     public static final Name Builtin_runProc = Name.create(Types.BUILTIN, "runProc");
+    public static final Name Builtin_createCHRContext = Name.create(Types.BUILTIN, "createCHRContext");
     public static final Name Data_XML_createElement = Name.create("Data/XML", "createElement");
     public static final Type Data_XML_Element = Types.con("Data/XML", "Element");
     public static final TCon Expressions_Context_Context = Types.con("Expressions/Context", "Context");    
index cc883c0eafc9ceefd03212975777a54377419beb..5d258dd9e2b819c9d2ea4576718c65522586c384 100644 (file)
@@ -189,7 +189,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);            
         }
@@ -205,7 +205,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);            
         }
@@ -217,7 +217,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);
         }
index 652adf93efc769cb30cce495d99a53ed665bd35b..4bf5d847e8d8d745cd62c294ec51e8d786dbf6c2 100644 (file)
@@ -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<ImportDeclaration> importsAst = new ArrayList<ImportDeclaration>();
     ArrayList<DDataAst> dataTypesAst = new ArrayList<DDataAst>();
     ArrayList<DTypeAst> typeAliasesAst = new ArrayList<DTypeAst>();
@@ -53,6 +52,7 @@ public class DeclarationClassification {
     ArrayList<DEffectAst> effectsAst = new ArrayList<DEffectAst>();
     ArrayList<DRuleAst> rulesAst = new ArrayList<DRuleAst>();
     ArrayList<DMappingRelationAst> mappingRelationsAst = new ArrayList<DMappingRelationAst>();
+    ArrayList<DRulesetAst> rulesetsAst = new ArrayList<DRulesetAst>();
     
     THashMap<String, DDocumentationAst> valueDocumentation = new THashMap<String, DDocumentationAst>();
     THashMap<String, DDocumentationAst> relationDocumentation = new THashMap<String, DDocumentationAst>();
@@ -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) {
index 7887ed717f032b7d29aed50782a69e0f6b42c916..359448e1d65adf505e970e80e328ddb8d62cc079 100644 (file)
@@ -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;
@@ -48,6 +50,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;
@@ -85,6 +88,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;
@@ -212,7 +216,8 @@ public class Elaboration {
     public void addTypesToEnvironment(
             ArrayList<DDataAst> dataTypesAst,
             ArrayList<DTypeAst> typeAliasesAst,
-            ArrayList<DEffectAst> effectsAst) {
+            ArrayList<DEffectAst> effectsAst,
+            ArrayList<DRulesetAst> rulesetsAst) {
         for(DDataAst dataType : dataTypesAst) {
             dataType.parameterKinds = new Kind[dataType.parameters.length];
             Kind constructorKind = Kinds.STAR;
@@ -227,8 +232,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;
         }
         
@@ -236,9 +240,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) {
@@ -249,11 +251,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];
     
@@ -704,6 +719,18 @@ public class Elaboration {
         }
     }
     
+    public void processRulesets(ArrayList<DRulesetAst> rulesetsAst) {
+        for(DRulesetAst ruleset : rulesetsAst) {
+            String constructorName = "create" + ruleset.name;
+            supplementedTypeAnnotations.add(new SupplementedValueType(ruleset.location, constructorName, Types.functionE(Types.PUNIT, Types.PROC, ruleset.type)));
+            try {
+                valueDefinitionsAst.add(new DValueAst(new EVar(constructorName), new EPreCHRRulesetConstructor(ruleset)));
+            } catch (NotPatternException e) {
+                throw new InternalCompilerError(ruleset.location, e);
+            }
+        }
+    }
+    
     /**
      * Convert a java class method into a {@link CallJava} instance.
      * Compilation errors are logged for failures in finding the named class or in accessing the method.
index 77e6e96df9a4390f4c7ef4ef70758f20b15d35f7..8621283b73dc5e12bb7a1c5473d36cc438518567 100644 (file)
@@ -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 {
index 643513d67720537450e8c98fbd411bdd781b000e..cd43b76e15dec63e81b6ca704238ee2f956aec4c 100644 (file)
@@ -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<DeclarationAst>)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);
index d37b75089f9aab03a6a0eb908d425548fa78396a..dcef289f02763d9521532f30bc02bd7242714e52 100644 (file)
@@ -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});
index 48aefbdac541459f783c7becb5d013bd488d6a9b..b30021c1c514b1e9f7542973f8ec25c96560bfdc 100644 (file)
@@ -1,8 +1,10 @@
 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.PlanOp;
-import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;
+import org.simantics.scl.compiler.elaboration.chr.plan.CHRSearchPlan;
 import org.simantics.scl.compiler.elaboration.chr.planning.QueryPlanningContext;
 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
@@ -28,9 +30,15 @@ public class CHRRule extends Symbol {
     public Variable[] existentialVariables;
     
     // Analysis
-    public int firstPriorityExecuted;
+    //public int firstPriorityExecuted;
     public int lastPriorityExecuted;
     
+    // Plans
+    public ArrayList<CHRSearchPlan> plans = new ArrayList<CHRSearchPlan>();
+    
+    // Code generation, move to CHRPriority
+    public String containerClassName;
+    
     public CHRRule(long location, CHRQuery head, CHRQuery body, Variable[] existentialVariables) {
         this.location = location;
         this.head = head;
@@ -98,7 +106,7 @@ public class CHRRule extends Symbol {
             if(!head.createQueryPlan(context, new EVariable(activeFact), i))
                 return;
             body.createEnforcePlan(context, priority);
-            constraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));
+            addPlan(new CHRSearchPlan(constraint, activeFact, context.getPlanOps()));
             
             hasActiveLiteral = true;
         }
@@ -111,10 +119,14 @@ public class CHRRule extends Symbol {
             /*System.out.println(this);
             for(PlanOp planOp : context.getPlanOps())
                 System.out.println("    " + planOp);*/
-            initConstraint.plans.add(new PrioritizedPlan(priority, activeFact, context.getPlanOps()));
+            addPlan(new CHRSearchPlan(initConstraint, activeFact, context.getPlanOps()));
         }
     }
     
+    private void addPlan(CHRSearchPlan plan) {
+        plans.add(plan);
+    }
+
     public String toString() {
         StringBuilder b = new StringBuilder();
         ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
index bb5491ad17111c79aa7fc30ee2742cd2ef782149..bb00f08850f8fa3cd6f21586a8b60a6e052ff640 100644 (file)
@@ -7,23 +7,30 @@ import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.constants.BooleanConstant;
 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;
-import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;
 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 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.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.CHRCodeGenerator;
+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;
@@ -31,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;
@@ -42,15 +51,22 @@ public class CHRRuleset extends Symbol {
     
     public ArrayList<CHRConstraint> constraints = new ArrayList<CHRConstraint>();
     public ArrayList<CHRRule> rules = new ArrayList<CHRRule>();
+    public ArrayList<IncludeStatement> includes = new ArrayList<IncludeStatement>();
+    public THashMap<CHRConstraint, IncludeStatement> constraintSourceMap = new THashMap<CHRConstraint, IncludeStatement>();
+    public THashMap<CHRConstraint, CHRConstraintGGInfo> activeConstraintGGInfo = new THashMap<CHRConstraint, CHRConstraintGGInfo>(); // contains also imported constraints
+    public THashMap<IncludeStatement, ArrayList<CHRConstraint>> inverseActiveConstraintSourceMap = new THashMap<IncludeStatement, ArrayList<CHRConstraint>>();
+    
+    public boolean extensible;
     
     public CHRConstraint initConstraint;
     public int priorityCount;
     
-    public String storeClassName;
-    public TCon storeType;
-    public BoundVar storeVariable;
-    public TypeDesc storeTypeDesc;
-    public Constant activateProcedure;
+    public int initialPriorityNumber = 0;
+    
+    public String runtimeRulesetClassName;
+    public TCon runtimeRulesetType;
+    public BoundVar runtimeRulesetVariable;
+    public TypeDesc runtimeRulesetTypeDesc;
     public Constant readCurrentId;
     public Constant writeCurrentId;
     
@@ -58,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);
@@ -68,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;
@@ -81,26 +118,36 @@ public class CHRRuleset extends Symbol {
     }
 
     public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
+        for(IncludeStatement include : includes)
+            include.value.collectRefs(allRefs, refs);
         for(CHRRule rule : rules)
             rule.collectRefs(allRefs, refs);
     }
 
     public void checkType(TypingContext context) {
+        for(IncludeStatement include : includes)
+            include.value = include.value.checkType(context, include.ruleset.runtimeRulesetType);
         for(CHRRule rule : rules)
             rule.checkType(context);
     }
 
     public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+        for(IncludeStatement include : includes)
+            include.value.collectVars(allVars, vars);
         for(CHRRule rule : rules)
             rule.collectVars(allVars, vars);
     }
 
     public void forVariables(VariableProcedure procedure) {
+        for(IncludeStatement include : includes)
+            include.value.forVariables(procedure);
         for(CHRRule rule : rules)
             rule.forVariables(procedure);
     }
 
     public void collectFreeVariables(THashSet<Variable> vars) {
+        for(IncludeStatement include : includes)
+            include.value.collectFreeVariables(vars);
         for(CHRRule rule : rules)
             rule.collectFreeVariables(vars);
     }
@@ -112,77 +159,167 @@ 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<CHRConstraint> list = inverseActiveConstraintSourceMap.get(include);
+                        if(list == null) {
+                            list = new ArrayList<CHRConstraint>(4);
+                            inverseActiveConstraintSourceMap.put(include, list);
+                        }
+                        list.add(constraint);
+                    }
+                }
+            }
+        }
         // remove init constraint if it is not useful
-        if(initConstraint.plans.isEmpty()) {
+        if(getMinimumPriority(initConstraint) == Integer.MAX_VALUE) {
             constraints.remove(0);
             initConstraint = null;
         }
+    }
+
+    private void applyExtensibleDefaults() {
         for(CHRConstraint constraint : constraints) {
-            constraint.plans.sort((PrioritizedPlan a, PrioritizedPlan b) -> {
-                return Integer.compare(a.priority, b.priority);
-            });
-            /*System.out.println(constraint.name);
-            for(PrioritizedPlan plan : constraint.plans) {
-                System.out.println("  priority " + plan.priority);
-                for(PlanOp op : plan.ops)
-                    System.out.println("    " + op);
-            }*/
+            // FIXME Too much indexing!!!
+            int max = 1 << constraint.parameterTypes.length;
+            for(int i=0;i<max;++i)
+                constraint.getOrCreateIndex(cachedContext, i);
+            constraint.setMayBeRemoved();
+            /*
+            constraint.getOrCreateIndex(cachedContext, 0);
+            if(constraint.parameterTypes.length > 0)
+                constraint.getOrCreateIndex(cachedContext, 1);*/
         }
     }
 
     public void simplify(SimplificationContext context) {
+        for(IncludeStatement include : includes)
+            include.value = include.value.simplify(context);
         for(CHRRule rule : rules)
             rule.simplify(context);
     }
     
+    public void setRulesetType(TCon type, String className) {
+        this.runtimeRulesetType = type;
+        this.runtimeRulesetClassName = className;
+    }
+    
     public void initializeCodeGeneration(CompilationContext context) {
         cachedContext = context; // FIXME remove
         
-        String suffix = context.namingPolicy.getFreshClosureClassNameSuffix();
-        storeType = Types.con(context.namingPolicy.getModuleName(), "CHR" + suffix);
-        storeClassName = context.namingPolicy.getModuleClassName() + suffix;
-        storeTypeDesc = TypeDesc.forClass(storeClassName);
-        storeVariable = new BoundVar(storeType); 
+        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);
-        activateProcedure = new JavaMethod(true, storeClassName, "activate", Types.PROC, Types.UNIT, storeType, Types.INTEGER);
-        readCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {storeType},
-                null, new FieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null);
-        writeCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {storeType, Types.INTEGER},
-                null, new SetFieldRef(storeClassName, "currentId", CHRCodeGenerator.FACT_ID_TYPE), null);
-        if(context.module != null) // for unit testing
-            context.module.addTypeDescriptor(storeType.name, new StandardTypeConstructor(storeType, TVar.EMPTY_ARRAY, storeTypeDesc));
+        readCurrentId = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {Types.CHRContext},
+                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(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) {
-        CHRRulesetObject object = new CHRRulesetObject(storeVariable, this);
+    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(CHRConstraint constraint : constraints) {
-            //System.out.println(constraint);
-            for(PrioritizedPlan plan : constraint.plans) {
+        for(CHRRule rule : rules) {
+            for(CHRSearchPlan plan : rule.plans) {
                 /*System.out.println("    plan " + plan.priority);
                 for(PlanOp planOp : plan.ops)
                     System.out.println("        " + planOp);*/
-                PlanRealizer realizer = new PlanRealizer(cachedContext, this, storeVariable, plan.ops);
-                CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.BOOLEAN, new Type[] {constraint.factType});
+                CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.BOOLEAN, new Type[] {Types.CHRContext, plan.constraint.factType});
                 plan.implementation = methodWriter.getFunction();
-                plan.activeFact.setVal(methodWriter.getParameters()[0]);
+                IVal[] implementationParameters = methodWriter.getParameters();
+                plan.activeFact.setVal(implementationParameters[1]);
+                PlanRealizer realizer = new PlanRealizer(cachedContext, this, runtimeRulesetVariable, implementationParameters[0], plan.ops);
                 realizer.nextOp(methodWriter);
                 if(methodWriter.isUnfinished())
                     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, storeVariable, initFact);
-            w.apply(location, activateProcedure, storeVariable, new IntegerConstant(Integer.MAX_VALUE));
+            w.apply(location, initConstraint.addProcedure, runtimeRulesetVariable, chrContext, initFact);
+            w.apply(location, ACTIVATE, chrContext, new IntegerConstant(Integer.MAX_VALUE));
+            if(deinitializer != null) {
+                w.apply(location,
+                        new JavaMethod(true, runtimeRulesetClassName, "deinitialize", Types.PROC, Types.UNIT, new Type[] {runtimeRulesetType, Types.CHRContext}),
+                        object.getTarget(), chrContext);
+            }
         }
+        return runtimeRulesetVariable;
     }
 
     public void collectEffects(THashSet<Type> effects) {
index 73ba8ea1a1c4e5fc21822a15ded514e380d31785..96e86aed1df99760e52a6f6184665c0f50364238 100644 (file)
@@ -1,31 +1,83 @@
 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.CHRCodeGenerator;
+import org.simantics.scl.compiler.internal.codegen.chr.CHRRuntimeRulesetCodeGenerator;
 import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
 import org.simantics.scl.compiler.internal.codegen.ssa.SSAObject;
+import org.simantics.scl.compiler.internal.codegen.utils.LocalVariable;
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;
 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
 import org.simantics.scl.compiler.types.Types;
 
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TIntProcedure;
+import gnu.trove.set.hash.TIntHashSet;
+
 public class CHRRulesetObject extends SSAObject {
     CHRRuleset ruleset;
 
+    public BoundVar this_;
+    public BoundVar[] parameters;
+    public TObjectIntHashMap<BoundVar> parameterIndexMap; 
+    public TypeDesc[] parameterTypeDescs;
+    
     public CHRRulesetObject(BoundVar target, CHRRuleset ruleset) {
-        super(ruleset.storeType);
+        super(ruleset.runtimeRulesetType);
         this.setTarget(target);
         this.ruleset = ruleset;
     }
     
     @Override
     public Constant liftClosure(BoundVar newTarget, BoundVar[] parameters) {
-        ruleset.this_ = newTarget;
-        ruleset.parameters = parameters;
-        return new JavaConstructor(ruleset.storeClassName, Types.PROC, ruleset.storeType, Types.getTypes(parameters));
+        ruleset.rulesetObject = this;
+        this.this_ = newTarget;
+        this.parameters = parameters;
+        this.parameterIndexMap = new TObjectIntHashMap<>(parameters.length);
+        for(int i=0;i<parameters.length;++i)
+            this.parameterIndexMap.put(parameters[i], i);
+        return new JavaConstructor(ruleset.runtimeRulesetClassName, Types.PROC, ruleset.runtimeRulesetType, Types.getTypes(parameters));
     }
     
     @Override
     public void generateCode(ModuleBuilder moduleBuilder) {
-        CHRCodeGenerator.generateStore(moduleBuilder, ruleset);
+        CHRRuntimeRulesetCodeGenerator.generateRuntimeRuleset(moduleBuilder, ruleset);
+    }
+    
+    @FunctionalInterface
+    public interface ParameterDefiner {
+        public void defineParameter(int index, BoundVar var);
+    }
+    
+    public void realizeMethod(MethodBuilder mb, ParameterDefiner loader, SSAFunction function, LocalVariable this_, LocalVariable ... callParameters) {
+        mb.setLocalVariable(this.this_, this_);
+        BoundVar[] functionParameters = function.getParameters();
+        if(functionParameters.length != callParameters.length)
+            throw new InternalCompilerError();
+        for(int i=0;i<callParameters.length;++i)
+            mb.setLocalVariable(functionParameters[i], callParameters[i]);
+
+        // Set closure parameters
+        TIntHashSet usedParameterIndices = new TIntHashSet(parameters.length);
+        function.forValRefs(valRef -> {
+            Val binding = valRef.getBinding();
+            if(parameterIndexMap.containsKey(binding))
+                usedParameterIndices.add(parameterIndexMap.get((BoundVar)binding));
+        });
+        usedParameterIndices.forEach(new TIntProcedure() {
+            @Override
+            public boolean execute(int i) {
+                loader.defineParameter(i, parameters[i]);
+                return true;
+            }
+        });
+
+        // Generate code
+        function.markGenerateOnFly();
+        function.generateCodeWithAlreadyPreparedParameters(mb);
     }
 }
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 (file)
index 0000000..dbe33d6
--- /dev/null
@@ -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;
+    }
+}
index 3d5e0246bfd0a44e62dee6312fd29e2f3a37384b..a738c1f42126ebc7d0f01788f2e48ce1129021f3 100644 (file)
@@ -12,13 +12,14 @@ import gnu.trove.map.hash.THashMap;
 public class UsageAnalysis {
     public static void analyzeUsage(CHRRuleset ruleset) {
         THashMap<CHRConstraint,ArrayList<CHRRule>> headConstraintMap = createHeadConstraintMap(ruleset);
-        calculateFirstPriorities(ruleset, headConstraintMap);
+        //calculateFirstPriorities(ruleset, headConstraintMap);
         calculateLastPriorities(ruleset, headConstraintMap);
-        for(CHRRule rule : ruleset.rules)
-            determinePassiveLiterals(rule);
+        if(!ruleset.extensible)
+            for(CHRRule rule : ruleset.rules)
+                determinePassiveLiterals(rule);
         //printPriorities(ruleset);
     }
-
+    /*
     private static void calculateFirstPriorities(CHRRuleset ruleset,
             THashMap<CHRConstraint, ArrayList<CHRRule>> headConstraintMap) {
         for(CHRRule rule : ruleset.rules)
@@ -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<CHRConstraint, ArrayList<CHRRule>> headConstraintMap) {
         for(CHRRule rule : ruleset.rules)
             rule.lastPriorityExecuted = Integer.MIN_VALUE;
-        for(CHRConstraint constraint : ruleset.constraints) {
+        for(CHRConstraint constraint : headConstraintMap.keySet()) {
             constraint.lastPriorityAdded = Integer.MIN_VALUE;
             constraint.lastPriorityRemoved = Integer.MIN_VALUE;
         }
@@ -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) {
similarity index 59%
rename from bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PrioritizedPlan.java
rename to bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/CHRSearchPlan.java
index f7a072e5d43cdc6dc42bf05827b08f359bff1e6c..f958e459b76956127b0f0224c734c74ede839a9b 100644 (file)
@@ -2,17 +2,18 @@ package org.simantics.scl.compiler.elaboration.chr.plan;
 
 import java.util.List;
 
+import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 import org.simantics.scl.compiler.elaboration.expressions.Variable;
 import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
 
-public class PrioritizedPlan {
-    public int priority;
+public class CHRSearchPlan {
+    public CHRConstraint constraint;
     public Variable activeFact;
     public List<PlanOp> ops;
     public SSAFunction implementation;
     
-    public PrioritizedPlan(int priority, Variable activeFact, List<PlanOp> ops) {
-        this.priority = priority;
+    public CHRSearchPlan(CHRConstraint constraint, Variable activeFact, List<PlanOp> ops) {
+        this.constraint = constraint;
         this.activeFact = activeFact;
         this.ops = ops;
     }
index ad6129aad8b59ec5e6c76151f5761527fc6d008a..5b7f81664770503a81b70ed59ac29804f602ece7 100644 (file)
@@ -31,7 +31,7 @@ public class ClaimOp extends PlanOp {
         for(int i=0;i<parameters.length;++i)
             parameterVars[i+1] = parameters[i].toVal(context.environment, w);
         IVal newFact = w.apply(location, constraint.constructor, parameterVars);
-        w.apply(location, constraint.addProcedure, planContext.storeVar, newFact);
+        w.apply(location, constraint.addProcedure, planContext.getStoreVar(constraint), planContext.contextVar, newFact);
         planContext.nextOp(w);
     }
 
index b51ca1e43549659e2afcdac4b2495f6920648758..95c341e9f369ecce5558f4ea0a1013da94a0c378 100644 (file)
@@ -12,7 +12,6 @@ import org.simantics.scl.compiler.elaboration.expressions.Variable;
 import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
 import org.simantics.scl.compiler.internal.codegen.references.IVal;
 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
-import org.simantics.scl.compiler.types.Types;
 
 public class IterateConstraintOp extends PlanOp {
     
@@ -56,7 +55,7 @@ public class IterateConstraintOp extends PlanOp {
         IVal fact = body.getParameters()[0];
 
         ArrayList<IVal> parameters = new ArrayList<IVal>(expressions.length+1);
-        parameters.add(planContext.storeVar);
+        parameters.add(planContext.getStoreVar(constraint));
         for(int i=0;i<expressions.length;++i)
             if(((boundMask>>i)&1)==1)
                 parameters.add(expressions[i].toVal(context.environment, w));
index aea2cbfdcd47b0921222e4ccde6a50fd0c34db1c..bc6b7da580e3b43a5e43bbf3b646fb1902ee01e7 100644 (file)
@@ -2,8 +2,6 @@ package org.simantics.scl.compiler.elaboration.chr.plan;
 
 import java.util.ArrayList;
 
-import javax.crypto.CipherInputStream;
-
 import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.constants.IntegerConstant;
 import org.simantics.scl.compiler.constants.JavaComparisonOperation;
@@ -12,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;
@@ -24,21 +24,23 @@ 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<PartnerFact> partnerFacts = new ArrayList<PartnerFact>();
     public IVal currentId;
     
-    public PlanContext(CompilationContext context, CHRRuleset ruleset, IVal storeVar) {
+    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;
     }
 
     public abstract void nextOp(CodeWriter w);
 
     public IVal generateNewId(long location, CodeWriter w) {
         if(currentId == null)
-            currentId = w.apply(location, ruleset.readCurrentId, storeVar);
+            currentId = w.apply(location, ruleset.readCurrentId, contextVar);
         IVal result = currentId;
         currentId = w.apply(location, IncreaseByOne.INSTANCE, currentId);
         return result;
@@ -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;
+    }
 }
index 0fbbcfba475be60a5f7c75ae5252c6b54e0c5f16..43fedf765aecb0d2581a0af5bf5f7e021cca0691 100644 (file)
@@ -11,8 +11,8 @@ public class PlanRealizer extends PlanContext {
     List<PlanOp> ops;
     int id = 0;
 
-    public PlanRealizer(CompilationContext context, CHRRuleset ruleset, IVal storeVar, List<PlanOp> ops) {
-        super(context, ruleset, storeVar);
+    public PlanRealizer(CompilationContext context, CHRRuleset ruleset, IVal storeVar, IVal contextVar, List<PlanOp> ops) {
+        super(context, ruleset, storeVar, contextVar);
         this.ops = ops;
     }
 
index af41f932b69f08084b6818134493606e33bb7574..5b3057dd9dc099da6d13121568f399fc912d4285 100644 (file)
@@ -3,6 +3,7 @@ package org.simantics.scl.compiler.elaboration.chr.plan;
 import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.constants.IntegerConstant;
 import org.simantics.scl.compiler.constants.singletons.NullCheck;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
 import org.simantics.scl.compiler.internal.codegen.references.IVal;
@@ -24,9 +25,9 @@ public class PostCommitOp extends PlanOp {
     @Override
     public void generateCode(CompilationContext context, PlanContext planContext, CodeWriter w) {
         if(planContext.currentId != null) {
-            w.apply(location, planContext.ruleset.writeCurrentId, planContext.storeVar, planContext.currentId);
+            w.apply(location, planContext.ruleset.writeCurrentId, planContext.contextVar, planContext.currentId);
             planContext.currentId = null;
-            w.apply(location, planContext.ruleset.activateProcedure, planContext.storeVar, new IntegerConstant(priority));
+            w.apply(location, CHRRuleset.ACTIVATE, planContext.contextVar, new IntegerConstant(priority+planContext.ruleset.initialPriorityNumber));
         }
         for(PartnerFact activeFact : planContext.partnerFacts) {
             if(activeFact.killAfterMatch) {
@@ -35,7 +36,7 @@ public class PostCommitOp extends PlanOp {
                 else {
                     CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType);
                     w.jump(iterateAlive.getContinuation(), w.apply(location, activeFact.nextFact, activeFact.factVar));
-                    iterateUntilLiveFactFound(iterateAlive, activeFact);                    
+                    iterateUntilLiveFactFound(iterateAlive, activeFact);
                 }
                 break;
             }
index 95e865be30afd94e1aceff39330bb5f8db642bbb..c4629f6d0c8e8c4f690163bbd544456dfe631e2b 100644 (file)
@@ -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);
     }
index 868d70a6f1b51faa2765fc14961d87c1007cd5e5..c0f43928877458cbb9a9241ad3e764481acd3ce5 100644 (file)
@@ -16,9 +16,8 @@ import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
 import org.simantics.scl.compiler.constants.generic.StackItem;
 import org.simantics.scl.compiler.elaboration.chr.CHRRelation;
 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
-import org.simantics.scl.compiler.elaboration.chr.plan.PrioritizedPlan;
-import org.simantics.scl.compiler.internal.codegen.chr.CHRCodeGenerator;
-import org.simantics.scl.compiler.internal.codegen.chr.CHRFactCodeGenerator;
+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.IVal;
 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
 import org.simantics.scl.compiler.internal.codegen.types.StandardTypeConstructor;
@@ -39,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,12 +55,10 @@ public class CHRConstraint extends Symbol implements CHRRelation {
     public Constant[] accessors;
     public Constant addProcedure;
     public Constant removeProcedure;
-    public Constant isAlive;
     
-    public TIntObjectHashMap<IndexInfo> indices;
+    public String nextContainerFieldName;
     
-    // Query plans
-    public ArrayList<PrioritizedPlan> plans = new ArrayList<PrioritizedPlan>();
+    public TIntObjectHashMap<IndexInfo> indices;
     
     public static class IndexInfo {
         public final int indexMask;
@@ -87,8 +84,8 @@ public class CHRConstraint extends Symbol implements CHRRelation {
         JavaTypeTranslator jtt = context.javaTypeTranslator;
         
         this.parentRuleset = parentRuleset;
-        this.factClassName = parentRuleset.storeClassName + "$" + name;
-        TCon factTypeConstructor = Types.con(parentRuleset.storeType.module, parentRuleset.storeType.name + "$" + 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);
         
@@ -109,24 +106,29 @@ public class CHRConstraint extends Symbol implements CHRRelation {
                 null);
         //this.constructor = new JavaConstructor(factClassName, Types.PROC, factType, constructorTypes);
         this.accessId = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, Types.INTEGER, new Type[] {factType},
-                null, new FieldRef(factClassName, "id", CHRCodeGenerator.FACT_ID_TYPE), null);
+                null, new FieldRef(CHRCodeGenerationConstants.CHRFact_name, "id", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE), null);
         this.accessors = new Constant[parameterTypes.length];
         for(int i=0;i<parameterTypes.length;++i) {
             TypeDesc typeDesc = jtt.toTypeDesc(parameterTypes[i]);
             if(typeDesc.equals(TypeDesc.VOID))
                 continue;
             this.accessors[i] = new CallJava(TVar.EMPTY_ARRAY, Types.NO_EFFECTS, parameterTypes[i], new Type[] {factType},
-                    null, new FieldRef(factClassName, CHRFactCodeGenerator.fieldName(i), jtt.toTypeDesc(parameterTypes[i])), null);
+                    null, new FieldRef(factClassName, CHRCodeGenerationConstants.fieldName(i), jtt.toTypeDesc(parameterTypes[i])), null);
         }
-        this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
-                new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
-                new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
+        this.addProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, Types.CHRContext, factType},
+                new StackItem[] {new ParameterStackItem(2, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType), new ParameterStackItem(1, Types.CHRContext)},
+                new ObjectMethodRef(false, factClassName, "add", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc, CHRCodeGenerationConstants.CHRContext}),
                 null);
         
         this.indices = new TIntObjectHashMap<IndexInfo>(Math.min(10, 1 << parameterTypes.length));
         
         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
@@ -154,19 +156,19 @@ public class CHRConstraint extends Symbol implements CHRRelation {
 
     private IndexInfo createIndexInfo(CompilationContext context, int indexMask) {
         ArrayList<Type> keyTypeList = new ArrayList<Type>(parameterTypes.length+1);
-        keyTypeList.add(parentRuleset.storeType);
+        keyTypeList.add(parentRuleset.runtimeRulesetType);
         for(int i=0;i<parameterTypes.length;++i)
             if(((indexMask>>i)&1)==1)
                 keyTypeList.add(parameterTypes[i]);
         String indexName = nameOfIndex(indexMask, parameterTypes.length);
         Constant accessIndex;
         if(indexMask == 0) {
-            accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.storeType},
-                    null, new FieldRef(parentRuleset.storeClassName, name + "$" + indexName, factTypeDesc), null);
+            accessIndex = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, factType, new Type[] {parentRuleset.runtimeRulesetType},
+                    null, new FieldRef(parentRuleset.runtimeRulesetClassName, name + "$" + indexName, factTypeDesc), null);
         }
         else {
             Type[] keyTypes = keyTypeList.toArray(new Type[keyTypeList.size()]);
-            accessIndex = new JavaMethod(true, parentRuleset.storeClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
+            accessIndex = new JavaMethod(true, parentRuleset.runtimeRulesetClassName, name + "$" + indexName, Types.PROC, factType, keyTypes);
         }
         return new IndexInfo(
                 indexMask,
@@ -177,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) {
@@ -192,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;
     }
 
     
@@ -205,22 +211,13 @@ public class CHRConstraint extends Symbol implements CHRRelation {
 
     public void setMayBeRemoved() {
         if(removeProcedure == null) {
-            removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.storeType, factType},
-                    new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.storeType)},
-                    new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.storeTypeDesc}),
+            removeProcedure = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {parentRuleset.runtimeRulesetType, factType},
+                    new StackItem[] {new ParameterStackItem(1, factType), new ParameterStackItem(0, parentRuleset.runtimeRulesetType)},
+                    new ObjectMethodRef(false, factClassName, "remove", TypeDesc.VOID, new TypeDesc[] {parentRuleset.runtimeRulesetTypeDesc}),
                     null);
-            isAlive = new JavaMethod(true, factClassName, "isAlive", Types.PROC, Types.BOOLEAN, factType);
         }
     }
 
-    public int getMinimumPriority() {
-        return plans.get(0).priority;
-    }
-    
-    public boolean isPassive() {
-        return plans.isEmpty();
-    }
-
     public TPred[] getTypeConstraints() {
         return TPred.EMPTY_ARRAY;
     }
index 203bd81d2d2bd925b9fd9ee969aa475db7b31331..d9746bb04c1d9a2524e82a03193c80a6773ee450 100644 (file)
@@ -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);
+    }
 }
index 927720611de5cab6816d5b517223bea54ff34995..1eea959fd249459273a9139008b86d29ac9a2d0c 100644 (file)
@@ -126,4 +126,8 @@ public class TypeTranslationContext {
             errorLog.log(loc, "Expected a type with kind " + expectedKind + " but got " + provided + ".");
         }
     }
+    
+    public CompilationContext getCompilationContext() {
+        return compilationContext;
+    }
 }
index c5f30417eed13983d839b211a1a8cf1f88aacc25..157efb360302cdf5767ce936f7c64454f9a5baa1 100644 (file)
@@ -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<Statement> statements = new LinkedList<Statement>();
+    ArrayList<Statement> statements = new ArrayList<Statement>();
     boolean monadic;
     
     public EBlock() {
@@ -33,9 +33,17 @@ public class EBlock extends ASTExpression {
         this.monadic = monadic;
     }
     
-    public LinkedList<Statement> getStatements() {
+    public ArrayList<Statement> getStatements() {
         return statements;
     }
+    
+    public Statement getFirst() {
+        return statements.get(0);
+    }
+    
+    public Statement getLast() {
+        return statements.get(statements.size()-1);
+    }
 
     @Override
     public Expression resolve(TranslationContext context) {
@@ -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<end;++i) {
@@ -87,12 +95,18 @@ public class EBlock extends ASTExpression {
                 ruleset.rules.add(CHRTranslation.convertCHRStatement(context, (CHRStatement)statement));
             else if(statement instanceof ConstraintStatement)
                 ruleset.constraints.add(CHRTranslation.convertConstraintStatement(context, (ConstraintStatement)statement));
+            else if(statement instanceof IncludeStatement)
+                ruleset.includes.add((IncludeStatement)statement);
             else
-                throw new InternalCompilerError("Invalid CHR statement.");
+                context.getErrorLog().log(statement.location, "Invalid CHR statement.");
         }
-        return new ECHRRuleset(ruleset, in);
+        return ruleset;
     }
 
+    public CHRRuleset extractCHRRules(TranslationContext context) {
+        return extractCHRRules(context, 0, statements.size());
+    }
+    
     @SuppressWarnings("unchecked")
     private Expression extractLet(int begin, int end, Expression in) {
         return new EPreLet((List<LetStatement>)(List<?>)statements.subList(begin, end), in);
@@ -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 (file)
index 0000000..e8a5cb8
--- /dev/null
@@ -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<Object> allRefs, TIntHashSet refs) {
+        ruleset.collectRefs(allRefs, refs);
+    }
+    @Override
+    public void collectVars(TObjectIntHashMap<Variable> allVars, TIntHashSet vars) {
+        ruleset.collectVars(allVars, vars);
+    }
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        ruleset.forVariables(procedure);
+    }
+    @Override
+    protected void updateType() throws MatchException {
+        throw new InternalCompilerError("Type of ECHRRulesetConstructor should be already given.");
+    }
+    @Override
+    public IVal toVal(Environment env, CodeWriter w) {
+        return ruleset.generateCode(w);
+    }
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        ruleset.collectFreeVariables(vars);
+    }
+    @Override
+    public Expression resolve(TranslationContext context) {
+        context.pushFrame();
+        context.pushCHRConstraintFrame();
+        ruleset.resolve(context);
+        context.popCHRConstraintFrame(ruleset.constraints);
+        context.popFrame();
+        return this;
+    }
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            this.location = loc;
+            ruleset.setLocationDeep(loc);
+        }
+    }
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        return this;
+    }
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        ruleset.collectEffects(effects);
+    }
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+    
+    @Override
+    public Expression inferType(TypingContext context) {
+        ruleset.checkType(context);
+        return this;
+    }
+    
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        ruleset.simplify(context);
+        ruleset.compile(context);
+        return this;
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+    
+    @Override
+    public IExpression toIExpression(ExpressionInterpretationContext context) {
+        throw new UnsupportedOperationException();
+    }
+
+}
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 (file)
index 0000000..500c805
--- /dev/null
@@ -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;
+    }
+}
index 8d54d50633c7289c5311cfc03e4b7f2b48993e83..4cf513c542647b1ccc3c8e1dd7cc8f020447c66d 100644 (file)
@@ -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);
index 62e21f204b182b66a9446e3ed28aeea285eeb502..ad32098baadb7538d27c699c41d4dcf906df486a 100644 (file)
@@ -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);
index 5d1d2eb9544493172ee1cb24af7085734659998c..ac61eb4866844c1822abf0c7323f958df6b9cbaa 100644 (file)
@@ -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<lit.parameters.length;++i)
                     lit.parameters[i] = lit.parameters[i].accept(this);
@@ -128,6 +133,18 @@ EquationVisitor {
                 for(int i=0;i<lit.parameters.length;++i)
                     lit.parameters[i] = lit.parameters[i].accept(this);
         }
+    }
+    
+    @Override
+    public Expression transform(ECHRRuleset expression) {
+        expression.in = expression.in.accept(this);
+        transform(expression.ruleset);
+        return expression;
+    }
+    
+    @Override
+    public Expression transform(ECHRRulesetConstructor expression) {
+        transform(expression.ruleset);
         return expression;
     }
 
index ef247bf131279042292cad01a6889e0be700b378..be9be3109c75fe29a08fe119f88529a8788519aa 100644 (file)
@@ -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;
@@ -13,6 +14,7 @@ import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
@@ -351,10 +353,9 @@ EquationVisitor, StatementVisitor {
         for(Equation equation : expression.equations)
             equation.accept(this);
     }
-
-    @Override
-    public void visit(ECHRRuleset ruleset) {
-        for(CHRRule rule : ruleset.ruleset.rules) {
+    
+    public void visit(CHRRuleset ruleset) {
+        for(CHRRule rule : ruleset.rules) {
             for(CHRLiteral literal : rule.head.literals)
                 for(Expression parameter : literal.parameters)
                     parameter.accept(this);
@@ -362,7 +363,17 @@ EquationVisitor, StatementVisitor {
                 for(Expression parameter : literal.parameters)
                     parameter.accept(this);
         }
-        ruleset.in.accept(this);
+    }
+
+    @Override
+    public void visit(ECHRRuleset expression) {
+        visit(expression.ruleset);
+        expression.in.accept(this);
+    }
+    
+    @Override
+    public void visit(ECHRRulesetConstructor expression) {
+        visit(expression.ruleset);
     }
 
     @Override
@@ -428,4 +439,8 @@ EquationVisitor, StatementVisitor {
         statement.body.accept(this);
     }
 
+    @Override
+    public void visit(IncludeStatement statement) {
+        statement.value.accept(this);
+    }
 }
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/block/IncludeStatement.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/block/IncludeStatement.java
new file mode 100644 (file)
index 0000000..52152b1
--- /dev/null
@@ -0,0 +1,72 @@
+package org.simantics.scl.compiler.elaboration.expressions.block;
+
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
+import org.simantics.scl.compiler.elaboration.contexts.EnvironmentalContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.codegen.references.IVal;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;
+import org.simantics.scl.compiler.internal.parsing.Token;
+import org.simantics.scl.compiler.types.Type;
+
+public class IncludeStatement extends Statement implements ValRefBinder {
+    public Token name;
+    public Expression value;
+    
+    public CHRRuleset ruleset;
+    public IVal storeVar; 
+    
+    public IncludeStatement(Token name, Expression value) {
+        this.name = name;
+        this.value = value;
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            value.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public StatementGroup getStatementGroup() {
+        return StatementGroup.CHR;
+    }
+
+    @Override
+    public Expression toExpression(EnvironmentalContext context, boolean monadic, Expression in) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void resolvePattern(TranslationContext context) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean mayBeRecursive() {
+        return true;
+    }
+
+    @Override
+    public void accept(StatementVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public SSAFunction getParentFunction() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void replaceByApply(ValRef valRef, Val function, Type[] typeParameters, Val[] parameters2) {
+         throw new UnsupportedOperationException();
+    }
+
+}
\ No newline at end of file
index 5b0d2c0f30c4224ebbfdd66de5a4a7973f1a78b7..2d90774feff1345c144be9392015537ad86417e8 100644 (file)
@@ -5,4 +5,5 @@ public interface StatementVisitor {
     void visit(GuardStatement statement);
     void visit(LetStatement statement);
     void visit(RuleStatement statement);
+    void visit(IncludeStatement statement);
 }
index 59e7d8909f24967e71400ba86067053550e6f5e9..3f6da74cb9ffd9f7cf0daddd78f4dfe4bbc775ba 100644 (file)
@@ -15,6 +15,7 @@ import org.simantics.scl.compiler.elaboration.expressions.EBinary;
 import org.simantics.scl.compiler.elaboration.expressions.EBind;
 import org.simantics.scl.compiler.elaboration.expressions.EBlock;
 import org.simantics.scl.compiler.elaboration.expressions.ECHRRuleset;
+import org.simantics.scl.compiler.elaboration.expressions.ECHRRulesetConstructor;
 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
 import org.simantics.scl.compiler.elaboration.expressions.ECoveringBranchPoint;
 import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
@@ -520,13 +521,18 @@ public class ExpressionToStringVisitor implements ExpressionVisitor, QueryVisito
     }
 
     @Override
-    public void visit(EEquations eEquations) {
+    public void visit(EEquations expression) {
         b.append("eq");
     }
 
     @Override
-    public void visit(ECHRRuleset echrRuleset) {
-        b.append("CHRRuleset");
+    public void visit(ECHRRuleset expression) {
+        b.append("ECHRRuleset");
+    }
+    
+    @Override
+    public void visit(ECHRRulesetConstructor expression) {
+        b.append("ECHRRulesetConstructor");
     }
 
     public void visit(CHRRule rule) {
index 14808c820f3b4c91f5ac305645ff9b9ffc1d3260..334cb4560cc488e2ae2a9101dc245f64c0f10c04 100644 (file)
@@ -9,6 +9,7 @@ import org.simantics.scl.compiler.common.precedence.Associativity;
 import org.simantics.scl.compiler.common.precedence.Precedence;
 import org.simantics.scl.compiler.constants.BooleanConstant;
 import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.constants.JavaConstructor;
 import org.simantics.scl.compiler.constants.JavaStaticField;
 import org.simantics.scl.compiler.constants.JavaStaticMethod;
 import org.simantics.scl.compiler.constants.NoRepConstant;
@@ -47,6 +48,7 @@ import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.compiler.types.Types;
 import org.simantics.scl.compiler.types.kinds.Kind;
 import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.simantics.scl.runtime.chr.CHRContext;
 import org.simantics.scl.runtime.profiling.BranchPoint;
 
 public class Builtins extends ConcreteModule {
@@ -350,6 +352,10 @@ public class Builtins extends ConcreteModule {
         }
         
         setParentClassLoader(getClass().getClassLoader());
+        
+        // CHR
+        
+        addTypeDescriptor("CHRContext", new StandardTypeConstructor(Types.CHRContext, Kinds.STAR, TypeDesc.forClass(CHRContext.class)));
     }
     
     @Override
index f40221eb57cb79717ef93bc7a51f07fdeffc7de5..c5cd410f48b4aa5e0d346991dd3a0fc473a170d2 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.compiler.environment;
 
 import java.util.function.Consumer;
 
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
 import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
@@ -73,4 +74,9 @@ public enum EmptyNamespace implements Namespace {
     @Override
     public void findTypesForPrefix(String prefix, NamespaceFilter filter, Consumer<TCon> consumer) {
     }
+
+    @Override
+    public CHRRuleset getRuleset(String name) throws AmbiguousNameException {
+        return null;
+    }
 }
index df86c1130e7930b0866a4d8f046d5e14edf3473a..3be214d2d6bd69f66aa4ae59347adeba2b5cb572 100644 (file)
@@ -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<CHRRuleset> getRuleset = new NamespaceValueAccessor<CHRRuleset>() {
+        @Override
+        public CHRRuleset get(Namespace ns, String name) throws AmbiguousNameException {
+            return ns.getRuleset(name);
+        }
+    };
     
        private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
         Namespace namespace = environment.getLocalNamespace();
index 9b4712c847bacd1ff049d86b0b0d31f1cd88fb1b..e5af69204006bb768891a9665b9c0aeb54af4380 100644 (file)
@@ -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
index 0c97d308ab680ed87ee6a2dbace1b971ea6e9d3c..214749bcb05b881c660325f29c2d53bd26e61553 100644 (file)
@@ -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<String> conflictingModules = null;
+        for(ModuleImport moduleImport : moduleImports) {
+            Module module = moduleImport.module;
+            temp = module.getRuleset(name);
+            if(temp != null) {
+                if(result != null) {
+                    if(conflictingModules == null) {
+                        conflictingModules = new ArrayList<String>(2);
+                        conflictingModules.add(resultModule.getName());
+                    }
+                    conflictingModules.add(module.getName());
+                }   
+                else {
+                    result = temp;
+                    resultModule = module;
+                }
+            }
+        }
+        if(conflictingModules != null)
+            throw new AmbiguousNameException(conflictingModules, name);
+        return result;
+    }
+    
     @Override
     public void findValuesForPrefix(String prefix, NamespaceFilter filter, TObjectProcedure<SCLValue> proc) {
         for(ModuleImport moduleImport : moduleImports)
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
new file mode 100644 (file)
index 0000000..37f1202
--- /dev/null
@@ -0,0 +1,46 @@
+package org.simantics.scl.compiler.internal.codegen.chr;
+
+import org.cojen.classfile.TypeDesc;
+import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
+
+public interface CHRCodeGenerationConstants {
+
+    public static final TypeDesc FACT_ID_TYPE = TypeDesc.INT;
+    
+    public static final String CHRHashIndex_name = "org/simantics/scl/runtime/chr/CHRHashIndex";
+    public static final TypeDesc CHRHashIndex = TypeDesc.forClass(CHRHashIndex_name);
+    
+    public static final String CHRFact_name = "org/simantics/scl/runtime/chr/CHRFact";
+    public static final TypeDesc CHRFact = TypeDesc.forClass(CHRFact_name);
+    
+    public static final String CHRPriority_name = "org/simantics/scl/runtime/chr/CHRPriority";
+    
+    public static final String CHRPriorityFactContainer_name = "org/simantics/scl/runtime/chr/CHRPriorityFactContainer";
+    public static final TypeDesc CHRPriorityFactContainer = TypeDesc.forClass(CHRPriorityFactContainer_name);
+    
+    public static final String CHRContext_name = "org/simantics/scl/runtime/chr/CHRContext";
+    public static final TypeDesc CHRContext = TypeDesc.forClass(CHRContext_name);
+    
+    public static final String CHRRuntimeRuleset_name = "org/simantics/scl/runtime/chr/CHRRuntimeRuleset";
+    public static final TypeDesc CHRRuntimeRuleset = TypeDesc.forClass(CHRRuntimeRuleset_name);
+
+    public static String priorityName(int priority) {
+        return "l" + priority;
+    }
+
+    public static String fieldName(int id) {
+        return "c" + id;
+    }
+
+    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/CHRCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRCodeGenerator.java
deleted file mode 100644 (file)
index 3a249c5..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-package org.simantics.scl.compiler.internal.codegen.chr;
-
-import java.util.ArrayList;
-
-import org.cojen.classfile.TypeDesc;
-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.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.MethodBuilderBase;
-import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
-
-public class CHRCodeGenerator {
-
-    public static final TypeDesc FACT_ID_TYPE = TypeDesc.INT;
-    private static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue";
-    private static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name);
-    private static final String QUEUE = "queue";
-
-    public static void generateStore(ModuleBuilder moduleBuilder, CHRRuleset ruleset) {
-        ClassBuilder storeClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, ruleset.storeClassName, "java/lang/Object");
-        if(ruleset.parameters == null)
-            ruleset.parameters = new BoundVar[0];
-        ruleset.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.parameters); 
-
-        ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<>();
-        for(CHRConstraint constraint : ruleset.constraints)
-            generateFact(storeClassBuilder, constraint, hashIndexInitializations);
-
-        // Fields
-        for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
-            TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
-            if(typeDesc.equals(TypeDesc.VOID))
-                continue;
-            storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "p" + i, typeDesc);
-        }
-        storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);
-        for(StoreInitialization ini : hashIndexInitializations)
-            storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);
-        storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, QUEUE, FactActivationQueue);
-
-        // Constructors
-
-        {
-            MethodBuilderBase mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, ruleset.parameterTypeDescs);
-            mb.loadThis();
-            mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
-            for(int i=0;i<ruleset.parameterTypeDescs.length;++i) {
-                TypeDesc typeDesc = ruleset.parameterTypeDescs[i];
-                if(typeDesc.equals(TypeDesc.VOID))
-                    continue;
-                mb.loadThis();
-                mb.loadLocal(mb.getParameter(i));
-                mb.storeField(ruleset.storeClassName, "p" + i, ruleset.parameterTypeDescs[i]);
-            }
-            mb.loadThis();
-            mb.loadConstant(1);
-            mb.storeField(storeClassBuilder.getClassName(), "currentId", TypeDesc.INT);
-            for(StoreInitialization ini : hashIndexInitializations) {
-                mb.loadThis();
-                mb.newObject(ini.className);
-                mb.dup();
-                mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);
-                mb.storeField(ruleset.storeClassName, ini.fieldName, ini.fieldType);
-            }
-            {
-                mb.loadThis();
-                mb.newObject(FactActivationQueue_name);
-                mb.dup();
-                mb.loadConstant(ruleset.priorityCount);
-                mb.invokeConstructor(FactActivationQueue_name, new TypeDesc[] {TypeDesc.INT});
-                mb.storeField(ruleset.storeClassName, QUEUE, FactActivationQueue);
-            }
-            mb.returnVoid();
-            mb.finish();
-        }
-
-        // Activate
-
-        {
-            MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT});
-            mb.loadThis();
-            mb.loadField(ruleset.storeClassName, QUEUE, FactActivationQueue);
-            mb.loadThis();
-            mb.loadLocal(mb.getParameter(0));
-            mb.invokeVirtual(FactActivationQueue_name, "activate", TypeDesc.VOID, new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.INT});
-            mb.returnVoid();
-            mb.finish();
-        }
-
-        moduleBuilder.addClass(storeClassBuilder);
-    }
-
-    private static void generateFact(ClassBuilder storeClassBuilder, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
-        CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, constraint);
-        generator.generate(hashIndexInitializations);
-    }
-}
index 06725ec2b813dc4f0693a3b7a066d2f310a1dd4c..865ab22e6c8e18ed31248bfef8bb17e700a083ac 100644 (file)
@@ -6,42 +6,27 @@ 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.plan.PrioritizedPlan;
 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.references.BoundVar;
 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
 import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
-import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;
 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;
 
-import gnu.trove.list.array.TIntArrayList;
-import gnu.trove.set.hash.THashSet;
-
-public class CHRFactCodeGenerator {
-    private static final TypeDesc FACT_ID_TYPE = TypeDesc.INT;
-    private static final String CHRHashIndex_name = "org/simantics/scl/runtime/chr/CHRHashIndex";
-    private static final TypeDesc CHRHashIndex = TypeDesc.forClass(CHRHashIndex_name);
-    private static final String FactActivationQueue_name = "org/simantics/scl/runtime/chr/FactActivationQueue";
-    private static final TypeDesc FactActivationQueue = TypeDesc.forClass(FactActivationQueue_name);
-    private static final String Fact_name = "org/simantics/scl/runtime/chr/Fact";
-    private static final TypeDesc Fact = TypeDesc.forClass(Fact_name);
-    private static final String QUEUE = "queue";
+public class CHRFactCodeGenerator implements CHRCodeGenerationConstants {
 
     private ModuleBuilder moduleBuilder; 
     private JavaTypeTranslator jtt;
-    private CHRRuleset ruleset;
 
     private ClassBuilder storeClassBuilder;
+    private CHRRuleset ruleset;
     private CHRConstraint constraint;
 
     private String factClassName;
     private TypeDesc factTypeDesc;
-    private ClassBuilder factClassBuilder;
+    private ClassBuilder classBuilder;
 
     private TypeDesc storeTypeDesc;
     private TypeDesc[] storeTypeDescArray;
@@ -49,10 +34,10 @@ public class CHRFactCodeGenerator {
     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.ruleset = constraint.parentRuleset;
 
         this.moduleBuilder = storeClassBuilder.getModuleBuilder();
         this.jtt = moduleBuilder.getJavaTypeTranslator();
@@ -61,7 +46,7 @@ public class CHRFactCodeGenerator {
 
         this.factClassName = storeClassBuilder.getClassName() + "$" + constraint.name;
         this.factTypeDesc = TypeDesc.forClass(factClassName);
-        this.factClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, factClassName, "java/lang/Object", Fact_name);
+        this.classBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, factClassName, CHRFact_name);
 
         this.parameterTypeDescs = jtt.toTypeDescs(constraint.parameterTypes);
         this.supportsRemoval = constraint.mayBeRemoved();
@@ -77,16 +62,10 @@ public class CHRFactCodeGenerator {
         if(supportsRemoval)
             generateRemove();
 
-        generateIsAlive();
-
-        for(int i=0;i<constraint.plans.size();++i) 
-            generateActivateI(i);
-        generateActivate();
-
         generateConstructor();
-        factClassBuilder.addDefaultConstructor();
+        classBuilder.addDefaultConstructor();
 
-        moduleBuilder.addClass(factClassBuilder);
+        moduleBuilder.addClass(classBuilder);
     }
 
     private void generateIndices() {
@@ -116,7 +95,7 @@ public class CHRFactCodeGenerator {
                         if(!typeDesc.equals(TypeDesc.VOID)) {
                             mb.loadLocal(tempFactVar);
                             mb.loadLocal(mb.getParameter(parameterId));
-                            mb.storeField(factClassName, fieldName(i), typeDesc);
+                            mb.storeField(factClassName, CHRCodeGenerationConstants.fieldName(i), typeDesc);
                         }
                         ++parameterId;
                     }
@@ -133,94 +112,6 @@ public class CHRFactCodeGenerator {
         }   
     }
 
-    private THashSet<BoundVar> usedParameters = new THashSet<BoundVar>();
-
-    private void generateActivateI(int i) {
-        PrioritizedPlan plan = constraint.plans.get(i);
-        MethodBuilder mb = factClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "activate" + i, TypeDesc.BOOLEAN, storeTypeDescArray);
-        LocalVariable storeVar = mb.getParameter(0);
-        LocalVariable factVar = new LocalVariable(0, factTypeDesc);
-        mb.setLocalVariable(ruleset.this_, storeVar);
-        mb.setLocalVariable(plan.implementation.getParameters()[0], factVar);
-
-        // Set closure parameters
-        usedParameters.clear();
-        plan.implementation.forValRefs(valRef -> {
-            if(valRef.getBinding() instanceof BoundVar)
-                usedParameters.add((BoundVar)valRef.getBinding());
-        });
-        for(int j=0;j<ruleset.parameters.length;++j) {
-            BoundVar parameter = ruleset.parameters[j];
-            if(!usedParameters.contains(parameter))
-                continue;
-            mb.loadLocal(storeVar);
-            mb.loadField(storeClassBuilder.getClassName(), "p"+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.finish();
-    }
-
-    private void generateActivate() {
-        // @Override
-        // public int activate(Object context, int priority) {
-        //     return -1;
-        // }
-
-        MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.INT, new TypeDesc[] {TypeDesc.OBJECT, TypeDesc.INT});
-        Label defaultLabel = mb.createLabel();
-
-        if(!constraint.isPassive()) {
-            // Check if the fact is alive
-            mb.loadThis();
-            mb.loadField(factClassName, "id", TypeDesc.INT);
-            mb.ifZeroComparisonBranch(defaultLabel, "<");
-
-            mb.loadLocal(mb.getParameter(0));
-            mb.checkCast(storeTypeDesc);
-            LocalVariable storeVariable = new LocalVariable(1, storeTypeDesc);
-            mb.storeLocal(storeVariable);
-
-            TIntArrayList priorities = new TIntArrayList(constraint.plans.size());
-            ArrayList<Label> labels = new ArrayList<Label>();
-            int lastPriority = -1;
-            for(PrioritizedPlan plan : constraint.plans)
-                if(plan.priority != lastPriority) {
-                    priorities.add(plan.priority);
-                    labels.add(mb.createLabel());
-                    lastPriority = plan.priority;
-                }
-
-            mb.loadLocal(mb.getParameter(1));
-            mb.switch_(priorities.toArray(), labels.toArray(new Label[labels.size()]), defaultLabel);
-            int labelId = -1;
-            for(int i=0;i<constraint.plans.size();++i) {
-                PrioritizedPlan plan = constraint.plans.get(i);
-                if(labelId == -1 || plan.priority != priorities.get(labelId)) {
-                    if(labelId >= 0) {
-                        mb.loadConstant(plan.priority);
-                        mb.returnValue(TypeDesc.INT);
-                    }
-                    ++labelId;
-                    mb.setLocation(labels.get(labelId));
-                }
-                mb.loadThis();
-                mb.loadLocal(storeVariable);
-                mb.invokeVirtual(factClassName, "activate" + i, TypeDesc.BOOLEAN, new TypeDesc[] {storeTypeDesc});
-                mb.ifZeroComparisonBranch(defaultLabel, "==");
-            }
-            mb.setLocation(defaultLabel);
-        }
-        mb.loadConstant(-1);
-        mb.returnValue(TypeDesc.INT);
-        mb.finish();
-    }
-
     private void generateConstructor() {
         // public ExampleFact(int id, int c0, int c1) {
         //     this.id = id;            
@@ -235,54 +126,29 @@ public class CHRFactCodeGenerator {
                 continue;
             constructorParameters.add(typeDesc);
         }
-        MethodBuilderBase mb = factClassBuilder.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(factClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
+        mb.invokeConstructor(classBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
         mb.loadThis();
         mb.loadLocal(mb.getParameter(0));
-        mb.storeField(factClassName, "id", FACT_ID_TYPE);
+        mb.storeField(CHRFact_name, "id", FACT_ID_TYPE);
         for(int i=0,parameterId=1;i<constraint.parameterTypes.length;++i) {
             TypeDesc typeDesc = parameterTypeDescs[i];
             if(typeDesc.equals(TypeDesc.VOID))
                 continue;
             mb.loadThis();
             mb.loadLocal(mb.getParameter(parameterId++));
-            mb.storeField(factClassName, fieldName(i), typeDesc);
+            mb.storeField(factClassName, CHRCodeGenerationConstants.fieldName(i), typeDesc);
         }
         mb.returnVoid();
         mb.finish();
     }
 
-    private void generateIsAlive() {
-        // @Override
-        // public boolean isAlive() {
-        //     return id >= 0;
-        // }
-
-        MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "isAlive", TypeDesc.BOOLEAN, Constants.EMPTY_TYPEDESC_ARRAY);
-        if(supportsRemoval) {
-            mb.loadThis();
-            mb.loadField(factClassName, "id", FACT_ID_TYPE);
-
-            Label thenBranch = mb.createLabel();
-            mb.ifZeroComparisonBranch(thenBranch, "<");
-            mb.loadConstant(true);
-            mb.returnValue(TypeDesc.BOOLEAN);
-
-            mb.setLocation(thenBranch);
-            mb.loadConstant(false);
-            mb.returnValue(TypeDesc.BOOLEAN);
-        }
-        else {
-            mb.loadConstant(true);
-            mb.returnValue(TypeDesc.BOOLEAN);
-        }
-        mb.finish();
-    }
-
     private void generateAdd() {
-        MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "add", TypeDesc.VOID, storeTypeDescArray);
+        MethodBuilderBase mb = classBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "add", TypeDesc.VOID, new TypeDesc[] {storeTypeDesc, CHRContext});
         LocalVariable storeParameter = mb.getParameter(0);
+        
+        // Add fact to indices
         for(IndexInfo indexInfo : constraint.getIndices()) {
             String linkedListPrev = indexInfo.indexName + "Prev";
             String linkedListNext = indexInfo.indexName + "Next";
@@ -339,13 +205,32 @@ public class CHRFactCodeGenerator {
                     mb.setLocation(cont);
                 }
             }
-        }            
-        if(!constraint.isPassive()) {
+        }
+        
+        // Add fact to priority queue
+        int minimumPriority = ruleset.getMinimumPriority(constraint);
+        if(minimumPriority != Integer.MAX_VALUE) {
             mb.loadLocal(storeParameter);
-            mb.loadField(storeClassBuilder.getClassName(), QUEUE, FactActivationQueue);
-            mb.loadConstant(constraint.getMinimumPriority());
+            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(FactActivationQueue_name, "add", TypeDesc.VOID, new TypeDesc[] {TypeDesc.INT, Fact});
+            mb.invokeVirtual(CHRPriorityFactContainer_name, "addFact", TypeDesc.VOID, new TypeDesc[] {CHRContext, CHRFact});
+            mb.setLocation(finishLabel);
         }
         mb.returnVoid();
         mb.finish();
@@ -358,19 +243,19 @@ public class CHRFactCodeGenerator {
         // public ExampleFact bfPrev;
         // public ExampleFact bfNext;
 
-        factClassBuilder.addField(Opcodes.ACC_PUBLIC, "id", FACT_ID_TYPE);
+        //classBuilder.addField(Opcodes.ACC_PUBLIC, "id", FACT_ID_TYPE);
         for(int i=0;i<constraint.parameterTypes.length;++i) {
             TypeDesc typeDesc = parameterTypeDescs[i];
             if(typeDesc.equals(TypeDesc.VOID))
                 continue;
             if(parameterTypeDescs[i] != TypeDesc.VOID)
-                factClassBuilder.addField(Opcodes.ACC_PUBLIC, fieldName(i), typeDesc);
+                classBuilder.addField(Opcodes.ACC_PUBLIC, CHRCodeGenerationConstants.fieldName(i), typeDesc);
         }
 
         for(IndexInfo indexInfo : constraint.getIndices()) {
             if(supportsRemoval)
-                factClassBuilder.addField(Opcodes.ACC_PUBLIC, indexInfo.indexName + "Prev", factTypeDesc);
-            factClassBuilder.addField(Opcodes.ACC_PUBLIC, indexInfo.indexName + "Next", factTypeDesc);
+                classBuilder.addField(Opcodes.ACC_PUBLIC, indexInfo.indexName + "Prev", factTypeDesc);
+            classBuilder.addField(Opcodes.ACC_PUBLIC, indexInfo.indexName + "Next", factTypeDesc);
 
             String hashIndexField = constraint.name + "$" + indexInfo.indexName;
             if(indexInfo.indexMask == 0) {
@@ -378,7 +263,7 @@ public class CHRFactCodeGenerator {
                 storeClassBuilder.addField(Opcodes.ACC_PUBLIC, hashIndexField, factTypeDesc);
             }
             else {
-                ClassBuilder hashClass = generateSpecializedHashIndex(storeClassBuilder, constraint, indexInfo, factTypeDesc, factClassName);
+                ClassBuilder hashClass = CHRHashIndexCodeGenerator.generateHashIndex(storeClassBuilder, constraint, indexInfo, factTypeDesc, factClassName);
                 moduleBuilder.addClass(hashClass);
                 hashIndexInitializations.add(new StoreInitialization(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, hashIndexField, CHRHashIndex, hashClass.getClassName()));
             }
@@ -402,7 +287,7 @@ public class CHRFactCodeGenerator {
         //     }
         // }
 
-        MethodBuilderBase mb = factClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "remove", TypeDesc.VOID, storeTypeDescArray);
+        MethodBuilderBase mb = classBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "remove", TypeDesc.VOID, storeTypeDescArray);
         LocalVariable storeParameter = mb.getParameter(0);
         for(IndexInfo indexInfo : constraint.getIndices()) {
             String linkedListPrev = indexInfo.indexName + "Prev";
@@ -489,114 +374,8 @@ public class CHRFactCodeGenerator {
         }
         mb.loadThis();
         mb.loadConstant(-1);
-        mb.storeField(factClassName, "id", FACT_ID_TYPE);
+        mb.storeField(CHRFact_name, "id", FACT_ID_TYPE);
         mb.returnVoid();
         mb.finish();
     }
-
-    public static String fieldName(int id) {
-        return "c" + id;
-    }
-
-    private static ClassBuilder generateSpecializedHashIndex(ClassBuilder storeClassBuilder, CHRConstraint constraint, IndexInfo indexInfo, TypeDesc factClassTypeDesc, String factClassName) {
-        // new CHRHashIndex() {
-        //     @Override
-        //     protected boolean keyEquals(Object a, Object b) {
-        //         return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
-        //     }
-        //     @Override
-        //     protected int keyHashCode(Object key) {
-        //         return ((ExampleFact)key).c0;
-        //     }
-        // }
-
-        ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder();
-        JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator();
-
-        String hashIndexClassName = factClassName + "$" + indexInfo.indexName; 
-        ClassBuilder hashIndexClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, hashIndexClassName, "org/simantics/scl/runtime/chr/CHRHashIndex");
-
-        // Method: keyEquals
-
-        {
-
-            // @Override
-            // protected boolean keyEquals(Object a, Object b) {
-            //     return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
-            // }
-
-            MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyEquals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);
-            mb.loadLocal(mb.getParameter(0));
-            mb.checkCast(factClassTypeDesc);
-            LocalVariable aVar = mb.createLocalVariable("a", factClassTypeDesc);
-            mb.storeLocal(aVar);
-
-            mb.loadLocal(mb.getParameter(1));
-            mb.checkCast(factClassTypeDesc);
-            LocalVariable bVar = mb.createLocalVariable("b", factClassTypeDesc);
-            mb.storeLocal(bVar);
-
-            Label failure = mb.createLabel();
-
-            int curMask = indexInfo.indexMask;
-            for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
-                if((curMask&1) == 1) {
-                    TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
-                    if(fieldTypeDesc.equals(TypeDesc.VOID))
-                        continue;
-                    mb.loadLocal(aVar);
-                    mb.loadField(factClassName, fieldName(i), fieldTypeDesc);
-
-                    mb.loadLocal(bVar);
-                    mb.loadField(factClassName, fieldName(i), fieldTypeDesc);
-
-                    CodeBuilderUtils.equals(mb, fieldTypeDesc, failure);
-                }
-            mb.loadConstant(true);
-            mb.returnValue(TypeDesc.BOOLEAN);
-
-            mb.setLocation(failure);
-            mb.loadConstant(false);
-            mb.returnValue(TypeDesc.BOOLEAN);
-            mb.finish();
-        }
-
-        // Method: keyHashCode
-
-        {
-            // @Override
-            // protected int keyHashCode(Object key) {
-            //     return (0x811C9DC5^((ExampleFact)key).c0)*16777619;
-            // }
-
-            MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyHashCode", TypeDesc.INT, Constants.OBJECTS[1]);
-            mb.loadLocal(mb.getParameter(0));
-            mb.checkCast(factClassTypeDesc);
-            LocalVariable factVar = mb.createLocalVariable("fact", factClassTypeDesc);
-            mb.storeLocal(factVar);
-
-            mb.loadConstant(0x811C9DC5);
-
-            int curMask = indexInfo.indexMask;
-            for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
-                if((curMask&1) == 1) {
-                    TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
-                    if(fieldTypeDesc.equals(TypeDesc.VOID))
-                        continue;
-                    mb.loadLocal(factVar);
-                    mb.loadField(factClassName, fieldName(i), fieldTypeDesc);
-                    CodeBuilderUtils.hashCode(mb, fieldTypeDesc);
-                    mb.math(Opcodes.IXOR);
-                    mb.loadConstant(16777619);
-                    mb.math(Opcodes.IMUL);
-
-                }
-            mb.returnValue(TypeDesc.INT);
-            mb.finish();
-        }
-
-        hashIndexClassBuilder.addDefaultConstructor();
-
-        return hashIndexClassBuilder;
-    }
 }
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRHashIndexCodeGenerator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/chr/CHRHashIndexCodeGenerator.java
new file mode 100644 (file)
index 0000000..bafd83e
--- /dev/null
@@ -0,0 +1,120 @@
+package org.simantics.scl.compiler.internal.codegen.chr;
+
+import org.cojen.classfile.TypeDesc;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.Opcodes;
+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;
+import org.simantics.scl.compiler.internal.codegen.utils.ClassBuilder;
+import org.simantics.scl.compiler.internal.codegen.utils.CodeBuilderUtils;
+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.MethodBuilderBase;
+import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
+
+public class CHRHashIndexCodeGenerator implements CHRCodeGenerationConstants {
+    
+    public static ClassBuilder generateHashIndex(ClassBuilder storeClassBuilder, CHRConstraint constraint, IndexInfo indexInfo, TypeDesc factClassTypeDesc, String factClassName) {
+        // new CHRHashIndex() {
+        //     @Override
+        //     protected boolean keyEquals(Object a, Object b) {
+        //         return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
+        //     }
+        //     @Override
+        //     protected int keyHashCode(Object key) {
+        //         return ((ExampleFact)key).c0;
+        //     }
+        // }
+
+        ModuleBuilder moduleBuilder = storeClassBuilder.getModuleBuilder();
+        JavaTypeTranslator jtt = moduleBuilder.getJavaTypeTranslator();
+
+        String hashIndexClassName = factClassName + "$" + indexInfo.indexName; 
+        ClassBuilder hashIndexClassBuilder = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, hashIndexClassName, "org/simantics/scl/runtime/chr/CHRHashIndex");
+
+        // Method: keyEquals
+
+        {
+
+            // @Override
+            // protected boolean keyEquals(Object a, Object b) {
+            //     return ((ExampleFact)a).c0 == ((ExampleFact)b).c0;
+            // }
+
+            MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyEquals", TypeDesc.BOOLEAN, Constants.OBJECTS[2]);
+            mb.loadLocal(mb.getParameter(0));
+            mb.checkCast(factClassTypeDesc);
+            LocalVariable aVar = mb.createLocalVariable("a", factClassTypeDesc);
+            mb.storeLocal(aVar);
+
+            mb.loadLocal(mb.getParameter(1));
+            mb.checkCast(factClassTypeDesc);
+            LocalVariable bVar = mb.createLocalVariable("b", factClassTypeDesc);
+            mb.storeLocal(bVar);
+
+            Label failure = mb.createLabel();
+
+            int curMask = indexInfo.indexMask;
+            for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
+                if((curMask&1) == 1) {
+                    TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
+                    if(fieldTypeDesc.equals(TypeDesc.VOID))
+                        continue;
+                    mb.loadLocal(aVar);
+                    mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
+
+                    mb.loadLocal(bVar);
+                    mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
+
+                    CodeBuilderUtils.equals(mb, fieldTypeDesc, failure);
+                }
+            mb.loadConstant(true);
+            mb.returnValue(TypeDesc.BOOLEAN);
+
+            mb.setLocation(failure);
+            mb.loadConstant(false);
+            mb.returnValue(TypeDesc.BOOLEAN);
+            mb.finish();
+        }
+
+        // Method: keyHashCode
+
+        {
+            // @Override
+            // protected int keyHashCode(Object key) {
+            //     return (0x811C9DC5^((ExampleFact)key).c0)*16777619;
+            // }
+
+            MethodBuilderBase mb = hashIndexClassBuilder.addMethodBase(Opcodes.ACC_PROTECTED, "keyHashCode", TypeDesc.INT, Constants.OBJECTS[1]);
+            mb.loadLocal(mb.getParameter(0));
+            mb.checkCast(factClassTypeDesc);
+            LocalVariable factVar = mb.createLocalVariable("fact", factClassTypeDesc);
+            mb.storeLocal(factVar);
+
+            mb.loadConstant(0x811C9DC5);
+
+            int curMask = indexInfo.indexMask;
+            for(int i=0;i<constraint.parameterTypes.length;++i,curMask>>=1)
+                if((curMask&1) == 1) {
+                    TypeDesc fieldTypeDesc = jtt.toTypeDesc(constraint.parameterTypes[i]);
+                    if(fieldTypeDesc.equals(TypeDesc.VOID))
+                        continue;
+                    mb.loadLocal(factVar);
+                    mb.loadField(factClassName, CHRCodeGenerationConstants.fieldName(i), fieldTypeDesc);
+                    CodeBuilderUtils.hashCode(mb, fieldTypeDesc);
+                    mb.math(Opcodes.IXOR);
+                    mb.loadConstant(16777619);
+                    mb.math(Opcodes.IMUL);
+
+                }
+            mb.returnValue(TypeDesc.INT);
+            mb.finish();
+        }
+
+        hashIndexClassBuilder.addDefaultConstructor();
+
+        return hashIndexClassBuilder;
+    }
+
+}
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
new file mode 100644 (file)
index 0000000..496a33b
--- /dev/null
@@ -0,0 +1,179 @@
+package org.simantics.scl.compiler.internal.codegen.chr;
+
+import java.util.ArrayList;
+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.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.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+
+public class CHRPriorityFactContainerCodeGenerator implements CHRCodeGenerationConstants {
+    ClassBuilder storeClassBuilder;
+    String containerClassName;
+    private TypeDesc containerTypeDesc;
+
+    private ClassBuilder classBuilder;
+    
+    private TypeDesc storeTypeDesc;
+    
+    private CHRRuleset ruleset;
+    private CHRRule rule;
+
+    public CHRPriorityFactContainerCodeGenerator(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRRule rule) {
+        this.storeClassBuilder = storeClassBuilder;
+        
+        this.containerClassName = storeClassBuilder.getClassName() + "$" + "CHRPriorityFactContainer" + rule.priority;
+        this.containerTypeDesc = TypeDesc.forClass(containerClassName);
+        this.classBuilder = new ClassBuilder(storeClassBuilder.getModuleBuilder(), Opcodes.ACC_PUBLIC, containerClassName, CHRPriorityFactContainer_name);
+        
+        this.storeTypeDesc = storeClassBuilder.getType();
+        
+        this.ruleset = ruleset;
+        this.rule = rule;
+    }
+    
+    public void generate() {
+        generateFields();
+        generateContructor();
+        
+        THashMap<CHRConstraint, ArrayList<CHRSearchPlan>> planMap = new THashMap<CHRConstraint, ArrayList<CHRSearchPlan>>(); 
+        for(CHRSearchPlan plan : rule.plans) {
+            ArrayList<CHRSearchPlan> list = planMap.get(plan.constraint);
+            if(list == null) {
+                list = new ArrayList<CHRSearchPlan>(4);
+                planMap.put(plan.constraint, list);
+            }
+            list.add(plan);
+        }
+        planMap.forEachEntry(new TObjectObjectProcedure<CHRConstraint, ArrayList<CHRSearchPlan>>() {
+            @Override
+            public boolean execute(CHRConstraint constraint, ArrayList<CHRSearchPlan> plans) {
+                for(int i=0;i<plans.size();++i)
+                    generateActivate(constraint, plans.get(i), i);
+                return true;
+            }
+        });
+        generateActivate(planMap);
+        
+        classBuilder.getModuleBuilder().addClass(classBuilder);
+    }
+    
+    private void generateContructor() {
+        MethodBuilderBase mb = classBuilder.addConstructorBase(Opcodes.ACC_PUBLIC, new TypeDesc[] {storeTypeDesc});
+        mb.loadThis();
+        mb.loadConstant(rule.priority + ruleset.initialPriorityNumber);
+        mb.invokeSuperConstructor(new TypeDesc[] {TypeDesc.INT});
+        mb.loadThis();
+        mb.loadLocal(mb.getParameter(0));
+        mb.storeField(containerClassName, "parent", storeTypeDesc);
+        mb.returnVoid();
+        mb.finish();
+    }
+    
+    private void generateFields() {
+        classBuilder.addField(Opcodes.ACC_PUBLIC, "parent", storeTypeDesc);
+    }
+
+    // protected abstract void activate(CHRContext context, CHRFact fact);
+    private void generateActivate(THashMap<CHRConstraint, ArrayList<CHRSearchPlan>> planMap) {
+        // @Override
+        // public int activate(Object context, int priority) {
+        //     return -1;
+        // }
+
+        MethodBuilderBase mb = classBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "activate", TypeDesc.VOID, new TypeDesc[] {CHRContext, CHRFact});
+        Label finishLabel = mb.createLabel();
+
+        AtomicReference<Label> nextLabel = new AtomicReference<Label>();
+        planMap.forEachEntry(new TObjectObjectProcedure<CHRConstraint, ArrayList<CHRSearchPlan>>() {
+            @Override
+            public boolean execute(CHRConstraint constraint, ArrayList<CHRSearchPlan> plans) {
+                int nextPriority = ruleset.getAndUpdateNextPriority(constraint, rule.priority);
+                
+                Label next = nextLabel.get();
+                if(next != null)
+                    mb.setLocation(next);
+                mb.loadLocal(mb.getParameter(1));
+                mb.instanceOf(constraint.factTypeDesc);
+                next = mb.createLabel();
+                nextLabel.set(next);
+                mb.ifZeroComparisonBranch(next, "==");
+                
+                for(int id=0;id<plans.size();++id) {
+                    mb.loadThis();
+                    mb.loadLocal(mb.getParameter(0));
+                    mb.loadLocal(mb.getParameter(1));
+                    mb.checkCast(constraint.factTypeDesc);
+                    mb.invokeVirtual(classBuilder.getClassName(), "activate_" + constraint.name + "_" + id, TypeDesc.BOOLEAN, new TypeDesc[] {CHRContext, constraint.factTypeDesc});
+                    mb.ifZeroComparisonBranch(finishLabel, "==");
+                }
+                
+                // Add to priority queue
+                if(nextPriority != Integer.MAX_VALUE) {
+                    mb.loadThis();
+                    mb.loadField(containerClassName, "parent", storeTypeDesc);
+                    mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.priorityName(nextPriority), CHRPriorityFactContainer);
+                    mb.loadLocal(mb.getParameter(0));
+                    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;
+            }
+        });
+        {
+            Label next = nextLabel.get();
+            if(next != null)
+                mb.setLocation(next);
+        }
+        
+        mb.setLocation(finishLabel);
+        mb.returnVoid();
+        mb.finish();
+    }
+    
+    // protected abstract void activate(CHRContext context, CHRFact fact);
+
+    private void generateActivate(CHRConstraint constraint, CHRSearchPlan plan, int id) {
+        MethodBuilder mb = classBuilder.addMethod(Opcodes.ACC_PUBLIC, "activate_" + constraint.name + "_" + id, TypeDesc.BOOLEAN, new TypeDesc[] {CHRContext, constraint.factTypeDesc});
+        LocalVariable priorityVar = new LocalVariable(0, containerTypeDesc);
+        mb.loadLocal(priorityVar);
+        mb.loadField(containerClassName, "parent", storeTypeDesc);
+        LocalVariable parent = mb.createLocalVariable("parent", storeTypeDesc);
+        mb.storeLocal(parent);
+        ruleset.rulesetObject.realizeMethod(mb, (i, target) -> {
+            mb.loadLocal(parent);
+            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
new file mode 100644 (file)
index 0000000..9ff56ed
--- /dev/null
@@ -0,0 +1,184 @@
+package org.simantics.scl.compiler.internal.codegen.chr;
+
+import java.util.ArrayList;
+
+import org.cojen.classfile.TypeDesc;
+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.runtimeRulesetClassName, CHRRuntimeRuleset_name);
+        if(ruleset.rulesetObject.parameters == null)
+            ruleset.rulesetObject.parameters = new BoundVar[0];
+        TypeDesc[] parameterTypeDescs = ruleset.rulesetObject.parameterTypeDescs = moduleBuilder.getJavaTypeTranslator().getTypeDescs(ruleset.rulesetObject.parameters); 
+
+        ArrayList<StoreInitialization> hashIndexInitializations = new ArrayList<StoreInitialization>();
+        for(CHRConstraint constraint : ruleset.constraints)
+            generateFact(storeClassBuilder, 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<parameterTypeDescs.length;++i) {
+            TypeDesc typeDesc = parameterTypeDescs[i];
+            if(typeDesc.equals(TypeDesc.VOID))
+                continue;
+            storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.parameterName(i), typeDesc);
+        }
+        for(StoreInitialization ini : hashIndexInitializations)
+            storeClassBuilder.addField(ini.access, ini.fieldName, ini.fieldType);
+        for(CHRRule rule : ruleset.rules)
+            storeClassBuilder.addField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
+        if(ruleset.extensible)
+            for(CHRConstraint constraint : ruleset.constraints)
+                if(constraint.nextContainerFieldName != null)
+                    storeClassBuilder.addField(Opcodes.ACC_PUBLIC, constraint.nextContainerFieldName, CHRPriorityFactContainer);
+        if(ruleset.extensible)
+            storeClassBuilder.addField(Opcodes.ACC_PUBLIC, "currentId", FACT_ID_TYPE);
+        
+        // Constructors
+
+        {
+            MethodBuilder mb = storeClassBuilder.addConstructor(Opcodes.ACC_PUBLIC, parameterTypeDescs);
+                    //TypeDesc.concat(ruleset.parameterTypeDescs, includeTypeDescs));
+            mb.loadThis();
+            mb.invokeConstructor(storeClassBuilder.getSuperClassName(), Constants.EMPTY_TYPEDESC_ARRAY);
+            int p=0;
+            for(int i=0;i<parameterTypeDescs.length;++i) {
+                TypeDesc typeDesc = parameterTypeDescs[i];
+                if(typeDesc.equals(TypeDesc.VOID))
+                    continue;
+                mb.loadThis();
+                mb.loadLocal(mb.getParameter(p++));
+                mb.storeField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
+            }
+            for(StoreInitialization ini : hashIndexInitializations) {
+                mb.loadThis();
+                mb.newObject(ini.className);
+                mb.dup();
+                mb.invokeConstructor(ini.className, Constants.EMPTY_TYPEDESC_ARRAY);
+                mb.storeField(ruleset.runtimeRulesetClassName, ini.fieldName, ini.fieldType);
+            }
+            TypeDesc[] runtimeRulesetTypeDescArray = new TypeDesc[] {TypeDesc.forClass(storeClassBuilder.getClassName())};
+            for(CHRRule rule : ruleset.rules) {
+                mb.loadThis();
+                mb.newObject(rule.containerClassName);
+                mb.dup();
+                mb.loadThis();
+                mb.invokeConstructor(rule.containerClassName, runtimeRulesetTypeDescArray);
+                mb.storeField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.priorityName(rule.priority), CHRPriorityFactContainer);
+            }
+            mb.returnVoid();
+            mb.finish();
+        }
+        
+        // Registration
+        
+        for(IncludeStatement include : ruleset.includes) {
+            {
+                MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "register", TypeDesc.VOID,
+                        new TypeDesc[] {CHRContext, include.ruleset.runtimeRulesetTypeDesc});
+                LocalVariable contextVar = mb.getParameter(0);
+                LocalVariable importedStore = mb.getParameter(1);
+                ArrayList<CHRConstraint> list = ruleset.inverseActiveConstraintSourceMap.get(include);
+                if(list != null)
+                    for(CHRConstraint constraint : list) {
+                        int minimumPriority = ruleset.getMinimumPriority(constraint);
+                        if(minimumPriority == Integer.MAX_VALUE)
+                            continue;
+                        mb.loadLocal(importedStore);
+                        mb.loadThis();
+                        mb.loadField(storeClassBuilder.getClassName(), CHRCodeGenerationConstants.priorityName(minimumPriority), CHRPriorityFactContainer);
+                        mb.storeField(include.ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.nextContainerName(constraint.name), CHRPriorityFactContainer);
+                    }
+                
+                // update context id
+                mb.loadLocal(contextVar);
+                mb.loadLocal(contextVar);
+                mb.loadField(CHRContext_name, "currentId", FACT_ID_TYPE);
+                mb.loadLocal(importedStore);
+                mb.loadField(include.ruleset.runtimeRulesetClassName, "currentId", FACT_ID_TYPE);
+                mb.invokeStatic("java/lang/Math", "max", FACT_ID_TYPE, new TypeDesc[] {FACT_ID_TYPE, FACT_ID_TYPE});
+                mb.storeField(CHRContext_name, "currentId", FACT_ID_TYPE);
+                
+                mb.returnVoid();
+                mb.finish();
+            }
+            
+            {
+                MethodBuilderBase mb = storeClassBuilder.addMethodBase(Opcodes.ACC_PUBLIC, "unregister", TypeDesc.VOID,
+                        new TypeDesc[] {CHRContext, include.ruleset.runtimeRulesetTypeDesc});
+                LocalVariable contextVar = mb.getParameter(0);
+                LocalVariable importedStore = mb.getParameter(1);
+                ArrayList<CHRConstraint> list = ruleset.inverseActiveConstraintSourceMap.get(include);
+                if(list != null)
+                    for(CHRConstraint constraint : list) {
+                        int minimumPriority = ruleset.getMinimumPriority(constraint);
+                        if(minimumPriority == Integer.MAX_VALUE)
+                            continue;
+                        mb.loadLocal(importedStore);
+                        mb.loadNull();
+                        mb.storeField(include.ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.nextContainerName(constraint.name), CHRPriorityFactContainer);
+                    }
+                
+                // store context id
+                mb.loadLocal(importedStore);
+                mb.loadLocal(contextVar);
+                mb.loadField(CHRContext_name, "currentId", FACT_ID_TYPE);
+                mb.storeField(include.ruleset.runtimeRulesetClassName, "currentId", FACT_ID_TYPE);
+                
+                mb.returnVoid();
+                mb.finish();
+            }
+        }
+        
+        if(ruleset.initializer != null) {
+            MethodBuilder mb = storeClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "initialize", TypeDesc.VOID, new TypeDesc[] {CHRContext});
+            ruleset.rulesetObject.realizeMethod(mb,
+                    (i, target) -> {
+                        mb.loadThis();
+                        mb.loadField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
+                        mb.store(target);
+                    },
+                    ruleset.initializer, mb.getThis(ruleset.runtimeRulesetTypeDesc), mb.getParameter(0));
+            mb.finish();
+        }
+        if(ruleset.deinitializer != null) {
+            MethodBuilder mb = storeClassBuilder.addMethod(Opcodes.ACC_PUBLIC, "deinitialize", TypeDesc.VOID, new TypeDesc[] {CHRContext});
+            ruleset.rulesetObject.realizeMethod(mb,
+                    (i, target) -> {
+                        mb.loadThis();
+                        mb.loadField(ruleset.runtimeRulesetClassName, CHRCodeGenerationConstants.parameterName(i), parameterTypeDescs[i]);
+                        mb.store(target);
+                    },
+                    ruleset.deinitializer, mb.getThis(ruleset.runtimeRulesetTypeDesc), mb.getParameter(0));
+            mb.finish();
+        }
+
+        moduleBuilder.addClass(storeClassBuilder);
+    }
+
+    private static void generateFact(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRConstraint constraint, ArrayList<StoreInitialization> hashIndexInitializations) {
+        CHRFactCodeGenerator generator = new CHRFactCodeGenerator(storeClassBuilder, ruleset, constraint);
+        generator.generate(hashIndexInitializations);
+    }
+
+    private static void generateFactContainer(ClassBuilder storeClassBuilder, CHRRuleset ruleset, CHRRule rule) {
+        CHRPriorityFactContainerCodeGenerator generator = new CHRPriorityFactContainerCodeGenerator(storeClassBuilder, ruleset, rule); 
+        generator.generate();
+        rule.containerClassName = generator.containerClassName;
+    }
+}
index 315d2e82943acb9df3a6ecfc85bf1a3e78dc77bd..d4c102204fe95e50f6bfa126c1868301ce5f7065 100644 (file)
@@ -1,10 +1,10 @@
 package org.simantics.scl.compiler.internal.codegen.chr;
 
+import org.simantics.scl.runtime.chr.CHRFact;
 import org.simantics.scl.runtime.chr.CHRHashIndex;
-import org.simantics.scl.runtime.chr.Fact;
-import org.simantics.scl.runtime.chr.FactActivationQueue;
+import org.simantics.scl.runtime.chr.CHRRuntimeRuleset;
 
-public class ExampleStore {
+public class ExampleStore extends CHRRuntimeRuleset {
     /*
      * constraint ExampleFact Integer Integer where
      *     index(bf)
@@ -33,8 +33,6 @@ public class ExampleStore {
         }
     };
     
-    public FactActivationQueue queue = new FactActivationQueue(2);
-    
     private ExampleFact ExampleFact_temp = new ExampleFact();
         
     public ExampleFact getExampleFact_bf(int c0) {
@@ -42,8 +40,7 @@ public class ExampleStore {
         return (ExampleFact)ExampleFact_bfIndex.getEqual(ExampleFact_temp);
     }
     
-    public static class ExampleFact implements Fact {
-        public int id;
+    public static class ExampleFact extends CHRFact {
         public int c0; // key
         public int c1;
         public ExampleFact bfPrev;
@@ -78,16 +75,6 @@ public class ExampleStore {
                     bfNext.bfPrev = bfPrev;
             }
         }
-
-        @Override
-        public int activate(Object context, int priority) {
-            return -1;
-        }
-
-        @Override
-        public boolean isAlive() {
-            return id >= 0;
-        }
     }
 
 }
index aaab03e1aae8c3e49686ec7d1960c4dc9dbf1b44..ba9d62d27ce730bffc2b99772321406736125e07 100644 (file)
@@ -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) {
index 17c695e518fdcd8b7b94566a6976d0e02645df50..57748b284b436c727109433613296de9e6910148 100644 (file)
@@ -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;
index ab643f9a15b1669be060ae165c07a403cb3888c3..b9e8bfbb398e0803977e305533259eb0eb6d4982 100644 (file)
@@ -359,6 +359,8 @@ public final class SSAFunction extends SSAClosure {
     }
 
     public void mergeBlocks(SSAFunction function) {
+        if(this == function)
+            throw new InternalCompilerError();
         SSABlock block = function.firstBlock;
         while(block != null) {
             SSABlock next = block.next;
index b8b7def598175705f4beb2cb1f3b768688afe873..400cb6e4e373f78c480e8fc37c1da3dc203a47f2 100644 (file)
@@ -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);
@@ -399,7 +399,7 @@ public class LetApply extends LetStatement implements ValRefBinder {
         tailBlock.setExit(headBlock.getExit());
         
         // Merge blocks        
-        thisFunction.mergeBlocks(function);           
+        thisFunction.mergeBlocks(function);
         
         headBlock.setExit(new Jump(function.getFirstBlock().createOccurrence(), 
                 parameters));
index cf46899f645b48b2b516c5a895c56b25cb566390..9f6fe9f01d8511bf86e6f49f740a9795e6f16531 100644 (file)
@@ -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());
index bbcd370bbc19cef0401a155e44b9270b35ae9f88..6af3bd3101487d9efcfceb9573ad81d242c0f479 100644 (file)
@@ -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);
index 0fe185e611df41ae90efad7e394b77119b0328f4..5316b861dc52e3e7a2e9b6424e0debf29ce96a13 100644 (file)
@@ -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, "<init>", TypeDesc.VOID, params);
     }
+    
+    public MethodBuilder addConstructor(int access, TypeDesc[] params) {
+        return addMethod(access, "<init>", TypeDesc.VOID, params);
+    }
 
     public MethodBuilder addInitializer() {
         return addMethod(Opcodes.ACC_PUBLIC, "<clinit>", TypeDesc.VOID, Constants.EMPTY_TYPEDESC_ARRAY);
index 81f7b117a82f61f7ade860cd1362d5b4a85559e3..71ce63e5c360d11eb7d5f76b2dd13d85e1838327 100644 (file)
@@ -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();
index 843659d6c12abe1f86fad86c0fda9b16e11e89f3..bd1a911a15f4ec4fe2342284baec23414da7a1a2 100644 (file)
@@ -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)
index 8db288a8976196486ec14ee0601ddbf4a14575b8..32d4283392bc093b9b083735488284bb73b71e95 100644 (file)
@@ -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 });
index 33a88ffba83dee70893e841c6cb516407ebca6fb..80acf17c571cb242e2db401233525006f118908d 100644 (file)
@@ -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<EVar> export;
+    // Features
+    public boolean chr;
+    public boolean fields;
     
-    private void read(ErrorLog errorLog, DModuleHeader header) {
-        for(FieldAssignment assignment : header.fields)
+    private void read(ErrorLog errorLog, FieldAssignment[] fields) {
+        for(FieldAssignment assignment : fields)
             switch(assignment.name) {
             case "bundle":
                 if(assignment.value == null)
@@ -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 (file)
index 25d14e2..0000000
+++ /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;i<indentation;++i) b.append("    ");
-        b.append("module {");
-        ExpressionToStringVisitor visitor = new ExpressionToStringVisitor(b);
-        boolean first = true;
-        for(FieldAssignment field : fields) {
-            if(first)
-                first = false;
-            else
-                b.append(',');
-            b.append('\n');
-            for(int i=0;i<=indentation;++i) b.append("    ");
-            b.append(field.name);
-            b.append(" = ");
-            field.value.accept(visitor);
-        }
-        b.append('\n');
-        for(int i=0;i<indentation;++i) b.append("    ");
-        b.append('}');
-    }
-}
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DRulesetAst.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/declarations/DRulesetAst.java
new file mode 100644 (file)
index 0000000..f23d272
--- /dev/null
@@ -0,0 +1,18 @@
+package org.simantics.scl.compiler.internal.parsing.declarations;
+
+import org.simantics.scl.compiler.elaboration.expressions.EBlock;
+import org.simantics.scl.compiler.types.TCon;
+
+public class DRulesetAst extends DeclarationAst {
+    public final String name;
+    public final EBlock block;
+    public DDocumentationAst documentation;
+    
+    public TCon type;
+    public String className;
+    
+    public DRulesetAst(String name, EBlock block) {
+        this.name = name;
+        this.block = block;
+    }
+}
index 7551271af416cd323ab16f89e45d6d7a2bdfe4d1..b0911febe69bf3540f928cee928e9b84c5086edf 100644 (file)
@@ -55,6 +55,7 @@ declaration
       WHERE ruleDeclarations                                 # RuleDefinition
     | MAPPING_RELATION ID atype*                             # MappingRelationDefinition
     | bexp FOLLOWS ruleDeclarations                          # RelationDefinition
+    | RULESET ID WHERE statements                            # RulesetDefinition
     ;
 
 import
@@ -200,6 +201,7 @@ statement
     | chrQuery IMPLIES chrQuery                              # CHRStatement
     | WHEN verboseChrQuery THEN_AFTER_WHEN verboseChrQuery   # VerboseCHRStatement
     | CONSTRAINT ID atype*                                   # ConstraintStatement
+    | INCLUDE ID aexp                                        # LocalInclude
     ;
 
 chrQuery 
index b064a07aea9fb0a47e01c2010c2d6e50d47a56cc..0f45c2511b297a3e6575c7a953c6cd5e9f752c34 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.scl.compiler.internal.parsing.parser;
 
+import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.internal.parsing.Token;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
@@ -27,6 +28,7 @@ import gnu.trove.list.array.TIntArrayList;
     TIntArrayList stateStack = new TIntArrayList(2);
 
     StringBuffer string = new StringBuffer();
+    CompilationContext context;
     
     private Token sym(int id) {
         return new Token(id, yychar, yychar+yylength(), yytext());
@@ -34,6 +36,12 @@ import gnu.trove.list.array.TIntArrayList;
     private Token sym(int id, String text) {
         return new Token(id, yychar, yychar+yylength(), text);
     }
+    public void setCompilationContext(CompilationContext context) {
+        this.context = context;
+    }
+    public boolean supportCHR() {
+        return context.header == null ? false : context.header.chr;
+    }
 %}
 
 letter          = [a-zA-Z_]
@@ -84,11 +92,12 @@ char_literal    = "'" ([^'\\\ufffd] | "\\" [^\ufffd]) "'"
   else            { return sym(SCLTerminals.ELSE); }
   where           { return sym(SCLTerminals.WHERE); }
   when            { return sym(SCLTerminals.WHEN); }
-  rule            { return sym(SCLTerminals.RULE); }
+  ruleset         { return sym(supportCHR() ? SCLTerminals.RULESET : SCLTerminals.ID); }
+  rule            { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.RULE); }
   abstract{whitespace}rule { return sym(SCLTerminals.ABSTRACT_RULE); }
   extends         { return sym(SCLTerminals.EXTENDS); }
   mapping{whitespace}relation { return sym(SCLTerminals.MAPPING_RELATION); }
-  transformation  { return sym(SCLTerminals.TRANSFORMATION); }
+  transformation  { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.TRANSFORMATION); }
   select{whitespace}first { return sym(SCLTerminals.SELECT_FIRST); }
   select{whitespace}distinct { return sym(SCLTerminals.SELECT_DISTINCT); }
   select          { return sym(SCLTerminals.SELECT); }
index a717005bc2def5c12c9cb92cc60f50471ec4a8bd..5944d12e1cf288e701348305082a2d101eb07591 100644 (file)
@@ -2,6 +2,7 @@
 
 package org.simantics.scl.compiler.internal.parsing.parser;
 
+import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.internal.parsing.Token;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
@@ -11,7 +12,7 @@ import gnu.trove.list.array.TIntArrayList;
 /**
  * This class is a scanner generated by 
  * <a href="http://www.jflex.de/">JFlex</a> 1.6.1
- * from the specification file <tt>C:/Users/hannu/git/scl/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex</tt>
+ * from the specification file <tt>C:/Simugawa.git/git/platform/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLLexer.flex</tt>
  */
 public class SCLLexer {
 
@@ -76,17 +77,17 @@ public class SCLLexer {
     "\1\74\1\75\1\0\1\76\2\0\1\46\1\0\1\2"+
     "\1\77\6\2\1\100\1\101\2\2\1\102\3\2\1\103"+
     "\1\2\1\104\2\2\1\105\3\2\1\0\1\46\1\0"+
-    "\2\2\1\106\11\2\1\107\1\2\1\110\1\2\1\111"+
-    "\1\2\1\0\1\112\1\113\1\2\1\114\1\115\2\2"+
+    "\3\2\1\106\11\2\1\107\1\2\1\110\1\2\1\111"+
+    "\1\2\1\0\1\112\1\113\2\2\1\114\1\115\2\2"+
     "\1\116\1\2\1\117\1\120\2\2\1\121\3\2\1\122"+
-    "\2\2\1\123\2\2\1\124\1\125\1\0\4\2\1\126"+
-    "\2\2\2\0\1\2\1\127\2\0\2\2\2\0\1\2"+
-    "\2\0\1\130\1\2\2\0\1\131\2\0\1\2\4\0"+
-    "\1\2\1\132\2\0\1\133\1\2\2\0\1\134\2\0"+
-    "\1\135\1\0\1\136";
+    "\1\123\2\2\1\124\2\2\1\125\1\126\1\0\4\2"+
+    "\1\127\2\2\2\0\1\2\1\130\2\0\2\2\2\0"+
+    "\1\2\2\0\1\131\1\2\2\0\1\132\2\0\1\2"+
+    "\4\0\1\2\1\133\2\0\1\134\1\2\2\0\1\135"+
+    "\2\0\1\136\1\0\1\137";
 
   private static int [] zzUnpackAction() {
-    int [] result = new int[293];
+    int [] result = new int[296];
     int offset = 0;
     offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
     return result;
@@ -132,25 +133,25 @@ public class SCLLexer {
     "\0\370\0\u1876\0\u18b4\0\u18f2\0\u1930\0\u196e\0\u19ac\0\u19ea"+
     "\0\u1a28\0\u1a66\0\u1aa4\0\u1ae2\0\u1b20\0\u1b5e\0\u1b9c\0\u1bda"+
     "\0\u1c18\0\u1c56\0\u1c94\0\u1cd2\0\u1d10\0\u1d4e\0\370\0\272"+
-    "\0\u1d8c\0\272\0\u1dca\0\u1e08\0\u01b2\0\u1e46\0\u1e84\0\370"+
-    "\0\u1ec2\0\u1f00\0\u1f3e\0\u1f7c\0\u1fba\0\u1ff8\0\370\0\370"+
-    "\0\u2036\0\u2074\0\370\0\u20b2\0\u20f0\0\u212e\0\370\0\u216c"+
-    "\0\370\0\u21aa\0\u21e8\0\370\0\u2226\0\u2264\0\u22a2\0\u22e0"+
-    "\0\272\0\u231e\0\u235c\0\u239a\0\u23d8\0\u2416\0\u2454\0\u2492"+
-    "\0\u24d0\0\u250e\0\u254c\0\u258a\0\u25c8\0\u2606\0\370\0\u2644"+
-    "\0\370\0\u2682\0\370\0\u26c0\0\u26fe\0\272\0\370\0\u273c"+
-    "\0\370\0\370\0\u277a\0\u27b8\0\u27f6\0\u2834\0\370\0\370"+
-    "\0\u2872\0\u28b0\0\u28ee\0\u292c\0\u296a\0\u29a8\0\272\0\u29e6"+
-    "\0\u2a24\0\370\0\u2a62\0\u2aa0\0\370\0\370\0\u2ade\0\u2b1c"+
-    "\0\u2b5a\0\u2b98\0\u2bd6\0\370\0\u2c14\0\u2c52\0\u2c90\0\u2cce"+
-    "\0\u2d0c\0\370\0\u2d4a\0\u2d88\0\u2dc6\0\u2e04\0\u2e42\0\u2e80"+
-    "\0\u2ebe\0\u2efc\0\u2f3a\0\370\0\u2f78\0\u2fb6\0\u2ff4\0\370"+
-    "\0\u3032\0\u3070\0\u30ae\0\u30ec\0\u312a\0\u3168\0\u31a6\0\u31e4"+
-    "\0\272\0\u3222\0\u3260\0\272\0\u329e\0\u32dc\0\u331a\0\370"+
-    "\0\u3358\0\u3396\0\272\0\u33d4\0\272";
+    "\0\u1d8c\0\272\0\u1dca\0\u1e08\0\u01b2\0\u1e46\0\u1e84\0\u1ec2"+
+    "\0\u1f00\0\u1f3e\0\u1f7c\0\u1fba\0\u1ff8\0\u2036\0\370\0\370"+
+    "\0\u2074\0\u20b2\0\370\0\u20f0\0\u212e\0\u216c\0\370\0\u21aa"+
+    "\0\370\0\u21e8\0\u2226\0\370\0\u2264\0\u22a2\0\u22e0\0\u231e"+
+    "\0\272\0\u235c\0\u239a\0\u23d8\0\u2416\0\u2454\0\u2492\0\u24d0"+
+    "\0\u250e\0\u254c\0\u258a\0\u25c8\0\u2606\0\u2644\0\u2682\0\370"+
+    "\0\u26c0\0\370\0\u26fe\0\370\0\u273c\0\u277a\0\272\0\370"+
+    "\0\u27b8\0\u27f6\0\370\0\370\0\u2834\0\u2872\0\u28b0\0\u28ee"+
+    "\0\370\0\370\0\u292c\0\u296a\0\u29a8\0\u29e6\0\u2a24\0\u2a62"+
+    "\0\272\0\370\0\u2aa0\0\u2ade\0\370\0\u2b1c\0\u2b5a\0\370"+
+    "\0\370\0\u2b98\0\u2bd6\0\u2c14\0\u2c52\0\u2c90\0\370\0\u2cce"+
+    "\0\u2d0c\0\u2d4a\0\u2d88\0\u2dc6\0\370\0\u2e04\0\u2e42\0\u2e80"+
+    "\0\u2ebe\0\u2efc\0\u2f3a\0\u2f78\0\u2fb6\0\u2ff4\0\370\0\u3032"+
+    "\0\u3070\0\u30ae\0\370\0\u30ec\0\u312a\0\u3168\0\u31a6\0\u31e4"+
+    "\0\u3222\0\u3260\0\u329e\0\272\0\u32dc\0\u331a\0\272\0\u3358"+
+    "\0\u3396\0\u33d4\0\370\0\u3412\0\u3450\0\272\0\u348e\0\272";
 
   private static int [] zzUnpackRowMap() {
-    int [] result = new int[293];
+    int [] result = new int[296];
     int offset = 0;
     offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
     return result;
@@ -346,112 +347,116 @@ public class SCLLexer {
     "\1\310\42\0\1\206\57\0\25\213\1\311\1\254\47\213"+
     "\47\0\1\312\27\0\4\6\2\0\1\76\12\0\1\6"+
     "\6\0\4\6\1\313\23\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\2\6\1\314\25\6"+
+    "\2\0\1\76\12\0\1\6\6\0\12\6\1\314\15\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\17\6\1\315\10\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\3\6\1\316\24\6"+
+    "\6\0\2\6\1\315\25\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\17\6\1\316\10\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\14\6\1\317\13\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\2\6\1\320\25\6"+
+    "\6\0\3\6\1\317\24\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\14\6\1\320\13\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\12\6\1\321\15\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\11\6\1\322\16\6"+
+    "\6\0\2\6\1\321\25\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\12\6\1\322\15\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\16\6\1\323\11\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\2\6\1\324\25\6"+
+    "\6\0\11\6\1\323\16\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\16\6\1\324\11\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\11\6\1\325\16\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\16\6\1\326\11\6"+
+    "\6\0\2\6\1\325\25\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\11\6\1\326\16\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\10\6\1\327\17\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\6\6\1\330\21\6"+
+    "\6\0\16\6\1\327\11\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\10\6\1\330\17\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\12\6\1\331\15\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\25\6\1\332\2\6"+
+    "\6\0\6\6\1\331\21\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\12\6\1\332\15\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\7\6\1\333\20\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\5\6\1\334\22\6"+
-    "\11\0\1\6\5\0\2\335\16\0\1\335\6\0\1\335"+
-    "\2\0\1\335\4\0\1\335\4\0\2\335\1\0\1\335"+
-    "\64\0\1\336\36\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\4\6\1\337\23\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\3\6\1\340\24\6"+
+    "\6\0\25\6\1\333\2\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\7\6\1\334\20\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\2\6\1\341\1\6\1\342\23\6\11\0\1\6"+
+    "\6\0\5\6\1\335\22\6\11\0\1\6\5\0\2\336"+
+    "\16\0\1\336\6\0\1\336\2\0\1\336\4\0\1\336"+
+    "\4\0\2\336\1\0\1\336\64\0\1\337\36\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\4\6\1\340\23\6"+
+    "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
+    "\6\0\10\6\1\341\17\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\3\6\1\342\24\6"+
+    "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
+    "\6\0\2\6\1\343\1\6\1\344\23\6\11\0\1\6"+
     "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\11\6"+
-    "\1\343\16\6\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\20\6\1\344\7\6\11\0\1\6"+
+    "\1\345\16\6\11\0\1\6\4\0\4\6\2\0\1\76"+
+    "\12\0\1\6\6\0\20\6\1\346\7\6\11\0\1\6"+
     "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\6\6"+
-    "\1\345\21\6\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\1\346\27\6\11\0\1\6\4\0"+
-    "\4\6\2\0\1\76\12\0\1\6\6\0\23\6\1\347"+
+    "\1\347\21\6\11\0\1\6\4\0\4\6\2\0\1\76"+
+    "\12\0\1\6\6\0\1\350\27\6\11\0\1\6\4\0"+
+    "\4\6\2\0\1\76\12\0\1\6\6\0\23\6\1\351"+
     "\4\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+
-    "\1\6\6\0\6\6\1\350\21\6\11\0\1\6\4\0"+
-    "\4\6\2\0\1\76\12\0\1\6\6\0\16\6\1\351"+
+    "\1\6\6\0\6\6\1\352\21\6\11\0\1\6\4\0"+
+    "\4\6\2\0\1\76\12\0\1\6\6\0\16\6\1\353"+
     "\11\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+
-    "\1\6\6\0\20\6\1\352\7\6\11\0\1\6\4\0"+
-    "\4\6\2\0\1\76\12\0\1\6\6\0\6\6\1\353"+
+    "\1\6\6\0\20\6\1\354\7\6\11\0\1\6\4\0"+
+    "\4\6\2\0\1\76\12\0\1\6\6\0\6\6\1\355"+
     "\21\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+
-    "\1\6\6\0\2\6\1\354\25\6\11\0\1\6\4\0"+
-    "\4\6\2\0\1\76\12\0\1\6\6\0\5\6\1\355"+
+    "\1\6\6\0\2\6\1\356\25\6\11\0\1\6\4\0"+
+    "\4\6\2\0\1\76\12\0\1\6\6\0\5\6\1\357"+
     "\22\6\11\0\1\6\4\0\4\6\2\0\1\76\12\0"+
-    "\1\6\6\0\11\6\1\356\16\6\11\0\1\6\5\0"+
-    "\2\357\16\0\1\357\6\0\1\357\2\0\1\357\4\0"+
-    "\1\357\4\0\2\357\1\0\1\357\25\0\4\6\2\0"+
-    "\1\76\12\0\1\6\6\0\16\6\1\360\11\6\11\0"+
+    "\1\6\6\0\11\6\1\360\16\6\11\0\1\6\5\0"+
+    "\2\361\16\0\1\361\6\0\1\361\2\0\1\361\4\0"+
+    "\1\361\4\0\2\361\1\0\1\361\25\0\4\6\2\0"+
+    "\1\76\12\0\1\6\6\0\6\6\1\362\21\6\11\0"+
     "\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+
-    "\16\6\1\361\11\6\11\0\1\6\4\0\4\6\2\0"+
-    "\1\76\12\0\1\6\6\0\10\6\1\362\17\6\11\0"+
+    "\16\6\1\363\11\6\11\0\1\6\4\0\4\6\2\0"+
+    "\1\76\12\0\1\6\6\0\16\6\1\364\11\6\11\0"+
     "\1\6\4\0\4\6\2\0\1\76\12\0\1\6\6\0"+
-    "\27\6\1\363\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\1\6\1\364\26\6\11\0\1\6"+
-    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\10\6"+
-    "\1\365\17\6\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\12\6\1\366\15\6\11\0\1\6"+
-    "\4\0\4\6\2\0\1\76\12\0\1\6\1\0\1\367"+
-    "\4\0\30\6\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\3\6\1\370\24\6\11\0\1\6"+
-    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\11\6"+
-    "\1\371\16\6\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\23\6\1\372\4\6\11\0\1\6"+
-    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\6\6"+
-    "\1\373\21\6\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\10\6\1\374\17\6\11\0\1\6"+
+    "\10\6\1\365\17\6\11\0\1\6\4\0\4\6\2\0"+
+    "\1\76\12\0\1\6\6\0\27\6\1\366\11\0\1\6"+
+    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\1\6"+
+    "\1\367\26\6\11\0\1\6\4\0\4\6\2\0\1\76"+
+    "\12\0\1\6\6\0\10\6\1\370\17\6\11\0\1\6"+
+    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\12\6"+
+    "\1\371\15\6\11\0\1\6\4\0\4\6\2\0\1\76"+
+    "\12\0\1\6\1\0\1\372\4\0\30\6\11\0\1\6"+
     "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\3\6"+
-    "\1\375\24\6\11\0\1\6\4\0\4\6\2\0\1\76"+
-    "\12\0\1\6\6\0\2\6\1\376\25\6\11\0\1\6"+
-    "\27\0\1\367\4\0\1\377\17\0\1\u0100\25\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\5\6\1\u0101\22\6"+
-    "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\23\6\1\u0102\4\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\1\0\1\u0103\4\0\30\6"+
-    "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\1\0\1\u0104\4\0\30\6\11\0\1\6\4\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\25\6\1\u0105\2\6"+
+    "\1\373\24\6\11\0\1\6\4\0\4\6\2\0\1\76"+
+    "\12\0\1\6\6\0\11\6\1\374\16\6\11\0\1\6"+
+    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\23\6"+
+    "\1\375\4\6\11\0\1\6\4\0\4\6\2\0\1\76"+
+    "\12\0\1\6\6\0\6\6\1\376\21\6\11\0\1\6"+
+    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\10\6"+
+    "\1\377\17\6\11\0\1\6\4\0\4\6\2\0\1\76"+
+    "\12\0\1\6\6\0\3\6\1\u0100\24\6\11\0\1\6"+
+    "\4\0\4\6\2\0\1\76\12\0\1\6\6\0\2\6"+
+    "\1\u0101\25\6\11\0\1\6\27\0\1\372\4\0\1\u0102"+
+    "\17\0\1\u0103\25\0\4\6\2\0\1\76\12\0\1\6"+
+    "\6\0\5\6\1\u0104\22\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\23\6\1\u0105\4\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\21\6\1\u0106\6\6\11\0\1\6\41\0\1\u0107"+
-    "\75\0\1\u0108\40\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\11\6\1\u0109\16\6\11\0\1\6\27\0\1\u0103"+
-    "\6\0\1\u010a\66\0\1\u0104\6\0\1\u010b\43\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\3\6\1\u010c\24\6"+
+    "\1\0\1\u0106\4\0\30\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\1\0\1\u0107\4\0\30\6"+
     "\11\0\1\6\4\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\3\6\1\u010d\24\6\11\0\1\6\36\0\1\u010e"+
-    "\105\0\1\u010f\33\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\6\6\1\u0110\21\6\11\0\1\6\44\0\1\u0111"+
-    "\101\0\1\u0112\31\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\6\6\1\u0113\21\6\11\0\1\6\46\0\1\u0114"+
-    "\71\0\1\u0115\73\0\1\u0116\75\0\1\u0117\41\0\4\6"+
-    "\2\0\1\76\12\0\1\6\6\0\5\6\1\u0118\22\6"+
-    "\11\0\1\6\42\0\1\u0119\74\0\1\u011a\73\0\1\u011b"+
-    "\102\0\1\u011c\35\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\1\6\1\u011d\26\6\11\0\1\6\45\0\1\u011e"+
-    "\72\0\1\u011f\37\0\4\6\2\0\1\76\12\0\1\6"+
-    "\6\0\11\6\1\u0120\16\6\11\0\1\6\52\0\1\u0121"+
-    "\64\0\1\u0122\76\0\1\u0123\70\0\1\u0124\105\0\1\u0125"+
-    "\33\0";
+    "\6\0\25\6\1\u0108\2\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\21\6\1\u0109\6\6"+
+    "\11\0\1\6\41\0\1\u010a\75\0\1\u010b\40\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\11\6\1\u010c\16\6"+
+    "\11\0\1\6\27\0\1\u0106\6\0\1\u010d\66\0\1\u0107"+
+    "\6\0\1\u010e\43\0\4\6\2\0\1\76\12\0\1\6"+
+    "\6\0\3\6\1\u010f\24\6\11\0\1\6\4\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\3\6\1\u0110\24\6"+
+    "\11\0\1\6\36\0\1\u0111\105\0\1\u0112\33\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\6\6\1\u0113\21\6"+
+    "\11\0\1\6\44\0\1\u0114\101\0\1\u0115\31\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\6\6\1\u0116\21\6"+
+    "\11\0\1\6\46\0\1\u0117\71\0\1\u0118\73\0\1\u0119"+
+    "\75\0\1\u011a\41\0\4\6\2\0\1\76\12\0\1\6"+
+    "\6\0\5\6\1\u011b\22\6\11\0\1\6\42\0\1\u011c"+
+    "\74\0\1\u011d\73\0\1\u011e\102\0\1\u011f\35\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\1\6\1\u0120\26\6"+
+    "\11\0\1\6\45\0\1\u0121\72\0\1\u0122\37\0\4\6"+
+    "\2\0\1\76\12\0\1\6\6\0\11\6\1\u0123\16\6"+
+    "\11\0\1\6\52\0\1\u0124\64\0\1\u0125\76\0\1\u0126"+
+    "\70\0\1\u0127\105\0\1\u0128\33\0";
 
   private static int [] zzUnpackTrans() {
-    int [] result = new int[13330];
+    int [] result = new int[13516];
     int offset = 0;
     offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
     return result;
@@ -495,14 +500,14 @@ public class SCLLexer {
     "\4\0\5\1\2\0\37\1\1\0\5\11\1\1\1\11"+
     "\2\0\2\1\1\0\3\11\1\0\1\11\2\0\1\11"+
     "\1\1\1\0\1\1\1\0\32\1\1\11\1\0\1\11"+
-    "\2\0\1\1\1\0\31\1\1\0\1\11\1\0\22\1"+
-    "\1\0\1\11\20\1\1\11\7\1\1\0\7\1\2\0"+
+    "\2\0\1\1\1\0\31\1\1\0\1\11\1\0\23\1"+
+    "\1\0\1\11\21\1\1\11\10\1\1\0\7\1\2\0"+
     "\2\1\2\0\2\1\2\0\1\1\2\0\2\1\2\0"+
     "\1\1\2\0\1\1\4\0\1\1\1\11\2\0\1\11"+
     "\1\1\2\0\1\1\2\0\1\11\1\0\1\11";
 
   private static int [] zzUnpackAttribute() {
-    int [] result = new int[293];
+    int [] result = new int[296];
     int offset = 0;
     offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
     return result;
@@ -585,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());
@@ -592,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;
+    }
 
 
   /**
@@ -910,11 +922,11 @@ public class SCLLexer {
             case STRING: {
               throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Unclosed string literal.");
             }
-            case 294: break;
+            case 297: break;
             case LONG_STRING: {
               throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Unclosed string literal.");
             }
-            case 295: break;
+            case 298: break;
             default:
           {     return sym(SCLTerminals.EOF);
  }
@@ -925,39 +937,39 @@ public class SCLLexer {
           case 1: 
             { throw new SCLSyntaxErrorException(Locations.location(yychar, yychar+1), "Illegal character '" + yytext() + "'.");
             }
-          case 95: break;
+          case 96: break;
           case 2: 
             { return sym(SCLTerminals.ID);
             }
-          case 96: break;
+          case 97: break;
           case 3: 
             { return sym(SCLTerminals.INTEGER);
             }
-          case 97: break;
+          case 98: break;
           case 4: 
             { return sym(SCLTerminals.SYMBOL, yytext().trim());
             }
-          case 98: break;
+          case 99: break;
           case 5: 
             { return sym(SCLTerminals.ATTACHED_HASH, "#");
             }
-          case 99: break;
+          case 100: break;
           case 6: 
             { return sym(SCLTerminals.ATTACHED_DOT, ".");
             }
-          case 100: break;
+          case 101: break;
           case 7: 
             { return sym(SCLTerminals.AT);
             }
-          case 101: break;
+          case 102: break;
           case 8: 
             { ++parenCount; return sym(SCLTerminals.LPAREN);
             }
-          case 102: break;
+          case 103: break;
           case 9: 
             { return sym(SCLTerminals.COMMA);
             }
-          case 103: break;
+          case 104: break;
           case 10: 
             { --parenCount;
                     if(parenCount == 0 && !parenCountStack.isEmpty()) { 
@@ -970,164 +982,164 @@ public class SCLLexer {
                     else
                        return sym(SCLTerminals.RPAREN);
             }
-          case 104: break;
+          case 105: break;
           case 11: 
             { return new Token(SCLTerminals.EOL, yychar, yychar+yylength(), "");
             }
-          case 105: break;
+          case 106: break;
           case 12: 
             { return sym(SCLTerminals.LESS, "<");
             }
-          case 106: break;
+          case 107: break;
           case 13: 
             { return sym(SCLTerminals.GREATER, ">");
             }
-          case 107: break;
+          case 108: break;
           case 14: 
             { return sym(SCLTerminals.MINUS, "-");
             }
-          case 108: break;
+          case 109: break;
           case 15: 
             { 
             }
-          case 109: break;
+          case 110: break;
           case 16: 
             { throw new SCLSyntaxErrorException(Locations.location(yychar, yychar+1), "Character does not conform to UTF-8 encoding.");
             }
-          case 110: break;
+          case 111: break;
           case 17: 
             { return sym(SCLTerminals.LAMBDA);
             }
-          case 111: break;
+          case 112: break;
           case 18: 
             { return sym(SCLTerminals.LBRACE);
             }
-          case 112: break;
+          case 113: break;
           case 19: 
             { return sym(SCLTerminals.RBRACE);
             }
-          case 113: break;
+          case 114: break;
           case 20: 
             { return sym(SCLTerminals.LBRACKET);
             }
-          case 114: break;
+          case 115: break;
           case 21: 
             { return sym(SCLTerminals.RBRACKET);
             }
-          case 115: break;
+          case 116: break;
           case 22: 
             { return sym(SCLTerminals.EQUALS);
             }
-          case 116: break;
+          case 117: break;
           case 23: 
             { return sym(SCLTerminals.COLON);
             }
-          case 117: break;
+          case 118: break;
           case 24: 
             { return sym(SCLTerminals.SEMICOLON);
             }
-          case 118: break;
+          case 119: break;
           case 25: 
             { return sym(SCLTerminals.BAR);
             }
-          case 119: break;
+          case 120: break;
           case 26: 
             { string.setLength(0); stringStart=yychar; yybegin(STRING); return sym(SCLTerminals.BEGIN_STRING);
             }
-          case 120: break;
+          case 121: break;
           case 27: 
             { return sym(SCLTerminals.BLANK);
             }
-          case 121: break;
+          case 122: break;
           case 28: 
             { throw new SCLSyntaxErrorException(Locations.location(yychar, yychar+1), "Tabulator is not allowed except inside string literals.");
             }
-          case 122: break;
+          case 123: break;
           case 29: 
             { string.append( yytext() );
             }
-          case 123: break;
+          case 124: break;
           case 30: 
             { throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Unclosed string literal.");
             }
-          case 124: break;
+          case 125: break;
           case 31: 
             { yybegin(YYINITIAL); 
                     return new Token(SCLTerminals.END_STRING, stringStart, yychar+1, string.toString());
             }
-          case 125: break;
+          case 126: break;
           case 32: 
             { string.append('\n');
             }
-          case 126: break;
+          case 127: break;
           case 33: 
             { return sym(SCLTerminals.DOTDOT, ".");
             }
-          case 127: break;
+          case 128: break;
           case 34: 
             { return sym(SCLTerminals.SEPARATED_DOT, ".");
             }
-          case 128: break;
+          case 129: break;
           case 35: 
             { return sym(SCLTerminals.ANNOTATION_ID);
             }
-          case 129: break;
+          case 130: break;
           case 36: 
             { return sym(SCLTerminals.BINDS);
             }
-          case 130: break;
+          case 131: break;
           case 37: 
             { return sym(SCLTerminals.ARROW);
             }
-          case 131: break;
+          case 132: break;
           case 38: 
             { return sym(SCLTerminals.COMMENT);
             }
-          case 132: break;
+          case 133: break;
           case 39: 
             { return sym(SCLTerminals.AS);
             }
-          case 133: break;
+          case 134: break;
           case 40: 
             { return sym(SCLTerminals.IF);
             }
-          case 134: break;
+          case 135: break;
           case 41: 
             { return sym(SCLTerminals.IN);
             }
-          case 135: break;
+          case 136: break;
           case 42: 
             { return sym(options.supportEq ? SCLTerminals.EQ : SCLTerminals.ID);
             }
-          case 136: break;
+          case 137: break;
           case 43: 
             { return sym(SCLTerminals.BY);
             }
-          case 137: break;
+          case 138: break;
           case 44: 
             { return sym(SCLTerminals.DO);
             }
-          case 138: break;
+          case 139: break;
           case 45: 
             { return sym(SCLTerminals.IMPLIES);
             }
-          case 139: break;
+          case 140: break;
           case 46: 
             { return sym(SCLTerminals.FOLLOWS);
             }
-          case 140: break;
+          case 141: break;
           case 47: 
             { return sym(SCLTerminals.HASTYPE);
             }
-          case 141: break;
+          case 142: break;
           case 48: 
             { throw new SCLSyntaxErrorException(Locations.location(stringStart, yychar), "Illegal string escape character.");
             }
-          case 142: break;
+          case 143: break;
           case 49: 
             { string.append(yytext().substring(1));
             }
-          case 143: break;
+          case 144: break;
           case 50: 
             { parenCountStack.add(parenCount);
                     parenCount = 1;
@@ -1135,15 +1147,15 @@ public class SCLLexer {
                     yybegin(YYINITIAL); 
                     return new Token(SCLTerminals.SUSPEND_STRING, stringStart, yychar+1, string.toString());
             }
-          case 144: break;
+          case 145: break;
           case 51: 
             { string.append('\r');
             }
-          case 145: break;
+          case 146: break;
           case 52: 
             { string.append('\t');
             }
-          case 146: break;
+          case 147: break;
           case 53: 
             { parenCountStack.add(parenCount);
                     parenCount = 1;
@@ -1151,174 +1163,178 @@ public class SCLLexer {
                     yybegin(YYINITIAL); 
                     return new Token(SCLTerminals.SUSPEND_STRING, stringStart, yychar+1, string.toString());
             }
-          case 147: break;
+          case 148: break;
           case 54: 
             { return sym(SCLTerminals.FLOAT);
             }
-          case 148: break;
+          case 149: break;
           case 55: 
             { return sym(SCLTerminals.CHAR);
             }
-          case 149: break;
+          case 150: break;
           case 56: 
             { String text = yytext();
                      return sym(SCLTerminals.ID, text.substring(1, text.length()-1));
             }
-          case 150: break;
+          case 151: break;
           case 57: 
             { String text = yytext();
                      return sym(SCLTerminals.SYMBOL, text.substring(1, text.length()-1));
             }
-          case 151: break;
+          case 152: break;
           case 58: 
             { return sym(SCLTerminals.QUERY_OP);
             }
-          case 152: break;
+          case 153: break;
           case 59: 
             { return sym(SCLTerminals.LET);
             }
-          case 153: break;
+          case 154: break;
           case 60: 
             { return sym(SCLTerminals.MDO);
             }
-          case 154: break;
+          case 155: break;
           case 61: 
             { string.setLength(0); stringStart=yychar; yybegin(LONG_STRING); return sym(SCLTerminals.BEGIN_STRING);
             }
-          case 155: break;
+          case 156: break;
           case 62: 
             { yybegin(YYINITIAL); 
                       return new Token(SCLTerminals.END_STRING, stringStart, yychar+3, string.toString());
             }
-          case 156: break;
+          case 157: break;
           case 63: 
-            { return sym(SCLTerminals.RULE);
+            { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.RULE);
             }
-          case 157: break;
+          case 158: break;
           case 64: 
             { return sym(SCLTerminals.THEN);
             }
-          case 158: break;
+          case 159: break;
           case 65: 
             { return sym(SCLTerminals.TYPE);
             }
-          case 159: break;
+          case 160: break;
           case 66: 
             { return sym(SCLTerminals.ELSE);
             }
-          case 160: break;
+          case 161: break;
           case 67: 
             { return sym(SCLTerminals.WITH);
             }
-          case 161: break;
+          case 162: break;
           case 68: 
             { return sym(SCLTerminals.WHEN);
             }
-          case 162: break;
+          case 163: break;
           case 69: 
             { return sym(SCLTerminals.DATA);
             }
-          case 163: break;
+          case 164: break;
           case 70: 
             { return sym(SCLTerminals.INFIX);
             }
-          case 164: break;
+          case 165: break;
           case 71: 
             { return sym(SCLTerminals.WHERE);
             }
-          case 165: break;
+          case 166: break;
           case 72: 
             { return sym(SCLTerminals.CLASS);
             }
-          case 166: break;
+          case 167: break;
           case 73: 
             { return sym(SCLTerminals.MATCH);
             }
-          case 167: break;
+          case 168: break;
           case 74: 
             { return sym(SCLTerminals.LAMBDA_MATCH);
             }
-          case 168: break;
+          case 169: break;
           case 75: 
             { return sym(SCLTerminals.FORALL);
             }
-          case 169: break;
+          case 170: break;
           case 76: 
             { return sym(SCLTerminals.INFIXR);
             }
-          case 170: break;
+          case 171: break;
           case 77: 
             { return sym(SCLTerminals.INFIXL);
             }
-          case 171: break;
+          case 172: break;
           case 78: 
             { return sym(SCLTerminals.IMPORT);
             }
-          case 172: break;
+          case 173: break;
           case 79: 
             { return sym(SCLTerminals.HIDING);
             }
-          case 173: break;
+          case 174: break;
           case 80: 
             { return sym(SCLTerminals.EFFECT);
             }
-          case 174: break;
+          case 175: break;
           case 81: 
             { return sym(SCLTerminals.SELECT);
             }
-          case 175: break;
+          case 176: break;
           case 82: 
             { string.append((char)Integer.parseInt(yytext().substring(2), 16));
             }
-          case 176: break;
+          case 177: break;
           case 83: 
-            { return sym(SCLTerminals.INCLUDE);
+            { return sym(supportCHR() ? SCLTerminals.RULESET : SCLTerminals.ID);
             }
-          case 177: break;
+          case 178: break;
           case 84: 
-            { return sym(SCLTerminals.ENFORCE);
+            { return sym(SCLTerminals.INCLUDE);
             }
-          case 178: break;
+          case 179: break;
           case 85: 
-            { return sym(SCLTerminals.EXTENDS);
+            { return sym(SCLTerminals.ENFORCE);
             }
-          case 179: break;
+          case 180: break;
           case 86: 
-            { return sym(SCLTerminals.INSTANCE);
+            { return sym(SCLTerminals.EXTENDS);
             }
-          case 180: break;
+          case 181: break;
           case 87: 
-            { return sym(SCLTerminals.DERIVING);
+            { return sym(SCLTerminals.INSTANCE);
             }
-          case 181: break;
+          case 182: break;
           case 88: 
-            { return sym(SCLTerminals.IMPORTJAVA);
+            { return sym(SCLTerminals.DERIVING);
             }
-          case 182: break;
+          case 183: break;
           case 89: 
-            { return sym(SCLTerminals.CONSTRAINT);
+            { return sym(SCLTerminals.IMPORTJAVA);
             }
-          case 183: break;
+          case 184: break;
           case 90: 
-            { return sym(SCLTerminals.SELECT_FIRST);
+            { return sym(SCLTerminals.CONSTRAINT);
             }
-          case 184: break;
+          case 185: break;
           case 91: 
-            { return sym(SCLTerminals.ABSTRACT_RULE);
+            { return sym(SCLTerminals.SELECT_FIRST);
             }
-          case 185: break;
+          case 186: break;
           case 92: 
-            { return sym(SCLTerminals.TRANSFORMATION);
+            { return sym(SCLTerminals.ABSTRACT_RULE);
             }
-          case 186: break;
+          case 187: break;
           case 93: 
-            { return sym(SCLTerminals.SELECT_DISTINCT);
+            { return sym(supportCHR() ? SCLTerminals.ID : SCLTerminals.TRANSFORMATION);
             }
-          case 187: break;
+          case 188: break;
           case 94: 
+            { return sym(SCLTerminals.SELECT_DISTINCT);
+            }
+          case 189: break;
+          case 95: 
             { return sym(SCLTerminals.MAPPING_RELATION);
             }
-          case 188: break;
+          case 190: break;
           default:
             zzScanError(ZZ_NO_MATCH);
         }
index 51eafba3c75c8de5febcc4628b457aa146cc94d5..3b8a4c400293523d105ea223a57485b7a3b2e43a 100644 (file)
Binary files a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat and b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/parser/SCLParser.dat differ
index 735974868ec8d4ae851d4490661b95eccf93bdd1..527c66f5dc0b86e78988c8cf83b5e3e23970078a 100644 (file)
@@ -13,18 +13,18 @@ public abstract class SCLParser {
     public static final boolean TRACE = false;
 
     private static final int INITIAL_CAPACITY = 16;
-    private static final int STATE_COUNT = 345;
-    private static final int TERMINAL_COUNT = 83;
+    private static final int STATE_COUNT = 353;
+    private static final int TERMINAL_COUNT = 84;
     private static final int NONTERMINAL_COUNT = 51;
-    private static final int PRODUCT_COUNT = 132;
+    private static final int PRODUCT_COUNT = 134;
     
     private static final int[] ACTION_ROW_ID = new int[STATE_COUNT];
     private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT];
-    private static final short[] ACTION_TABLE = new short[6360];
-    private static final int[] ERROR_TABLE = new int[895];
+    private static final short[] ACTION_TABLE = new short[6588];
+    private static final int[] ERROR_TABLE = new int[927];
     private static final int[] GOTO_ROW_ID = new int[STATE_COUNT];
     private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT];
-    private static final short[] GOTO_TABLE = new short[1711];
+    private static final short[] GOTO_TABLE = new short[1620];
     private static final int[] PRODUCT_LHS = new int[PRODUCT_COUNT];
 
     private static final short STATE_MASK = (short)0x0fff;
@@ -64,6 +64,7 @@ public abstract class SCLParser {
         "EXTENDS",
         "MAPPING_RELATION",
         "FOLLOWS",
+        "RULESET",
         "IMPORT",
         "INCLUDE",
         "AS",
@@ -141,10 +142,10 @@ public abstract class SCLParser {
         "atype",
         "aexp",
         "ruleDeclarations",
+        "statements",
         "importSpec",
         "importItem",
         "fieldDeclaration",
-        "statements",
         "guardedExpEq",
         "fundep",
         "ruleDeclaration",
@@ -393,19 +394,19 @@ public abstract class SCLParser {
         return parse(0);
     }
     public Object parseCommands() {
-        return parse(330);
+        return parse(337);
     }
     public Object parseImport() {
-        return parse(337);
+        return parse(345);
     }
     public Object parseType() {
-        return parse(339);
+        return parse(347);
     }
     public Object parseExp() {
-        return parse(341);
+        return parse(349);
     }
     public Object parseEquationBlock() {
-        return parse(343);
+        return parse(351);
     }
 
 
@@ -461,208 +462,212 @@ public abstract class SCLParser {
         case 23:
             return reduceRelationDefinition();
         case 24:
-            return reduceStatementCommand();
+            return reduceRulesetDefinition();
         case 25:
-            return reduceImportCommand();
+            return reduceStatementCommand();
         case 26:
-            return reduceGuardStatement();
+            return reduceImportCommand();
         case 27:
-            return reduceLetStatement();
+            return reduceGuardStatement();
         case 28:
-            return reduceBindStatement();
+            return reduceLetStatement();
         case 29:
-            return reduceRuleStatement();
+            return reduceBindStatement();
         case 30:
-            return reduceCHRStatement();
+            return reduceRuleStatement();
         case 31:
-            return reduceVerboseCHRStatement();
+            return reduceCHRStatement();
         case 32:
-            return reduceConstraintStatement();
+            return reduceVerboseCHRStatement();
         case 33:
-            return reduceDeclarations();
+            return reduceConstraintStatement();
         case 34:
-            return reduceField();
+            return reduceLocalInclude();
         case 35:
-            return reduceFieldShorthand();
+            return reduceDeclarations();
         case 36:
-            return reduceVarId();
+            return reduceField();
         case 37:
-            return reduceEscapedSymbol();
+            return reduceFieldShorthand();
         case 38:
-            return reduceTupleConstructor();
+            return reduceVarId();
         case 39:
-            return reduceBinary();
+            return reduceEscapedSymbol();
         case 40:
-            return reduceSimpleRhs();
+            return reduceTupleConstructor();
         case 41:
-            return reduceGuardedRhs();
+            return reduceBinary();
         case 42:
-            return reduceConstructor();
+            return reduceSimpleRhs();
         case 43:
-            return reduceRecordConstructor();
+            return reduceGuardedRhs();
         case 44:
-            return reduceContext();
+            return reduceConstructor();
         case 45:
-            return reduceFundeps();
+            return reduceRecordConstructor();
         case 46:
-            return reduceTypeVar();
+            return reduceContext();
         case 47:
-            return reduceTupleType();
+            return reduceFundeps();
         case 48:
-            return reduceListType();
+            return reduceTypeVar();
         case 49:
-            return reduceListTypeConstructor();
+            return reduceTupleType();
         case 50:
-            return reduceTupleTypeConstructor();
+            return reduceListType();
         case 51:
-            return reduceLambda();
+            return reduceListTypeConstructor();
         case 52:
-            return reduceLambdaMatch();
+            return reduceTupleTypeConstructor();
         case 53:
-            return reduceLet();
+            return reduceLambda();
         case 54:
-            return reduceIf();
+            return reduceLambdaMatch();
         case 55:
-            return reduceMatch();
+            return reduceLet();
         case 56:
-            return reduceDo();
+            return reduceIf();
         case 57:
-            return reduceSelect();
+            return reduceMatch();
         case 58:
-            return reduceEnforce();
+            return reduceDo();
         case 59:
-            return reduceVar();
+            return reduceSelect();
         case 60:
-            return reduceHashedId();
+            return reduceEnforce();
         case 61:
-            return reduceBlank();
+            return reduceVar();
         case 62:
-            return reduceInteger();
+            return reduceHashedId();
         case 63:
-            return reduceFloat();
+            return reduceBlank();
         case 64:
-            return reduceString();
+            return reduceInteger();
         case 65:
-            return reduceChar();
+            return reduceFloat();
         case 66:
-            return reduceTuple();
+            return reduceString();
         case 67:
-            return reduceViewPattern();
+            return reduceChar();
         case 68:
-            return reduceRightSection();
+            return reduceTuple();
         case 69:
-            return reduceLeftSection();
+            return reduceViewPattern();
         case 70:
-            return reduceListLiteral();
+            return reduceRightSection();
         case 71:
-            return reduceRange();
+            return reduceLeftSection();
         case 72:
-            return reduceListComprehension();
+            return reduceListLiteral();
         case 73:
-            return reduceAs();
+            return reduceRange();
         case 74:
-            return reduceRecord();
+            return reduceListComprehension();
         case 75:
-            return reduceTransformation();
+            return reduceAs();
         case 76:
-            return reduceEq();
+            return reduceRecord();
         case 77:
-            return reduceRuleDeclarations();
+            return reduceTransformation();
         case 78:
-            return reduceImportShowing();
+            return reduceEq();
         case 79:
-            return reduceImportHiding();
+            return reduceRuleDeclarations();
         case 80:
-            return reduceImportValueItem();
+            return reduceStatements();
         case 81:
-            return reduceFieldDescription();
+            return reduceImportShowing();
         case 82:
-            return reduceStatements();
+            return reduceImportHiding();
         case 83:
-            return reduceGuardedExpEq();
+            return reduceImportValueItem();
         case 84:
-            return reduceFundep();
+            return reduceFieldDescription();
         case 85:
-            return reduceQueryRuleDeclaration();
+            return reduceGuardedExpEq();
         case 86:
-            return reduceAnnotation();
+            return reduceFundep();
         case 87:
-            return reduceGuardQuery();
+            return reduceQueryRuleDeclaration();
         case 88:
-            return reduceEqualsQuery();
+            return reduceAnnotation();
         case 89:
-            return reduceBindQuery();
+            return reduceGuardQuery();
         case 90:
-            return reduceCompositeQuery();
+            return reduceEqualsQuery();
         case 91:
-            return reduceApply();
+            return reduceBindQuery();
         case 92:
-            return reduceSymbol();
+            return reduceCompositeQuery();
         case 93:
-            return reduceEscapedId();
+            return reduceApply();
         case 94:
-            return reduceMinus();
+            return reduceSymbol();
         case 95:
-            return reduceLess();
+            return reduceEscapedId();
         case 96:
-            return reduceGreater();
+            return reduceMinus();
         case 97:
-            return reduceDot();
+            return reduceLess();
         case 98:
-            return reduceFieldAccess();
+            return reduceGreater();
         case 99:
-            return reduceIdAccessor();
+            return reduceDot();
         case 100:
-            return reduceStringAccessor();
+            return reduceFieldAccess();
         case 101:
-            return reduceExpAccessor();
+            return reduceIdAccessor();
         case 102:
-            return reduceCase();
+            return reduceStringAccessor();
         case 103:
-            return reduceQueryBlock();
+            return reduceExpAccessor();
         case 104:
-            return reduceStringLiteral();
+            return reduceCase();
         case 105:
-            return reduceSymbol();
+            return reduceQueryBlock();
         case 106:
-            return reduceEscapedId();
+            return reduceStringLiteral();
         case 107:
-            return reduceLess();
+            return reduceSymbol();
         case 108:
-            return reduceGreater();
+            return reduceEscapedId();
         case 109:
-            return reduceDot();
+            return reduceLess();
         case 110:
-            return reduceGuardQualifier();
+            return reduceGreater();
         case 111:
-            return reduceLetQualifier();
+            return reduceDot();
         case 112:
-            return reduceBindQualifier();
+            return reduceGuardQualifier();
         case 113:
-            return reduceThenQualifier();
+            return reduceLetQualifier();
         case 114:
-            return reduceCHRQuery();
+            return reduceBindQualifier();
         case 115:
-            return reduceVerboseCHRQuery();
+            return reduceThenQualifier();
         case 116:
-            return reduceSimpleCaseRhs();
+            return reduceCHRQuery();
         case 117:
-            return reduceGuardedCaseRhs();
+            return reduceVerboseCHRQuery();
         case 118:
-            return reduceGuardedExpArrow();
+            return reduceSimpleCaseRhs();
         case 119:
-            return reduceGuardEquation();
+            return reduceGuardedCaseRhs();
         case 120:
-            return reduceBasicEquation();
+            return reduceGuardedExpArrow();
         case 121:
-            return reduceEffect();
+            return reduceGuardEquation();
         case 122:
-            return reduceJustEtype();
+            return reduceBasicEquation();
         case 123:
-            return reduceForAll();
+            return reduceEffect();
         case 124:
-            return reduceApplyType();
+            return reduceJustEtype();
         case 125:
+            return reduceForAll();
+        case 126:
+            return reduceApplyType();
+        case 127:
             return reduceDummy();
 
         default:
@@ -779,6 +784,10 @@ public abstract class SCLParser {
      * declaration ::= bexp FOLLOWS ruleDeclarations
      */
     protected abstract Object reduceRelationDefinition();
+    /**
+     * declaration ::= RULESET ID WHERE statements
+     */
+    protected abstract Object reduceRulesetDefinition();
     /**
      * command ::= statement
      */
@@ -815,6 +824,10 @@ public abstract class SCLParser {
      * statement ::= CONSTRAINT ID atype&#42;
      */
     protected abstract Object reduceConstraintStatement();
+    /**
+     * statement ::= INCLUDE ID aexp
+     */
+    protected abstract Object reduceLocalInclude();
     /**
      * declarations ::= LBRACE (declaration (SEMICOLON (declaration SEMICOLON)&#42; declaration)?)? RBRACE
      */
@@ -995,6 +1008,10 @@ public abstract class SCLParser {
      * ruleDeclarations ::= LBRACE (ruleDeclaration (SEMICOLON (ruleDeclaration SEMICOLON)&#42; ruleDeclaration)?)? RBRACE
      */
     protected abstract Object reduceRuleDeclarations();
+    /**
+     * statements ::= LBRACE (statement (SEMICOLON (statement SEMICOLON)&#42; statement)?)? RBRACE
+     */
+    protected abstract Object reduceStatements();
     /**
      * importSpec ::= LPAREN (importItem (COMMA (importItem COMMA)&#42; importItem)?)? RPAREN
      */
@@ -1011,10 +1028,6 @@ public abstract class SCLParser {
      * fieldDeclaration ::= ID HASTYPE type
      */
     protected abstract Object reduceFieldDescription();
-    /**
-     * statements ::= LBRACE (statement (SEMICOLON (statement SEMICOLON)&#42; statement)?)? RBRACE
-     */
-    protected abstract Object reduceStatements();
     /**
      * guardedExpEq ::= BAR exp (COMMA exp)&#42; EQUALS exp
      */
index 799e59099b924a005ff59d8a3bf048dfd3e6b3ee..09fc79e0f531030b8ff2d1dfa720a00c22428dfb 100644 (file)
@@ -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<length();i+=2) {
             DeclarationAst declaration = (DeclarationAst)get(i);
             if(declaration == null)
-                throw new NullPointerException();
+                continue;
             declarations.add(declaration);
         }
         return declarations;
@@ -169,7 +178,8 @@ public class SCLParserImpl extends SCLParser {
         FieldAssignment[] fields = new FieldAssignment[length()/2-1];
         for(int i=0;i<fields.length;++i)
             fields[i] = (FieldAssignment)get(2+i*2);
-        return new DModuleHeader(fields);
+        context.header = ModuleHeader.process(context.errorLog, fields);
+        return null;
     }
 
     @Override
@@ -1283,4 +1293,18 @@ public class SCLParserImpl extends SCLParser {
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    protected Object reduceRulesetDefinition() {
+        Token name = (Token)get(1);
+        EBlock block = (EBlock)get(3);
+        return new DRulesetAst(name.text, block);
+    }
+
+    @Override
+    protected Object reduceLocalInclude() {
+        Token name = (Token)get(1);
+        Expression value = (Expression)get(2);
+        return new IncludeStatement(name, value);
+    }
+
 }
index 9cc1ff27b16a288afb11f138b9d8755a84f642d0..a2253d8b7bc001cc7d0889a5ab69a0a5885e7922 100644 (file)
@@ -3,6 +3,7 @@ package org.simantics.scl.compiler.internal.parsing.parser;
 import java.io.IOException;
 import java.util.Arrays;
 
+import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.parsing.Token;
 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
@@ -16,6 +17,9 @@ import gnu.trove.set.hash.TIntHashSet;
  * @author Hannu Niemistö
  */
 public class SCLPostLexer {
+    
+    private static final int PATCH_SIZE = 16;
+    private static final int INITIAL_QUEUE_SIZE = 32;
         
     public static TIntHashSet INDENTABLE = new TIntHashSet();
     public static TIntHashSet NO_SEMICOLON_BEFORE = new TIntHashSet();
@@ -49,7 +53,7 @@ public class SCLPostLexer {
     }
     
     SCLLexer lexer;
-    Token[] queue = new Token[16];
+    Token[] queue = new Token[INITIAL_QUEUE_SIZE];
     int queuePos=0, queueSize=0;
     TIntArrayList indentations = new TIntArrayList();
     TIntArrayList indentationTokens = new TIntArrayList();
@@ -58,6 +62,12 @@ public class SCLPostLexer {
     boolean firstTokenOfLine = true;
     private SCLParserOptions options;
     private boolean isFirstToken = true;
+    private CompilationContext context;
+    
+    /**
+     * We are parsing a module header and therefore should process tokens one by one and not by patches.
+     */
+    private boolean isInsideModule = false; 
             
     {
         indentations.add(0);
@@ -71,6 +81,11 @@ public class SCLPostLexer {
     public SCLPostLexer(java.io.Reader in) {
         this(new SCLLexer(in));
     }
+    
+    public void setCompilationContext(CompilationContext context) {
+        lexer.setCompilationContext(context);
+        this.context = context;
+    }
 
     public Token nextToken() throws Exception {
         while(queuePos == queueSize)
@@ -98,8 +113,15 @@ public class SCLPostLexer {
         queuePos = 0;
         queueSize = 0;
         
-        for(int i=0;i<8;++i)
+        for(int i=0;i<PATCH_SIZE;++i) {
             handleToken(lexer.nextToken());
+            if(isInsideModule) {
+                if(context.header == null)
+                    break;
+                else
+                    isInsideModule = false;
+            }
+        }
     }
     
     private SCLSyntaxErrorException error(int start, int end, String description) {
@@ -156,6 +178,7 @@ public class SCLPostLexer {
                 isFirstToken = false;
                 if(symbol.id == SCLTerminals.ID && symbol.text.equals("module") && options != null && options.isModule) {
                     push(new Token(SCLTerminals.MODULE, symbol.location, symbol.text));
+                    isInsideModule = true;
                     return;
                 }
             }
index c7723eea8e5a41f8dacab76bbecbd8a9105f97ae..58a40f61ea64bfce284ace557fd935f5e5cc4356 100644 (file)
@@ -30,58 +30,59 @@ public interface SCLTerminals {
     public static final int EXTENDS = 26;
     public static final int MAPPING_RELATION = 27;
     public static final int FOLLOWS = 28;
-    public static final int IMPORT = 29;
-    public static final int INCLUDE = 30;
-    public static final int AS = 31;
-    public static final int LPAREN = 32;
-    public static final int RPAREN = 33;
-    public static final int HIDING = 34;
-    public static final int ARROW = 35;
-    public static final int COLON = 36;
-    public static final int MINUS = 37;
-    public static final int SYMBOL = 38;
-    public static final int LESS = 39;
-    public static final int GREATER = 40;
-    public static final int SEPARATED_DOT = 41;
-    public static final int ESCAPED_ID = 42;
-    public static final int LAMBDA = 43;
-    public static final int LAMBDA_MATCH = 44;
-    public static final int LET = 45;
-    public static final int IF = 46;
-    public static final int MATCH = 47;
-    public static final int DO = 48;
-    public static final int MDO = 49;
-    public static final int ENFORCE = 50;
-    public static final int BLANK = 51;
-    public static final int FLOAT = 52;
-    public static final int LBRACKET = 53;
-    public static final int ESCAPED_SYMBOL = 54;
-    public static final int CHAR = 55;
-    public static final int WHEN = 56;
-    public static final int ATTACHED_HASH = 57;
-    public static final int SELECT = 58;
-    public static final int SELECT_FIRST = 59;
-    public static final int SELECT_DISTINCT = 60;
-    public static final int TRANSFORMATION = 61;
-    public static final int EQ = 62;
-    public static final int ATTACHED_DOT = 63;
-    public static final int IN = 64;
-    public static final int THEN = 65;
-    public static final int ELSE = 66;
-    public static final int WITH = 67;
-    public static final int RBRACKET = 68;
-    public static final int DOTDOT = 69;
-    public static final int AT = 70;
-    public static final int SUSPEND_STRING = 71;
-    public static final int CONTINUE_STRING = 72;
-    public static final int BINDS = 73;
-    public static final int IMPLIES = 74;
-    public static final int THEN_AFTER_WHEN = 75;
-    public static final int CONSTRAINT = 76;
-    public static final int BY = 77;
-    public static final int QUERY_OP = 78;
-    public static final int FORALL = 79;
-    public static final int COMMENT = 80;
-    public static final int EOL = 81;
-    public static final int EOF = 82;
+    public static final int RULESET = 29;
+    public static final int IMPORT = 30;
+    public static final int INCLUDE = 31;
+    public static final int AS = 32;
+    public static final int LPAREN = 33;
+    public static final int RPAREN = 34;
+    public static final int HIDING = 35;
+    public static final int ARROW = 36;
+    public static final int COLON = 37;
+    public static final int MINUS = 38;
+    public static final int SYMBOL = 39;
+    public static final int LESS = 40;
+    public static final int GREATER = 41;
+    public static final int SEPARATED_DOT = 42;
+    public static final int ESCAPED_ID = 43;
+    public static final int LAMBDA = 44;
+    public static final int LAMBDA_MATCH = 45;
+    public static final int LET = 46;
+    public static final int IF = 47;
+    public static final int MATCH = 48;
+    public static final int DO = 49;
+    public static final int MDO = 50;
+    public static final int ENFORCE = 51;
+    public static final int BLANK = 52;
+    public static final int FLOAT = 53;
+    public static final int LBRACKET = 54;
+    public static final int ESCAPED_SYMBOL = 55;
+    public static final int CHAR = 56;
+    public static final int WHEN = 57;
+    public static final int ATTACHED_HASH = 58;
+    public static final int SELECT = 59;
+    public static final int SELECT_FIRST = 60;
+    public static final int SELECT_DISTINCT = 61;
+    public static final int TRANSFORMATION = 62;
+    public static final int EQ = 63;
+    public static final int ATTACHED_DOT = 64;
+    public static final int IN = 65;
+    public static final int THEN = 66;
+    public static final int ELSE = 67;
+    public static final int WITH = 68;
+    public static final int RBRACKET = 69;
+    public static final int DOTDOT = 70;
+    public static final int AT = 71;
+    public static final int SUSPEND_STRING = 72;
+    public static final int CONTINUE_STRING = 73;
+    public static final int BINDS = 74;
+    public static final int IMPLIES = 75;
+    public static final int THEN_AFTER_WHEN = 76;
+    public static final int CONSTRAINT = 77;
+    public static final int BY = 78;
+    public static final int QUERY_OP = 79;
+    public static final int FORALL = 80;
+    public static final int COMMENT = 81;
+    public static final int EOL = 82;
+    public static final int EOF = 83;
 }
index c6210ce49dcf99498b68e09946fb02593c06c308..73311e99ab9ab4a17f087d1f215b15de89286929 100644 (file)
@@ -9,6 +9,7 @@ import java.util.function.Consumer;
 
 import org.simantics.scl.compiler.common.names.Name;
 import org.simantics.scl.compiler.constants.Constant;
+import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
 import org.simantics.scl.compiler.elaboration.modules.Documentation;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
@@ -38,10 +39,11 @@ public class ConcreteModule implements Module {
     THashMap<TCon, ArrayList<TypeClassInstance>> typeClassInstances = new THashMap<TCon, ArrayList<TypeClassInstance>>();
     THashMap<String, SCLValue> values = new THashMap<String, SCLValue>();
     THashMap<String, List<Constant>> fieldAccessors = new THashMap<String, List<Constant>>();
-    THashMap<String, SCLRelation> relations = new THashMap<String, SCLRelation>();
-    THashMap<String, SCLEntityType> entityTypes = new THashMap<String, SCLEntityType>();
-    THashMap<String, TransformationRule> rules = new THashMap<String, TransformationRule>();
-    THashMap<String, MappingRelation> mappingRelations = new THashMap<String, MappingRelation>();
+    THashMap<String, SCLRelation> relations = new THashMap<String, SCLRelation>(2);
+    THashMap<String, SCLEntityType> entityTypes = new THashMap<String, SCLEntityType>(2);
+    THashMap<String, TransformationRule> rules = new THashMap<String, TransformationRule>(2);
+    THashMap<String, MappingRelation> mappingRelations = new THashMap<String, MappingRelation>(2);
+    THashMap<String, CHRRuleset> rulesets = new THashMap<String, CHRRuleset>(2);
     ArrayList<ImportDeclaration> dependencies = new ArrayList<ImportDeclaration>();
     THashMap<String, BranchPoint[]> branchPoints;
     CompilationError[] warnings = CompilationError.EMPTY_ARRAY;
@@ -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<TypeClass> 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);
+    }
 }
index a53a90b916e8bb8ca7bb6e210f91e13077e54a9d..61d2c29288992f63ddb6ab2209a9336f86e918d8 100644 (file)
@@ -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;
+    }
 }
index 51d39e103c96b53a7e44a13dd175ea0bf2ae349e..ee90b5e1a3f7f263406debf52453ea531f394d25 100644 (file)
@@ -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<TypeClassInstance> getInstances(TCon typeClass);
     MappingRelation getMappingRelation(String name);
     TransformationRule getRule(String name);
+    CHRRuleset getRuleset(String name);
     Collection<TransformationRule> getRules();
     
     void findValuesForPrefix(String prefix, NamespaceFilter filter, TObjectProcedure<SCLValue> proc);
index 4ed45005b9659aa8fc42f1c6790e1c8f851abf64..5ae73c41240700f44662e1b70f6851487752b290 100644 (file)
@@ -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);
         }
index 2b42bc7bab865c75d8873ba8150504eb6aa47cc6..a5b9a65417e79e095acc83149f49d40ffa47690d 100644 (file)
@@ -236,7 +236,7 @@ public class ExpressionEvaluator {
         ArrayList<Type> lvTypes = new ArrayList<Type>(); 
         if(expression instanceof EBlock) {
             EBlock block = (EBlock)expression;
-            if(localStorage != null && !(block.getStatements().getLast() instanceof GuardStatement)) {
+            if(localStorage != null && !(block.getLast() instanceof GuardStatement)) {
                 THashSet<String> localVariables = new THashSet<String>();
                 ListIterator<Statement> it = block.getStatements().listIterator();
                 while(it.hasNext()) {
@@ -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])));
         }
         
index 57f7102cb7dbec38a03c0268a2d3333203ac3690..1331530dda6dfe5249fda811387f850d8022e6c4 100644 (file)
@@ -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;
+    }
     
 }
index f793754eed215be13e6ead654b115dac722b5df2..9ea064cfd11bf4abf4094a900a53d9951dc24878 100644 (file)
@@ -112,6 +112,9 @@ public class Types {
     public static final TCon PROC = con(BUILTIN, "Proc");
     
     public static final TCon BRANCH_POINT = con(BUILTIN, "BranchPoint");
+    
+    public static final TCon CHRContext = con(BUILTIN, "CHRContext");
+    
 
     private volatile static TCon[] tupleCache = new TCon[] {
         UNIT, null
@@ -128,7 +131,7 @@ public class Types {
         }
 
     };
-    
+
     public static boolean isPrimitive(Type type) {
        return type == BOOLEAN || type == BYTE || type == CHARACTER || type == SHORT ||
                        type == INTEGER || type == LONG || type == FLOAT || type == DOUBLE || type == STRING;
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRContext.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRContext.java
new file mode 100644 (file)
index 0000000..59fe191
--- /dev/null
@@ -0,0 +1,17 @@
+package org.simantics.scl.runtime.chr;
+
+public class CHRContext {
+    public CHRPriority topPriority;
+    public int currentId = 1;
+    
+    public void activate(int maxPriority) {
+        //System.out.println("--- ACTIVATE " + maxPriority + "---------------------------------------------");
+        while(topPriority != null && topPriority.priority < maxPriority) {
+            CHRPriority currentPriority = topPriority;
+            topPriority = currentPriority.nextPriority();
+            currentPriority.activate(this);
+            currentPriority.inContext = false;
+        }
+        //System.out.println("--- FINISHED " + maxPriority + "---------------------------------------------");
+    }
+}
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRFact.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRFact.java
new file mode 100644 (file)
index 0000000..7107303
--- /dev/null
@@ -0,0 +1,5 @@
+package org.simantics.scl.runtime.chr;
+
+public class CHRFact {
+    public int id;
+}
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriority.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriority.java
new file mode 100644 (file)
index 0000000..008830b
--- /dev/null
@@ -0,0 +1,78 @@
+package org.simantics.scl.runtime.chr;
+
+/**
+ * This class implements a pairing heap of CHR priorities.
+ */
+public abstract class CHRPriority implements Comparable<CHRPriority> {
+    
+    public final int priority;
+    
+    // Pairing heap
+    private CHRPriority sibling;
+    private CHRPriority child;
+    
+    boolean inContext;
+    
+    public CHRPriority(int priority) {
+        this.priority = priority;
+    }
+    
+    /**
+     * This method assume that a and b are roots and their sibling field
+     * can be overridden. 
+     */
+    public static CHRPriority merge(CHRPriority a, CHRPriority b) {
+        if(a.priority <= b.priority) {
+            a.sibling = null;
+            b.sibling = a.child;
+            a.child = b;
+            return a;
+        }
+        else {
+            a.sibling = b.child;
+            b.sibling = null;
+            b.child = a;
+            return b;
+        }
+    }
+    
+    protected void ensureInContext(CHRContext context) {
+        if(!inContext) {
+            CHRPriority topPriority = context.topPriority;
+            if(topPriority == null)
+                context.topPriority = this;
+            else
+                context.topPriority = merge(topPriority, this);
+            inContext = true;
+        }
+    }
+    
+    private CHRPriority mergeSiblings() {
+        if(sibling == null)
+            return this;
+        CHRPriority nextSibling = sibling.sibling;
+        CHRPriority merged = merge(this, sibling);
+        if(nextSibling == null)
+            return merged;
+        else
+            return merge(merged, nextSibling.mergeSiblings());
+    }
+    
+    public CHRPriority nextPriority() {
+        if(child == null)
+            return null;
+        else {
+            CHRPriority result = child.mergeSiblings();
+            child = null;
+            return result;
+        }
+    }
+    
+    @Override
+    public int compareTo(CHRPriority o) {
+        return Double.compare(priority, o.priority);
+    }
+    
+    public abstract void activate(CHRContext context);
+    //public abstract CHRRuntimeRuleset getParent();
+}
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriorityFactContainer.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRPriorityFactContainer.java
new file mode 100644 (file)
index 0000000..bedb8e0
--- /dev/null
@@ -0,0 +1,59 @@
+package org.simantics.scl.runtime.chr;
+
+import java.util.Arrays;
+
+import org.simantics.scl.runtime.reporting.SCLReporting;
+
+public abstract class CHRPriorityFactContainer extends CHRPriority {
+    private static final boolean CLEANUP_ENABLED = true;
+    private static final int INITIAL_FACT_ARRAY_SIZE = 4;
+    
+    private CHRFact[] facts = new CHRFact[INITIAL_FACT_ARRAY_SIZE];
+    private int size;
+
+    public CHRPriorityFactContainer(int priority) {
+        super(priority);
+    }
+
+    public boolean isEmpty() {
+        return size == 0;
+    }
+
+    public void addFact(CHRContext context, CHRFact item) {
+        //SCLReporting.print("added " + item + " to " + this);
+        ensureInContext(context);
+        if(size == facts.length)
+            increaseCapacity();
+        facts[size++] = item;
+    }
+    
+    private void increaseCapacity() {
+        if(CLEANUP_ENABLED) {
+            // Cleanup dead facts
+            int j=0;
+            for(int i=0;i<size;++i) {
+                CHRFact fact = facts[i];
+                if(fact.id >= 0)
+                    facts[j++] = fact;
+            }
+            size = j;
+        }
+        
+        // Resize if necessary
+        if(size >= facts.length*3/4)
+            facts = Arrays.copyOf(facts, size*2);
+    }
+
+    @Override
+    public void activate(CHRContext context) {
+        while(size > 0) {
+            --size;
+            CHRFact fact = facts[size];
+            facts[size] = null;
+            if(fact.id >= 0)
+                activate(context, fact);
+        }
+    }
+
+    protected abstract void activate(CHRContext context, CHRFact fact);
+}
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRRuntimeRuleset.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/CHRRuntimeRuleset.java
new file mode 100644 (file)
index 0000000..8f6ca3e
--- /dev/null
@@ -0,0 +1,5 @@
+package org.simantics.scl.runtime.chr;
+
+public class CHRRuntimeRuleset {
+
+}
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/Fact.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/Fact.java
deleted file mode 100644 (file)
index a75009e..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.simantics.scl.runtime.chr;
-
-public interface Fact {
-    /**
-     * Activates the fact with the given priority. The method returns
-     * the new priority of the fact or a negative number if the fact
-     * is deactivated.
-     */
-    int activate(Object context, int priority);
-    boolean isAlive();
-}
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/FactActivationQueue.java
deleted file mode 100644 (file)
index fcfa01f..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.simantics.scl.runtime.chr;
-
-import java.util.Arrays;
-
-public class FactActivationQueue {
-    public static final boolean TRACE = false;
-    
-    private final PriorityContainer[] containers;
-    private PriorityContainer[] activeContainers = new PriorityContainer[8];
-    private int activeContainerCount; 
-
-    public FactActivationQueue(int priorityCount) {
-        if(TRACE)
-            System.out.println("priorityCount = " + priorityCount);
-        containers = new PriorityContainer[priorityCount];
-        for(int i=0;i<priorityCount;++i)
-            containers[i] = new PriorityContainer(i); 
-    }
-    
-    /**
-     * Adds a new fact with a given priority
-     */
-    public void add(int priority, Fact item) {
-        if(TRACE)
-            System.out.println("FactActivationQueue.add " + priority + "@" + item);
-        PriorityContainer container = containers[priority];
-        if(container.size == 0)
-            activateContainer(container);
-        container.push(item);
-    }
-    
-    private void activateContainer(PriorityContainer container) {
-        if(TRACE)
-            System.out.println("FactActivationQueue.activate priority " + container.priority);
-        if(activeContainers.length == activeContainerCount)
-            activeContainers = Arrays.copyOf(activeContainers, activeContainerCount*2);
-        adjustUpwards(activeContainerCount, container);
-        ++activeContainerCount;
-    }
-
-    private void deactivateContainer() {
-        --activeContainerCount;
-        adjustDownwards(0, activeContainers[activeContainerCount]);
-        activeContainers[activeContainerCount] = null;
-    }
-
-    private void adjustDownwards(int pos, PriorityContainer item) {
-        int priority = item.priority;
-        while(true) {
-            int npos = 2*pos+1;
-            if(npos+1 >= activeContainerCount) {
-                if(npos >= activeContainerCount)
-                    break;
-                PriorityContainer item1 = activeContainers[npos];
-                if(priority > item1.priority) {
-                    activeContainers[pos] = item1;
-                    activeContainers[npos] = item;
-                    return;
-                }
-                else
-                    break;
-            }
-            PriorityContainer item1 = activeContainers[npos];
-            PriorityContainer item2 = activeContainers[npos+1];
-            if(priority < item1.priority) {
-                if(priority < item2.priority)
-                    break;
-            }
-            else {
-                if(item1.priority < item2.priority) {
-                    activeContainers[pos] = item1;
-                    pos = npos;
-                    continue;
-                }
-            }
-            activeContainers[pos] = item2;
-            pos = npos+1;
-        }
-        activeContainers[pos] = item;
-    }
-
-    private void adjustUpwards(int pos, PriorityContainer item) {
-        int priority = item.priority;
-        while(pos > 0) {
-            int npos = (pos-1)/2;
-            PriorityContainer item1 = activeContainers[npos];
-            if(item1.priority > priority) {
-                activeContainers[pos] = item1;
-                pos = npos;
-            }
-            else
-                break;
-        }
-        activeContainers[pos] = item;
-    }
-    
-    /**
-     * Activates all facts with priority less than the current priority
-     */
-    public void activate(Object context, int currentPriority) {
-        if(TRACE)
-            System.out.println("FactActivationQueue.activate " + currentPriority);
-        while(activeContainerCount > 0) {
-            PriorityContainer topContainer = activeContainers[0];
-            int priority = topContainer.priority;
-            if(priority >= currentPriority)
-                return;
-            
-            Fact fact = topContainer.pop();
-            if(topContainer.size == 0)
-                deactivateContainer();
-            
-            int newPriority = fact.activate(context, priority);
-            if(TRACE)
-                System.out.println("    [" + currentPriority + "] " + fact + " oldPriority=" + priority + ", newPriority=" + newPriority);
-            if(newPriority >= 0)
-                add(newPriority, fact);
-        }
-    }
-}
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/PriorityContainer.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/chr/PriorityContainer.java
deleted file mode 100644 (file)
index 867628f..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.simantics.scl.runtime.chr;
-
-import java.util.Arrays;
-
-class PriorityContainer {
-    private static final boolean CLEANUP_ENABLED = true;
-    
-    final int priority;
-    Fact[] facts = new Fact[4];
-    int size;
-
-    public PriorityContainer(int priority) {
-        this.priority = priority;
-    }
-    
-    public void push(Fact item) {
-        if(size == facts.length)
-            increaseCapacity();
-        facts[size++] = item;
-    }
-
-    private void increaseCapacity() {
-        if(CLEANUP_ENABLED) {
-            // Cleanup dead facts
-            int j=0;
-            for(int i=0;i<size;++i) {
-                Fact fact = facts[i];
-                if(fact.isAlive())
-                    facts[j++] = fact;
-            }
-            size = j;
-        }
-        
-        // Resize if necessary
-        if(size >= facts.length*3/4)
-            facts = Arrays.copyOf(facts, size*2);
-    }
-
-    public Fact pop() {
-        return facts[--size];
-    }
-}
diff --git a/bundles/org.simantics.scl.runtime/tests/org/simantics/scl/runtime/tests/TestFactActivationQueue.java b/bundles/org.simantics.scl.runtime/tests/org/simantics/scl/runtime/tests/TestFactActivationQueue.java
deleted file mode 100644 (file)
index 5f69f4a..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.simantics.scl.runtime.tests;
-
-import java.util.Random;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.simantics.scl.runtime.chr.Fact;
-import org.simantics.scl.runtime.chr.FactActivationQueue;
-
-import gnu.trove.list.array.TIntArrayList;
-
-public class TestFactActivationQueue {
-    public static Random RANDOM = new Random();
-    
-    private static class MyFact implements Fact {
-        TIntArrayList list;
-        int priority;
-
-        public MyFact(TIntArrayList list, int priority) {
-            this.list = list;
-            this.priority = priority;
-        }
-
-        @Override
-        public int activate(Object context, int priority) {
-            Assert.assertEquals(this.priority, priority);
-            list.add(priority);
-            return -1;
-        }
-
-        @Override
-        public boolean isAlive() {
-            return true;
-        }
-    }
-    
-    private void testRandomly(int priorities, int size) {
-        FactActivationQueue queue = new FactActivationQueue(priorities);
-        TIntArrayList list = new TIntArrayList(size); 
-        for(int i=0;i<size;++i) {
-            int val = RANDOM.nextInt(priorities);
-            queue.add(val, new MyFact(list, val));
-        }
-        queue.activate(null, priorities);
-        Assert.assertEquals(size, list.size());
-        for(int i=1;i<list.size();++i) {
-            int a = list.get(i-1);
-            int b = list.get(i);
-            Assert.assertTrue(a <= b);
-        }
-    }
-    
-    @Test
-    public void testRandomly() {
-        for(int i=0;i<10000;++i)
-            testRandomly(10, 10000);
-    }
-}
index 63b2338f4754ff825ab57c35d16957cc9360c21b..c37a9421f53bacb3f4c310381b160e7716d32727 100644 (file)
@@ -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,8 @@ public class SCLInfo {
         "as",
         "forall",
         "rule",
+        "ruleset",
+        "constraint",
         "extends",
         "by",
         "select",
index f3069f13b0bfa36b508243c679ef8e5cd65b3f94..fe18da61d1fdc215fe3c7a5f342cf96a47eaed96 100644 (file)
@@ -1,7 +1,5 @@
 package org.simantics.scl.compiler.tests;
 
-import org.junit.Test;
-
 public class ActiveTests extends TestBase {
     
     public ActiveTests() { super("scl"); }
@@ -19,6 +17,5 @@ public class ActiveTests extends TestBase {
   */  
     
     //@Test public void Bug6989() { test(); }
-    
-    
+
 }
index 5bd0c85d7b48c9ad8f03f925f9e401d0713c68d8..769a1bde952daaa9de2d5f25d4b1d6c1b6f866bf 100644 (file)
@@ -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() {