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\