]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "Resolve some dependency problems with SDK features"
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Mon, 5 Jun 2017 19:36:33 +0000 (22:36 +0300)
committerGerrit Code Review <gerrit2@www.simantics.org>
Mon, 5 Jun 2017 19:36:33 +0000 (22:36 +0300)
136 files changed:
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java
bundles/org.simantics.graph/src/org/simantics/graph/refactoring/GraphRefactoringUtils.java
bundles/org.simantics.graph/src/org/simantics/graph/representation/PrettyPrintTG.java
bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java
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/CHRLiteral.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRelation.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/chr/relations/ExternalCHRRelation.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/translation/CHRTranslation.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/ERecord.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EVar.java
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/ConstraintStatement.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/elaboration/relations/SCLRelation.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/ConstructorAst.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/module/options/ModuleCompilationOptions.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/module/options/ModuleCompilationOptionsAdvisor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/runtime/RuntimeModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/TextualModuleSource.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.db/scl/Simantics/DB.scl
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/src/org/simantics/scl/runtime/reporting/WriterSCLReportingHandler.java [new file with mode: 0644]
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
bundles/org.simantics.tests.modelled.ontology/graph/Tests.pgraph
bundles/org.simantics.tests.modelled.ui.ontology/graph/TestsUI.pgraph
bundles/org.simantics.tests.modelled.ui/scl/Simantics/TestsUI.scl
bundles/org.simantics.tests.modelled.ui/src/org/simantics/tests/modelled/ui/STSCounterPanel.java
bundles/org.simantics.tests.modelled.ui/src/org/simantics/tests/modelled/ui/STSTestEditor.java
bundles/org.simantics.tests.modelled.ui/src/org/simantics/tests/modelled/ui/STSTestRunnerView.java
bundles/org.simantics.tests.modelled.ui/src/org/simantics/tests/modelled/ui/STSTestSuiteModel.java
bundles/org.simantics.tests.modelled/scl/Simantics/Tests.scl
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/TestsGraphUtils.java
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/junit/v2/ModelledSTSRunner.java
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/junit/v2/ModelledSTSSuiteRunner.java
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/junit/v2/ModelledSTSTestRunner.java
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/utils/ModelledSTSSuite.java
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/utils/ModelledSTSTest.java
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/utils/STSSuiteTestCollector.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/TestBase.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR1.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR10.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR3.scl
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/scl/CHR7.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR8.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR9.scl [new file with mode: 0644]
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Formula.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Transformation2.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Transformation3.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Transformation4.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/Transformation7.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/TransformationOrder.scl
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/unit/TestCHRCodeGenerator.java

index adc51c16d88ef0f74f1f849f421e9156398c69f1..08dd63ce0e25c4bf11084bc8402eb802cd51a49d 100644 (file)
@@ -106,6 +106,7 @@ import org.simantics.graph.db.TransferableGraphs;
 import org.simantics.graph.diff.Diff;
 import org.simantics.graph.diff.TransferableGraphDelta1;
 import org.simantics.graph.refactoring.GraphRefactoringUtils;
+import org.simantics.graph.representation.PrettyPrintTG;
 import org.simantics.graph.representation.TransferableGraph1;
 import org.simantics.layer0.Layer0;
 import org.simantics.operation.Layer0X;
@@ -1193,7 +1194,7 @@ public class Layer0Utils {
 
     }
 
-    private static TransferableGraphSource makeTGSource(ReadGraph graph, Resource r) throws DatabaseException {
+    public static TransferableGraphSource makeTGSource(ReadGraph graph, Resource r) throws DatabaseException {
 
        SimanticsClipboardImpl cp = new SimanticsClipboardImpl();
        CopyHandler c1 = graph.adapt(r, CopyHandler.class);
@@ -1378,4 +1379,11 @@ public class Layer0Utils {
        
     }
 
+    public static String prettyPrintResource(ReadGraph graph, Resource resource) throws Exception {
+        TransferableGraphSource source = makeTGSource(graph, resource);
+        TransferableGraph1 tg = TransferableGraphs.create(graph, source);
+        GraphRefactoringUtils.fixOntologyExport(tg);
+        return PrettyPrintTG.print(tg);
+    }
+
 }
index 9f8eca398f139c10a5a18801522230427fa29f08..90b134e33762b5f991baa5288a2974906f2bad7b 100644 (file)
@@ -128,6 +128,22 @@ public class GraphRefactoringUtils {
                                
                        return;
                        
+                } else if (ext.type.startsWith("http://")) {
+                    String first = "http://Projects/Development Project";
+                    Identity path = recursePath(tg, first);
+                    id.definition = new Internal(path.resource, ext.name);
+                    
+                    GraphStore store = TransferableGraphConversion.convert(tg);
+                    int rootId = store.identities.createPathToId(UriUtils.uriToPath(first + "/" + ext.name));
+                    propagateNewMarks(store.identities, rootId);
+
+                    TransferableGraph1 tgNew = TransferableGraphConversion.convert(store);
+                        
+                    tg.resourceCount = tgNew.resourceCount;
+                    tg.identities = tgNew.identities;
+                    tg.values = tgNew.values;
+                    tg.statements = tgNew.statements;
+
                 }
             }
         }
index 00d17100ec461bb5800a63e93e1b40175d90a204..bb776d5df649eaa08ac455942e453718c9d2a721 100644 (file)
@@ -11,6 +11,7 @@ import java.nio.file.Paths;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -19,22 +20,29 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.simantics.databoard.Bindings;
-import org.simantics.databoard.Datatypes;
 import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.databoard.container.DataContainers;
-import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.parser.DataValuePrinter;
+import org.simantics.databoard.parser.PrintFormat;
+import org.simantics.databoard.parser.repository.DataValueRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.hash.TIntIntHashMap;
 import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.procedure.TIntIntProcedure;
 import gnu.trove.set.hash.TLongHashSet;
 
 /**
  * @author Antti Villberg
  * @since 1.24.0
  */
-public class PrettyPrintTG extends TransferableGraphUtils {
+public class PrettyPrintTG {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(PrettyPrintTG.class);
+    
        int blankCounter = 0;
        MessageDigest m;
 
@@ -50,16 +58,33 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                final int resource;
                boolean newResource = false;
                
+               int parent;
+               
+               boolean inlined = false;
+               
                // -1 = no owner, -2 = multiple owners
-               int owner = -1;
-               int ownerPredicate = 0;
+               
+               // Set<ResourceInfo> ownedBy
+               Set<ResourceInfo> ownedBy = new HashSet<>();
+               
+               // A Map<Integer, Integer> containing information about resource that this resource owns and what are the predicates for forming this ownership
+               TIntIntHashMap ownedResourcesWithPredicates = new TIntIntHashMap();
+               
+//             int owner = -1;
+//             int ownerPredicate = 0;
                String aliasURI = null;
                TIntArrayList owned = new TIntArrayList();
                //TIntObjectHashMap<TIntHashSet> statements = new TIntObjectHashMap<TIntHashSet>();
-               public ResourceInfo(boolean hasURI, String name, int resource) {
+               public ResourceInfo(boolean hasURI, String name, int resource, int parent) {
                        this.hasURI = hasURI;
                        this.name = name;
                        this.resource = resource;
+                       this.parent = parent;
+               }
+               
+               @Override
+               public String toString() {
+                   return name + (aliasURI != null ? " = <" + aliasURI + ">" : "");
                }
        }
 
@@ -79,32 +104,32 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                else return name;
        }
 
-       ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName) {
-               String name = parentName + "." + tgNodeName(getName(parent));
-               ResourceInfo info = new ResourceInfo(true, name, parent.resource); 
+       ResourceInfo recurseURI(TransferableGraph1 graph, Identity parent, String parentName, int parentId) {
+               String name = parentName + "." + tgNodeName(TransferableGraphUtils.getName(parent));
+               ResourceInfo info = new ResourceInfo(true, name, parent.resource, parentId); 
                infos.put(parent.resource, info);
-               for(Identity child : getChildren(graph, parent)) {
-                       recurseURI(graph, child, name);
+               for(Identity child : TransferableGraphUtils.getChildren(graph, parent)) {
+                       recurseURI(graph, child, name, info.resource);
                }
                return info;
        }
 
        void discoverBlank(TransferableGraph1 graph, int resource, TIntArrayList todo) throws Exception {
-               TIntArrayList statements = getStatements(graph, resource);
+               TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource);
                for(int i=0;i<statements.size();i+=2) {
                        int object = statements.get(i+1);
-                       Identity objectId = getIdentity(graph, object);
+                       Identity objectId = TransferableGraphUtils.getIdentity(graph, object);
                        if(objectId != null) {
                                if(objectId.definition instanceof External) continue;
                        }
                        Value value = TransferableGraphUtils.findValue(graph, object);
                        if(value != null) {
-                               infos.put(object, new ResourceInfo(false, printValue(value), object));
+                               infos.put(object, new ResourceInfo(false, printValue(value), object, resource));
                                continue;
                        }
                        ResourceInfo existing = infos.get(object);
                        if(existing == null) {
-                               existing = new ResourceInfo(false, "blank" + blankCounter++, object);
+                               existing = new ResourceInfo(false, "blank" + blankCounter++, object, resource);
                                infos.put(object, existing);
                                todo.add(object);
                        }
@@ -112,52 +137,99 @@ public class PrettyPrintTG extends TransferableGraphUtils {
        }
 
        void discoverOwners(TransferableGraph1 graph, ResourceInfo info) {
+           if (LOGGER.isDebugEnabled())
+               LOGGER.debug("Discovering owners for " + info);
                int resource = info.resource;
-               TIntArrayList statements = getStatements(graph, resource);
+               TIntArrayList statements = TransferableGraphUtils.getStatements(graph, resource);
                for(int i=0;i<statements.size();i+=2) {
                        int predicate = statements.get(i);
                        int object = statements.get(i+1);
                        ResourceInfo existing = infos.get(object);
-                       if(existing == null) continue;
-                       if(existing.owner == -1) {
-                               existing.owner = resource;
-                               existing.ownerPredicate = predicate;
-                               //System.err.println("First owner " + info.name + " => " + predicateURI + " " + existing.name);
-                       } else {
-                               existing.owner = -2;
-                               //System.err.println("Multiple owners " + info.name + " => " + predicateURI + " " + existing.name);
+                       if(existing != null) {
+                // Add all owners here for now and resolve the best owner later
+                existing.ownedResourcesWithPredicates.put(resource, predicate);
+                           // Check if predicate is inverse, this just resolves all predicates to be inverse with ending "Inverse"..
+                           String predicateUri = rewritePredicateURI(graph, predicate);
+                           if (!predicateUri.endsWith("Inverse")) {
+                               existing.ownedBy.add(info);
+                            if (LOGGER.isDebugEnabled()) {
+                                   LOGGER.debug("    " + existing + " owns " + info + " with " + predicateUri);
+                            }
+                           }
                        }
                }
-               
        }
 
-       String printValue(Value value) throws Exception {
-               Variant variant = value.value;
-               Datatype dt = variant.getBinding().type();
-               if(Datatypes.STRING.equals(dt)) {
-                       String s = (String)variant.getValue(Bindings.STRING);
-                       if(s.contains("\n")) {
-                               return "\"\"\"" + s + "\"\"\"";
-                       } else {
-                               return "\"" + s + "\"";         
-                       }
-               } else if(Datatypes.BOOLEAN.equals(dt)) {
-                       Boolean i = (Boolean)variant.getValue(Bindings.BOOLEAN);
-                       return i ? "true" : "false";
-               } else if(Datatypes.INTEGER.equals(dt)) {
-                       Integer i = (Integer)variant.getValue(Bindings.INTEGER);
-                       return i.toString();
-               } else if(Datatypes.LONG.equals(dt)) {
-                       Long i = (Long)variant.getValue(Bindings.LONG);
-                       return i.toString();
-               } else {
-                       byte[] data = variant.getBinding().serializer().serialize(variant.getValue());
-                       m.reset();
-                       m.update(data, 0, data.length);
-                       return "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
-               }
-
-       }
+    DataValueRepository repo = new DataValueRepository();
+    DataValuePrinter printer = new DataValuePrinter(null, repo);
+       
+    String printValue(Value value) throws Exception {
+        StringBuilder sb = new StringBuilder();
+        printer.setFormat(PrintFormat.SINGLE_LINE);
+        printer.setOutput(sb);
+        
+        Variant variant = value.value;
+        printer.print(variant.getBinding(), variant.getValue());
+        String formattedOutput = sb.toString();
+        if (formattedOutput.length() > 100) {
+            // Ok, value too long, lets calculate a hash for it and store first 100 chars as comment
+              byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue());
+              m.reset();
+              m.update(data, 0, data.length);
+              String hash = "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
+              return hash + " // " + formattedOutput.substring(0, 100) + "..";
+        } else {
+            return formattedOutput;
+        }
+//        
+//        Variant variant = value.value;
+//        Datatype dt = variant.getBinding().type();
+//        if (Datatypes.STRING.equals(dt)) {
+//            String s = (String) variant.getValue(Bindings.STRING);
+//            if (s.contains("\n")) {
+//                return "\"\"\"" + s + "\"\"\"";
+//            } else {
+//                return "\"" + s + "\"";
+//            }
+//        } else if (Datatypes.BOOLEAN.equals(dt)) {
+//            Boolean i = (Boolean) variant.getValue(Bindings.BOOLEAN);
+//            return i ? "true" : "false";
+//        } else if (Datatypes.INTEGER.equals(dt)) {
+//            Integer i = (Integer) variant.getValue(Bindings.INTEGER);
+//            return i.toString();
+//        } else if (Datatypes.LONG.equals(dt)) {
+//            Long i = (Long) variant.getValue(Bindings.LONG);
+//            return i.toString();
+//        } else if (Datatypes.DOUBLE.equals(dt)) {
+//            Double d = (Double) variant.getValue();
+//            return d.toString();
+//        } else if (Datatypes.FLOAT.equals(dt)) {
+//            Float f = (Float) variant.getValue();
+//            return f.toString();
+//        } else if (Datatypes.STRING_ARRAY.equals(dt)) {
+//            return Arrays.toString((String []) variant.getValue());
+//        } else if (Datatypes.BOOLEAN_ARRAY.equals(dt)) {
+//            return Arrays.toString((boolean []) variant.getValue());
+//        } else if (Datatypes.INTEGER_ARRAY.equals(dt)) {
+//            return Arrays.toString((int []) variant.getValue());
+//        } else if (Datatypes.LONG_ARRAY.equals(dt)) {
+//            return Arrays.toString((long []) variant.getValue());
+//        } else if (Datatypes.DOUBLE_ARRAY.equals(dt)) {
+//            return Arrays.toString((double []) variant.getValue());
+//        } else if (Datatypes.FLOAT_ARRAY.equals(dt)) {
+//            return Arrays.toString((float []) variant.getValue());
+//        } else if (Datatypes.BYTE_ARRAY.equals(dt)) {
+//            return Arrays.toString((byte []) variant.getValue());
+////        } else if (dt instanceof ArrayType) {
+////            return Arrays.toString((Object []) variant.getValue());
+//        } else {
+//            byte[] data = Bindings.getSerializerUnchecked(variant.getBinding()).serialize(variant.getValue());
+//            m.reset();
+//            m.update(data, 0, data.length);
+//            return "\"" + new BigInteger(1, m.digest()).toString(16) + "\"";
+//        }
+
+    }
 
        //      void fixInstanceOf(TransferableGraph1 graph, ResourceInfo info) {
        //              Identity id = getIdentity(graph, info.resource);
@@ -176,7 +248,7 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                int parentId = ext.parent;
                //if(parentId == 0) return ext.name;
                //              else {
-               Identity id = getIdentity(tg, parentId);
+               Identity id = TransferableGraphUtils.getIdentity(tg, parentId);
                if(id.definition instanceof External) {
                        return getExternalURI(tg, (External)id.definition) + "/" + name;
                } else if(id.definition instanceof Root) {
@@ -189,7 +261,7 @@ public class PrettyPrintTG extends TransferableGraphUtils {
        }
 
        public static String getExternalURI(TransferableGraph1 tg, int resource) {
-               Identity id = getIdentity(tg, resource);
+               Identity id = TransferableGraphUtils.getIdentity(tg, resource);
                if(id == null) return null;
                if(id.definition instanceof External) {
                        External ext = (External)id.definition;
@@ -221,27 +293,56 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                
        }
 
-       void indent(int indent) {
-               for(int i=0;i<indent;i++) output.append("  ");
+       static void indent(StringBuilder output, int indent) {
+               for(int i=0;i<indent;i++)
+                   output.append("  ");
        }
        
-       void printBlank(TransferableGraph1 graph, String predicateURI2, ResourceInfo info, int indent) {
+       String printBlank(TransferableGraph1 graph, String predicateURI2, ResourceInfo info, int indent) {
 
-               if(info.hasURI) return;
-               indent(indent);
+               if(info.hasURI)
+                   return null;
+               
+               StringBuilder output = new StringBuilder();
+               indent(output, indent);
                output.append(predicateURI2 + " " + info.name + "\n");
 
-               if(info.owner < 0) {
-                       printURI(graph, info, false, indent);
+               if (info.ownedResourcesWithPredicates.isEmpty()) {
+                   String uri = printURI(graph, info, false, indent, false);
+                   if (uri != null)
+                       output.append(uri);
                }
-               
+//             if(info.owner < 0) {
+//                     printURI(graph, info, false, indent);
+//             }
+               return output.toString();
        }
 
-       long longStm(int predicate, int object) {
+       static long longStm(int predicate, int object) {
                return (predicate<<32) | (object & 0xffffffffL); 
        }
 
+
+    private void addInlineStatement(TransferableGraph1 graph, Map<String, Set<String>> statements, String predicate, ResourceInfo objectInfo, int indent) {
+        Set<String> objects = statements.get(predicate);
+        if(objects == null) {
+            objects = new TreeSet<>();
+            statements.put(predicate, objects);
+        }
+        String uri = printURI(graph, objectInfo, false, indent + 1, true);
+        if (uri != null) {
+            // TODO: this is not the right place to remove trailing newline
+            uri = uri.endsWith("\n") ? uri.substring(0, uri.length() - 2) : uri;
+            objects.add(uri);
+        }
+        objectInfo.inlined = true;
+    }
+
+       
        void addStatement(Map<String,Set<String>> statements, String predicate, String object) {
+           // TODO: fix this
+           if (predicate.endsWith("Inverse"))
+               return;
                Set<String> objects = statements.get(predicate);
                if(objects == null) {
                        objects = new TreeSet<>();
@@ -250,19 +351,24 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                objects.add(object);
        }
 
-       void printURI(TransferableGraph1 graph, ResourceInfo info, boolean requireURI, int indent) {
+       String printURI(TransferableGraph1 graph, ResourceInfo info, boolean requireURI, int indent, boolean inline) {
 
-               if(requireURI && !info.hasURI) return;
+               if(requireURI && !info.hasURI)
+                   return null;
+               
+               // Check if this ResourceInfo is already inlined with some other ResourceInfo 
+               if (info.inlined) 
+                   return null;
 
                Map<String,Set<String>> statements = new TreeMap<>();
-               Identity consistsOf = findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
+               Identity consistsOf = TransferableGraphUtils.findExternal(graph, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
                TLongHashSet processed = new TLongHashSet();
                for(int i=0;i<info.owned.size();i+=2) {
                        long stmId = longStm(info.owned.get(i), info.owned.get(i+1));
                        processed.add(stmId);
                }
                
-               TIntArrayList rawStatements = getStatements(graph, info.resource);
+               TIntArrayList rawStatements = TransferableGraphUtils.getStatements(graph, info.resource);
                for(int i=0;i<rawStatements.size();i+=2) {
                        long stmId = longStm(rawStatements.get(i), rawStatements.get(i+1));
                        if(!processed.add(stmId)) continue;
@@ -272,18 +378,38 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                        if(objectInfo == null) {
                                String objectURI = rewritePredicateURI(graph, rawStatements.get(i+1));
                                addStatement(statements, predicateURI, objectURI);
+                       } else if (objectInfo.ownedBy.size() == 1 && objectInfo.ownedBy.contains(info)) {
+                           // inline printing with _
+                           addInlineStatement(graph, statements, predicateURI, objectInfo, indent);
                        } else {
                                addStatement(statements, predicateURI, objectInfo.name);
                        }
                }
 
-               if(indent == 0) {
+               HashSet<ResourceInfo> debug = new HashSet<>();
+               info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() {
+            
+            @Override
+            public boolean execute(int owner, int predicate) {
+                ResourceInfo ownerInfo = infos.get(owner);
+                debug.add(ownerInfo);
+//                ResourceInfo predicateInfo = infos.get(predicate);
+//                debug.add(predicateInfo);
+                return true;
+            }
+        });
+
+               StringBuilder output = new StringBuilder();
+               
+               if(indent == 0 || inline) {
                        if("ROOT".equals(info.name)) {
                                output.append("ROOT=<http:/>");
                        } else if (info.aliasURI != null) {
                                output.append(info.name + " = <" + info.aliasURI + ">");
                        } else {
-                               output.append(info.name);
+                           if (inline)
+                               System.out.println("asdasd");
+                               output.append(inline ? "_" : info.name);
                        }
                        Set<String> instanceOfs = statements.get("L0.InstanceOf");
                        if(instanceOfs != null) {
@@ -316,14 +442,13 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                        if("L0.Inherits".equals(predicate)) continue;
                        if("L0.PartOf".equals(predicate)) continue;
                        Set<String> objects = entry.getValue();
+                       indent(output, indent+1);
                        if(objects.size() == 1) {
-                               indent(indent+1);
                                output.append(predicate + " " + objects.iterator().next() + "\n");      
                        } else{
-                               indent(indent+1);
                                output.append(predicate + "\n");        
                                for(String object : objects) {
-                                       indent(indent+1);
+                                       indent(output, indent+1);
                                        output.append("  " + object + "\n");    
                                }
                        }
@@ -332,12 +457,15 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                for(int i=0;i<info.owned.size();i+=2) {
                        String predicateURI = rewritePredicateURI(graph, info.owned.get(i));
                        ResourceInfo ownedInfo = infos.get(info.owned.get(i+1));
-                       printBlank(graph, predicateURI, ownedInfo, indent+1);
+                       String blank = printBlank(graph, predicateURI, ownedInfo, indent+1);
+                       if (blank != null)
+                           output.append(blank);
                }
                
+               return output.toString();
        }
 
-       void prettyPrint(Path input, Path output) throws Exception {
+    void prettyPrint(Path input, Path output) throws Exception {
 
                System.out.format("Converting exported shared ontology%n\t" + input.toString() + "%nto bundle-compatible ontology%n\t" + output.toString());
                try (InputStream is = new BufferedInputStream(Files.newInputStream(input), 128*1024)) {
@@ -376,54 +504,73 @@ public class PrettyPrintTG extends TransferableGraphUtils {
        
        void prettyPrint(TransferableGraph1 graph) throws Exception {
 
+           if (LOGGER.isDebugEnabled())
+               LOGGER.debug("Starting prettyPrint for TransferableGraph with " + graph.resourceCount + " resources, " + graph.identities + " identities, " + graph.statements.length + " statements and " + graph.values.length + " values");
+           
                for(Identity id : graph.identities) {
                        if(id.definition instanceof Internal) {
                                Internal internal = (Internal)id.definition;
                                Identity parent = TransferableGraphUtils.getIdentity(graph, internal.parent);
                                if(parent.definition instanceof External) {
+                       if (LOGGER.isDebugEnabled())
+                           LOGGER.debug("Resolving internal identity " + id);
                                        String name = "BASE";
-                                       ResourceInfo info = new ResourceInfo(true, name, id.resource);
+                                       ResourceInfo info = new ResourceInfo(true, name, id.resource, -1);
                                        info.aliasURI = TransferableGraphUtils.getURI(graph, id.resource);
                                        info.newResource = true;
                                        infos.put(id.resource, info);
-                                       for(Identity child : getChildren(graph, id)) {
-                                               recurseURI(graph, child, name);
+                    if (LOGGER.isDebugEnabled())
+                        LOGGER.debug("    which parent is external " + parent + " and has an aliasURI " + info.aliasURI) ;
+                                       for(Identity child : TransferableGraphUtils.getChildren(graph, id)) {
+                                               recurseURI(graph, child, name, info.resource);
                                        }
+                                       if (LOGGER.isDebugEnabled())
+                                           LOGGER.debug("    and has " + (infos.size() - 1) + " children");
                                }
                        } else if (id.definition instanceof External) {
                                External ext = (External)id.definition;
                                // Try to detect shared libraries
                                if(ext.name.contains("@")) {
-                                       
+                                   
+                                   if (LOGGER.isDebugEnabled())
+                                       LOGGER.debug("Detected an external shared library " + ext);
+                                   
                                        int index = ext.name.indexOf('@');
                                        String prefix = ext.name.substring(0, index);
                                        int index2 = ext.name.indexOf('/', index);
                                        String ontology = index2 == -1 ? ext.name : ext.name.substring(0, index2);  
                                        String uri = TransferableGraphUtils.getURI(graph, id.resource);
+                                       
+                                       if (LOGGER.isDebugEnabled())
+                                           LOGGER.debug("    which was resolved as URI=" + uri + " and prefix " + prefix);
+                                       
                                        ontologies.put(uri, prefix);
                                        
                                } else if (ext.name.contains("-")) {
-
+                                   if (LOGGER.isDebugEnabled())
+                                       LOGGER.debug("Resolving possible ontology " + ext);
                                        String uri = TransferableGraphUtils.getURI(graph, id.resource);
                                Matcher m = versionExtractPattern.matcher(uri);
                                if (m.matches()) {
                                        if(!ontologies.containsKey(uri)) {
                                                        int index = ext.name.indexOf('-');
-                                                       String prefix = ext.name.substring(0, index);
-                                                       ontologies.put(uri, prefix);
+                            String prefix = ext.name.substring(0, index);
+                            if (LOGGER.isDebugEnabled())
+                                LOGGER.debug("    and it was resolved as URI=" + uri + " and prefix " + prefix);
+                            ontologies.put(uri, prefix);
                                        }
                                }
-
                                }
-                               
-
-                               
                        }
                }
                // Discover other resources
+               if (LOGGER.isDebugEnabled())
+                   LOGGER.debug("Discovering other resources..");
+               
                TIntArrayList todo = new TIntArrayList();
                for(ResourceInfo info : infos.valueCollection())
                        todo.add(info.resource);
+               
                while(!todo.isEmpty()) {
                        int resource = todo.removeAt(todo.size()-1);
                        discoverBlank(graph, resource, todo);
@@ -432,34 +579,74 @@ public class PrettyPrintTG extends TransferableGraphUtils {
                        discoverOwners(graph, info);
                //                      for(ResourceInfo info : infos.valueCollection())
                //                              fixInstanceOf(graph, info);
-               for(ResourceInfo info : infos.valueCollection())
-                       if(info.owner >= 0) {
-                               ResourceInfo ownerInfo = infos.get(info.owner);
-                               ownerInfo.owned.add(info.ownerPredicate);
-                               ownerInfo.owned.add(info.resource);
-                       }
-
+               
+        for (ResourceInfo info : infos.valueCollection()) {
+//          Old implementation
+//            if (info.owner >= 0) {
+//                ResourceInfo ownerInfo = infos.get(info.owner);
+//                System.out.println("originalOwner : " + info.owner + " originalPredicate: " + info.ownerPredicate);
+//                ownerInfo.owned.add(info.ownerPredicate);
+//                ownerInfo.owned.add(info.resource);
+//            }
+            
+            if (!info.ownedResourcesWithPredicates.isEmpty() && info.ownedResourcesWithPredicates.size() == 1) {
+                info.ownedResourcesWithPredicates.forEachEntry(new TIntIntProcedure() {
+                    
+                    @Override
+                    public boolean execute(int owner, int predicate) {
+                        ResourceInfo ownerInfo = infos.get(owner);
+                        ownerInfo.owned.add(predicate);
+                        ownerInfo.owned.add(info.resource);
+                        return false;
+                    }
+                });
+            }
+        }
+
+        // Resolve inverses from ownedBy list
+        for (ResourceInfo info : infos.valueCollection()) {
+            for (int i = 0; i < info.owned.size(); i+=2) {
+                int object = info.owned.get(i+1);
+                ResourceInfo inf = infos.get(object);
+                if (inf != null) {
+                    info.ownedBy.remove(inf);
+                }
+            }
+        }
+        
                TreeMap<String,ResourceInfo> order = new TreeMap<>();
                for(ResourceInfo info : infos.valueCollection())
                        order.put(info.name, info);
 
-               for(ResourceInfo info : order.values())
-                       printURI(graph, info, true, 0);
+               for(ResourceInfo info : order.values()) {
+                       String uri = printURI(graph, info, true, 0, false);
+                       if (uri != null)
+                           output.append(uri);
+               }
 
-               for(ResourceInfo info : order.values())
-                       if(!info.hasURI && info.owner < 0)
-                               printURI(graph, info, false, 0);
+               for (ResourceInfo info : order.values()) {
+                   if (!info.hasURI && info.ownedResourcesWithPredicates.size() != 1) {
+                       String uri = printURI(graph, info, false, 0, false);
+                       if (uri != null)
+                           output.append(uri);
+                   }
+               }
+//             for(ResourceInfo info : order.values())
+//                     if(!info.hasURI && info.owner < 0)
+//                             printURI(graph, info, false, 0);
 
                StringBuilder refs = new StringBuilder();
                for(String ontology : referencedOntologies) {
                        String key = ontologies.get(ontology);
                        refs.append(key + " = <" + ontology + ">\n");   
                }
+               if (!referencedOntologies.isEmpty())
+                   refs.append("\n");
                output.insert(0, refs.toString());
                
        }
 
-       public static String print(TransferableGraph1 tg) throws Exception {
+    public static String print(TransferableGraph1 tg) throws Exception {
                StringBuilder b = new StringBuilder();
                new PrettyPrintTG(b).prettyPrint(tg);
                return b.toString();
index 4b113fa499b6bc1208d64b62e2be5be66713cc10..a7b92c8d015727880d256a9c17494bed54b70ce9 100644 (file)
@@ -71,6 +71,9 @@ public class TransferableGraphUtils {
                String[] tokens = uri.substring("http://".length()).split("/");
                for(String token : tokens) {
                        identity = findExternalWithNameAndParent(tg, identity.resource, token);
+                       if (identity == null) {
+                           return null;
+                       }
                }
                return identity;
                
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..fccf2681507466ef7f4c9b6f44dc6aab04f76b04 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];
     
@@ -361,7 +376,7 @@ public class Elaboration {
             dataTypes.add(dataType);
             for(int j=0;j<constructors.length;++j) {
                 ConstructorAst constructor = dataTypeAst.constructors[j];
-                String name = constructor.name;
+                String name = constructor.name.text;
                 Type[] parameterTypes = new Type[constructor.parameters.length];
                 for(int i=constructor.parameters.length-1;i>=0;--i)
                     parameterTypes[i] = context.toType(constructor.parameters[i]);
@@ -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 b34328a53ebb494d0586d331b712b9c361bcb6ab..7b4a5bc26b1c7afb59addb97fa91d93985d7cc39 100644 (file)
@@ -7,11 +7,14 @@ import org.simantics.scl.compiler.elaboration.chr.relations.SpecialCHRRelation;
 import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelation;
 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext.ExistentialFrame;
 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.ERecord;
 import org.simantics.scl.compiler.elaboration.expressions.Expression;
 import org.simantics.scl.compiler.elaboration.expressions.Variable;
 import org.simantics.scl.compiler.elaboration.expressions.VariableProcedure;
 import org.simantics.scl.compiler.elaboration.expressions.printing.ExpressionToStringVisitor;
+import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.parsing.Symbol;
@@ -29,6 +32,7 @@ public class CHRLiteral extends Symbol {
     public CHRRelation relation;
     public Type[] typeParameters;
     public Expression[] parameters;
+    public FieldAssignment[] fields; // optional
     public Expression[] typeConstraintEvidenceParameters;
     public boolean killAfterMatch;
     public boolean negated;
@@ -55,6 +59,10 @@ public class CHRLiteral extends Symbol {
                 if(sclRelation != null)
                     relation = new ExternalCHRRelation(sclRelation);
                 else {
+                    if(parameters == null) {
+                        context.getErrorLog().log(location, "Relation must be declared if record syntax is used.");
+                        return;
+                    }
                     Type[] parameterTypes = new Type[parameters.length];
                     for(int i=0;i<parameterTypes.length;++i)
                         parameterTypes[i] = Types.metaVar(Kinds.STAR);
@@ -67,8 +75,33 @@ public class CHRLiteral extends Symbol {
                 }
             }
         }
-        for(int i=0;i<parameters.length;++i)
-            parameters[i] = parameters[i].resolve(context);
+        if(parameters == null && fields != null) {
+            String[] fieldNames = relation.getFieldNames();
+            if(fieldNames == null) {
+                context.getErrorLog().log(location, "Relation " + relation + " does not define field names.");
+                return;
+            }
+            parameters = ERecord.translateFieldsToFunctionParameters(context, fields, fieldNames);
+            if(parameters == null)
+                return;
+            for(int i=0;i<parameters.length;++i) {
+                Expression parameter = parameters[i];
+                if(parameter == null) {
+                    ExistentialFrame frame = context.getCurrentExistentialFrame();
+                    if(frame == null || frame.disallowNewExistentials)
+                        context.getErrorLog().log(location, "Field " + fieldNames[i] + " not defined.");
+                    else
+                        parameters[i] = frame.createBlank(location);
+                }
+                else
+                    parameters[i] = parameters[i].resolve(context);
+            }
+            fields = null;
+        }
+        else {
+            for(int i=0;i<parameters.length;++i)
+                parameters[i] = parameters[i].resolve(context);
+        }
     }
 
     public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
index 7369d496c95530b0726f2a3333a17bafb9c8ba54..3daae67a94a348681d489f19915bf7ba36020e23 100644 (file)
@@ -12,4 +12,7 @@ public interface CHRRelation {
     TVar[] getTypeVariables();
     Type[] getParameterTypes();
     TPred[] getTypeConstraints();
+    default String[] getFieldNames() {
+        return null;
+    }
 }
index 48aefbdac541459f783c7becb5d013bd488d6a9b..0c81daafd8d3ddfa3b36b5ec327b5ca73f0c8a43 100644 (file)
@@ -1,8 +1,9 @@
 package org.simantics.scl.compiler.elaboration.chr;
 
+import java.util.ArrayList;
+
 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;
@@ -22,15 +23,22 @@ import gnu.trove.set.hash.THashSet;
 import gnu.trove.set.hash.TIntHashSet;
 
 public class CHRRule extends Symbol {
+    public CHRRuleset parentRuleset;
     public int priority;
     public CHRQuery head;
     public CHRQuery body;
     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;
@@ -41,6 +49,7 @@ public class CHRRule extends Symbol {
     public void resolve(TranslationContext context) {
         context.pushExistentialFrame();
         head.resolve(context);
+        context.disallowNewExistentials();
         body.resolve(context);
         existentialVariables = context.popExistentialFrame();
     }
@@ -86,7 +95,7 @@ public class CHRRule extends Symbol {
     }
 
     public void compile(CompilationContext compilationContext, CHRConstraint initConstraint) {
-        boolean hasActiveLiteral = false;
+        boolean hasLocalActiveLiteral = false;
         for(int i=0;i<head.literals.length;++i) {
             CHRLiteral literal = head.literals[i];
             if(literal.passive)
@@ -98,11 +107,12 @@ 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;
+            if(constraint.parentRuleset == parentRuleset)
+                hasLocalActiveLiteral = true;
         }
-        if(!hasActiveLiteral) {
+        if(!hasLocalActiveLiteral) {
             Variable activeFact = new Variable("activeFact", initConstraint.factType);
             QueryPlanningContext context = new QueryPlanningContext(compilationContext, existentialVariables);
             if(!head.createQueryPlan(context, null, -1))
@@ -111,10 +121,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..13eb8491b529bdeb2943d6b15eb996195d4014ff 100644 (file)
@@ -7,24 +7,33 @@ 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.ObjectMethodRef;
 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.utils.Constants;
 import org.simantics.scl.compiler.internal.codegen.writer.CodeWriter;
 import org.simantics.scl.compiler.internal.parsing.Symbol;
 import org.simantics.scl.compiler.types.TCon;
@@ -32,6 +41,7 @@ import org.simantics.scl.compiler.types.TVar;
 import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.compiler.types.Types;
 
+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,25 +52,37 @@ 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 Constant readCurrentId;
-    public Constant writeCurrentId;
+    public int initialPriorityNumber = 0;
+    
+    public String runtimeRulesetClassName;
+    public TCon runtimeRulesetType;
+    public BoundVar runtimeRulesetVariable;
+    public TypeDesc runtimeRulesetTypeDesc;
+    
+    public static final Constant READ_CURRENT_ID = 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);
+    public static final Constant WRITE_CURRENT_ID = 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);
+    public static final Constant GENERATE_ID = new CallJava(TVar.EMPTY_ARRAY, Types.PROC, Types.INTEGER, new Type[] {Types.CHRContext},
+            null, new ObjectMethodRef(false, CHRCodeGenerationConstants.CHRContext_name, "generateId", CHRRuntimeRulesetCodeGenerator.FACT_ID_TYPE, Constants.EMPTY_TYPEDESC_ARRAY), null);
     
     // FIXME remove and change the parameter of Expression.toVal
     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 +90,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 +124,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 +165,163 @@ 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));
+        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 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));
+            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, w.apply(location, GENERATE_ID, chrContext));
+            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) {
@@ -193,4 +332,9 @@ public class CHRRuleset extends Symbol {
                 literal.collectEnforceEffects(effects);
         }
     }
+
+    public void addRule(CHRRule rule) {
+        rules.add(rule);
+        rule.parentRuleset = this;
+    }
 }
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..2a03c89435e7de85ab9a8ac75a7346b60ca0a45c 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, CHRRuleset.READ_CURRENT_ID, 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..a43e97d4cfcc1094933e56f93511c1016552c299 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, CHRRuleset.WRITE_CURRENT_ID, 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..ee73477912e3d8ff385f83a29e33562eae8ce0a2 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;
@@ -35,13 +34,14 @@ import gnu.trove.map.hash.TIntObjectHashMap;
 public class CHRConstraint extends Symbol implements CHRRelation {
     public final String name;
     public final Type[] parameterTypes;
+    public String[] fieldNames;
     
     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 +56,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 +85,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 +107,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 +157,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 +180,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 +199,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 +212,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;
     }
@@ -232,4 +230,9 @@ public class CHRConstraint extends Symbol implements CHRRelation {
         else
             return w.apply(location, accessor, fact);
     }
+    
+    @Override
+    public String[] getFieldNames() {
+        return fieldNames;
+    }
 }
index 5e4f5868c15bccec310e3dca43295a02a6299abb..6f44bc2ab6852bd0211f6f508f5b629ff8fda4a2 100644 (file)
@@ -32,4 +32,9 @@ public class ExternalCHRRelation implements CHRRelation {
     public String toString() {
         return relation.toString();
     }
+    
+    @Override
+    public String[] getFieldNames() {
+        return relation.getFieldNames();
+    }
 }
index 6972eb8647a1e6646fd88956d6ddee9c9dc52121..367960dfafc0a35f5f2ddb0d9870bd9152c6924c 100644 (file)
@@ -3,6 +3,7 @@ package org.simantics.scl.compiler.elaboration.chr.translation;
 import java.util.ArrayList;
 import java.util.Arrays;
 
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
 import org.simantics.scl.compiler.elaboration.chr.CHRLiteral;
 import org.simantics.scl.compiler.elaboration.chr.CHRQuery;
 import org.simantics.scl.compiler.elaboration.chr.CHRRule;
@@ -12,6 +13,7 @@ import org.simantics.scl.compiler.elaboration.chr.relations.UnresolvedCHRRelatio
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.expressions.EApply;
 import org.simantics.scl.compiler.elaboration.expressions.EBinary;
+import org.simantics.scl.compiler.elaboration.expressions.ERecord;
 import org.simantics.scl.compiler.elaboration.expressions.EVar;
 import org.simantics.scl.compiler.elaboration.expressions.Expression;
 import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
@@ -20,9 +22,11 @@ import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;
+import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
 import org.simantics.scl.compiler.environment.AmbiguousNameException;
 import org.simantics.scl.compiler.environment.Environments;
 import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
 
 public class CHRTranslation {
@@ -35,18 +39,27 @@ public class CHRTranslation {
     }
 
     private static CHRLiteral convertConstraint(boolean remove, boolean negated, Expression expression) {
-        ArrayList<Expression> parameters = new ArrayList<Expression>(4);
-        while(expression instanceof EApply) {
+        long location = expression.location;
+        Expression[] parameters;
+        FieldAssignment[] fields = null;
+        if(expression instanceof EApply) {
             EApply apply = (EApply)expression;
-            for(int i=apply.parameters.length-1;i>=0;--i)
-                parameters.add(apply.parameters[i]);
+            parameters = apply.parameters;
             expression = apply.function;
         }
-        EVar var = (EVar)expression;
-        Expression[] parametersArray = new Expression[parameters.size()];
-        for(int i=0,j=parametersArray.length-1;i<parametersArray.length;++i,--j)
-            parametersArray[i] = parameters.get(j);
-        return new CHRLiteral(expression.location, new UnresolvedCHRRelation(var.location, var.name), parametersArray, remove, negated);
+        else if(expression instanceof ERecord) {
+            ERecord record = (ERecord)expression;
+            parameters = null;
+            fields = record.fields;
+            expression = record.constructor;
+        }
+        else // if(expression instanceof EVar)
+            parameters = Expression.EMPTY_ARRAY;
+        EVar var = (EVar)expression; // this should succeed because of isConstraint test
+        CHRLiteral literal = new CHRLiteral(location, new UnresolvedCHRRelation(var.location, var.name),
+                parameters, remove, negated);
+        literal.fields = fields;
+        return literal;
     }
     
     private static CHRLiteral convertListQualifier(TranslationContext context, boolean isHead, ListQualifier qualifier) {
@@ -102,8 +115,10 @@ public class CHRTranslation {
     }
     
     private static boolean isConstraint(TranslationContext context, Expression expression) {
-        while(expression instanceof EApply)
+        if(expression instanceof EApply)
             expression = ((EApply)expression).function;
+        else if(expression instanceof ERecord)
+            expression = ((ERecord)expression).constructor;
         if(!(expression instanceof EVar))
             return false;
         String name = ((EVar)expression).name;
@@ -136,7 +151,15 @@ public class CHRTranslation {
     }
 
     public static CHRConstraint convertConstraintStatement(TranslationContext context, ConstraintStatement statement) {
-        return new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));
+        CHRConstraint constraint = new CHRConstraint(statement.location, statement.name.text, TypeAst.toTypes(context, statement.parameterTypes));
+        for(DAnnotationAst annotation : statement.annotations)
+            applyConstraintAnnotation(context, constraint, annotation);
+        constraint.fieldNames = statement.fieldNames;
+        return constraint;
+    }
+
+    private static void applyConstraintAnnotation(TranslationContext context, CHRConstraint constraint, DAnnotationAst annotation) {
+        context.getErrorLog().log(annotation.location, "Invalid constraint annotation");
     }
     
 }
index 203bd81d2d2bd925b9fd9ee969aa475db7b31331..0331f9a50b86a7715405afc9bb37da2441d8b5b2 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;
@@ -42,13 +43,26 @@ import gnu.trove.set.hash.THashSet;
 
 public class TranslationContext extends TypeTranslationContext implements EnvironmentalContext {
 
+    public static class ExistentialFrame {
+        THashSet<String> variables = new THashSet<String>(4);
+        ArrayList<Variable> blanks = new ArrayList<Variable>(2); 
+        public boolean disallowNewExistentials;
+        
+        public EVariable createBlank(long location) {
+            Variable variable = new Variable("_");
+            blanks.add(variable);
+            EVariable result = new EVariable(variable);
+            result.location = location;
+            return result;
+        }
+    }
+    
     THashMap<String, Variable> variables = new THashMap<String, Variable>();
     ArrayList<Entry> variableEntries = new ArrayList<Entry>();
     LocalEnvironment localEnvironment;
     TIntArrayList frames = new TIntArrayList();
     ArrayList<THashSet<String>> frameNameSets = new ArrayList<THashSet<String>>(); 
-    ArrayList<THashSet<String>> existentialFrames = new ArrayList<THashSet<String>>();
-    ArrayList<ArrayList<Variable>> blanksInExistentialFrame = new ArrayList<ArrayList<Variable>>();
+    ArrayList<ExistentialFrame> existentialFrames = new ArrayList<ExistentialFrame>(2);
     SCLValue bindFunction;
     
     public PreQuery currentPreQuery;
@@ -109,30 +123,40 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
         
         char c = name.charAt(0);
         switch(c) {
-        case '?':
-            if(existentialFrames.isEmpty()) {
-                errorLog.log(location, "Existential variables can be used only in queries.");
+        case '?': {
+            ExistentialFrame existentialFrame = getCurrentExistentialFrame();
+            if(existentialFrame == null || existentialFrame.disallowNewExistentials) {
+                errorLog.log(location, "New existential variables can be defined only in queries.");
                 return new EError(location);
             }
             variable = new Variable(name);
             variables.put(name, variable);
-            existentialFrames.get(existentialFrames.size()-1).add(name);
+            existentialFrame.variables.add(name);
             return new EVariable(variable);
-        case '_':
+        }
+        case '_': {
             if(name.length()==1) {
-                variable = new Variable("_");
-                if(blanksInExistentialFrame.isEmpty()) {
-                    errorLog.log(location, "Cannot use blank variables in this context.");
+                ExistentialFrame existentialFrame = getCurrentExistentialFrame();
+                if(existentialFrame == null || existentialFrame.disallowNewExistentials) {
+                    errorLog.log(location, "Blank variables can be used only in queries.");
                     return new EError(location);
                 }
-                blanksInExistentialFrame.get(blanksInExistentialFrame.size()-1).add(variable);
-                return new EVariable(variable);
+                return existentialFrame.createBlank(location);
             }
             break;
         }
+        }
         return null;
     }
     
+    public ExistentialFrame getCurrentExistentialFrame() {
+        int size = existentialFrames.size(); 
+        if(size == 0)
+            return null;
+        else
+            return existentialFrames.get(size-1);
+    }
+    
     private Expression resolveFieldAccess(Expression base, int pos, String name) {
         while(pos != -1) {
             int p = findSeparator(name, pos+1);
@@ -379,19 +403,17 @@ public class TranslationContext extends TypeTranslationContext implements Enviro
     
     public void pushExistentialFrame() {
         pushFrame();
-        existentialFrames.add(new THashSet<String>());
-        blanksInExistentialFrame.add(new ArrayList<Variable>(2));
+        existentialFrames.add(new ExistentialFrame());
     }
     
     public Variable[] popExistentialFrame() {
         popFrame();
-        THashSet<String> set = existentialFrames.remove(existentialFrames.size()-1);
-        ArrayList<Variable> blanks = blanksInExistentialFrame.remove(blanksInExistentialFrame.size()-1);
-        Variable[] result = new Variable[set.size() + blanks.size()];
+        ExistentialFrame frame = existentialFrames.remove(existentialFrames.size()-1);
+        Variable[] result = new Variable[frame.variables.size() + frame.blanks.size()];
         int i=0;
-        for(String name : set)
+        for(String name : frame.variables)
             result[i++] = variables.remove(name);
-        for(Variable blank : blanks)
+        for(Variable blank : frame.blanks)
             result[i++] = blank;
         return result;
     }
@@ -521,4 +543,12 @@ 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);
+    }
+
+    public void disallowNewExistentials() {
+        getCurrentExistentialFrame().disallowNewExistentials = true;
+    }
 }
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..a509616bbb4bf669e08e1ece55584d58355309a3 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,21 +86,27 @@ 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) {
             Statement statement = statements.get(i);
             if(statement instanceof CHRStatement)
-                ruleset.rules.add(CHRTranslation.convertCHRStatement(context, (CHRStatement)statement));
+                ruleset.addRule(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 a41c0f042d46034e782ec06b78888bfe146cf7c9..e1f444d8220a12801d3ad430c55c11065a4edef8 100644 (file)
@@ -2,20 +2,20 @@ package org.simantics.scl.compiler.elaboration.expressions;
 
 import org.simantics.scl.compiler.constants.SCLConstructor;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
+import org.simantics.scl.compiler.elaboration.contexts.TranslationContext.ExistentialFrame;
 import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
 import org.simantics.scl.compiler.environment.AmbiguousNameException;
 import org.simantics.scl.compiler.errors.Locations;
-import org.simantics.scl.compiler.internal.parsing.Token;
 
 import gnu.trove.map.hash.THashMap;
 
 public class ERecord extends ASTExpression {
 
-    Token constructor;
-    FieldAssignment[] fields;
+    public final EVar constructor;
+    public final FieldAssignment[] fields;
     
-    public ERecord(Token constructor, FieldAssignment[] fields) {
+    public ERecord(EVar constructor, FieldAssignment[] fields) {
         this.constructor = constructor;
         this.fields = fields;
     }
@@ -33,30 +33,67 @@ public class ERecord extends ASTExpression {
     public Expression resolve(TranslationContext context, boolean asPattern) {
         SCLValue constructorValue; 
         try {
-            constructorValue = context.getEnvironment().getLocalNamespace().getValue(constructor.text);
+            constructorValue = context.getEnvironment().getLocalNamespace().getValue(constructor.name);
         } catch (AmbiguousNameException e) {
             context.getErrorLog().log(constructor.location, e.getMessage());
             return new EError(constructor.location);
         }
         if(constructorValue == null) {
-            context.getErrorLog().log(constructor.location, "Couldn't resolve the record constructor " + constructor.text + ".");
+            context.getErrorLog().log(constructor.location, "Couldn't resolve the record constructor " + constructor.name + ".");
             return new EError(constructor.location);
         }
         if(!(constructorValue.getValue() instanceof SCLConstructor)) {
-            context.getErrorLog().log(constructor.location, "Value " + constructor.text + " is not a record constructor.");
+            context.getErrorLog().log(constructor.location, "Value " + constructor.name + " is not a record constructor.");
             return new EError(constructor.location);
         }
         String[] fieldNames = ((SCLConstructor)constructorValue.getValue()).recordFieldNames;
         if(fieldNames == null) {
-            context.getErrorLog().log(constructor.location, "Value " + constructor.text + " is not a record constructor.");
+            context.getErrorLog().log(constructor.location, "Value " + constructor.name + " is not a record constructor.");
             return new EError(constructor.location);
         }
+        Expression[] parameters = translateFieldsToFunctionParameters(context, fields, fieldNames);
+        if(parameters == null)
+            return new EError(location);
+        if(asPattern)
+            for(int i=0;i<parameters.length;++i) {
+                Expression parameter = parameters[i];
+                if(parameter == null)
+                    parameters[i] = Expressions.blank(null);
+                else
+                    parameters[i] = parameter.resolveAsPattern(context);
+            }
+        else {
+            boolean error = false;
+            for(int i=0;i<parameters.length;++i) {
+                Expression parameter = parameters[i];
+                if(parameter == null) {
+                    ExistentialFrame frame = context.getCurrentExistentialFrame();
+                    if(frame == null || frame.disallowNewExistentials) {
+                        context.getErrorLog().log(location, "Field " + fieldNames[i] + " not defined.");
+                        error = true;
+                    }
+                    else
+                        parameters[i] = frame.createBlank(location); 
+                }
+                else
+                    parameters[i] = parameter.resolve(context);
+            }
+            if(error)
+                return new EError(location);
+        }
+        EApply result = new EApply(new EConstant(constructorValue), parameters);
+        result.setLocationDeep(location);
+        return result;
+    }
+    
+    public static Expression[] translateFieldsToFunctionParameters(TranslationContext context, FieldAssignment[] fields, String[] fieldNames) {
         THashMap<String,FieldAssignment> recordMap = new THashMap<String,FieldAssignment>(fields.length);
+        boolean error = false;
         for(FieldAssignment field : fields) {
             if(field.value == null) {
-               String actualName = field.name;
-               if(actualName.charAt(0) == '?')
-                       actualName = actualName.substring(1);
+                String actualName = field.name;
+                if(actualName.charAt(0) == '?')
+                    actualName = actualName.substring(1);
                 String bestMatch = null;
                 int bestMatchLength = 0;
                 for(int i=0;i<fieldNames.length;++i) {
@@ -68,46 +105,30 @@ public class ERecord extends ASTExpression {
                 }
                 if(bestMatch == null) {
                     context.getErrorLog().log(field.location, "Invalid shorthand field " + field.name + " is defined twice.");
-                    return new EError(location);
+                    error = true;
                 }
                 field.value = new EVar(field.location, field.name);
                 field.name = bestMatch;
             }
             if(recordMap.put(field.name, field) != null) {
                 context.getErrorLog().log(field.location, "Field " + field.name + " is defined more than once.");
-                return new EError(location);
+                error = true;
             }
         }
+        if(error)
+            return null;
         Expression[] parameters = new Expression[fieldNames.length];
-        boolean error = false;
         for(int i=0;i<fieldNames.length;++i) {
             FieldAssignment assignment = recordMap.remove(fieldNames[i]);
-            if(assignment == null) {
-                if(asPattern) {
-                    parameters[i] = Expressions.blank(null);
-                }
-                else {
-                    context.getErrorLog().log(location, "Field " + fieldNames[i] + " not defined.");
-                    error = true;
-                }
-            }
-            else
-                parameters[i] = asPattern
-                        ? assignment.value.resolveAsPattern(context) 
-                        : assignment.value.resolve(context);
+            if(assignment != null)
+                parameters[i] = assignment.value;
         }
         if(!recordMap.isEmpty()) {
             for(FieldAssignment field : recordMap.values())
                 context.getErrorLog().log(field.location, "Field " + field.name + " is not defined in the constructor.");
-            error = true;
-        }
-        if(error)
-            return new EError(location);
-        else {
-            EApply result = new EApply(new EConstant(constructorValue), parameters);
-            result.setLocationDeep(location);
-            return result;
+            return null;
         }
+        return parameters;
     }
 
     @Override
index fda9d37ace3971278859e75ab390de257dccee14..d78fa8565abf2fa3c8147baf797bd0a10f7920b1 100644 (file)
@@ -2,17 +2,22 @@ package org.simantics.scl.compiler.elaboration.expressions;
 
 import java.util.ArrayList;
 
-import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
 import org.simantics.scl.compiler.elaboration.expressions.lhstype.FunctionDefinitionLhs;
 import org.simantics.scl.compiler.elaboration.expressions.lhstype.LhsType;
 import org.simantics.scl.compiler.elaboration.expressions.lhstype.PatternMatchingLhs;
 import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.compiler.internal.parsing.Token;
 
 public class EVar extends ASTExpression {
     public final String name;
 
+    public EVar(Token token) {
+        this.location = token.location;
+        this.name = token.text;
+    }
+    
     public EVar(long location, String name) {
         this.location = location;
         this.name = name;
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);
+    }
 }
index fc92190a9c5657034cb7e7e9bae0cc203a5cb27e..4cccf2f46e591df3091a421b424563c3bd6fa17d 100644 (file)
@@ -5,16 +5,21 @@ 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.parsing.Token;
+import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
 
 public class ConstraintStatement extends Statement {
 
     public Token name;
     public TypeAst[] parameterTypes;
+    public String[] fieldNames;
+    public DAnnotationAst[] annotations;
     
-    public ConstraintStatement(Token name, TypeAst[] parameterTypes) {
+    public ConstraintStatement(Token name, TypeAst[] parameterTypes, String[] fieldNames, DAnnotationAst[] annotations) {
         this.name = name;
         this.parameterTypes = parameterTypes;
+        this.fieldNames = fieldNames;
+        this.annotations = annotations;
     }
     
     @Override
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 4ac37bbc1f733b4084f22a17d6bde77c141bf50d..e93ff6e8fe16a7b5eb1aeb5a45164a86302c0be2 100644 (file)
@@ -35,7 +35,7 @@ public interface SCLRelation {
         return TPred.EMPTY_ARRAY;
     }
     int getPhase();
-    
+
     double getSelectivity(int boundVariables);
     int getRequiredVariablesMask();
     void generate(long location,
@@ -45,7 +45,10 @@ public interface SCLRelation {
     Expression generateEnforce(long location, EnforcingContext context,
             Type[] typeParameters,
             Variable[] parameters);
-
+    default String[] getFieldNames() {
+        return null;
+    }
+    
     void generateIterate(
             PlanContext context,
             CodeWriter w,
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;
     }
 }
index 3edb9ce816dc83abcb988cd48d8251adf924853f..bbb669506f7c3d6b3511354c48e178eb28686cf8 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.scl.compiler.internal.parsing.declarations;
 
 import org.simantics.scl.compiler.internal.parsing.Symbol;
+import org.simantics.scl.compiler.internal.parsing.Token;
 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
 
 
@@ -8,11 +9,11 @@ public class ConstructorAst extends Symbol {
     public static final ConstructorAst[] EMPTY_ARRAY = new ConstructorAst[0];
     
     public final DAnnotationAst[] annotations;
-    public final String name;
+    public final Token name;
     public final TypeAst[] parameters;
     public final String[] fieldNames; // null, if no field names
     
-    public ConstructorAst(DAnnotationAst[] annotations, String name,
+    public ConstructorAst(DAnnotationAst[] annotations, Token name,
             TypeAst[] parameters, String[] fieldNames) {
         this.annotations = annotations;
         this.name = name;
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..f7ea1b263617cee6eae8dbc4e5dda34139e10e45 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
@@ -199,7 +200,8 @@ statement
     | exp FOLLOWS queryBlock                                 # RuleStatement
     | chrQuery IMPLIES chrQuery                              # CHRStatement
     | WHEN verboseChrQuery THEN_AFTER_WHEN verboseChrQuery   # VerboseCHRStatement
-    | CONSTRAINT ID atype*                                   # ConstraintStatement
+    | CONSTRAINT constructor                                 # 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..378013be5fbabbeb1085e6d43b3854b269873bf0 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..fc2242dce632d482d95170a31f9bafe86d8a1eb3 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 NONTERMINAL_COUNT = 51;
-    private static final int PRODUCT_COUNT = 132;
+    private static final int STATE_COUNT = 358;
+    private static final int TERMINAL_COUNT = 84;
+    private static final int NONTERMINAL_COUNT = 52;
+    private static final int PRODUCT_COUNT = 135;
     
     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[6944];
+    private static final int[] ERROR_TABLE = new int[940];
     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[1708];
     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",
@@ -160,6 +161,7 @@ public abstract class SCLParser {
         "listQualifier",
         "chrQuery",
         "verboseChrQuery",
+        "constraintSpec",
         "caseRhs",
         "guardedExpArrow",
         "equation",
@@ -393,19 +395,19 @@ public abstract class SCLParser {
         return parse(0);
     }
     public Object parseCommands() {
-        return parse(330);
+        return parse(342);
     }
     public Object parseImport() {
-        return parse(337);
+        return parse(350);
     }
     public Object parseType() {
-        return parse(339);
+        return parse(352);
     }
     public Object parseExp() {
-        return parse(341);
+        return parse(354);
     }
     public Object parseEquationBlock() {
-        return parse(343);
+        return parse(356);
     }
 
 
@@ -461,208 +463,214 @@ 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 reduceConstraintSpec();
         case 119:
-            return reduceGuardEquation();
+            return reduceSimpleCaseRhs();
         case 120:
-            return reduceBasicEquation();
+            return reduceGuardedCaseRhs();
         case 121:
-            return reduceEffect();
+            return reduceGuardedExpArrow();
         case 122:
-            return reduceJustEtype();
+            return reduceGuardEquation();
         case 123:
-            return reduceForAll();
+            return reduceBasicEquation();
         case 124:
-            return reduceApplyType();
+            return reduceEffect();
         case 125:
+            return reduceJustEtype();
+        case 126:
+            return reduceForAll();
+        case 127:
+            return reduceApplyType();
+        case 128:
             return reduceDummy();
 
         default:
@@ -779,6 +787,10 @@ public abstract class SCLParser {
      * declaration ::= bexp FOLLOWS ruleDeclarations
      */
     protected abstract Object reduceRelationDefinition();
+    /**
+     * declaration ::= RULESET ID WHERE statements
+     */
+    protected abstract Object reduceRulesetDefinition();
     /**
      * command ::= statement
      */
@@ -812,9 +824,13 @@ public abstract class SCLParser {
      */
     protected abstract Object reduceVerboseCHRStatement();
     /**
-     * statement ::= CONSTRAINT ID atype&#42;
+     * statement ::= CONSTRAINT constructor (WHERE constraintSpec)?
      */
     protected abstract Object reduceConstraintStatement();
+    /**
+     * statement ::= INCLUDE ID aexp
+     */
+    protected abstract Object reduceLocalInclude();
     /**
      * declarations ::= LBRACE (declaration (SEMICOLON (declaration SEMICOLON)&#42; declaration)?)? RBRACE
      */
@@ -995,6 +1011,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 +1031,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
      */
@@ -1123,6 +1139,10 @@ public abstract class SCLParser {
      * verboseChrQuery ::= LBRACE listQualifier (SEMICOLON listQualifier)&#42; RBRACE
      */
     protected abstract Object reduceVerboseCHRQuery();
+    /**
+     * constraintSpec ::= LBRACE exp (SEMICOLON exp)&#42; RBRACE
+     */
+    protected abstract Object reduceConstraintSpec();
     /**
      * caseRhs ::= ARROW exp (WHERE statements)?
      */
index 799e59099b924a005ff59d8a3bf048dfd3e6b3ee..34f8d6a9f0da95e4e6a01a95021d82f893176ca8 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
@@ -298,7 +308,7 @@ public class SCLParserImpl extends SCLParser {
         else
             context = (ArrayList<TypeAst>)get(i++);
         Token nameToken = (Token)get(i++);
-        EVar name = new EVar(nameToken.location, nameToken.text);
+        EVar name = new EVar(nameToken);
         ArrayList<TypeAst> parameters = new ArrayList<TypeAst>();
         while(i < length()) {
             Object symbol = get(i++);
@@ -324,7 +334,7 @@ public class SCLParserImpl extends SCLParser {
         else
             context = (ArrayList<TypeAst>)get(i++);
         Token nameToken = (Token)get(i++);
-        EVar name = new EVar(nameToken.location, nameToken.text);
+        EVar name = new EVar(nameToken);
         ArrayList<TypeAst> parameters = new ArrayList<TypeAst>();
         while(i < length()) {
             Object symbol = get(i++);
@@ -414,12 +424,12 @@ public class SCLParserImpl extends SCLParser {
 
     @Override
     protected Object reduceVarId() {
-        return new EVar(((Token)get(0)).text);
+        return new EVar((Token)get(0));
     }
 
     @Override
     protected Object reduceEscapedSymbol() {
-        return new EVar(((Token)get(0)).text);
+        return new EVar((Token)get(0));
     }
 
     @Override
@@ -450,7 +460,7 @@ public class SCLParserImpl extends SCLParser {
         EVar negation = null;
         if(get(i) instanceof Token) {
             Token token = (Token)get(i++);
-            negation = new EVar(token.location, token.text);
+            negation = new EVar(token);
         }
         EBinary binary = new EBinary((Expression)get(i++), negation);
         while(i < length()) {
@@ -517,7 +527,7 @@ public class SCLParserImpl extends SCLParser {
         TypeAst[] parameters = new TypeAst[length()-idPos-1];
         for(int i=0;i<parameters.length;++i)
             parameters[i] = (TypeAst)get(i+idPos+1);
-        return new ConstructorAst(annotations, ((Token)get(idPos)).text, parameters, null);
+        return new ConstructorAst(annotations, (Token)get(idPos), parameters, null);
     }
 
     @Override
@@ -571,7 +581,7 @@ public class SCLParserImpl extends SCLParser {
 
     @Override
     protected Object reduceBlank() {
-        return new EVar("_");
+        return new EVar(((Token)get(0)).location, "_");
     }
 
     @Override
@@ -1168,7 +1178,7 @@ 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 ERecord((Token)get(0), fields);
+        return new ERecord(new EVar((Token)get(0)), fields);
     }
 
     @Override
@@ -1198,7 +1208,7 @@ public class SCLParserImpl extends SCLParser {
             parameters[i] = fieldDesc.type;
             fieldNames[i] = fieldDesc.name;
         }
-        return new ConstructorAst(annotations, ((Token)get(idPos)).text, parameters, fieldNames);
+        return new ConstructorAst(annotations, (Token)get(idPos), parameters, fieldNames);
     }
 
     @Override
@@ -1243,10 +1253,8 @@ public class SCLParserImpl extends SCLParser {
 
     @Override
     protected Object reduceConstraintStatement() {
-        TypeAst[] parameterTypes = new TypeAst[length()-2];
-        for(int i=0;i<parameterTypes.length;++i)
-            parameterTypes[i] = (TypeAst)get(2+i);
-        return new ConstraintStatement((Token)get(1), parameterTypes);
+        ConstructorAst constructor = (ConstructorAst)get(1);
+        return new ConstraintStatement(constructor.name, constructor.parameters, constructor.fieldNames, constructor.annotations);
     }
 
     @Override
@@ -1283,4 +1291,26 @@ 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);
+    }
+
+    @Override
+    protected Object reduceConstraintSpec() {
+        Expression[] expressions = new Expression[length()/2-1];
+        for(int i=0;i<expressions.length;++i)
+            expressions[i] = (Expression)get(2*i+1);
+        return expressions;
+    }
+
 }
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 045741d35a34495f4bb662dfe2637bb1b53ae263..41c5f776314b9a948bcba47ddd119318a8f82f15 100644 (file)
@@ -2,8 +2,14 @@ package org.simantics.scl.compiler.module.options;
 
 public class ModuleCompilationOptions {
     public static final ModuleCompilationOptions STANDARD_OPTIONS = new ModuleCompilationOptions(false);
+    public static final ModuleCompilationOptions SILENT = new ModuleCompilationOptions(false);
 
-    public final boolean computeCoverage;
+    static {
+        SILENT.silent = true;
+    }
+    
+    public boolean computeCoverage;
+    public boolean silent = false;
 
     public ModuleCompilationOptions(boolean computeCoverage) {
         this.computeCoverage = computeCoverage;
index 9243758a909ce0ce66e87b1b0e94c943da6d9c63..2aaa0785aef5c7a51a0d514e4ce098314cffcc81 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.scl.compiler.module.options;
 
+@FunctionalInterface
 public interface ModuleCompilationOptionsAdvisor {
     ModuleCompilationOptions getOptions(String moduleName);
 }
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 9a6f4c97fb07c33689e21885a1a641d4bdcadf01..50cbb1ac461ea271e0c4700d37d149fc23a351a2 100644 (file)
@@ -93,11 +93,14 @@ public abstract class TextualModuleSource implements ModuleSource {
             if(compiler.getErrorLog().hasNoErrors())
                 return new Success<Module>(compiler.getModule());
             else {
-                LOGGER.error("While compiling " + getModuleName() + ":");
-                LOGGER.error(CompilationErrorFormatter.toString(getSourceReader(null), compiler.getErrorLog().getErrors()));
+                if(options == null || !options.silent)
+                    LOGGER.error("While compiling " + getModuleName() + ":\n    " +
+                            CompilationErrorFormatter.toString(getSourceReader(null), compiler.getErrorLog().getErrors()).replaceAll("\n", "\n    "));
                 return new Failure(compiler.getErrorLog().getErrors());
             }
         } catch (IOException e) {
+            if(options == null || !options.silent)
+                LOGGER.error("Compilation of module " + moduleName + " failed.", e);
             return new Failure(e);
         }
     }
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;
index b725d6c74afca7914d62fb38909fb1a85c7e4209..19e83d30b571a7dfd9cf197090b1fecbe72939ea 100644 (file)
@@ -343,6 +343,7 @@ importJava "org.simantics.db.layer0.util.Layer0Utils" where
     listOntologies :: () -> <ReadGraph> [Resource]
     emptyTrashBin :: () -> <Proc> ()
     purgeDatabase :: () -> <Proc> ()
+    prettyPrintResource :: Resource -> <ReadGraph> String
 
     @private
     @JavaName copyTo
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..b79cf6d
--- /dev/null
@@ -0,0 +1,21 @@
+package org.simantics.scl.runtime.chr;
+
+public class CHRContext {
+    public CHRPriority topPriority;
+    public int currentId = 0;
+    
+    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 + "---------------------------------------------");
+    }
+    
+    public int generateId() {
+        return currentId++;
+    }
+}
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/src/org/simantics/scl/runtime/reporting/WriterSCLReportingHandler.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/reporting/WriterSCLReportingHandler.java
new file mode 100644 (file)
index 0000000..3cc3f4b
--- /dev/null
@@ -0,0 +1,22 @@
+package org.simantics.scl.runtime.reporting;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public class WriterSCLReportingHandler extends AbstractSCLReportingHandler {
+    private final Writer writer;
+
+    public WriterSCLReportingHandler(Writer writer) {
+        this.writer = writer;
+    }
+
+    @Override
+    public void print(String text) {
+        try {
+            writer.write(text);
+            writer.write('\n');
+        } catch(IOException e) {
+            e.printStackTrace();
+        }
+    }
+}
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 8364abd1875c6cec0b9a99f27345a80d983a78e4..e3aa1f61f0a3aacd47b0ec72be8030506f191b26 100644 (file)
@@ -31,6 +31,7 @@ TESTS.STSTest <T L0.Entity
     @L0.assert TESTS.STSTest.executionPriority -1
     @L0.assert TESTS.ignore false
     @L0.assert TESTS.ignoreReason ""
+    @L0.assert TESTS.dependencies ""
 
 TESTS.STSTest : MOD.TypeWithChangeInformation 
 TESTS.STSTest : L0.TypeWithIdentifier
@@ -39,6 +40,18 @@ TESTS.STSSuite <T L0.Entity
     >-- TESTS.STSSuite.moduleNameFilter --> L0.String <R L0.HasProperty : L0.TotalFunction : SEL.GenericParameterType
     @L0.assert TESTS.STSSuite.moduleNameFilter ""
     @L0.assert TESTS.ignore false
+    @L0.assert TESTS.dependencies ""
 
 TESTS.STSSuite : MOD.TypeWithChangeInformation 
-TESTS.STSSuite : L0.TypeWithIdentifier
\ No newline at end of file
+TESTS.STSSuite : L0.TypeWithIdentifier
+
+TESTS.STSVariable <T L0.Entity
+    TESTS.STSVariable.definition ""
+
+TESTS.STSVariable.definition <R L0.HasProperty : L0.TotalFunction : SEL.GenericParameterType
+    L0.HasRange L0.String
+    L0.HasLabel "Variable definition"
+
+TESTS.dependencies <R L0.HasProperty : L0.TotalFunction : SEL.GenericParameterType
+    L0.HasRange L0.String
+    L0.HasLabel "Test dependencies"
index f92524b797ae40dd43dee90286f60a2e01c8db5f..a0e60d0b31e2882935a98a802a8bf7f82776757f 100644 (file)
@@ -36,6 +36,8 @@ MBC
     @VP.namedConstantImageRule    TestsUI.Contributions.SuiteImage          TESTS.STSSuite                         TestsUI.testSuiteImage
     @VP.namedRelationChildRule    TestsUI.Contributions.STSTests            L0.Entity                              L0.ConsistsOf TESTS.STSTest
     @VP.customImageRule           TESTS.STSTest                             MBC.TestImageRule
+    @VP.namedRelationChildRule    TestsUI.Contributions.STSVariables        L0.Entity                              L0.ConsistsOf TESTS.STSVariable
+    @VP.namedConstantImageRule    TestsUI.Contributions.VariableImage       TESTS.STSVariable                      SILK.page_white_edit
 
 MBC
     VP.BrowseContext.HasVisualsContribution _ : VP.VisualsContribution
@@ -55,6 +57,8 @@ ACTIONS.NewSTSTest
   @MOD.sclAction "createSTSTestAction"
 ACTIONS.RunSTSTest
   @MOD.sclAction "runSTSTestAction"
+ACTIONS.NewSTSVariable
+  @MOD.sclAction "createSTSVariableAction"
 
 MAC
     VP.BrowseContext.HasActionContribution TestsUI.Contributions.NewSTSSuite : VP.ActionContribution
@@ -76,10 +80,12 @@ MAC
         VP.ActionContribution.HasImage SILK.control_play
         VP.ActionContribution.HasCategory VP.EditActionCategory
         VP.ActionContribution.HasNodeType TESTS.STSSuite
+        VP.ActionContribution.HasNodeType TESTS.STSTest
         VP.ActionContribution.HasAction ACTIONS.RunSTSTest
     VP.BrowseContext.HasActionContribution _ : VP.ActionContribution
-        L0.HasLabel "Run"
-        VP.ActionContribution.HasImage SILK.control_play
-        VP.ActionContribution.HasCategory VP.EditActionCategory
+        L0.HasLabel "STS Variable"
+        VP.ActionContribution.HasImage SILK.page_white_edit
+        VP.ActionContribution.HasCategory VP.NewActionCategory
+        VP.ActionContribution.HasNodeType TESTS.STSSuite
         VP.ActionContribution.HasNodeType TESTS.STSTest
-        VP.ActionContribution.HasAction ACTIONS.RunSTSTest
\ No newline at end of file
+        VP.ActionContribution.HasAction ACTIONS.NewSTSVariable
index d834c36756fe5a8d3ab254dc0ff34b608af9d23f..53218224a089feac163ae5e475d245afe05a25e2 100644 (file)
@@ -11,4 +11,9 @@ importJava "org.simantics.tests.modelled.ui.TestsUIUtils" where
 createSTSSuiteAction :: Resource -> <Proc> ()
 createSTSSuiteAction res = do
   syncWrite (\() -> createSTSSuite res)
+  ()
+
+createSTSVariableAction :: Resource -> <Proc> ()
+createSTSVariableAction res = do
+  syncWrite(\() -> createSTSVariable res)
   ()
\ No newline at end of file
index e93c793e74aa90e94362392770edb0440a61b5fe..d4d58129d61ce0f42f13d106ab3d983d121fe4bd 100644 (file)
@@ -28,6 +28,7 @@ import org.eclipse.swt.widgets.Text;
  */
 public class STSCounterPanel extends Composite {
     protected Text numberOfErrors;
+    protected Text numberOfSkipped;
     protected Text numberOfFailures;
     protected Text numberOfRuns;
     protected int total;
@@ -46,6 +47,7 @@ public class STSCounterPanel extends Composite {
         setLayout(gridLayout);
 
         numberOfRuns= createLabel("Runs:", null, " 0/0  "); //$NON-NLS-1$
+        numberOfSkipped = createLabel("Skipped:", null," 0 ");
         numberOfErrors= createLabel("Errors:", fErrorIcon, " 0 "); //$NON-NLS-1$
         numberOfFailures= createLabel("Failures:", fFailureIcon, " 0 "); //$NON-NLS-1$
 
@@ -129,6 +131,11 @@ public class STSCounterPanel extends Composite {
         assumptionFailedCount= assumptionFailureCount;
     }
 
+    public void setIgnoredValue(int value) {
+        numberOfSkipped.setText(Integer.toString(value));
+        redraw();
+    }
+    
     public void setErrorValue(int value) {
         numberOfErrors.setText(Integer.toString(value));
         redraw();
index 21bb5e4d7011bd87b1d6efefb13112cae22623de..ea00d8f07ab2f61e695826b831e77cb8edcff5e7 100644 (file)
@@ -4,5 +4,11 @@ import org.simantics.scl.ui.editor2.SCLModuleEditor2;
 
 public class STSTestEditor extends SCLModuleEditor2 {
 
+    
+    @Override
+    public void setFocus() {
+        // TODO Auto-generated method stub
+        super.setFocus();
+    }
 
 }
index 203f2832501c57d98aa48bd54e344c833fb373d3..b8b8094491da298706a44b976731a051b487674e 100644 (file)
@@ -7,6 +7,7 @@ import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 
 import org.eclipse.e4.ui.di.Focus;
+import org.eclipse.e4.ui.model.application.ui.basic.MPart;
 import org.eclipse.jface.layout.TreeColumnLayout;
 import org.eclipse.jface.viewers.CellLabelProvider;
 import org.eclipse.jface.viewers.ColumnWeightData;
@@ -32,6 +33,9 @@ import org.eclipse.swt.layout.GridLayout;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
 import org.eclipse.swt.widgets.Tree;
 import org.eclipse.swt.widgets.TreeColumn;
 import org.eclipse.ui.part.PageBook;
@@ -54,19 +58,21 @@ public class STSTestRunnerView {
     private Composite counterComposite;
 
     @PostConstruct
-    void createView(Composite parent) {
+    void createView(MPart part, Composite parent) {
         
         GridLayout gridLayout= new GridLayout();
         gridLayout.marginWidth= 0;
         gridLayout.marginHeight= 0;
         parent.setLayout(gridLayout);
         
-        counterComposite= createProgressCountPanel(parent);
+        counterComposite = createProgressCountPanel(parent);
         counterComposite.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
         counterComposite.pack();
         
         SashForm sashForm = createSashForm(parent);
         sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
+        
+//        IToolBarManager toolBarManager = getViewSite().getActionBars().getToolBarManager();
     }
     
     private SashForm createSashForm(Composite parent) {
@@ -335,6 +341,26 @@ public class STSTestRunnerView {
         treeViewer.setContentProvider(provider);
         treeViewer.setLabelProvider(provider);
 
+        
+        Menu menu = new Menu(treeViewer.getControl());
+        
+        MenuItem item1 = new MenuItem(menu, SWT.PUSH);
+        item1.setText("Stop");
+        item1.addListener(SWT.Selection, new Listener() {
+            
+            @Override
+            public void handleEvent(Event event) {
+                TreeSelection selec = (TreeSelection) treeViewer.getSelection();
+                if (!selec.isEmpty()) {
+                    Object elem = selec.getFirstElement();
+                    provider.getModel().interrupt();
+                    
+                }
+            }
+        });
+        
+        treeViewer.getControl().setMenu(menu);
+        
 
         viewerbook.showPage(treeViewer.getTree());
         
@@ -388,6 +414,7 @@ public class STSTestRunnerView {
 
        counterPanel.setTotal(totalCount);
        counterPanel.setRunValue(startedCount, ignoredCount, assumptionFailureCount);
+       counterPanel.setIgnoredValue(ignoredCount);
        counterPanel.setErrorValue(errorCount);
        counterPanel.setFailureValue(failureCount);
 
index 976efa2c2d2a0aab10b40125ed664672c2b4f9d9..b6cda3fdc817aaafc77e1560b89a16195eb2c3ab 100644 (file)
@@ -1,13 +1,16 @@
 package org.simantics.tests.modelled.ui;
 
-import java.io.BufferedReader;
-import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
-import java.util.regex.Pattern;
+import java.util.Map;
 import java.util.stream.Collectors;
 
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.swt.graphics.Image;
 import org.simantics.Simantics;
 import org.simantics.db.ReadGraph;
@@ -15,22 +18,21 @@ import org.simantics.db.Resource;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.layer0.Layer0;
-import org.simantics.scl.compiler.commands.CommandSession;
-import org.simantics.scl.compiler.commands.TestScriptExecutor;
 import org.simantics.scl.compiler.module.coverage.CombinedCoverage;
-import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
-import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;
-import org.simantics.scl.compiler.module.repository.ModuleRepository;
-import org.simantics.scl.osgi.SCLOsgi;
+import org.simantics.scl.runtime.SCLContext;
 import org.simantics.scl.runtime.reporting.AbstractSCLReportingHandler;
+import org.simantics.scl.runtime.reporting.SCLReportingHandler;
 import org.simantics.tests.modelled.ontology.TestsResource;
 import org.simantics.tests.modelled.utils.ModelledSTSSuite;
 import org.simantics.tests.modelled.utils.ModelledSTSTest;
+import org.simantics.tests.modelled.utils.ModelledSTSTest.CommandSessionVariable;
 import org.simantics.tests.modelled.utils.STSSuiteTestCollector;
 
 public class STSTestSuiteModel {
 
-    static class STSTest {
+    private Map<String, List<CommandSessionVariable>> storedVars = new HashMap<>();
+    
+    class STSTest {
         
         private final ModelledSTSTest test;
         
@@ -66,31 +68,41 @@ public class STSTestSuiteModel {
             return parent;
         }
 
-        public void execute(CommandSession session) {
+        public void execute() {
             isRunning = true;
-            
-            TestScriptExecutor executor = new TestScriptExecutor(session, new BufferedReader(new StringReader(getDefinition())), new AbstractSCLReportingHandler() {
-                
-                @Override
-                public void print(String text) {
-                    appendOutput(text + "\n");
-                }
-                
-                @Override
-                public void printCommand(String command) {
-                    appendOutput("> " + command + "\n");
-                }
-                
-                @Override
-                public void printError(String error) {
-                    appendOutput(error + "\n");
-                }
-            }, true);
             long start = System.currentTimeMillis();
+            Object old = SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
             try {
                 if (parent != null)
                     parent.startedCount++;
-                executor.execute();
+
+                SCLContext.getCurrent().put(SCLReportingHandler.REPORTING_HANDLER, new AbstractSCLReportingHandler() {
+                    
+                    @Override
+                    public void print(String text) {
+                        appendOutput(text + "\n");
+                    }
+                    
+                    @Override
+                    public void printCommand(String command) {
+                        appendOutput("> " + command + "\n");
+                    }
+                    
+                    @Override
+                    public void printError(String error) {
+                        appendOutput(error + "\n");
+                    }
+                });
+                List<CommandSessionVariable> resolvedVars = new ArrayList<>();
+                for (String deps : test.getDependencies()) {
+                    List<CommandSessionVariable> vars = storedVars.get(deps);
+                    if (vars != null)
+                        resolvedVars.addAll(vars);
+                }
+                
+                List<CommandSessionVariable> vars = test.run(resolvedVars);
+                storedVars.put(test.getName(), vars);
+                
                 executed = true;
             } catch (Throwable t) {
                 t.printStackTrace();
@@ -101,8 +113,9 @@ public class STSTestSuiteModel {
                 isRunning = false;
                 long end = System.currentTimeMillis();
                 duration = end - start;
+                
+                SCLContext.getCurrent().put(SCLReportingHandler.REPORTING_HANDLER, old);
             }
-
         }
 
         protected void appendOutput(String text) {
@@ -135,7 +148,7 @@ public class STSTestSuiteModel {
         }
     }
 
-    static class STSSuite {
+    class STSSuite {
 
         private ModelledSTSSuite suite;
         private STSTest[] children;
@@ -216,6 +229,7 @@ public class STSTestSuiteModel {
     private STSSuite suite;
     private STSTest test;
     private final List<STSExecutionListener> listeners = new ArrayList<>();
+    private Job currentJob;
     
     public STSTestSuiteModel() {
     }
@@ -237,30 +251,47 @@ public class STSTestSuiteModel {
     }
 
     public void execute() {
-        
-        ModuleRepository repo = new ModuleRepository(SCLOsgi.SOURCE_REPOSITORY);
-        if (suite != null) {
-            repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {
+        String command;
+        if (suite != null)
+            command = suite.getName();
+        else
+            command = test.getName();
+        if (currentJob != null)
+            currentJob.cancel();
+        currentJob = new Job(command) {
+            @Override
+            protected IStatus run(IProgressMonitor monitor) {
+                if (suite != null) {
+                    executeSuite();
+                } else if (test != null) {
+                    executeTest();
+                }
+                return Status.OK_STATUS;
+            }
+            
+            @Override
+            protected void canceling() {
+                Thread thread = getThread();
+                if(thread != null)
+                    thread.interrupt();
                 
-                @Override
-                public ModuleCompilationOptions getOptions(String moduleName) {
-                    boolean coverage = false;
-                    for (Pattern p : suite.suite.getModuleNameFilterPatterns()) {
-                        if (p.matcher(moduleName.toLowerCase()).find()) {
-                            coverage = true;
-                            break;
-                        }
-                    }
-                    return new ModuleCompilationOptions(coverage);
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
                 }
-            });
-        }
-        CommandSession session = new CommandSession(repo, null);
-        if (suite != null) {
-            executeSuite(session);
-        } else if (test != null) {
-            executeTest(session);
-        }
+                
+                thread = getThread();
+                if(thread != null)
+                    thread.stop();
+            }
+        };
+        currentJob.schedule();
+    }
+    
+    public void interrupt() {
+        if (currentJob != null)
+            currentJob.cancel();
     }
     
     private void testExecuted() {
@@ -269,23 +300,21 @@ public class STSTestSuiteModel {
         });
     }
     
-    private void executeSuite(CommandSession session) {
+    private void executeSuite() {
         for (STSTest test : suite.getChildren()) {
             if (test.isIgnored()) {
                 testExecuted();
                 test.getParent().ignoredCount++;
                 continue;
             }
-            test.execute(session);
-            STSSuiteTestCollector.setSuiteCoverage(test.test, suite.suite, session);
+            test.execute();
             testExecuted();
         }
     }
 
-    private void executeTest(CommandSession session) {
-        test.execute(session);
+    private void executeTest() {
+        test.execute();
         testExecuted();
-        STSSuiteTestCollector.setTestCoverage(test.test, session);
     }
 
     public boolean hasChildren(Object element) {
index fe80e1303cb4ae115e742312fcc2c3aea36c971f..ce3cfb1548a0b316571afd533c443f84087558ea 100644 (file)
@@ -1,5 +1,6 @@
 include "Simantics/DB"
 
 importJava "org.simantics.tests.modelled.TestsGraphUtils" where
-    createSTSTest :: Resource -> <Proc, WriteGraph> Resource
-    createSTSSuite :: Resource -> <WriteGraph, Proc> ()
+    createSTSTest :: Resource -> <WriteGraph, Proc> Resource
+    createSTSSuite :: Resource -> <WriteGraph, Proc> Resource
+    createSTSVariable :: Resource -> <WriteGraph, Proc> Resource
index e9ce7d06ff24d775992a896969cb71ccb034a0a7..c5253bd5a37ad138d159b4b7b938ad3a159cbf6e 100644 (file)
@@ -31,9 +31,24 @@ public class TestsGraphUtils {
 
     private static final String STS_TEST_PREFIX = "STSTest";
     private static final String STS_SUITE_PREFIX = "STSSuite";
+    private static final String STS_VARIABLE_PREFIX = "STSVariable";
     
     private TestsGraphUtils() {}
     
+    public static Resource createSTSVariable(WriteGraph graph, Resource parent) throws DatabaseException {
+        String name = NameUtils.findFreshEscapedName(graph, STS_VARIABLE_PREFIX, parent);
+        Resource stsVariable = graph.newResource();
+        
+        Layer0 L0 = Layer0.getInstance(graph);
+        TestsResource TESTS = TestsResource.getInstance(graph);
+        
+        graph.claim(parent, L0.ConsistsOf, L0.PartOf, stsVariable);
+        graph.claim(stsVariable, L0.InstanceOf, TESTS.STSVariable);
+        graph.claimLiteral(stsVariable, L0.HasName, name, Bindings.STRING);
+        graph.claimLiteral(stsVariable, TESTS.STSVariable_definition, "", Bindings.STRING);
+        return stsVariable;
+    }
+    
     public static Resource createSTSTest(WriteGraph graph, Resource parent) throws DatabaseException {
         String name = NameUtils.findFreshEscapedName(graph, STS_TEST_PREFIX, parent);
         Resource stsTest = graph.newResource();
index c74f6efaea0fb0485f377177eba45ecfe26191d2..e77224b58c72caa59b1e290831e817803844368e 100644 (file)
@@ -1,7 +1,8 @@
 package org.simantics.tests.modelled.junit.v2;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
-import java.util.stream.Collectors;
 
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.junit.runner.Description;
@@ -12,28 +13,30 @@ import org.junit.runners.ParentRunner;
 import org.junit.runners.model.InitializationError;
 import org.simantics.Simantics;
 import org.simantics.db.testing.common.AcornTests;
-import org.simantics.scl.compiler.commands.CommandSession;
-import org.simantics.scl.osgi.SCLOsgi;
+import org.simantics.tests.modelled.utils.ModelledSTSSuite;
 import org.simantics.tests.modelled.utils.STSSuiteTestCollector;
 
 public class ModelledSTSRunner extends ParentRunner<ModelledSTSSuiteRunner> {
 
-    private CommandSession commandSession;
+    private final List<ModelledSTSSuiteRunner> children;
 
-    public ModelledSTSRunner(Class<?> testClass) throws Exception {
+    public ModelledSTSRunner(Class<?> testClass) throws InitializationError {
         super(testClass);
-        initialize0();
+        try {
+            initialize0();
+            Collection<ModelledSTSSuite> suites = STSSuiteTestCollector.collectTests();
+            children = new ArrayList<>(suites.size());
+            for (ModelledSTSSuite suite : suites) {
+                children.add(new ModelledSTSSuiteRunner(suite));
+            }
+        } catch (Exception e) {
+            throw new InitializationError(e);
+        }
     }
 
     @Override
     protected List<ModelledSTSSuiteRunner> getChildren() {
-        return STSSuiteTestCollector.collectTests().stream().map(suite -> {
-            try {
-                return new ModelledSTSSuiteRunner(suite);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }).collect(Collectors.toList());
+        return children;
     }
 
     @Override
@@ -55,7 +58,6 @@ public class ModelledSTSRunner extends ParentRunner<ModelledSTSSuiteRunner> {
 
     @Override
     protected void runChild(ModelledSTSSuiteRunner child, RunNotifier notifier) {
-        child.setCommandSesssion(commandSession);
         child.run(notifier);
         // TODO: Add coverage reporting to ModelledSTSRunner
 //        CombinedCoverage cover = child.getCoverage();
@@ -70,7 +72,6 @@ public class ModelledSTSRunner extends ParentRunner<ModelledSTSSuiteRunner> {
 
     private void initialize0() throws Exception {
         AcornTests.newSimanticsWorkspace(null, null);
-        this.commandSession = new CommandSession(SCLOsgi.MODULE_REPOSITORY, null);
         initialize();
     }
 
index a568976cc6da745db0beba6a818ad738c98487c7..5b7a8ef0ac3d5b352052476055bd160b7c58531b 100644 (file)
@@ -1,26 +1,32 @@
 package org.simantics.tests.modelled.junit.v2;
 
+import java.util.ArrayList;
 import java.util.List;
-import java.util.stream.Collectors;
+import java.util.Map;
 
 import org.junit.runner.Description;
 import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.ParentRunner;
-import org.simantics.scl.compiler.commands.CommandSession;
+import org.junit.runners.model.InitializationError;
 import org.simantics.scl.compiler.module.coverage.CombinedCoverage;
-import org.simantics.scl.osgi.SCLOsgi;
 import org.simantics.tests.modelled.utils.ModelledSTSSuite;
-import org.simantics.tests.modelled.utils.STSSuiteTestCollector;
+import org.simantics.tests.modelled.utils.ModelledSTSTest;
+import org.simantics.tests.modelled.utils.ModelledSTSTest.CommandSessionVariable;
 
 public class ModelledSTSSuiteRunner extends ParentRunner<ModelledSTSTestRunner> {
 
     private final ModelledSTSSuite suite;
-    private CommandSession commandSession;
+    private final List<ModelledSTSTestRunner> children;
+    private Map<String, List<CommandSessionVariable>> storedVariables;
 
-    public ModelledSTSSuiteRunner(ModelledSTSSuite suite) throws Exception {
+    public ModelledSTSSuiteRunner(ModelledSTSSuite suite) throws InitializationError {
         super(ModelledSTSSuiteRunner.class);
         this.suite = suite;
+        this.children = new ArrayList<>(suite.getChildren().size());
+        for (ModelledSTSTest test : suite.getSortedChildren()) {
+            children.add(new ModelledSTSTestRunner(test));
+        }
     }
 
     @Override
@@ -30,7 +36,7 @@ public class ModelledSTSSuiteRunner extends ParentRunner<ModelledSTSTestRunner>
 
     @Override
     protected List<ModelledSTSTestRunner> getChildren() {
-        return suite.getChildren().stream().map(test -> new ModelledSTSTestRunner(test)).collect(Collectors.toList());
+        return children;
     }
 
     @Override
@@ -44,15 +50,21 @@ public class ModelledSTSSuiteRunner extends ParentRunner<ModelledSTSTestRunner>
         if (isIgnored(child)) {
             notifier.fireTestIgnored(description);
         } else {
-            notifier.fireTestStarted(description);
             try {
-                child.run(getCommandSession());
+                List<CommandSessionVariable> variables = new ArrayList<>();
+                for (String dep : child.getTest().getDependencies()) {
+                    List<CommandSessionVariable> storedVars = storedVariables.get(dep);
+                    if (storedVars != null) {
+                        variables.addAll(storedVars);
+                    }
+                }
+                List<CommandSessionVariable> newVars = child.runWithVars(variables);
+                storedVariables.put(child.getTest().getName(), newVars);
                 notifier.fireTestFinished(description);
-                STSSuiteTestCollector.setSuiteCoverage(child.getTest(), suite, getCommandSession());
-            } catch (Throwable e) {
+            } catch (Exception e) {
                 notifier.fireTestFailure(new Failure(description, e));
             }
-        }
+        } 
     }
 
     @Override
@@ -60,16 +72,6 @@ public class ModelledSTSSuiteRunner extends ParentRunner<ModelledSTSTestRunner>
         return child.isIgnored();
     }
 
-    public void setCommandSesssion(CommandSession commandSession) {
-        this.commandSession = commandSession;
-    }
-
-    public CommandSession getCommandSession() {
-        if (commandSession == null)
-            commandSession = new CommandSession(SCLOsgi.MODULE_REPOSITORY, null);
-        return commandSession;
-    }
-
     public CombinedCoverage getCoverage() {
         return suite.getCoverage();
     }
index a2acbfcb8d23edc93ab0a64d76c2ff6bc56a4377..5f8ea6c16117fe90f4e4bad19b7095a54200e756 100644 (file)
@@ -1,18 +1,14 @@
 package org.simantics.tests.modelled.junit.v2;
 
-import java.io.BufferedReader;
-import java.io.StringReader;
+import java.io.IOException;
+import java.util.List;
 
 import org.junit.runner.Description;
 import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
-import org.simantics.scl.compiler.commands.CommandSession;
-import org.simantics.scl.compiler.commands.TestScriptExecutor;
-import org.simantics.scl.osgi.SCLOsgi;
-import org.simantics.scl.runtime.SCLContext;
-import org.simantics.scl.runtime.reporting.SCLReportingHandler;
 import org.simantics.tests.modelled.utils.ModelledSTSTest;
-import org.simantics.tests.modelled.utils.STSSuiteTestCollector;
+import org.simantics.tests.modelled.utils.ModelledSTSTest.CommandSessionVariable;
 
 public class ModelledSTSTestRunner extends Runner {
 
@@ -23,41 +19,20 @@ public class ModelledSTSTestRunner extends Runner {
         this.test = test;
     }
 
-    public String getName() {
-        return test.getName();
-    }
-
     @Override
     public Description getDescription() {
         if (description == null)
-            description = Description.createTestDescription(ModelledSTSTestRunner.class, getName());
+            description = Description.createTestDescription(ModelledSTSTestRunner.class, test.getName());
         return description;
     }
 
-    /**
-     * This method is called from ModelledSTSSuite (ParentRunner) with the same
-     * CommandSession
-     * 
-     * @param session
-     */
-    public void run(CommandSession session) {
-        try (BufferedReader reader = new BufferedReader(new StringReader(test.getCode()))) {
-            SCLReportingHandler handler = (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
-            new TestScriptExecutor(session, reader, handler, true).execute();
-            STSSuiteTestCollector.setTestCoverage(test, session);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
+    public List<CommandSessionVariable> runWithVars(List<CommandSessionVariable> vars) throws IOException {
+        return test.run(vars);
     }
-
+    
     @Override
     public void run(RunNotifier notifier) {
-        notifier.fireTestStarted(getDescription());
-        try {
-            run(new CommandSession(SCLOsgi.MODULE_REPOSITORY, null));
-        } finally {
-            notifier.fireTestFinished(getDescription());
-        }
+        throw new UnsupportedOperationException();
     }
 
     public boolean isIgnored() {
index b856787cfc560c4c634e471909cdc86e48d49bdb..7ccb3ccd358f52b7b443476ff8ade20b8c05883b 100644 (file)
@@ -1,10 +1,15 @@
 package org.simantics.tests.modelled.utils;
 
 import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
-import java.util.stream.Collectors;
 
 import org.simantics.scl.compiler.module.Module;
 import org.simantics.scl.compiler.module.coverage.CombinedCoverage;
@@ -19,10 +24,12 @@ public class ModelledSTSSuite {
     private List<Pattern> moduleNameFilterPatterns = new ArrayList<>();
 
     private CoverageBuilder coverageBuilder;
+    private Map<String, String> variables;
 
-    ModelledSTSSuite(String name, List<ModelledSTSTest> children, String moduleNameFilter) {
+    ModelledSTSSuite(String name, List<ModelledSTSTest> children, String moduleNameFilter, Map<String, String> variables) {
         this.name = name;
         this.children = children;
+        this.variables = variables;
         this.moduleNameFilter = moduleNameFilter;
         for (String s : moduleNameFilter.split(",")) {
             try {
@@ -42,8 +49,46 @@ public class ModelledSTSSuite {
         return children;
     }
 
+    static Comparator<ModelledSTSTest> comparator = (test1, test2) -> compareTests(test1, test2);
+    
     public List<ModelledSTSTest> getSortedChildren() {
-        return new ArrayList<>(children).stream().sorted(ModelledSTSSuite::compareTests).collect(Collectors.toList());
+        Set<ModelledSTSTest> testsWithDeps = new HashSet<>();
+        // This TreeMap sorts the tests with the comparator 
+        TreeMap<ModelledSTSTest, String> sortedTests = new TreeMap<>(comparator);
+        for (ModelledSTSTest test : getChildren()) {
+            Set<String> testDependencies = test.getDependencies();
+            if (testDependencies.isEmpty()) {
+                // First tests that have no dependencies
+                sortedTests.put(test, test.getName());
+            } else {
+                // These are resolved later
+                testsWithDeps.add(test);
+            }
+        }
+        
+        // Construct a LinkedList that is returned as a result
+        LinkedList<ModelledSTSTest> results = new LinkedList<>(sortedTests.keySet());
+        
+//        Set<ModelledSTSTest> temp = new HashSet<>(testsWithDeps);
+        // Now resolve tests with dependencies
+        for (ModelledSTSTest testWithDep : testsWithDeps) {
+            boolean satisfied = true;
+            for (String dep : testWithDep.getDependencies()) {
+                if (!sortedTests.containsValue(dep)) {
+                    satisfied = false;
+                } else {
+                    testWithDep.resolveDependency(dep);
+                }
+            }
+            if (satisfied) {
+                results.addLast(testWithDep);
+                sortedTests.put(testWithDep, testWithDep.getName());
+            } else {
+                // Not satisfied
+                System.out.println(testWithDep.getName() + " not satisfied");
+            }
+        }
+        return results;
     }
 
     private static int compareTests(ModelledSTSTest test1, ModelledSTSTest test2) {
index 00d825d2e215017e9de0d554ece44dd6afa4eeb5..3430696b81456e5959d35b001da7319df906baac 100644 (file)
@@ -1,6 +1,26 @@
 package org.simantics.tests.modelled.utils;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.simantics.scl.compiler.commands.CommandSession;
+import org.simantics.scl.compiler.commands.TestScriptExecutor;
 import org.simantics.scl.compiler.module.coverage.CombinedCoverage;
+import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
+import org.simantics.scl.compiler.module.options.ModuleCompilationOptionsAdvisor;
+import org.simantics.scl.compiler.module.repository.ModuleRepository;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.osgi.SCLOsgi;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.reporting.SCLReportingHandler;
 
 public class ModelledSTSTest {
 
@@ -8,14 +28,20 @@ public class ModelledSTSTest {
     private final String code;
     private final int priority;
     private final boolean ignored;
-
+    private Set<String> dependencies;
+    private Set<String> unresolvedDependencies;
+    
     private CombinedCoverage coverage;
+    private Map<String, String> variables;
 
-    ModelledSTSTest(String name, String code, int priority, boolean ignored) {
+    ModelledSTSTest(String name, String code, int priority, boolean ignored, Set<String> dependencies, Map<String, String> variables) {
         this.name = name;
         this.code = code;
         this.priority = priority;
         this.ignored = ignored;
+        this.dependencies = dependencies;
+        this.unresolvedDependencies = new HashSet<>(dependencies);
+        this.variables = variables;
     }
 
     public String getName() {
@@ -31,7 +57,7 @@ public class ModelledSTSTest {
     }
 
     public boolean isIgnored() {
-        return ignored;
+        return (ignored || !unresolvedDependencies.isEmpty());
     }
 
     public void setCoverage(CombinedCoverage coverage) {
@@ -41,4 +67,80 @@ public class ModelledSTSTest {
     public CombinedCoverage getCoverage() {
         return coverage;
     }
+
+    public static class CommandSessionVariable {
+
+        private final String name;
+        private final Type type;
+        private final Object value;
+
+        public CommandSessionVariable(String name, Type type, Object value) {
+            this.name = name;
+            this.type = type;
+            this.value = value;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public Type getType() {
+            return type;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+    }
+    
+    public List<CommandSessionVariable> run(List<CommandSessionVariable> vars) throws IOException {
+        ModuleRepository repo = new ModuleRepository(SCLOsgi.SOURCE_REPOSITORY);
+        repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {
+            
+            @Override
+            public ModuleCompilationOptions getOptions(String moduleName) {
+                // TODO: default to false
+                boolean coverage = true;
+                // TODO: add moduleName filters back
+//                for (Pattern p : getModuleNameFilterPatterns()) {
+//                    if (p.matcher(moduleName.toLowerCase()).find()) {
+//                        coverage = true;
+//                        break;
+//                    }
+//                }
+                return new ModuleCompilationOptions(coverage);
+            }
+        });
+        
+        SCLReportingHandler handler = (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
+        CommandSession session = new CommandSession(repo, handler);
+        
+        for (CommandSessionVariable var : vars)
+            session.setVariable(var.getName(), var.getType(), var.getValue());
+        
+        for (Map.Entry<String, String> entry : variables.entrySet())
+            session.setVariable(entry.getKey(), Types.STRING, entry.getValue());
+        
+        new TestScriptExecutor(session, new BufferedReader(new StringReader(code)), handler, true).execute();
+        STSSuiteTestCollector.setTestCoverage(this, session);
+        
+        // Return variables from this session
+        List<CommandSessionVariable> result = new ArrayList<>();
+        for (String var : session.getVariables())
+            result.add(new CommandSessionVariable(var, session.getVariableType(var), session.getVariableValue(var)));
+        
+        return result;
+    }
+
+    public Set<String> getDependencies() {
+        return dependencies;
+    }
+    
+    public Set<String> getUnresolvedDependencies() {
+        return unresolvedDependencies;
+    }
+    
+    public boolean resolveDependency(String testDep) {
+        return unresolvedDependencies.remove(testDep);
+    }
 }
index 10530e185b6dfcc833dc77ab5a262899cba76c40..8917d16462425ddf65e93b20636d19dcaa766a78 100644 (file)
@@ -1,10 +1,12 @@
 package org.simantics.tests.modelled.utils;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Pattern;
 
 import org.simantics.Simantics;
@@ -32,66 +34,84 @@ public class STSSuiteTestCollector {
     /**
      * TODO: The idea of this class was to collect all the tests from shared libraries and construct
      * JUnit tests out of them programmatically and then run them with JUnit to get results
+     * @throws DatabaseException 
      * 
      */
-    private static Collection<ModelledSTSSuite> collectTestsFromGraph() {
-        try {
-            Collection<ModelledSTSSuite> suitess = Simantics.getSession().syncRequest(new UniqueRead<Collection<ModelledSTSSuite>>() {
+    public static Collection<ModelledSTSSuite> collectTests() throws DatabaseException {
+        Collection<ModelledSTSSuite> suitess = Simantics.getSession().syncRequest(new UniqueRead<Collection<ModelledSTSSuite>>() {
 
-                @Override
-                public Collection<ModelledSTSSuite> perform(ReadGraph graph) throws DatabaseException {
-                    
-                    List<Resource> sharedOntologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE);
+            @Override
+            public Collection<ModelledSTSSuite> perform(ReadGraph graph) throws DatabaseException {
+                
+                List<Resource> sharedOntologies = Simantics.applySCL("Simantics/SharedOntologies", "getSharedOntologies", graph, Tuple0.INSTANCE);
+                if (LOGGER.isInfoEnabled())
+                    LOGGER.info("Found {} shared ontologies from graph",  sharedOntologies.size());
+                Collection<ModelledSTSSuite> suites = new HashSet<>();
+                TestsResource TESTS = TestsResource.getInstance(graph);
+                Layer0 L0 = Layer0.getInstance(graph);
+                for (Resource sharedOntology : sharedOntologies) {
                     if (LOGGER.isInfoEnabled())
-                        LOGGER.info("Found {} shared ontologies from graph",  sharedOntologies.size());
-                    Collection<ModelledSTSSuite> suites = new HashSet<>();
-                    TestsResource TESTS = TestsResource.getInstance(graph);
-                    Layer0 L0 = Layer0.getInstance(graph);
-                    for (Resource sharedOntology : sharedOntologies) {
-                        if (LOGGER.isInfoEnabled())
-                            LOGGER.info("Searching {} for modelled tests", graph.getURI(sharedOntology));
-                        List<Resource> stsSuites = ModelingUtils.searchByType(graph, sharedOntology, TESTS.STSSuite);
-                        for (Resource stsSuite : stsSuites) {
-                            try {
-                                Collection<Resource> tests = graph.syncRequest(new ObjectsWithType(stsSuite, L0.ConsistsOf, TESTS.STSTest));
-                                if (tests.isEmpty())
-                                    continue;
-    
-                                List<ModelledSTSTest> testRunners = new ArrayList<>(tests.size());
-                                for (Resource test : tests)
-                                    testRunners.add(toModelledTest(graph, test));
+                        LOGGER.info("Searching {} for modelled tests", graph.getURI(sharedOntology));
+                    List<Resource> stsSuites = ModelingUtils.searchByType(graph, sharedOntology, TESTS.STSSuite);
+                    for (Resource stsSuite : stsSuites) {
+                        try {
+                            Collection<Resource> tests = graph.syncRequest(new ObjectsWithType(stsSuite, L0.ConsistsOf, TESTS.STSTest));
+                            if (tests.isEmpty())
+                                continue;
+
+                            List<ModelledSTSTest> testRunners = new ArrayList<>(tests.size());
+                            for (Resource test : tests)
+                                testRunners.add(toModelledTest(graph, test));
 
-                                suites.add(toModelledSuite(graph, stsSuite, testRunners));
-                            } catch (Exception e) {
-                                LOGGER.error("", e);
-                            }
+                            suites.add(toModelledSuite(graph, stsSuite, testRunners));
+                        } catch (Exception e) {
+                            LOGGER.error("", e);
                         }
                     }
-                    return suites;
                 }
-            });
-            return suitess;
-        } catch (DatabaseException e) {
-            LOGGER.error("Could not find modelled tests", e);
-            return Collections.emptyList();
-        }
+                return suites;
+            }
+        });
+        return suitess;
     }
     
 
     public static ModelledSTSTest toModelledTest(ReadGraph graph, Resource test) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
         TestsResource TESTS = TestsResource.getInstance(graph);
-        String testName = graph.getRelatedValue(test, Layer0.getInstance(graph).HasName, Bindings.STRING);
+        String testName = graph.getRelatedValue(test, L0.HasName, Bindings.STRING);
         String code = graph.getRelatedValue(test, TESTS.STSTest_definition, Bindings.STRING);
         Integer priority = graph.getPossibleRelatedValue(test, TESTS.STSTest_executionPriority, Bindings.INTEGER);
         Boolean ignored = graph.getPossibleRelatedValue(test, TESTS.ignore, Bindings.BOOLEAN);
-        return new ModelledSTSTest(testName, code, priority != null ? priority : -1, ignored != null ? ignored : false);
+        
+        String dependencies = graph.getPossibleRelatedValue(test, TESTS.dependencies, Bindings.STRING);
+        String[] actualDeps = dependencies.isEmpty() ? new String[0] : dependencies.split(",");
+        
+        // collect variables
+        Collection<Resource> stsVariables = graph.getObjects(test, L0.ConsistsOf);
+        Map<String, String> variables = new HashMap<>(stsVariables.size());
+        for (Resource stsVariable : stsVariables) {
+            String name = graph.getRelatedValue(stsVariable, L0.HasName, Bindings.STRING);
+            String value = graph.getRelatedValue(stsVariable, TESTS.STSVariable_definition);
+            variables.put(name, value);
+        }
+        return new ModelledSTSTest(testName, code, priority != null ? priority : -1, ignored != null ? ignored : false, new HashSet<>(Arrays.asList(actualDeps)), variables);
     }
 
     public static ModelledSTSSuite toModelledSuite(ReadGraph graph, Resource suite, List<ModelledSTSTest> children) throws DatabaseException {
         TestsResource TESTS = TestsResource.getInstance(graph);
         String suiteName = graph.getURI(suite);
         String moduleNameFilter = graph.getPossibleRelatedValue2(suite, TESTS.STSSuite_moduleNameFilter, Bindings.STRING);
-        return new ModelledSTSSuite(suiteName, children, moduleNameFilter);
+        
+        Layer0 L0 = Layer0.getInstance(graph);
+        Collection<Resource> stsVariables = graph.sync(new ObjectsWithType(suite, L0.ConsistsOf, TESTS.STSVariable));
+        Map<String, String> variables = new HashMap<>(stsVariables.size());
+        for (Resource stsVariable : stsVariables) {
+            String name = graph.getRelatedValue(stsVariable, L0.HasName, Bindings.STRING);
+            String value = graph.getRelatedValue(stsVariable, TESTS.STSVariable_definition);
+            variables.put(name, value);
+        }
+        return new ModelledSTSSuite(suiteName, children, moduleNameFilter, variables);
     }
 
     public static void setTestCoverage(ModelledSTSTest test, CommandSession session) {
@@ -102,11 +122,6 @@ public class STSSuiteTestCollector {
         test.setCoverage(CoverageUtils.getCoverage(modules));
         CoverageUtils.resetCoverage(modules);
     }
-    
-    public static List<ModelledSTSSuite> collectTests() {
-        return new ArrayList<>(collectTestsFromGraph());
-    }
-
 
     public static void setSuiteCoverage(ModelledSTSTest test, ModelledSTSSuite suite, CommandSession session) {
         Collection<RuntimeModule> runtimeModules = session.getRuntimeEnvironment().getRuntimeModules();
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..f065b765e7ce871bb91882e9edcdecf8d28ee1c6 100644 (file)
@@ -26,6 +26,12 @@ public class ModuleRegressionTests extends TestBase {
     @Test public void CHR2() { test(); }
     @Test public void CHR3() { test(); }
     @Test public void CHR4() { test(); }
+    @Test public void CHR5() { test(); }
+    @Test public void CHR6() { test(); }
+    @Test public void CHR7() { test(); }
+    @Test public void CHR8() { test(); }
+    @Test public void CHR9() { test(); }
+    @Test public void CHR10() { test(); }
     @Test public void ClosureRecursion() { test(); }
     @Test public void Collaz() { test(); }
     @Test public void Compose() { test(); }
index 2dfaafee3660907b6b493e86e9ded837379ce17f..fa90f524cb4364386de2d71ff13c64209877702a 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.compiler.tests;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.StringWriter;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -12,12 +13,16 @@ import org.simantics.scl.compiler.errors.Failable;
 import org.simantics.scl.compiler.errors.Failure;
 import org.simantics.scl.compiler.module.ImportDeclaration;
 import org.simantics.scl.compiler.module.Module;
+import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
 import org.simantics.scl.compiler.module.repository.ModuleRepository;
 import org.simantics.scl.compiler.module.repository.UpdateListener;
 import org.simantics.scl.compiler.source.ModuleSource;
 import org.simantics.scl.compiler.source.StringModuleSource;
 import org.simantics.scl.compiler.source.repository.MapModuleSourceRepository;
 import org.simantics.scl.compiler.top.ValueNotFound;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.reporting.SCLReportingHandler;
+import org.simantics.scl.runtime.reporting.WriterSCLReportingHandler;
 
 public class TestBase {
     
@@ -93,16 +98,25 @@ public class TestBase {
                     return ImportDeclaration.ONLY_BUILTINS;
                 }
             };
-        ModuleRepository testEnvironment = new ModuleRepository(
+        ModuleRepository testRepository = new ModuleRepository(
                 PRELUDE_MODULE_REPOSITORY,
                 new MapModuleSourceRepository(moduleSources));
+        testRepository.setAdvisor(moduleName -> ModuleCompilationOptions.SILENT);
         int lastId = moduleNames.length-1;
-        Failable<Module> result = testEnvironment.getModule(moduleNames[lastId]);
+        Failable<Module> result = testRepository.getModule(moduleNames[lastId]);
         if(!result.didSucceed())
             return ((Failure)result).toString(moduleTexts[lastId]);
         else {
-            Object main = testEnvironment.getRuntimeModule(moduleNames[lastId]).getResult().getValue("main");
-            return String.valueOf(main);
+            SCLContext context = SCLContext.getCurrent();
+            StringWriter writer = new StringWriter();
+            Object oldReportingHandler = context.put(SCLReportingHandler.REPORTING_HANDLER, new WriterSCLReportingHandler(writer));
+            try {
+                Object main = testRepository.getRuntimeModule(moduleNames[lastId]).getResult().getValue("main");
+                writer.write(String.valueOf(main));
+                return writer.toString();
+            } finally {
+                context.put(SCLReportingHandler.REPORTING_HANDLER, oldReportingHandler);
+            }
         }
     }
 
index d305a2a83ba262fc7c6ce684bfa4d7143363b51b..c1e3402afd56c512b040f7eb7967fda016b36b93 100644 (file)
@@ -140,6 +140,11 @@ main = sort (MList.freeze answer)
     
     Edge ?x ?y => MList.add answer (?x, ?y)
 --
+Remove loop (5,5)
+Remove dangling edge (3,5)
+Remove node 5
+Simplify path (1,2,3)
+Simplify path (1,3,4)
 [(1,4), (1,4)]
 --
 import "StandardLibrary"
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR10.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR10.scl
new file mode 100644 (file)
index 0000000..758074d
--- /dev/null
@@ -0,0 +1,30 @@
+module { export = [main], chr }
+import "StandardLibrary"
+
+data V = V { x :: Double, y :: Double }
+
+main = ()
+  where
+    constraint X V 
+    X V { ?x } => print ?x
+    X V { ?y } => print ?y
+    True => X V { x = 1.0, y = 2.0 }
+    True => X V { x = 3.0, y = 4.0 }
+--
+1.0
+2.0
+3.0
+4.0
+()
+--
+module { export = [main], chr }
+import "StandardLibrary"
+
+data V = V { x :: Double, y :: Double }
+
+main = ()
+  where
+    constraint X V 
+    True => X V { x = 1.0 }
+--
+9:15-9:28: Field y not defined.
\ No newline at end of file
index 03df6896f3e84b637ed1d77e7bb33f9d72303049..1d8451439ee92b8b9d6cb680ffd92cbb67fa9ca2 100644 (file)
@@ -6,6 +6,5 @@ main = ()
     A ?x, not A (?x+1) => A (?x-1)
     True => A 0
 --
-()
-      
-
+0
+()
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR5.scl
new file mode 100644 (file)
index 0000000..c59c02d
--- /dev/null
@@ -0,0 +1,36 @@
+module { export = [main], chr }
+import "StandardLibrary"
+
+ruleset IntegerSet where
+    constraint Element Integer
+    // Set may not contain duplicates
+    Element ?x => print "added \(?x)"
+    -Element ?x, Element ?x => print "removed duplicate \(?x)"
+    
+addSet :: IntegerSet -> Integer -> <Proc> ()
+addSet set newElement = ()
+  where
+    include IntegerSet set
+    True => Element newElement
+    
+printSet :: IntegerSet -> <Proc> ()
+printSet set = ()
+  where
+    include IntegerSet set
+    Element ?x => print "printing \(?x)" 
+
+main = ()
+  where
+    set = createIntegerSet
+    addSet set 1
+    addSet set 2
+    addSet set 1
+    printSet set
+--
+added 1
+added 2
+added 1
+removed duplicate 1
+printing 2
+printing 1
+()
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR6.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR6.scl
new file mode 100644 (file)
index 0000000..f1e28d0
--- /dev/null
@@ -0,0 +1,23 @@
+module { export = [main], chr }
+import "StandardLibrary"
+
+ruleset RS where
+    constraint X Integer
+    -X ?value, X ?value => True
+    X ?value => print "A \(?value)"
+    
+main :: ()
+main = ()
+  where
+    rs = createRS
+    include RS rs
+    X ?value => print "B \(?value)"
+    True     => X 1
+    True     => X 2
+    True     => X 1
+--
+A 1
+B 1
+A 2
+B 2
+()
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR7.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR7.scl
new file mode 100644 (file)
index 0000000..b10257c
--- /dev/null
@@ -0,0 +1,16 @@
+module { export = [main], chr }
+import "StandardLibrary"
+
+ruleset RS where
+    constraint X Integer
+    True => X 3
+    
+main = ()
+  where
+    include RS createRS
+    -X ?value, ?value < 6 => print "X \(?value)", X (?value+1)
+--
+X 3
+X 4
+X 5
+()
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR8.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR8.scl
new file mode 100644 (file)
index 0000000..c3a88f5
--- /dev/null
@@ -0,0 +1,8 @@
+module { export = [main], chr }
+import "StandardLibrary"
+
+main = ()
+  where
+    X ?x => Y ?y
+--
+6:15-6:17: New existential variables can be defined only in queries.
\ No newline at end of file
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR9.scl b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/scl/CHR9.scl
new file mode 100644 (file)
index 0000000..0751482
--- /dev/null
@@ -0,0 +1,42 @@
+module { export = [main], chr }
+import "StandardLibrary"
+
+main = ()
+  where
+    constraint V { x :: Double, y :: Double } 
+    V { ?x } => print ?x
+    True => V { x = 1.0, y = 2.0 }
+--
+1.0
+()
+--
+module { export = [main], chr }
+import "StandardLibrary"
+
+main = ()
+  where
+    constraint V { x :: Double, y :: Double }
+    True => V { x = 1.0 }
+--
+7:13-7:26: Field y not defined.
+--
+module { export = [main], chr }
+
+import "StandardLibrary"
+
+main = ()
+  where
+    constraint V Double Double
+    True => V { x = 1.0, y = 2.0 }
+--
+8:13-8:35: Relation V does not define field names.
+--
+module { export = [main], chr }
+
+import "StandardLibrary"
+
+main = ()
+  where
+    True => V { x = 1.0, y = 2.0 }
+--
+7:13-7:35: Relation must be declared if record syntax is used.
\ No newline at end of file
index 10eafb0611a67377fcd775ad36e269a15a36cd64..d19263a53f60fd1212eba7e7fb730037eb6f806a 100644 (file)
@@ -128,4 +128,8 @@ main = do
     x := True
     print (evalV f)
 --
+("x" `UntilF` "y")
+false
+false
+("x" `UntilF` "y")
 ()
\ No newline at end of file
index 45ad0658afc17f8bced0682d0e1fb25262b77e0f..84e0c0b4f90dc1d04cd77a4c60e336174facb34c 100644 (file)
@@ -22,4 +22,26 @@ main = transformation OneShotForward where
     Fib 0 1
     Fib 1 1
 --
-()
+21 -> 11
+20 -> 11
+19 -> 10
+18 -> 10
+17 -> 9
+16 -> 9
+15 -> 8
+14 -> 8
+13 -> 7
+12 -> 7
+11 -> 6
+10 -> 6
+9 -> 5
+8 -> 5
+7 -> 4
+6 -> 4
+5 -> 3
+4 -> 3
+3 -> 2
+2 -> 2
+1 -> 1
+0 -> 1
+()
\ No newline at end of file
index f9b995cee1d98081588ec9f24372d0cce6d479aa..20c32335ce3316a3320a8e40b151f8031d22b2d3 100644 (file)
@@ -29,4 +29,25 @@ rule PrintIt where
 
 main = transformation OneShotForward where
 --
-()
+20 -> 10946
+19 -> 6765
+18 -> 4181
+17 -> 2584
+16 -> 1597
+15 -> 987
+14 -> 610
+13 -> 377
+12 -> 233
+11 -> 144
+10 -> 89
+9 -> 55
+8 -> 34
+7 -> 21
+6 -> 13
+5 -> 8
+4 -> 5
+3 -> 3
+2 -> 2
+1 -> 1
+0 -> 1
+()
\ No newline at end of file
index 5a889e1e0c5c1d4759a72bbdc1803c734619705e..92789e68739140e7d07147f31f809a239c881038 100644 (file)
@@ -24,4 +24,16 @@ rule Seed where
 
 main = transformation OneShotForward where
 --
-()
+11 -> 2, 1
+10 -> 1, 2
+9 -> 2, 1
+8 -> 1, 2
+7 -> 2, 1
+6 -> 1, 2
+5 -> 2, 1
+4 -> 1, 2
+3 -> 2, 1
+2 -> 1, 2
+1 -> 2, 1
+0 -> 1, 2
+()
\ No newline at end of file
index 87bd50aa25fa7beda114fb343321a98912a88b4f..2ec8ad5d6e128960f201e2b7fe65c8b86c19787d 100644 (file)
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 
 import org.junit.Assert;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.simantics.scl.compiler.compilation.CompilationContext;
 import org.simantics.scl.compiler.elaboration.chr.CHRRuleset;
@@ -12,7 +13,7 @@ import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint;
 import org.simantics.scl.compiler.elaboration.chr.relations.CHRConstraint.IndexInfo;
 import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
 import org.simantics.scl.compiler.errors.Locations;
-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.types.JavaTypeTranslator;
 import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
 import org.simantics.scl.compiler.internal.codegen.utils.ModuleBuilder;
@@ -24,6 +25,7 @@ import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.compiler.types.Types;
 
 public class TestCHRCodeGenerator {
+    @Ignore
     @Test
     public void testCodeGenerator() throws Throwable {
         try {
@@ -49,12 +51,12 @@ public class TestCHRCodeGenerator {
             exampleFact.indices.put(3, new IndexInfo(3, "bb", null, null));
             exampleFact.setMayBeRemoved();
 
-            CHRCodeGenerator.generateStore(moduleBuilder, ruleset);
+            CHRRuntimeRulesetCodeGenerator.generateRuntimeRuleset(moduleBuilder, ruleset);
             
             MutableClassLoader classLoader = environment.getMutableClassLoader();
             classLoader.addClasses(moduleBuilder.getClasses());
             
-            String storeClassName = ruleset.storeClassName.replace('/', '.');
+            String storeClassName = ruleset.runtimeRulesetClassName.replace('/', '.');
             Class<?> storeClass = classLoader.loadClass(storeClassName);
             Class<?> factClass = classLoader.loadClass(storeClassName+"$ExampleFact");
             Constructor<?> factConstructor = factClass.getConstructor(int.class, int.class, int.class);