aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2023-12-25 13:57:04 +0100
committerLibravatar GitHub <noreply@github.com>2023-12-25 13:57:04 +0100
commitfa25d614455dd0872bfa6ff88c5be3ecfc33a6af (patch)
tree84aba7f8ce90ff5aea38c912b3999ec7810f6f44
parentchore: upgrade to Eclipse 2023-12 (diff)
parentrefactor(generator): scope overrides (diff)
downloadrefinery-fa25d614455dd0872bfa6ff88c5be3ecfc33a6af.tar.gz
refinery-fa25d614455dd0872bfa6ff88c5be3ecfc33a6af.tar.zst
refinery-fa25d614455dd0872bfa6ff88c5be3ecfc33a6af.zip
Merge pull request #50 from kris7t/generator-roundtrip
Round-trip model serialization and command line application
-rw-r--r--.yarnrc.yml2
-rw-r--r--gradle/libs.versions.toml3
-rw-r--r--package.json4
-rw-r--r--settings.gradle.kts1
-rw-r--r--subprojects/frontend/config/graphvizUMDVitePlugin.ts12
-rw-r--r--subprojects/frontend/package.json54
-rw-r--r--subprojects/generator-cli/build.gradle.kts24
-rw-r--r--subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/RefineryCli.java64
-rw-r--r--subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java87
-rw-r--r--subprojects/generator/build.gradle.kts1
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java30
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java7
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java2
-rw-r--r--subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java88
-rw-r--r--subprojects/generator/src/test/java/tools/refinery/generator/ProblemLoaderTest.java129
-rw-r--r--subprojects/language-model/src/main/resources/model/problem.ecore2
-rw-r--r--subprojects/language-semantics/build.gradle.kts1
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java64
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java23
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java41
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java335
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java4
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java2
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java5
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java4
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java7
-rw-r--r--subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/SolutionSerializerTest.java164
-rw-r--r--subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java10
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java8
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java18
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java6
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/serializer/ProblemCrossReferenceSerializer.java167
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java87
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java4
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java2
-rw-r--r--subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java15
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/MapBasedSeed.java8
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java2
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInfo.java4
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInitializer.java52
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceTranslator.java104
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInfo.java3
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInitializer.java84
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceTranslator.java95
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java54
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfo.java6
-rw-r--r--subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfoBuilder.java84
-rw-r--r--subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java34
-rw-r--r--subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java30
-rw-r--r--yarn.lock549
50 files changed, 2055 insertions, 531 deletions
diff --git a/.yarnrc.yml b/.yarnrc.yml
index cf12e2d9..305b9b6a 100644
--- a/.yarnrc.yml
+++ b/.yarnrc.yml
@@ -4,7 +4,7 @@ enableTelemetry: false
4 4
5logFilters: 5logFilters:
6 - level: discard 6 - level: discard
7 text: "prettier is listed by your project with version 3.1.0, which doesn't satisfy what @xstate/cli (p708d6) and other dependencies request (^2.0.0)." 7 text: "prettier is listed by your project with version 3.1.1, which doesn't satisfy what @xstate/cli (p072c3) and other dependencies request (^2.0.0)."
8 8
9nodeLinker: pnp 9nodeLinker: pnp
10 10
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 06b76786..e65ffc03 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -4,7 +4,7 @@
4 4
5[versions] 5[versions]
6eclipseCollections = "12.0.0.M3" 6eclipseCollections = "12.0.0.M3"
7jetty = "12.0.3" 7jetty = "12.0.5"
8jmh = "1.37" 8jmh = "1.37"
9junit = "5.10.1" 9junit = "5.10.1"
10mockito = "5.8.0" 10mockito = "5.8.0"
@@ -23,6 +23,7 @@ gradlePlugin-shadow = { group = "com.github.johnrengelman", name = "shadow", ver
23gradlePlugin-sonarqube = { group = "org.sonarsource.scanner.gradle", name = "sonarqube-gradle-plugin", version = "4.4.1.3373" } 23gradlePlugin-sonarqube = { group = "org.sonarsource.scanner.gradle", name = "sonarqube-gradle-plugin", version = "4.4.1.3373" }
24gson = { group = "com.google.code.gson", name = "gson", version = "2.10.1" } 24gson = { group = "com.google.code.gson", name = "gson", version = "2.10.1" }
25hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "2.2" } 25hamcrest = { group = "org.hamcrest", name = "hamcrest", version = "2.2" }
26jcommander = { group = "org.jcommander", name = "jcommander", version = "1.83" }
26jetbrainsAnnotations = { group = "org.jetbrains", name = "annotations", version = "24.1.0" } 27jetbrainsAnnotations = { group = "org.jetbrains", name = "annotations", version = "24.1.0" }
27jetty-server = { group = "org.eclipse.jetty", name = "jetty-server", version.ref = "jetty" } 28jetty-server = { group = "org.eclipse.jetty", name = "jetty-server", version.ref = "jetty" }
28jetty-servlet = { group = "org.eclipse.jetty.ee10", name = "jetty-ee10-servlet", version.ref = "jetty" } 29jetty-servlet = { group = "org.eclipse.jetty.ee10", name = "jetty-ee10-servlet", version.ref = "jetty" }
diff --git a/package.json b/package.json
index 6dbe66ad..a61c71d4 100644
--- a/package.json
+++ b/package.json
@@ -25,8 +25,8 @@
25 }, 25 },
26 "packageManager": "yarn@4.0.2", 26 "packageManager": "yarn@4.0.2",
27 "devDependencies": { 27 "devDependencies": {
28 "eslint": "^8.55.0", 28 "eslint": "^8.56.0",
29 "typescript": "5.3.2" 29 "typescript": "5.3.3"
30 }, 30 },
31 "resolutions": { 31 "resolutions": {
32 "d3-zoom@npm:^3.0.0": "patch:d3-zoom@npm%3A3.0.0#~/.yarn/patches/d3-zoom-npm-3.0.0-18f706a421.patch", 32 "d3-zoom@npm:^3.0.0": "patch:d3-zoom@npm%3A3.0.0#~/.yarn/patches/d3-zoom-npm-3.0.0-18f706a421.patch",
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 40df30ff..6e5a72e9 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -9,6 +9,7 @@ rootProject.name = "refinery"
9include( 9include(
10 "frontend", 10 "frontend",
11 "generator", 11 "generator",
12 "generator-cli",
12 "interpreter", 13 "interpreter",
13 "interpreter-localsearch", 14 "interpreter-localsearch",
14 "interpreter-rete", 15 "interpreter-rete",
diff --git a/subprojects/frontend/config/graphvizUMDVitePlugin.ts b/subprojects/frontend/config/graphvizUMDVitePlugin.ts
index ab726e4f..0c3c9aa0 100644
--- a/subprojects/frontend/config/graphvizUMDVitePlugin.ts
+++ b/subprojects/frontend/config/graphvizUMDVitePlugin.ts
@@ -27,13 +27,15 @@ export default function graphvizUMDVitePlugin(): PluginOption {
27 async buildStart() { 27 async buildStart() {
28 const issuer = 28 const issuer =
29 root === undefined ? issuerFileName : path.join(root, issuerFileName); 29 root === undefined ? issuerFileName : path.join(root, issuerFileName);
30 const resolvedPath = pnpapi.resolveRequest( 30 // Since https://github.com/hpcc-systems/hpcc-js-wasm/commit/15e1ace5edae7f94714e547a3ac20e0e17cd6b0c,
31 '@hpcc-js/wasm/graphviz', 31 // hpcc-js has both a `.cjs` and a `.umd.js` build. PnPAPI will find the former, but we need the latter.
32 issuer, 32 const resolvedPath = pnpapi
33 ); 33 .resolveRequest('@hpcc-js/wasm/graphviz', issuer)
34 if (resolvedPath === null) { 34 ?.replace(/\.cjs$/, '.umd.js');
35 if (resolvedPath === undefined) {
35 return; 36 return;
36 } 37 }
38 console.log(resolvedPath);
37 if (command === 'serve') { 39 if (command === 'serve') {
38 url = `/@fs/${resolvedPath}`; 40 url = `/@fs/${resolvedPath}`;
39 } else { 41 } else {
diff --git a/subprojects/frontend/package.json b/subprojects/frontend/package.json
index f55093ce..9dec8b32 100644
--- a/subprojects/frontend/package.json
+++ b/subprojects/frontend/package.json
@@ -33,23 +33,23 @@
33 "@codemirror/language": "^6.9.3", 33 "@codemirror/language": "^6.9.3",
34 "@codemirror/lint": "^6.4.2", 34 "@codemirror/lint": "^6.4.2",
35 "@codemirror/search": "^6.5.5", 35 "@codemirror/search": "^6.5.5",
36 "@codemirror/state": "^6.3.2", 36 "@codemirror/state": "^6.3.3",
37 "@codemirror/view": "^6.22.1", 37 "@codemirror/view": "^6.22.3",
38 "@emotion/react": "^11.11.1", 38 "@emotion/react": "^11.11.3",
39 "@emotion/styled": "^11.11.0", 39 "@emotion/styled": "^11.11.0",
40 "@fontsource-variable/jetbrains-mono": "^5.0.18", 40 "@fontsource-variable/jetbrains-mono": "^5.0.19",
41 "@fontsource-variable/open-sans": "^5.0.18", 41 "@fontsource-variable/open-sans": "^5.0.21",
42 "@hpcc-js/wasm": "^2.15.0", 42 "@hpcc-js/wasm": "^2.15.3",
43 "@lezer/common": "^1.1.1", 43 "@lezer/common": "^1.1.2",
44 "@lezer/highlight": "^1.2.0", 44 "@lezer/highlight": "^1.2.0",
45 "@lezer/lr": "^1.3.14", 45 "@lezer/lr": "^1.3.14",
46 "@material-icons/svg": "^1.0.33", 46 "@material-icons/svg": "^1.0.33",
47 "@mui/icons-material": "5.14.19", 47 "@mui/icons-material": "^5.15.1",
48 "@mui/material": "5.14.19", 48 "@mui/material": "^5.15.1",
49 "@mui/system": "^5.14.19", 49 "@mui/system": "^5.15.1",
50 "@mui/x-data-grid": "^6.18.2", 50 "@mui/x-data-grid": "^6.18.6",
51 "ansi-styles": "^6.2.1", 51 "ansi-styles": "^6.2.1",
52 "csstype": "^3.1.2", 52 "csstype": "^3.1.3",
53 "d3": "^7.8.5", 53 "d3": "^7.8.5",
54 "d3-graphviz": "patch:d3-graphviz@npm%3A5.2.0#~/.yarn/patches/d3-graphviz-npm-5.2.0-161b1fbad4.patch", 54 "d3-graphviz": "patch:d3-graphviz@npm%3A5.2.0#~/.yarn/patches/d3-graphviz-npm-5.2.0-161b1fbad4.patch",
55 "d3-selection": "^3.0.0", 55 "d3-selection": "^3.0.0",
@@ -65,7 +65,7 @@
65 "notistack": "^3.0.1", 65 "notistack": "^3.0.1",
66 "react": "^18.2.0", 66 "react": "^18.2.0",
67 "react-dom": "^18.2.0", 67 "react-dom": "^18.2.0",
68 "react-resize-detector": "^9.1.0", 68 "react-resize-detector": "^9.1.1",
69 "xstate": "^4.38.3", 69 "xstate": "^4.38.3",
70 "zod": "^3.22.4" 70 "zod": "^3.22.4"
71 }, 71 },
@@ -75,38 +75,38 @@
75 "@types/d3-graphviz": "^2.6.10", 75 "@types/d3-graphviz": "^2.6.10",
76 "@types/d3-selection": "^3.0.10", 76 "@types/d3-selection": "^3.0.10",
77 "@types/d3-zoom": "^3.0.8", 77 "@types/d3-zoom": "^3.0.8",
78 "@types/eslint": "^8.44.8", 78 "@types/eslint": "^8.56.0",
79 "@types/html-minifier-terser": "^7.0.2", 79 "@types/html-minifier-terser": "^7.0.2",
80 "@types/lodash-es": "^4.17.12", 80 "@types/lodash-es": "^4.17.12",
81 "@types/micromatch": "^4.0.6", 81 "@types/micromatch": "^4.0.6",
82 "@types/ms": "^0.7.34", 82 "@types/ms": "^0.7.34",
83 "@types/node": "^20.10.2", 83 "@types/node": "^20.10.5",
84 "@types/pnpapi": "^0.0.5", 84 "@types/pnpapi": "^0.0.5",
85 "@types/react": "^18.2.41", 85 "@types/react": "^18.2.45",
86 "@types/react-dom": "^18.2.17", 86 "@types/react-dom": "^18.2.18",
87 "@typescript-eslint/eslint-plugin": "^6.13.1", 87 "@typescript-eslint/eslint-plugin": "^6.15.0",
88 "@typescript-eslint/parser": "^6.13.1", 88 "@typescript-eslint/parser": "^6.15.0",
89 "@vitejs/plugin-react-swc": "^3.5.0", 89 "@vitejs/plugin-react-swc": "^3.5.0",
90 "@xstate/cli": "^0.5.11", 90 "@xstate/cli": "^0.5.15",
91 "cross-env": "^7.0.3", 91 "cross-env": "^7.0.3",
92 "eslint": "^8.55.0", 92 "eslint": "^8.56.0",
93 "eslint-config-airbnb": "^19.0.4", 93 "eslint-config-airbnb": "^19.0.4",
94 "eslint-config-airbnb-typescript": "^17.1.0", 94 "eslint-config-airbnb-typescript": "^17.1.0",
95 "eslint-config-prettier": "^9.1.0", 95 "eslint-config-prettier": "^9.1.0",
96 "eslint-import-resolver-typescript": "^3.6.1", 96 "eslint-import-resolver-typescript": "^3.6.1",
97 "eslint-plugin-import": "^2.29.0", 97 "eslint-plugin-import": "^2.29.1",
98 "eslint-plugin-jsx-a11y": "^6.8.0", 98 "eslint-plugin-jsx-a11y": "^6.8.0",
99 "eslint-plugin-mobx": "^0.0.9", 99 "eslint-plugin-mobx": "^0.0.9",
100 "eslint-plugin-prettier": "^5.0.1", 100 "eslint-plugin-prettier": "^5.1.1",
101 "eslint-plugin-react": "^7.33.2", 101 "eslint-plugin-react": "^7.33.2",
102 "eslint-plugin-react-hooks": "^4.6.0", 102 "eslint-plugin-react-hooks": "^4.6.0",
103 "html-minifier-terser": "^7.2.0", 103 "html-minifier-terser": "^7.2.0",
104 "micromatch": "^4.0.5", 104 "micromatch": "^4.0.5",
105 "pnpapi": "^0.0.0", 105 "pnpapi": "^0.0.0",
106 "prettier": "^3.1.0", 106 "prettier": "^3.1.1",
107 "typescript": "5.3.2", 107 "typescript": "5.3.3",
108 "vite": "^5.0.4", 108 "vite": "^5.0.10",
109 "vite-plugin-pwa": "^0.17.2", 109 "vite-plugin-pwa": "^0.17.4",
110 "workbox-window": "^7.0.0" 110 "workbox-window": "^7.0.0"
111 } 111 }
112} 112}
diff --git a/subprojects/generator-cli/build.gradle.kts b/subprojects/generator-cli/build.gradle.kts
new file mode 100644
index 00000000..6c681222
--- /dev/null
+++ b/subprojects/generator-cli/build.gradle.kts
@@ -0,0 +1,24 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6
7plugins {
8 id("tools.refinery.gradle.java-application")
9}
10
11dependencies {
12 implementation(project(":refinery-generator"))
13 implementation(libs.jcommander)
14 implementation(libs.slf4j.api)
15}
16
17application {
18 mainClass.set("tools.refinery.generator.cli.RefineryCli")
19}
20
21tasks.shadowJar {
22 // Silence Xtext warning.
23 append("plugin.properties")
24}
diff --git a/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/RefineryCli.java b/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/RefineryCli.java
new file mode 100644
index 00000000..5de579e6
--- /dev/null
+++ b/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/RefineryCli.java
@@ -0,0 +1,64 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator.cli;
7
8import com.beust.jcommander.JCommander;
9import com.beust.jcommander.ParameterException;
10import com.google.inject.Inject;
11import tools.refinery.generator.cli.commands.GenerateCommand;
12import tools.refinery.generator.standalone.StandaloneRefinery;
13
14import java.io.IOException;
15
16public class RefineryCli {
17 private static final String GENERATE_COMMAND = "generate";
18
19 @Inject
20 private GenerateCommand generateCommand;
21
22 private JCommander jCommander;
23
24 public String parseArguments(String... args) {
25 var jc = getJCommander();
26 jc.parse(args);
27 return jc.getParsedCommand();
28 }
29
30 public void run(String command) throws IOException {
31 switch (command) {
32 case GENERATE_COMMAND -> generateCommand.run();
33 case null, default -> showUsageAndExit();
34 }
35 }
36
37 public void showUsageAndExit() {
38 getJCommander().usage();
39 System.exit(1);
40 }
41
42 private JCommander getJCommander() {
43 if (jCommander == null) {
44 jCommander = JCommander.newBuilder()
45 .programName("refinery")
46 .addObject(this)
47 .addCommand(GENERATE_COMMAND, generateCommand)
48 .build();
49 }
50 return jCommander;
51 }
52
53 public static void main(String[] args) throws IOException {
54 var cli = StandaloneRefinery.getInjector().getInstance(RefineryCli.class);
55 String command = null;
56 try {
57 command = cli.parseArguments(args);
58 } catch (ParameterException e) {
59 System.err.println(e.getMessage());
60 cli.showUsageAndExit();
61 }
62 cli.run(command);
63 }
64}
diff --git a/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java b/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java
new file mode 100644
index 00000000..b33fce23
--- /dev/null
+++ b/subprojects/generator-cli/src/main/java/tools/refinery/generator/cli/commands/GenerateCommand.java
@@ -0,0 +1,87 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator.cli.commands;
7
8import com.beust.jcommander.Parameter;
9import com.beust.jcommander.Parameters;
10import com.google.inject.Inject;
11import org.eclipse.emf.ecore.resource.Resource;
12import tools.refinery.generator.ModelGeneratorFactory;
13import tools.refinery.generator.ProblemLoader;
14
15import java.io.FileOutputStream;
16import java.io.IOException;
17import java.util.ArrayList;
18import java.util.List;
19import java.util.Map;
20
21@Parameters(commandDescription = "Generate a model from a partial model")
22public class GenerateCommand {
23 @Inject
24 private ProblemLoader loader;
25
26 @Inject
27 private ModelGeneratorFactory generatorFactory;
28
29 private String inputPath;
30 private String outputPath = "-";
31 private List<String> scopes = new ArrayList<>();
32 private List<String> overrideScopes = new ArrayList<>();
33 private long randomSeed = 1;
34
35 @Parameter(description = "input path", required = true)
36 public void setInputPath(String inputPath) {
37 this.inputPath = inputPath;
38 }
39
40 @Parameter(names = {"-output", "-o"}, description = "Output path")
41 public void setOutputPath(String outputPath) {
42 this.outputPath = outputPath;
43 }
44
45 @Parameter(names = {"-scope", "-s"}, description = "Extra scope constraints")
46 public void setScopes(List<String> scopes) {
47 this.scopes = scopes;
48 }
49
50 @Parameter(names = {"-scope-override", "-S"}, description = "Override scope constraints")
51 public void setOverrideScopes(List<String> overrideScopes) {
52 this.overrideScopes = overrideScopes;
53 }
54
55 @Parameter(names = {"-random-seed", "-r"}, description = "Random seed")
56 public void setRandomSeed(long randomSeed) {
57 this.randomSeed = randomSeed;
58 }
59
60 public void run() throws IOException {
61 var problem = isStandardStream(inputPath) ? loader.loadStream(System.in) : loader.loadFile(inputPath);
62 problem = loader.loadScopeConstraints(problem, scopes, overrideScopes);
63 var generator = generatorFactory.createGenerator(problem);
64 generator.setRandomSeed(randomSeed);
65 generator.generate();
66 var solution = generator.serializeSolution();
67 var solutionResource = solution.eResource();
68 var saveOptions = Map.of();
69 if (isStandardStream(outputPath)) {
70 printSolution(solutionResource, saveOptions);
71 } else {
72 try (var outputStream = new FileOutputStream(outputPath)) {
73 solutionResource.save(outputStream, saveOptions);
74 }
75 }
76 }
77
78 private boolean isStandardStream(String path) {
79 return path == null || path.equals("-");
80 }
81
82 // We deliberately write to the standard output if no output path is specified.
83 @SuppressWarnings("squid:S106")
84 private void printSolution(Resource solutionResource, Map<?, ?> saveOptions) throws IOException {
85 solutionResource.save(System.out, saveOptions);
86 }
87}
diff --git a/subprojects/generator/build.gradle.kts b/subprojects/generator/build.gradle.kts
index d87ce6de..f78fee4d 100644
--- a/subprojects/generator/build.gradle.kts
+++ b/subprojects/generator/build.gradle.kts
@@ -12,4 +12,5 @@ dependencies {
12 api(project(":refinery-language-semantics")) 12 api(project(":refinery-language-semantics"))
13 api(libs.eclipseCollections.api) 13 api(libs.eclipseCollections.api)
14 implementation(project(":refinery-store-query-interpreter")) 14 implementation(project(":refinery-store-query-interpreter"))
15 testImplementation(testFixtures(project(":refinery-language")))
15} 16}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
index 5b44c10a..1515dceb 100644
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java
@@ -5,7 +5,10 @@
5 */ 5 */
6package tools.refinery.generator; 6package tools.refinery.generator;
7 7
8import com.google.inject.Provider;
9import tools.refinery.language.model.problem.Problem;
8import tools.refinery.language.semantics.ProblemTrace; 10import tools.refinery.language.semantics.ProblemTrace;
11import tools.refinery.language.semantics.SolutionSerializer;
9import tools.refinery.store.dse.strategy.BestFirstStoreManager; 12import tools.refinery.store.dse.strategy.BestFirstStoreManager;
10import tools.refinery.store.map.Version; 13import tools.refinery.store.map.Version;
11import tools.refinery.store.model.ModelStore; 14import tools.refinery.store.model.ModelStore;
@@ -16,21 +19,22 @@ import tools.refinery.store.reasoning.seed.ModelSeed;
16 19
17public class ModelGenerator extends ModelFacade { 20public class ModelGenerator extends ModelFacade {
18 private final Version initialVersion; 21 private final Version initialVersion;
19 22 private final Provider<SolutionSerializer> solutionSerializerProvider;
20 private int randomSeed = 0; 23 private long randomSeed = 1;
21
22 private boolean lastGenerationSuccessful; 24 private boolean lastGenerationSuccessful;
23 25
24 public ModelGenerator(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) { 26 ModelGenerator(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed,
27 Provider<SolutionSerializer> solutionSerializerProvider) {
25 super(problemTrace, store, modelSeed, Concreteness.CANDIDATE); 28 super(problemTrace, store, modelSeed, Concreteness.CANDIDATE);
29 this.solutionSerializerProvider = solutionSerializerProvider;
26 initialVersion = getModel().commit(); 30 initialVersion = getModel().commit();
27 } 31 }
28 32
29 public int getRandomSeed() { 33 public long getRandomSeed() {
30 return randomSeed; 34 return randomSeed;
31 } 35 }
32 36
33 public void setRandomSeed(int randomSeed) { 37 public void setRandomSeed(long randomSeed) {
34 this.randomSeed = randomSeed; 38 this.randomSeed = randomSeed;
35 this.lastGenerationSuccessful = false; 39 this.lastGenerationSuccessful = false;
36 } 40 }
@@ -50,7 +54,7 @@ public class ModelGenerator extends ModelFacade {
50 if (solutions.isEmpty()) { 54 if (solutions.isEmpty()) {
51 return false; 55 return false;
52 } 56 }
53 getModel().restore(solutions.get(0).version()); 57 getModel().restore(solutions.getFirst().version());
54 lastGenerationSuccessful = true; 58 lastGenerationSuccessful = true;
55 return true; 59 return true;
56 } 60 }
@@ -63,9 +67,19 @@ public class ModelGenerator extends ModelFacade {
63 67
64 @Override 68 @Override
65 public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) { 69 public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) {
70 checkSuccessfulGeneration();
71 return super.getPartialInterpretation(partialSymbol);
72 }
73
74 public Problem serializeSolution() {
75 checkSuccessfulGeneration();
76 var serializer = solutionSerializerProvider.get();
77 return serializer.serializeSolution(getProblemTrace(), getModel());
78 }
79
80 private void checkSuccessfulGeneration() {
66 if (!lastGenerationSuccessful) { 81 if (!lastGenerationSuccessful) {
67 throw new IllegalStateException("No generated model is available"); 82 throw new IllegalStateException("No generated model is available");
68 } 83 }
69 return super.getPartialInterpretation(partialSymbol);
70 } 84 }
71} 85}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java
index 6642d591..587601f2 100644
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java
@@ -9,6 +9,7 @@ import com.google.inject.Inject;
9import com.google.inject.Provider; 9import com.google.inject.Provider;
10import tools.refinery.language.model.problem.Problem; 10import tools.refinery.language.model.problem.Problem;
11import tools.refinery.language.semantics.ModelInitializer; 11import tools.refinery.language.semantics.ModelInitializer;
12import tools.refinery.language.semantics.SolutionSerializer;
12import tools.refinery.store.dse.propagation.PropagationAdapter; 13import tools.refinery.store.dse.propagation.PropagationAdapter;
13import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; 14import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter;
14import tools.refinery.store.model.ModelStore; 15import tools.refinery.store.model.ModelStore;
@@ -25,6 +26,9 @@ public final class ModelGeneratorFactory {
25 @Inject 26 @Inject
26 private Provider<ModelInitializer> initializerProvider; 27 private Provider<ModelInitializer> initializerProvider;
27 28
29 @Inject
30 private Provider<SolutionSerializer> solutionSerializerProvider;
31
28 private CancellationToken cancellationToken = CancellationToken.NONE; 32 private CancellationToken cancellationToken = CancellationToken.NONE;
29 33
30 private boolean debugPartialInterpretations; 34 private boolean debugPartialInterpretations;
@@ -53,7 +57,8 @@ public final class ModelGeneratorFactory {
53 .requiredInterpretations(getRequiredInterpretations())); 57 .requiredInterpretations(getRequiredInterpretations()));
54 initializer.configureStoreBuilder(storeBuilder); 58 initializer.configureStoreBuilder(storeBuilder);
55 var store = storeBuilder.build(); 59 var store = storeBuilder.build();
56 return new ModelGenerator(initializer.getProblemTrace(), store, initializer.getModelSeed()); 60 return new ModelGenerator(initializer.getProblemTrace(), store, initializer.getModelSeed(),
61 solutionSerializerProvider);
57 } 62 }
58 63
59 private Collection<Concreteness> getRequiredInterpretations() { 64 private Collection<Concreteness> getRequiredInterpretations() {
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java
index bc02c887..7207a509 100644
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java
@@ -11,7 +11,7 @@ import tools.refinery.store.reasoning.literal.Concreteness;
11import tools.refinery.store.reasoning.seed.ModelSeed; 11import tools.refinery.store.reasoning.seed.ModelSeed;
12 12
13public class ModelSemantics extends ModelFacade { 13public class ModelSemantics extends ModelFacade {
14 public ModelSemantics(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) { 14 ModelSemantics(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) {
15 super(problemTrace, store, modelSeed, Concreteness.PARTIAL); 15 super(problemTrace, store, modelSeed, Concreteness.PARTIAL);
16 } 16 }
17} 17}
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java
index 29f80714..20ea8132 100644
--- a/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java
+++ b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java
@@ -10,20 +10,30 @@ import com.google.inject.Provider;
10import org.eclipse.emf.common.util.URI; 10import org.eclipse.emf.common.util.URI;
11import org.eclipse.emf.ecore.resource.Resource; 11import org.eclipse.emf.ecore.resource.Resource;
12import org.eclipse.xtext.diagnostics.Severity; 12import org.eclipse.xtext.diagnostics.Severity;
13import org.eclipse.xtext.resource.FileExtensionProvider;
13import org.eclipse.xtext.resource.IResourceFactory; 14import org.eclipse.xtext.resource.IResourceFactory;
14import org.eclipse.xtext.resource.XtextResourceSet; 15import org.eclipse.xtext.resource.XtextResourceSet;
15import org.eclipse.xtext.util.LazyStringInputStream; 16import org.eclipse.xtext.util.LazyStringInputStream;
16import org.eclipse.xtext.validation.CheckMode; 17import org.eclipse.xtext.validation.CheckMode;
17import org.eclipse.xtext.validation.IResourceValidator; 18import org.eclipse.xtext.validation.IResourceValidator;
18import tools.refinery.language.model.problem.Problem; 19import tools.refinery.language.model.problem.Problem;
20import tools.refinery.language.model.problem.Relation;
21import tools.refinery.language.model.problem.ScopeDeclaration;
19import tools.refinery.store.util.CancellationToken; 22import tools.refinery.store.util.CancellationToken;
20 23
24import java.io.ByteArrayOutputStream;
21import java.io.File; 25import java.io.File;
22import java.io.IOException; 26import java.io.IOException;
23import java.io.InputStream; 27import java.io.InputStream;
28import java.nio.charset.StandardCharsets;
29import java.util.ArrayList;
30import java.util.HashSet;
31import java.util.List;
24import java.util.Map; 32import java.util.Map;
25 33
26public class ProblemLoader { 34public class ProblemLoader {
35 private String fileExtension;
36
27 @Inject 37 @Inject
28 private Provider<XtextResourceSet> resourceSetProvider; 38 private Provider<XtextResourceSet> resourceSetProvider;
29 39
@@ -35,25 +45,39 @@ public class ProblemLoader {
35 45
36 private CancellationToken cancellationToken = CancellationToken.NONE; 46 private CancellationToken cancellationToken = CancellationToken.NONE;
37 47
48 @Inject
49 public void setFileExtensionProvider(FileExtensionProvider fileExtensionProvider) {
50 this.fileExtension = fileExtensionProvider.getPrimaryFileExtension();
51 }
52
38 public ProblemLoader cancellationToken(CancellationToken cancellationToken) { 53 public ProblemLoader cancellationToken(CancellationToken cancellationToken) {
39 this.cancellationToken = cancellationToken; 54 this.cancellationToken = cancellationToken;
40 return this; 55 return this;
41 } 56 }
42 57
43 public Problem loadString(String problemString) throws IOException { 58 public Problem loadString(String problemString, URI uri) throws IOException {
44 try (var stream = new LazyStringInputStream(problemString)) { 59 try (var stream = new LazyStringInputStream(problemString)) {
45 return loadStream(stream); 60 return loadStream(stream, uri);
46 } 61 }
47 } 62 }
48 63
49 public Problem loadStream(InputStream inputStream) throws IOException { 64 public Problem loadString(String problemString) throws IOException {
65 return loadString(problemString, null);
66 }
67
68 public Problem loadStream(InputStream inputStream, URI uri) throws IOException {
50 var resourceSet = resourceSetProvider.get(); 69 var resourceSet = resourceSetProvider.get();
51 var resource = resourceFactory.createResource(URI.createFileURI("__synthetic.problem")); 70 var resourceUri = uri == null ? URI.createFileURI("__synthetic." + fileExtension) : uri;
71 var resource = resourceFactory.createResource(resourceUri);
52 resourceSet.getResources().add(resource); 72 resourceSet.getResources().add(resource);
53 resource.load(inputStream, Map.of()); 73 resource.load(inputStream, Map.of());
54 return loadResource(resource); 74 return loadResource(resource);
55 } 75 }
56 76
77 public Problem loadStream(InputStream inputStream) throws IOException {
78 return loadStream(inputStream, null);
79 }
80
57 public Problem loadFile(File file) throws IOException { 81 public Problem loadFile(File file) throws IOException {
58 return loadFile(file.getAbsolutePath()); 82 return loadFile(file.getAbsolutePath());
59 } 83 }
@@ -82,9 +106,63 @@ public class ProblemLoader {
82 if (!errors.isEmpty()) { 106 if (!errors.isEmpty()) {
83 throw new ValidationErrorsException(resource.getURI(), errors); 107 throw new ValidationErrorsException(resource.getURI(), errors);
84 } 108 }
85 if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof Problem problem)) { 109 if (resource.getContents().isEmpty() || !(resource.getContents().getFirst() instanceof Problem problem)) {
86 throw new IllegalArgumentException("Model generation problem not found in resource " + resource.getURI()); 110 throw new IllegalArgumentException("Model generation problem not found in resource " + resource.getURI());
87 } 111 }
88 return problem; 112 return problem;
89 } 113 }
114
115 public Problem loadScopeConstraints(Problem problem, List<String> extraScopes,
116 List<String> overrideScopes) throws IOException {
117 var allScopes = new ArrayList<>(extraScopes);
118 allScopes.addAll(overrideScopes);
119 if (allScopes.isEmpty()) {
120 return problem;
121 }
122 int originalStatementCount = problem.getStatements().size();
123 var builder = new StringBuilder();
124 var problemResource = problem.eResource();
125 try (var outputStream = new ByteArrayOutputStream()) {
126 problemResource.save(outputStream, Map.of());
127 builder.append(outputStream.toString(StandardCharsets.UTF_8));
128 }
129 builder.append('\n');
130 for (var scope : allScopes) {
131 builder.append("scope ").append(scope).append(".\n");
132 }
133 var modifiedProblem = loadString(builder.toString(), problemResource.getURI());
134 var modifiedStatements = modifiedProblem.getStatements();
135 int modifiedStatementCount = modifiedStatements.size();
136 if (modifiedStatementCount != originalStatementCount + allScopes.size()) {
137 throw new IllegalArgumentException("Failed to parse scope constraints");
138 }
139 // Override scopes remove any scope constraint from the original problem with the same target type.
140 var overriddenScopes = new HashSet<Relation>();
141 for (int i = modifiedStatementCount - overrideScopes.size(); i < modifiedStatementCount; i++) {
142 var statement = modifiedStatements.get(i);
143 if (!(statement instanceof ScopeDeclaration scopeDeclaration)) {
144 throw new IllegalStateException("Invalid scope constraint: " + statement);
145 }
146 for (var typeScope : scopeDeclaration.getTypeScopes()) {
147 overriddenScopes.add(typeScope.getTargetType());
148 }
149 }
150 int statementIndex = 0;
151 var iterator = modifiedStatements.iterator();
152 // Scope overrides only affect type scopes from the original problem and leave type scopes added on the
153 // command line intact.
154 while (statementIndex < originalStatementCount && iterator.hasNext()) {
155 var statement = iterator.next();
156 if (statement instanceof ScopeDeclaration scopeDeclaration) {
157 var typeScopes = scopeDeclaration.getTypeScopes();
158 typeScopes.removeIf(typeScope -> overriddenScopes.contains(typeScope.getTargetType()));
159 // Scope declarations with no type scopes are invalid, so we have to remove them.
160 if (typeScopes.isEmpty()) {
161 iterator.remove();
162 }
163 }
164 statementIndex++;
165 }
166 return modifiedProblem;
167 }
90} 168}
diff --git a/subprojects/generator/src/test/java/tools/refinery/generator/ProblemLoaderTest.java b/subprojects/generator/src/test/java/tools/refinery/generator/ProblemLoaderTest.java
new file mode 100644
index 00000000..0c0db105
--- /dev/null
+++ b/subprojects/generator/src/test/java/tools/refinery/generator/ProblemLoaderTest.java
@@ -0,0 +1,129 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.generator;
7
8
9import com.google.inject.Inject;
10import org.eclipse.xtext.testing.InjectWith;
11import org.eclipse.xtext.testing.extensions.InjectionExtension;
12import org.junit.jupiter.api.extension.ExtendWith;
13import org.junit.jupiter.params.ParameterizedTest;
14import org.junit.jupiter.params.provider.Arguments;
15import org.junit.jupiter.params.provider.MethodSource;
16import tools.refinery.language.tests.ProblemInjectorProvider;
17
18import java.io.ByteArrayOutputStream;
19import java.io.IOException;
20import java.nio.charset.StandardCharsets;
21import java.util.List;
22import java.util.Map;
23import java.util.stream.Stream;
24
25import static org.hamcrest.MatcherAssert.assertThat;
26import static org.hamcrest.Matchers.is;
27
28@ExtendWith(InjectionExtension.class)
29@InjectWith(ProblemInjectorProvider.class)
30class ProblemLoaderTest {
31 private static final String PREFIX = """
32 class Foo.
33 class Bar.
34 """;
35
36 @Inject
37 private ProblemLoader loader;
38
39 @ParameterizedTest
40 @MethodSource
41 void loadScopeConstraintsTest(String originalScopes, List<String> scopes, List<String> overrideScopes,
42 String expectedScopes) throws IOException {
43 var problem = loader.loadString(PREFIX + originalScopes);
44 var modifiedProblem = loader.loadScopeConstraints(problem, scopes, overrideScopes);
45 String serializedProblem;
46 try (var outputStream = new ByteArrayOutputStream()) {
47 modifiedProblem.eResource().save(outputStream, Map.of());
48 serializedProblem = outputStream.toString(StandardCharsets.UTF_8);
49 }
50 assertThat(serializedProblem, is(PREFIX + expectedScopes));
51 }
52
53 static Stream<Arguments> loadScopeConstraintsTest() {
54 return Stream.of(Arguments.of("",
55 List.of(),
56 List.of(),
57 ""), Arguments.of("",
58 List.of("node=5..10"),
59 List.of(), """
60
61 scope node=5..10.
62 """), Arguments.of("",
63 List.of("Foo=2", "Bar=3"),
64 List.of(), """
65
66 scope Foo=2.
67 scope Bar=3.
68 """), Arguments.of("""
69 scope Foo = 1, Bar = 1.
70 """,
71 List.of("node=5..10"),
72 List.of(), """
73 scope Foo = 1, Bar = 1.
74
75 scope node=5..10.
76 """), Arguments.of("""
77 scope Foo = 0..10, Bar = 1.
78 """,
79 List.of("Foo = 5"),
80 List.of(), """
81 scope Foo = 0..10, Bar = 1.
82
83 scope Foo = 5.
84 """), Arguments.of("""
85 scope Foo = 1, Bar = 1.
86 """,
87 List.of(),
88 List.of("node=5..10"), """
89 scope Foo = 1, Bar = 1.
90
91 scope node=5..10.
92 """), Arguments.of("""
93 scope Foo = 1, Bar = 1.
94 """,
95 List.of(),
96 List.of("Foo=3..4"), """
97 scope Bar = 1.
98
99 scope Foo=3..4.
100 """), Arguments.of("""
101 scope Foo = 1, Bar = 1.
102 """,
103 List.of("Foo=2"),
104 List.of("Foo=3..4"), """
105 scope Bar = 1.
106
107 scope Foo=2.
108 scope Foo=3..4.
109 """), Arguments.of("""
110 scope Foo = 1.
111 scope Bar = 1.
112 """,
113 List.of(),
114 List.of("Bar=3..4"), """
115 scope Foo = 1.
116
117
118 scope Bar=3..4.
119 """), Arguments.of("""
120 scope Foo = 1, Bar = 1.
121 """,
122 List.of(),
123 List.of("Foo=3..4", "Bar=4..5"), """
124
125 scope Foo=3..4.
126 scope Bar=4..5.
127 """));
128 }
129}
diff --git a/subprojects/language-model/src/main/resources/model/problem.ecore b/subprojects/language-model/src/main/resources/model/problem.ecore
index 204f922c..74229a89 100644
--- a/subprojects/language-model/src/main/resources/model/problem.ecore
+++ b/subprojects/language-model/src/main/resources/model/problem.ecore
@@ -23,7 +23,7 @@
23 <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" eType="#//ReferenceKind"/> 23 <eStructuralFeatures xsi:type="ecore:EAttribute" name="kind" eType="#//ReferenceKind"/>
24 <eStructuralFeatures xsi:type="ecore:EReference" name="referenceType" eType="#//Relation"/> 24 <eStructuralFeatures xsi:type="ecore:EReference" name="referenceType" eType="#//Relation"/>
25 <eStructuralFeatures xsi:type="ecore:EReference" name="invalidMultiplicity" eType="#//Relation" 25 <eStructuralFeatures xsi:type="ecore:EReference" name="invalidMultiplicity" eType="#//Relation"
26 containment="true"/> 26 transient="true" containment="true"/>
27 </eClassifiers> 27 </eClassifiers>
28 <eClassifiers xsi:type="ecore:EClass" name="NamedElement" abstract="true"> 28 <eClassifiers xsi:type="ecore:EClass" name="NamedElement" abstract="true">
29 <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> 29 <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
diff --git a/subprojects/language-semantics/build.gradle.kts b/subprojects/language-semantics/build.gradle.kts
index 689f621e..777ef993 100644
--- a/subprojects/language-semantics/build.gradle.kts
+++ b/subprojects/language-semantics/build.gradle.kts
@@ -16,6 +16,7 @@ dependencies {
16 api(project(":refinery-store-reasoning")) 16 api(project(":refinery-store-reasoning"))
17 implementation(project(":refinery-store-reasoning-scope")) 17 implementation(project(":refinery-store-reasoning-scope"))
18 runtimeOnly(libs.eclipseCollections) 18 runtimeOnly(libs.eclipseCollections)
19 testImplementation(project(":refinery-generator"))
19 testImplementation(project(":refinery-store-dse-visualization")) 20 testImplementation(project(":refinery-store-dse-visualization"))
20 testImplementation(project(":refinery-store-query-interpreter")) 21 testImplementation(project(":refinery-store-query-interpreter"))
21 testImplementation(testFixtures(project(":refinery-language"))) 22 testImplementation(testFixtures(project(":refinery-language")))
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
index ecaa7e0d..38bf5a61 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
@@ -27,9 +27,7 @@ import tools.refinery.store.reasoning.seed.ModelSeed;
27import tools.refinery.store.reasoning.seed.Seed; 27import tools.refinery.store.reasoning.seed.Seed;
28import tools.refinery.store.reasoning.translator.TranslationException; 28import tools.refinery.store.reasoning.translator.TranslationException;
29import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; 29import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator;
30import tools.refinery.store.reasoning.translator.metamodel.Metamodel; 30import tools.refinery.store.reasoning.translator.metamodel.*;
31import tools.refinery.store.reasoning.translator.metamodel.MetamodelBuilder;
32import tools.refinery.store.reasoning.translator.metamodel.MetamodelTranslator;
33import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; 31import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator;
34import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity; 32import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity;
35import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; 33import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity;
@@ -73,6 +71,10 @@ public class ModelInitializer {
73 71
74 private ScopePropagator scopePropagator; 72 private ScopePropagator scopePropagator;
75 73
74 private int nodeCount;
75
76 private ModelSeed.Builder modelSeedBuilder;
77
76 private ModelSeed modelSeed; 78 private ModelSeed modelSeed;
77 79
78 public void readProblem(Problem problem) { 80 public void readProblem(Problem problem) {
@@ -101,13 +103,17 @@ public class ModelInitializer {
101 TruthValue.FALSE)); 103 TruthValue.FALSE));
102 collectNodes(); 104 collectNodes();
103 collectPartialSymbols(); 105 collectPartialSymbols();
106 nodeCount = problemTrace.getNodeTrace().size();
107 modelSeedBuilder = ModelSeed.builder(nodeCount);
108 collectAssertions();
104 collectMetamodel(); 109 collectMetamodel();
105 metamodel = metamodelBuilder.build(); 110 metamodel = metamodelBuilder.build();
106 problemTrace.setMetamodel(metamodel); 111 problemTrace.setMetamodel(metamodel);
107 collectAssertions(); 112 fixClassDeclarationAssertions();
108 int nodeCount = problemTrace.getNodeTrace().size();
109 var modelSeedBuilder = ModelSeed.builder(nodeCount);
110 for (var entry : relationInfoMap.entrySet()) { 113 for (var entry : relationInfoMap.entrySet()) {
114 if (entry.getKey() instanceof ReferenceDeclaration) {
115 continue;
116 }
111 var info = entry.getValue(); 117 var info = entry.getValue();
112 var partialRelation = info.partialRelation(); 118 var partialRelation = info.partialRelation();
113 modelSeedBuilder.seed(partialRelation, info.toSeed(nodeCount)); 119 modelSeedBuilder.seed(partialRelation, info.toSeed(nodeCount));
@@ -296,7 +302,20 @@ public class ModelInitializer {
296 } 302 }
297 var multiplicity = getMultiplicityConstraint(referenceDeclaration); 303 var multiplicity = getMultiplicityConstraint(referenceDeclaration);
298 try { 304 try {
299 metamodelBuilder.reference(relation, source, containment, multiplicity, target, oppositeRelation); 305 var seed = relationInfoMap.get(referenceDeclaration).toSeed(nodeCount);
306 var defaultValue = seed.majorityValue();
307 if (defaultValue.must()) {
308 defaultValue = TruthValue.FALSE;
309 }
310 modelSeedBuilder.seed(relation, seed);
311 metamodelBuilder.reference(relation, ReferenceInfo.builder()
312 .containment(containment)
313 .source(source)
314 .multiplicity(multiplicity)
315 .target(target)
316 .opposite(oppositeRelation)
317 .defaultValue(defaultValue)
318 .build());
300 } catch (RuntimeException e) { 319 } catch (RuntimeException e) {
301 throw TracedException.addTrace(classDeclaration, e); 320 throw TracedException.addTrace(classDeclaration, e);
302 } 321 }
@@ -355,10 +374,6 @@ public class ModelInitializer {
355 collectCardinalityAssertions(newNodeId, TruthValue.UNKNOWN); 374 collectCardinalityAssertions(newNodeId, TruthValue.UNKNOWN);
356 var tuple = Tuple.of(newNodeId); 375 var tuple = Tuple.of(newNodeId);
357 mergeValue(classDeclaration, tuple, TruthValue.TRUE); 376 mergeValue(classDeclaration, tuple, TruthValue.TRUE);
358 var typeInfo = metamodel.typeHierarchy().getAnalysisResult(getPartialRelation(classDeclaration));
359 for (var subType : typeInfo.getDirectSubtypes()) {
360 partialRelationInfoMap.get(subType).assertions().mergeValue(tuple, TruthValue.FALSE);
361 }
362 } 377 }
363 378
364 private void collectEnumAssertions(EnumDeclaration enumDeclaration) { 379 private void collectEnumAssertions(EnumDeclaration enumDeclaration) {
@@ -399,6 +414,27 @@ public class ModelInitializer {
399 } 414 }
400 } 415 }
401 416
417 private void fixClassDeclarationAssertions() {
418 for (var statement : problem.getStatements()) {
419 if (statement instanceof ClassDeclaration classDeclaration) {
420 fixClassDeclarationAssertions(classDeclaration);
421 }
422 }
423 }
424
425 private void fixClassDeclarationAssertions(ClassDeclaration classDeclaration) {
426 var newNode = classDeclaration.getNewNode();
427 if (newNode == null) {
428 return;
429 }
430 var newNodeId = getNodeId(newNode);
431 var tuple = Tuple.of(newNodeId);
432 var typeInfo = metamodel.typeHierarchy().getAnalysisResult(getPartialRelation(classDeclaration));
433 for (var subType : typeInfo.getDirectSubtypes()) {
434 partialRelationInfoMap.get(subType).assertions().mergeValue(tuple, TruthValue.FALSE);
435 }
436 }
437
402 private void mergeValue(Relation relation, Tuple key, TruthValue value) { 438 private void mergeValue(Relation relation, Tuple key, TruthValue value) {
403 getRelationInfo(relation).assertions().mergeValue(key, value); 439 getRelationInfo(relation).assertions().mergeValue(key, value);
404 } 440 }
@@ -482,7 +518,7 @@ public class ModelInitializer {
482 defaultValue = TruthValue.FALSE; 518 defaultValue = TruthValue.FALSE;
483 } else { 519 } else {
484 var seed = modelSeed.getSeed(partialRelation); 520 var seed = modelSeed.getSeed(partialRelation);
485 defaultValue = seed.reducedValue() == TruthValue.FALSE ? TruthValue.FALSE : TruthValue.UNKNOWN; 521 defaultValue = seed.majorityValue() == TruthValue.FALSE ? TruthValue.FALSE : TruthValue.UNKNOWN;
486 var cursor = seed.getCursor(defaultValue, problemTrace.getNodeTrace().size()); 522 var cursor = seed.getCursor(defaultValue, problemTrace.getNodeTrace().size());
487 // The symbol should be mutable if there is at least one non-default entry in the seed. 523 // The symbol should be mutable if there is at least one non-default entry in the seed.
488 mutable = mutable || cursor.move(); 524 mutable = mutable || cursor.move();
@@ -495,7 +531,7 @@ public class ModelInitializer {
495 var problemParameters = predicateDefinition.getParameters(); 531 var problemParameters = predicateDefinition.getParameters();
496 int arity = problemParameters.size(); 532 int arity = problemParameters.size();
497 var parameters = new NodeVariable[arity]; 533 var parameters = new NodeVariable[arity];
498 var parameterMap = new HashMap<tools.refinery.language.model.problem.Variable, Variable>(arity); 534 var parameterMap = HashMap.<tools.refinery.language.model.problem.Variable, Variable>newHashMap(arity);
499 var commonLiterals = new ArrayList<Literal>(); 535 var commonLiterals = new ArrayList<Literal>();
500 for (int i = 0; i < arity; i++) { 536 for (int i = 0; i < arity; i++) {
501 var problemParameter = problemParameters.get(i); 537 var problemParameter = problemParameters.get(i);
@@ -532,7 +568,7 @@ public class ModelInitializer {
532 return existing; 568 return existing;
533 } 569 }
534 int localScopeSize = existing.size() + newVariables.size(); 570 int localScopeSize = existing.size() + newVariables.size();
535 var localScope = new HashMap<tools.refinery.language.model.problem.Variable, Variable>(localScopeSize); 571 var localScope = HashMap.<tools.refinery.language.model.problem.Variable, Variable>newHashMap(localScopeSize);
536 localScope.putAll(existing); 572 localScope.putAll(existing);
537 for (var newVariable : newVariables) { 573 for (var newVariable : newVariables) {
538 localScope.put(newVariable, Variable.of(newVariable.getName())); 574 localScope.put(newVariable, Variable.of(newVariable.getName()));
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java
index cc634949..f686e980 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java
@@ -9,7 +9,6 @@ import com.google.inject.Inject;
9import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; 9import org.eclipse.collections.api.factory.primitive.ObjectIntMaps;
10import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; 10import org.eclipse.collections.api.map.primitive.MutableObjectIntMap;
11import org.eclipse.collections.api.map.primitive.ObjectIntMap; 11import org.eclipse.collections.api.map.primitive.ObjectIntMap;
12import org.eclipse.emf.ecore.util.EcoreUtil;
13import org.eclipse.xtext.naming.IQualifiedNameConverter; 12import org.eclipse.xtext.naming.IQualifiedNameConverter;
14import org.eclipse.xtext.naming.QualifiedName; 13import org.eclipse.xtext.naming.QualifiedName;
15import org.eclipse.xtext.scoping.IScope; 14import org.eclipse.xtext.scoping.IScope;
@@ -28,7 +27,7 @@ import java.util.HashMap;
28import java.util.LinkedHashMap; 27import java.util.LinkedHashMap;
29import java.util.Map; 28import java.util.Map;
30 29
31public class ProblemTraceImpl implements ProblemTrace { 30class ProblemTraceImpl implements ProblemTrace {
32 @Inject 31 @Inject
33 private IQualifiedNameConverter qualifiedNameConverter; 32 private IQualifiedNameConverter qualifiedNameConverter;
34 33
@@ -164,24 +163,6 @@ public class ProblemTraceImpl implements ProblemTrace {
164 } 163 }
165 164
166 private <T> T getElement(IScope scope, QualifiedName qualifiedName, Class<T> type) { 165 private <T> T getElement(IScope scope, QualifiedName qualifiedName, Class<T> type) {
167 var iterator = scope.getElements(qualifiedName).iterator(); 166 return semanticsUtils.getElement(problem, scope, qualifiedName, type);
168 if (!iterator.hasNext()) {
169 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
170 throw new IllegalArgumentException("No such %s: %s"
171 .formatted(type.getName(), qualifiedNameString));
172 }
173 var eObjectDescription = iterator.next();
174 if (iterator.hasNext()) {
175 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
176 throw new IllegalArgumentException("Ambiguous %s: %s"
177 .formatted(type.getName(), qualifiedNameString));
178 }
179 var eObject = EcoreUtil.resolve(eObjectDescription.getEObjectOrProxy(), getProblem());
180 if (!type.isInstance(eObject)) {
181 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
182 throw new IllegalArgumentException("Not a %s: %s"
183 .formatted(type.getName(), qualifiedNameString));
184 }
185 return type.cast(eObject);
186 } 167 }
187} 168}
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java
index b195a8e7..b72ba697 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java
@@ -8,8 +8,14 @@ package tools.refinery.language.semantics;
8import com.google.inject.Inject; 8import com.google.inject.Inject;
9import com.google.inject.Singleton; 9import com.google.inject.Singleton;
10import org.eclipse.emf.ecore.EObject; 10import org.eclipse.emf.ecore.EObject;
11import org.eclipse.emf.ecore.util.EcoreUtil;
11import org.eclipse.xtext.naming.IQualifiedNameConverter; 12import org.eclipse.xtext.naming.IQualifiedNameConverter;
12import org.eclipse.xtext.naming.IQualifiedNameProvider; 13import org.eclipse.xtext.naming.IQualifiedNameProvider;
14import org.eclipse.xtext.naming.QualifiedName;
15import org.eclipse.xtext.scoping.IScope;
16import org.jetbrains.annotations.NotNull;
17import org.jetbrains.annotations.Nullable;
18import tools.refinery.language.model.problem.Problem;
13 19
14import java.util.Optional; 20import java.util.Optional;
15 21
@@ -28,4 +34,39 @@ public class SemanticsUtils {
28 } 34 }
29 return Optional.of(qualifiedNameConverter.toString(qualifiedName)); 35 return Optional.of(qualifiedNameConverter.toString(qualifiedName));
30 } 36 }
37
38 @Nullable
39 public <T> T maybeGetElement(Problem problem, IScope scope, QualifiedName qualifiedName, Class<T> type) {
40 if (qualifiedName == null) {
41 throw new IllegalArgumentException("Element name must not be null");
42 }
43 var iterator = scope.getElements(qualifiedName).iterator();
44 if (!iterator.hasNext()) {
45 return null;
46 }
47 var eObjectDescription = iterator.next();
48 if (iterator.hasNext()) {
49 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
50 throw new IllegalArgumentException("Ambiguous %s: %s"
51 .formatted(type.getName(), qualifiedNameString));
52 }
53 var eObject = EcoreUtil.resolve(eObjectDescription.getEObjectOrProxy(), problem);
54 if (!type.isInstance(eObject)) {
55 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
56 throw new IllegalArgumentException("Not a %s: %s"
57 .formatted(type.getName(), qualifiedNameString));
58 }
59 return type.cast(eObject);
60 }
61
62 @NotNull
63 public <T> T getElement(Problem problem, IScope scope, QualifiedName qualifiedName, Class<T> type) {
64 var element = maybeGetElement(problem, scope, qualifiedName, type);
65 if (element == null) {
66 var qualifiedNameString = qualifiedNameConverter.toString(qualifiedName);
67 throw new IllegalArgumentException("No such %s: %s"
68 .formatted(type.getName(), qualifiedNameString));
69 }
70 return element;
71 }
31} 72}
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java
new file mode 100644
index 00000000..57af599e
--- /dev/null
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SolutionSerializer.java
@@ -0,0 +1,335 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.semantics;
7
8import com.google.inject.Inject;
9import com.google.inject.Provider;
10import org.eclipse.collections.api.factory.primitive.IntObjectMaps;
11import org.eclipse.collections.api.factory.primitive.ObjectIntMaps;
12import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
13import org.eclipse.collections.api.map.primitive.MutableObjectIntMap;
14import org.eclipse.emf.common.util.URI;
15import org.eclipse.emf.ecore.util.EcoreUtil;
16import org.eclipse.xtext.naming.IQualifiedNameConverter;
17import org.eclipse.xtext.naming.IQualifiedNameProvider;
18import org.eclipse.xtext.naming.QualifiedName;
19import org.eclipse.xtext.resource.FileExtensionProvider;
20import org.eclipse.xtext.resource.IResourceFactory;
21import org.eclipse.xtext.resource.XtextResource;
22import org.eclipse.xtext.resource.XtextResourceSet;
23import org.eclipse.xtext.scoping.IScopeProvider;
24import tools.refinery.language.model.problem.*;
25import tools.refinery.language.utils.ProblemDesugarer;
26import tools.refinery.language.utils.ProblemUtil;
27import tools.refinery.store.model.Model;
28import tools.refinery.store.reasoning.ReasoningAdapter;
29import tools.refinery.store.reasoning.interpretation.PartialInterpretation;
30import tools.refinery.store.reasoning.literal.Concreteness;
31import tools.refinery.store.reasoning.representation.PartialRelation;
32import tools.refinery.store.reasoning.translator.typehierarchy.InferredType;
33import tools.refinery.store.reasoning.translator.typehierarchy.TypeHierarchyTranslator;
34import tools.refinery.store.representation.TruthValue;
35import tools.refinery.store.tuple.Tuple;
36
37import java.io.ByteArrayInputStream;
38import java.io.ByteArrayOutputStream;
39import java.io.IOException;
40import java.util.Locale;
41import java.util.Map;
42import java.util.TreeMap;
43import java.util.TreeSet;
44import java.util.function.Function;
45import java.util.stream.Collectors;
46
47public class SolutionSerializer {
48 private String fileExtension;
49
50 @Inject
51 private Provider<XtextResourceSet> resourceSetProvider;
52
53 @Inject
54 private IResourceFactory resourceFactory;
55
56 @Inject
57 private IQualifiedNameProvider qualifiedNameProvider;
58
59 @Inject
60 private IQualifiedNameConverter qualifiedNameConverter;
61
62 @Inject
63 private SemanticsUtils semanticsUtils;
64
65 @Inject
66 private IScopeProvider scopeProvider;
67
68 @Inject
69 private ProblemDesugarer desugarer;
70
71 private ProblemTrace trace;
72 private Model model;
73 private ReasoningAdapter reasoningAdapter;
74 private PartialInterpretation<TruthValue, Boolean> existsInterpretation;
75 private Problem problem;
76 private final MutableIntObjectMap<Node> nodes = IntObjectMaps.mutable.empty();
77
78 @Inject
79 public void setFileExtensionProvider(FileExtensionProvider fileExtensionProvider) {
80 this.fileExtension = fileExtensionProvider.getPrimaryFileExtension();
81 }
82
83 public Problem serializeSolution(ProblemTrace trace, Model model) {
84 var uri = URI.createFileURI("__synthetic" + fileExtension);
85 return serializeSolution(trace, model, uri);
86 }
87
88 public Problem serializeSolution(ProblemTrace trace, Model model, URI uri) {
89 this.trace = trace;
90 this.model = model;
91 reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
92 existsInterpretation = reasoningAdapter.getPartialInterpretation(Concreteness.CANDIDATE,
93 ReasoningAdapter.EXISTS_SYMBOL);
94 var originalProblem = trace.getProblem();
95 problem = copyProblem(originalProblem, uri);
96 problem.getStatements().removeIf(SolutionSerializer::shouldRemoveStatement);
97 problem.getNodes().removeIf(this::shouldRemoveNode);
98 addExistsAssertions();
99 addClassAssertions();
100 addReferenceAssertions();
101 return problem;
102 }
103
104 private static boolean shouldRemoveStatement(Statement statement) {
105 return statement instanceof Assertion || statement instanceof ScopeDeclaration;
106 }
107
108 private boolean shouldRemoveNode(Node newNode) {
109 var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(newNode);
110 var scope = scopeProvider.getScope(trace.getProblem(), ProblemPackage.Literals.ASSERTION__RELATION);
111 var originalNode = semanticsUtils.maybeGetElement(problem, scope, qualifiedName, Node.class);
112 if (originalNode == null) {
113 return false;
114 }
115 int nodeId = trace.getNodeId(originalNode);
116 return !isExistingNode(nodeId);
117 }
118
119 private boolean isExistingNode(int nodeId) {
120 var exists = existsInterpretation.get(Tuple.of(nodeId));
121 if (!exists.isConcrete()) {
122 throw new IllegalStateException("Invalid EXISTS %s for node %d".formatted(exists, nodeId));
123 }
124 return exists.may();
125 }
126
127 private Problem copyProblem(Problem originalProblem, URI uri) {
128 var newResourceSet = resourceSetProvider.get();
129 if (!fileExtension.equals(uri.fileExtension())) {
130 uri = uri.appendFileExtension(fileExtension);
131 }
132 var newResource = resourceFactory.createResource(uri);
133 newResourceSet.getResources().add(newResource);
134 var originalResource = originalProblem.eResource();
135 if (originalResource instanceof XtextResource) {
136 byte[] bytes;
137 try {
138 try (var outputStream = new ByteArrayOutputStream()) {
139 originalResource.save(outputStream, Map.of());
140 bytes = outputStream.toByteArray();
141 }
142 try (var inputStream = new ByteArrayInputStream(bytes)) {
143 newResource.load(inputStream, Map.of());
144 }
145 } catch (IOException e) {
146 throw new IllegalStateException("Failed to copy problem", e);
147 }
148 var contents = newResource.getContents();
149 if (!contents.isEmpty() && contents.getFirst() instanceof Problem newProblem) {
150 return newProblem;
151 }
152 throw new IllegalStateException("Invalid contents of copied problem");
153 } else {
154 var newProblem = EcoreUtil.copy(originalProblem);
155 newResource.getContents().add(newProblem);
156 return newProblem;
157 }
158 }
159
160 private Relation findRelation(Relation originalRelation) {
161 var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(originalRelation);
162 var scope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION);
163 return semanticsUtils.getElement(problem, scope, qualifiedName, Relation.class);
164 }
165
166 private Relation findPartialRelation(PartialRelation partialRelation) {
167 return findRelation(trace.getRelation(partialRelation));
168 }
169
170 private Node findNode(Node originalNode) {
171 var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(originalNode);
172 return findNode(qualifiedName);
173 }
174
175 private Node findNode(String name) {
176 var qualifiedName = qualifiedNameConverter.toQualifiedName(name);
177 return findNode(qualifiedName);
178 }
179
180 private Node findNode(QualifiedName qualifiedName) {
181 var scope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE);
182 return semanticsUtils.maybeGetElement(problem, scope, qualifiedName, Node.class);
183 }
184
185 private void addAssertion(Relation relation, LogicValue value, Node... arguments) {
186 var assertion = ProblemFactory.eINSTANCE.createAssertion();
187 assertion.setRelation(relation);
188 for (var node : arguments) {
189 var argument = ProblemFactory.eINSTANCE.createNodeAssertionArgument();
190 argument.setNode(node);
191 assertion.getArguments().add(argument);
192 }
193 var logicConstant = ProblemFactory.eINSTANCE.createLogicConstant();
194 logicConstant.setLogicValue(value);
195 assertion.setValue(logicConstant);
196 problem.getStatements().add(assertion);
197 }
198
199 private void addExistsAssertions() {
200 var builtinSymbols = desugarer.getBuiltinSymbols(problem)
201 .orElseThrow(() -> new IllegalStateException("No builtin library in copied problem"));
202 // Make sure to output exists assertions in a deterministic order.
203 var sortedNewNodes = new TreeMap<Integer, Node>();
204 for (var pair : trace.getNodeTrace().keyValuesView()) {
205 var originalNode = pair.getOne();
206 int nodeId = pair.getTwo();
207 var newNode = findNode(originalNode);
208 // Since all implicit nodes that do not exist has already been remove in serializeSolution,
209 // we only need to add !exists assertions to ::new nodes (nodes marked as an individual must always exist).
210 if (ProblemUtil.isNewNode(originalNode)) {
211 sortedNewNodes.put(nodeId, newNode);
212 } else {
213 nodes.put(nodeId, newNode);
214 }
215 }
216 for (var newNode : sortedNewNodes.values()) {
217 // If a node is a new node of the class, we should replace it with a normal node.
218 addAssertion(builtinSymbols.exists(), LogicValue.FALSE, newNode);
219 }
220 }
221
222 private void addClassAssertions() {
223 var types = trace.getMetamodel().typeHierarchy().getPreservedTypes().keySet().stream()
224 .collect(Collectors.toMap(Function.identity(), this::findPartialRelation));
225 var indexMap = ObjectIntMaps.mutable.empty();
226 var cursor = model.getInterpretation(TypeHierarchyTranslator.TYPE_SYMBOL).getAll();
227 while (cursor.move()) {
228 var key = cursor.getKey();
229 var nodeId = key.get(0);
230 if (isExistingNode(nodeId)) {
231 createNodeAndAssertType(nodeId, cursor.getValue(), types, indexMap);
232 }
233 }
234 }
235
236 private void createNodeAndAssertType(int nodeId, InferredType inferredType, Map<PartialRelation, Relation> types,
237 MutableObjectIntMap<Object> indexMap) {
238 var candidateTypeSymbol = inferredType.candidateType();
239 var candidateRelation = types.get(candidateTypeSymbol);
240 if (candidateRelation instanceof EnumDeclaration) {
241 // Type assertions for enum literals are added implicitly.
242 return;
243 }
244 Node node = nodes.get(nodeId);
245 if (node == null) {
246 String typeName = candidateRelation.getName();
247 if (typeName == null || typeName.isEmpty()) {
248 typeName = "node";
249 } else {
250 typeName = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1);
251 }
252 int index = indexMap.getIfAbsent(typeName, 0);
253 String nodeName;
254 do {
255 index++;
256 nodeName = typeName + index;
257 } while (findNode(nodeName) != null);
258 node = ProblemFactory.eINSTANCE.createNode();
259 node.setName(nodeName);
260 problem.getNodes().add(node);
261 nodes.put(nodeId, node);
262 }
263 addAssertion(candidateRelation, LogicValue.TRUE, node);
264 var typeAnalysisResult = trace.getMetamodel().typeHierarchy().getPreservedTypes().get(candidateTypeSymbol);
265 for (var subtype : typeAnalysisResult.getDirectSubtypes()) {
266 var subtypeRelation = types.get(subtype);
267 addAssertion(subtypeRelation, LogicValue.FALSE, node);
268 }
269 }
270
271 private void addReferenceAssertions() {
272 var metamodel = trace.getMetamodel();
273 for (var partialRelation : metamodel.containmentHierarchy().keySet()) {
274 // No need to add a default value, because in a concrete model, each contained node has only a single
275 // container.
276 addAssertions(partialRelation);
277 }
278 for (var partialRelation : metamodel.directedCrossReferences().keySet()) {
279 addDefaultAssertion(partialRelation);
280 addAssertions(partialRelation);
281 }
282 // No need to add directed opposite references, because their default value is {@code unknown} and their
283 // actual value will always be computed from the value of the directed forward reference.
284 // However, undirected cross-references have to be serialized in both directions due to the default value of
285 // {@code false}.
286 for (var partialRelation : metamodel.undirectedCrossReferences().keySet()) {
287 addDefaultAssertion(partialRelation);
288 addAssertions(partialRelation);
289 }
290 }
291
292 private void addAssertions(PartialRelation partialRelation) {
293 var relation = findPartialRelation(partialRelation);
294 var cursor = reasoningAdapter.getPartialInterpretation(Concreteness.CANDIDATE, partialRelation).getAll();
295 // Make sure to output assertions in a deterministic order.
296 var sortedTuples = new TreeSet<Tuple>();
297 while (cursor.move()) {
298 var tuple = cursor.getKey();
299 var from = nodes.get(tuple.get(0));
300 var to = nodes.get(tuple.get(1));
301 if (from == null || to == null) {
302 // One of the endpoints does not exist in the candidate model.
303 continue;
304 }
305 var value = cursor.getValue();
306 if (!value.isConcrete()) {
307 throw new IllegalStateException("Invalid %s %s for tuple %s".formatted(partialRelation, value, tuple));
308 }
309 if (value.may()) {
310 sortedTuples.add(tuple);
311 }
312 }
313 for (var tuple : sortedTuples) {
314 var from = nodes.get(tuple.get(0));
315 var to = nodes.get(tuple.get(1));
316 addAssertion(relation, LogicValue.TRUE, from, to);
317 }
318 }
319
320 private void addDefaultAssertion(PartialRelation partialRelation) {
321 var relation = findPartialRelation(partialRelation);
322 var assertion = ProblemFactory.eINSTANCE.createAssertion();
323 assertion.setDefault(true);
324 assertion.setRelation(relation);
325 int arity = ProblemUtil.getArity(relation);
326 for (int i = 0; i < arity; i++) {
327 var argument = ProblemFactory.eINSTANCE.createWildcardAssertionArgument();
328 assertion.getArguments().add(argument);
329 }
330 var logicConstant = ProblemFactory.eINSTANCE.createLogicConstant();
331 logicConstant.setLogicValue(LogicValue.FALSE);
332 assertion.setValue(logicConstant);
333 problem.getStatements().add(assertion);
334 }
335}
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java
index c732f784..5d25f148 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java
@@ -40,8 +40,8 @@ class DecisionTree implements MutableSeed<TruthValue> {
40 } 40 }
41 41
42 @Override 42 @Override
43 public TruthValue reducedValue() { 43 public TruthValue majorityValue() {
44 return root.getOtherwiseReducedValue().getTruthValue(); 44 return root.getMajorityValue().getTruthValueOrElse(TruthValue.FALSE);
45 } 45 }
46 46
47 @Override 47 @Override
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java
index ebca2634..31d6fc78 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java
@@ -100,6 +100,8 @@ abstract class DecisionTreeNode {
100 100
101 protected abstract LazyIntIterable getChildKeys(); 101 protected abstract LazyIntIterable getChildKeys();
102 102
103 public abstract DecisionTreeValue getMajorityValue();
104
103 protected abstract boolean moveNextSparse(int level, DecisionTreeCursor cursor, int startIndex, 105 protected abstract boolean moveNextSparse(int level, DecisionTreeCursor cursor, int startIndex,
104 int[] sortedChildren); 106 int[] sortedChildren);
105 107
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java
index 0e2f5d18..2ad216ce 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java
@@ -130,6 +130,11 @@ final class IntermediateNode extends DecisionTreeNode {
130 return children.keysView(); 130 return children.keysView();
131 } 131 }
132 132
133 @Override
134 public DecisionTreeValue getMajorityValue() {
135 return otherwise.getMajorityValue();
136 }
137
133 protected boolean moveNextSparse(int level, DecisionTreeCursor cursor, int startIndex, int[] sortedChildren) { 138 protected boolean moveNextSparse(int level, DecisionTreeCursor cursor, int startIndex, int[] sortedChildren) {
134 for (int i = startIndex; i < sortedChildren.length; i++) { 139 for (int i = startIndex; i < sortedChildren.length; i++) {
135 var key = sortedChildren[i]; 140 var key = sortedChildren[i];
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java
index 7a72c656..f100c5a6 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java
@@ -29,14 +29,14 @@ class NullaryMutableSeed implements MutableSeed<TruthValue> {
29 } 29 }
30 30
31 @Override 31 @Override
32 public TruthValue reducedValue() { 32 public TruthValue majorityValue() {
33 return value.getTruthValue(); 33 return value.getTruthValue();
34 } 34 }
35 35
36 @Override 36 @Override
37 public TruthValue get(Tuple key) { 37 public TruthValue get(Tuple key) {
38 validateKey(key); 38 validateKey(key);
39 return reducedValue(); 39 return majorityValue();
40 } 40 }
41 41
42 private static void validateKey(Tuple key) { 42 private static void validateKey(Tuple key) {
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java
index d3dd757c..dc501479 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java
@@ -115,7 +115,7 @@ class TerminalNode extends DecisionTreeNode {
115 115
116 @Override 116 @Override
117 protected DecisionTreeValue getOtherwiseReducedValue() { 117 protected DecisionTreeValue getOtherwiseReducedValue() {
118 return otherwise; 118 return getMajorityValue();
119 } 119 }
120 120
121 @Override 121 @Override
@@ -124,6 +124,11 @@ class TerminalNode extends DecisionTreeNode {
124 } 124 }
125 125
126 @Override 126 @Override
127 public DecisionTreeValue getMajorityValue() {
128 return otherwise;
129 }
130
131 @Override
127 protected boolean moveNextSparse(int level, DecisionTreeCursor cursor, int startIndex, int[] sortedChildren) { 132 protected boolean moveNextSparse(int level, DecisionTreeCursor cursor, int startIndex, int[] sortedChildren) {
128 if (startIndex >= sortedChildren.length) { 133 if (startIndex >= sortedChildren.length) {
129 return false; 134 return false;
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/SolutionSerializerTest.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/SolutionSerializerTest.java
new file mode 100644
index 00000000..2d759c86
--- /dev/null
+++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/SolutionSerializerTest.java
@@ -0,0 +1,164 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.semantics;
7
8import com.google.inject.Inject;
9import org.eclipse.xtext.testing.InjectWith;
10import org.eclipse.xtext.testing.extensions.InjectionExtension;
11import org.junit.jupiter.api.extension.ExtendWith;
12import org.junit.jupiter.params.ParameterizedTest;
13import org.junit.jupiter.params.provider.Arguments;
14import org.junit.jupiter.params.provider.MethodSource;
15import tools.refinery.generator.ModelGeneratorFactory;
16import tools.refinery.generator.ProblemLoader;
17import tools.refinery.language.tests.ProblemInjectorProvider;
18
19import java.io.ByteArrayOutputStream;
20import java.io.IOException;
21import java.util.Map;
22import java.util.stream.Stream;
23
24import static org.hamcrest.MatcherAssert.assertThat;
25import static org.hamcrest.Matchers.is;
26
27@ExtendWith(InjectionExtension.class)
28@InjectWith(ProblemInjectorProvider.class)
29class SolutionSerializerTest {
30 @Inject
31 ProblemLoader loader;
32
33 @Inject
34 ModelGeneratorFactory generatorFactory;
35
36 @Inject
37 SolutionSerializer serializer;
38
39 @ParameterizedTest
40 @MethodSource
41 void solutionSerializerTest(String prefix, String input, String expectedOutput) throws IOException {
42 var problem = loader.loadString(prefix + "\n" + input);
43 var generator = generatorFactory.createGenerator(problem);
44 generator.generate();
45 var solution = serializer.serializeSolution(generator.getProblemTrace(), generator.getModel());
46 String actualOutput;
47 try (var outputStream = new ByteArrayOutputStream()) {
48 solution.eResource().save(outputStream, Map.of());
49 actualOutput = outputStream.toString();
50 }
51 assertThat(actualOutput, is(prefix + "\n" + expectedOutput));
52 }
53
54 static Stream<Arguments> solutionSerializerTest() {
55 return Stream.of(Arguments.of("""
56 class Foo.
57 """, """
58 scope Foo = 3.
59 """, """
60 !exists(Foo::new).
61 Foo(foo1).
62 Foo(foo2).
63 Foo(foo3).
64 """), Arguments.of("""
65 class Foo {
66 contains Bar[2] bars
67 }
68
69 class Bar.
70 """, """
71 scope Foo = 1.
72 """, """
73 !exists(Foo::new).
74 !exists(Bar::new).
75 Foo(foo1).
76 Bar(bar1).
77 Bar(bar2).
78 bars(foo1, bar1).
79 bars(foo1, bar2).
80 """), Arguments.of("""
81 class Foo {
82 Bar[2] bars opposite foo
83 }
84
85 class Bar {
86 Foo[1] foo opposite bars
87 }
88 """, """
89 scope Foo = 1, Bar = 2.
90 """, """
91 !exists(Foo::new).
92 !exists(Bar::new).
93 Foo(foo1).
94 Bar(bar1).
95 Bar(bar2).
96 default !bars(*, *).
97 bars(foo1, bar1).
98 bars(foo1, bar2).
99 """), Arguments.of("""
100 class Person {
101 Person[2] friend opposite friend
102 }
103 """, """
104 friend(a, b).
105 friend(a, c).
106 friend(b, c).
107
108 scope Person += 0.
109 """, """
110 !exists(Person::new).
111 Person(a).
112 Person(b).
113 Person(c).
114 default !friend(*, *).
115 friend(a, b).
116 friend(a, c).
117 friend(b, a).
118 friend(b, c).
119 friend(c, a).
120 friend(c, b).
121 """), Arguments.of("""
122 class Foo {
123 Bar bar
124 }
125
126 enum Bar {
127 BAR_A,
128 BAR_B
129 }
130 """, """
131 bar(foo, BAR_A).
132
133 scope Foo += 0.
134 """, """
135 !exists(Foo::new).
136 Foo(foo).
137 default !bar(*, *).
138 bar(foo, BAR_A).
139 """), Arguments.of("""
140 class Foo.
141 class Bar extends Foo.
142 """, """
143 scope Foo = 1, Bar = 0.
144 """, """
145 !exists(Foo::new).
146 !exists(Bar::new).
147 Foo(foo1).
148 !Bar(foo1).
149 """), Arguments.of("""
150 class Foo {
151 Foo[] ref
152 }
153 """, """
154 ref(a, b).
155 !exists(b).
156
157 scope Foo += 0.
158 """, """
159 !exists(Foo::new).
160 Foo(a).
161 default !ref(*, *).
162 """));
163 }
164}
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java
index 2320de2c..61ce850f 100644
--- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java
+++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java
@@ -276,6 +276,16 @@ class DecisionTreeTests {
276 assertThat(sut.getReducedValue(), is(TruthValue.TRUE)); 276 assertThat(sut.getReducedValue(), is(TruthValue.TRUE));
277 } 277 }
278 278
279 @Test
280 void overwriteWildcardAllTest() {
281 var first = new DecisionTree(2, TruthValue.UNKNOWN);
282 first.mergeValue(Tuple.of(-1, -1), TruthValue.FALSE);
283 var second = new DecisionTree(2, null);
284 second.mergeValue(Tuple.of(1, -1), TruthValue.TRUE);
285 first.overwriteValues(second);
286 assertThat(first.majorityValue(), is(TruthValue.FALSE));
287 }
288
279 private Map<Tuple, TruthValue> iterateAll(DecisionTree sut, TruthValue defaultValue, int nodeCount) { 289 private Map<Tuple, TruthValue> iterateAll(DecisionTree sut, TruthValue defaultValue, int nodeCount) {
280 var cursor = sut.getCursor(defaultValue, nodeCount); 290 var cursor = sut.getCursor(defaultValue, nodeCount);
281 var map = new LinkedHashMap<Tuple, TruthValue>(); 291 var map = new LinkedHashMap<Tuple, TruthValue>();
diff --git a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java
index 0a5cb3c2..00dd3de3 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java
@@ -20,6 +20,7 @@ import org.eclipse.xtext.scoping.IGlobalScopeProvider;
20import org.eclipse.xtext.scoping.IScopeProvider; 20import org.eclipse.xtext.scoping.IScopeProvider;
21import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; 21import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
22import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer; 22import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
23import org.eclipse.xtext.serializer.tokens.ICrossReferenceSerializer;
23import org.eclipse.xtext.validation.IDiagnosticConverter; 24import org.eclipse.xtext.validation.IDiagnosticConverter;
24import org.eclipse.xtext.validation.IResourceValidator; 25import org.eclipse.xtext.validation.IResourceValidator;
25import org.eclipse.xtext.xbase.annotations.validation.DerivedStateAwareResourceValidator; 26import org.eclipse.xtext.xbase.annotations.validation.DerivedStateAwareResourceValidator;
@@ -34,12 +35,15 @@ import tools.refinery.language.resource.ProblemResourceDescriptionStrategy;
34import tools.refinery.language.scoping.ProblemGlobalScopeProvider; 35import tools.refinery.language.scoping.ProblemGlobalScopeProvider;
35import tools.refinery.language.scoping.ProblemLocalScopeProvider; 36import tools.refinery.language.scoping.ProblemLocalScopeProvider;
36import tools.refinery.language.serializer.PreferShortAssertionsProblemSemanticSequencer; 37import tools.refinery.language.serializer.PreferShortAssertionsProblemSemanticSequencer;
38import tools.refinery.language.serializer.ProblemCrossReferenceSerializer;
37import tools.refinery.language.validation.ProblemDiagnosticConverter; 39import tools.refinery.language.validation.ProblemDiagnosticConverter;
38 40
39/** 41/**
40 * Use this class to register components to be used at runtime / without the 42 * Use this class to register components to be used at runtime / without the
41 * Equinox extension registry. 43 * Equinox extension registry.
42 */ 44 */
45// Unused methods in this class are called by reflection to configure the Xtext Injector.
46@SuppressWarnings("unused")
43public class ProblemRuntimeModule extends AbstractProblemRuntimeModule { 47public class ProblemRuntimeModule extends AbstractProblemRuntimeModule {
44 @Override 48 @Override
45 public Class<? extends IParser> bindIParser() { 49 public Class<? extends IParser> bindIParser() {
@@ -104,6 +108,10 @@ public class ProblemRuntimeModule extends AbstractProblemRuntimeModule {
104 return PreferShortAssertionsProblemSemanticSequencer.class; 108 return PreferShortAssertionsProblemSemanticSequencer.class;
105 } 109 }
106 110
111 public Class<? extends ICrossReferenceSerializer> bindICrossReferenceSerializer() {
112 return ProblemCrossReferenceSerializer.class;
113 }
114
107 public Class<? extends IDiagnosticConverter> bindIDiagnosticConverter() { 115 public Class<? extends IDiagnosticConverter> bindIDiagnosticConverter() {
108 return ProblemDiagnosticConverter.class; 116 return ProblemDiagnosticConverter.class;
109 } 117 }
diff --git a/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java b/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
index 55a5ac20..0f3bd3ee 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java
@@ -69,12 +69,24 @@ public class ProblemFormatter extends AbstractJavaFormatter {
69 doc.prepend(region.keyword("{"), this::oneSpace); 69 doc.prepend(region.keyword("{"), this::oneSpace);
70 doc.append(region.keyword("{"), it -> it.setNewLines(1, 1, 2)); 70 doc.append(region.keyword("{"), it -> it.setNewLines(1, 1, 2));
71 doc.prepend(region.keyword("}"), it -> it.setNewLines(1, 1, 2)); 71 doc.prepend(region.keyword("}"), it -> it.setNewLines(1, 1, 2));
72 doc.interior(region.keyword("{"), region.keyword("}"), IHiddenRegionFormatter::indent);
72 doc.prepend(region.keyword("."), this::noSpace); 73 doc.prepend(region.keyword("."), this::noSpace);
73 for (var featureDeclaration : classDeclaration.getFeatureDeclarations()) { 74 for (var featureDeclaration : classDeclaration.getFeatureDeclarations()) {
74 doc.format(featureDeclaration); 75 doc.format(featureDeclaration);
75 } 76 }
76 } 77 }
77 78
79 protected void format(EnumDeclaration enumDeclaration, IFormattableDocument doc) {
80 surroundNewLines(doc, enumDeclaration, this::twoNewLines);
81 var region = regionFor(enumDeclaration);
82 doc.append(region.keyword("enum"), this::oneSpace);
83 doc.prepend(region.keyword("{"), this::oneSpace);
84 doc.append(region.keyword("{"), it -> it.setNewLines(1, 1, 2));
85 doc.prepend(region.keyword("}"), it -> it.setNewLines(1, 1, 2));
86 doc.interior(region.keyword("{"), region.keyword("}"), IHiddenRegionFormatter::indent);
87 doc.prepend(region.keyword("."), this::noSpace);
88 }
89
78 protected void format(PredicateDefinition predicateDefinition, IFormattableDocument doc) { 90 protected void format(PredicateDefinition predicateDefinition, IFormattableDocument doc) {
79 surroundNewLines(doc, predicateDefinition, this::twoNewLines); 91 surroundNewLines(doc, predicateDefinition, this::twoNewLines);
80 var region = regionFor(predicateDefinition); 92 var region = regionFor(predicateDefinition);
@@ -151,14 +163,14 @@ public class ProblemFormatter extends AbstractJavaFormatter {
151 } 163 }
152 164
153 protected void surroundNewLines(IFormattableDocument doc, EObject eObject, 165 protected void surroundNewLines(IFormattableDocument doc, EObject eObject,
154 Procedure1<? super IHiddenRegionFormatter> init) { 166 Procedure1<? super IHiddenRegionFormatter> init) {
155 var region = doc.getRequest().getTextRegionAccess().regionForEObject(eObject); 167 var region = doc.getRequest().getTextRegionAccess().regionForEObject(eObject);
156 preprendNewLines(doc, region, init); 168 preprendNewLines(doc, region, init);
157 appendNewLines(doc, region, init); 169 appendNewLines(doc, region, init);
158 } 170 }
159 171
160 protected void preprendNewLines(IFormattableDocument doc, ISequentialRegion region, 172 protected void preprendNewLines(IFormattableDocument doc, ISequentialRegion region,
161 Procedure1<? super IHiddenRegionFormatter> init) { 173 Procedure1<? super IHiddenRegionFormatter> init) {
162 if (region == null) { 174 if (region == null) {
163 return; 175 return;
164 } 176 }
@@ -174,7 +186,7 @@ public class ProblemFormatter extends AbstractJavaFormatter {
174 } 186 }
175 187
176 protected void appendNewLines(IFormattableDocument doc, ISequentialRegion region, 188 protected void appendNewLines(IFormattableDocument doc, ISequentialRegion region,
177 Procedure1<? super IHiddenRegionFormatter> init) { 189 Procedure1<? super IHiddenRegionFormatter> init) {
178 if (region == null) { 190 if (region == null) {
179 return; 191 return;
180 } 192 }
diff --git a/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java b/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java
index b9cafbc2..3432b2d8 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java
@@ -21,8 +21,7 @@ public class PreferShortAssertionsProblemSemanticSequencer extends ProblemSemant
21 21
22 @Override 22 @Override
23 protected void sequence_Assertion(ISerializationContext context, Assertion semanticObject) { 23 protected void sequence_Assertion(ISerializationContext context, Assertion semanticObject) {
24 if (semanticObject.isDefault() || 24 if (!(semanticObject.getValue() instanceof LogicConstant logicConstant) ||
25 !(semanticObject.getValue() instanceof LogicConstant logicConstant) ||
26 logicConstant.getLogicValue() == LogicValue.ERROR) { 25 logicConstant.getLogicValue() == LogicValue.ERROR) {
27 super.sequence_Assertion(context, semanticObject); 26 super.sequence_Assertion(context, semanticObject);
28 return; 27 return;
@@ -39,6 +38,9 @@ public class PreferShortAssertionsProblemSemanticSequencer extends ProblemSemant
39 } 38 }
40 var feeder = createSequencerFeeder(context, semanticObject); 39 var feeder = createSequencerFeeder(context, semanticObject);
41 var access = grammarAccess.getAssertionAccess(); 40 var access = grammarAccess.getAssertionAccess();
41 if (semanticObject.isDefault()) {
42 feeder.accept(access.getDefaultDefaultKeyword_0_0());
43 }
42 feeder.accept(access.getValueShortLogicConstantParserRuleCall_1_1_0_0(), logicConstant); 44 feeder.accept(access.getValueShortLogicConstantParserRuleCall_1_1_0_0(), logicConstant);
43 feeder.accept(access.getRelationRelationQualifiedNameParserRuleCall_1_1_1_0_1(), semanticObject.getRelation()); 45 feeder.accept(access.getRelationRelationQualifiedNameParserRuleCall_1_1_1_0_1(), semanticObject.getRelation());
44 var iterator = semanticObject.getArguments().iterator(); 46 var iterator = semanticObject.getArguments().iterator();
diff --git a/subprojects/language/src/main/java/tools/refinery/language/serializer/ProblemCrossReferenceSerializer.java b/subprojects/language/src/main/java/tools/refinery/language/serializer/ProblemCrossReferenceSerializer.java
new file mode 100644
index 00000000..42950e61
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/serializer/ProblemCrossReferenceSerializer.java
@@ -0,0 +1,167 @@
1/*******************************************************************************
2 * Copyright (c) 2008, 2018 itemis AG (http://www.itemis.eu) and others.
3 * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/>
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License 2.0 which is available at
6 * http://www.eclipse.org/legal/epl-2.0.
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.language.serializer;
10
11import com.google.common.collect.Lists;
12import com.google.inject.Inject;
13import org.eclipse.emf.common.util.URI;
14import org.eclipse.emf.ecore.EObject;
15import org.eclipse.emf.ecore.EReference;
16import org.eclipse.xtext.CrossReference;
17import org.eclipse.xtext.EcoreUtil2;
18import org.eclipse.xtext.GrammarUtil;
19import org.eclipse.xtext.IGrammarAccess;
20import org.eclipse.xtext.conversion.IValueConverterService;
21import org.eclipse.xtext.conversion.ValueConverterException;
22import org.eclipse.xtext.linking.impl.LinkingHelper;
23import org.eclipse.xtext.naming.IQualifiedNameConverter;
24import org.eclipse.xtext.naming.QualifiedName;
25import org.eclipse.xtext.nodemodel.INode;
26import org.eclipse.xtext.scoping.IScope;
27import org.eclipse.xtext.scoping.IScopeProvider;
28import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic;
29import org.eclipse.xtext.serializer.diagnostic.SerializationDiagnostic;
30import org.eclipse.xtext.serializer.tokens.CrossReferenceSerializer;
31import org.eclipse.xtext.serializer.tokens.SerializerScopeProviderBinding;
32import org.eclipse.xtext.util.EmfFormatter;
33
34import java.util.List;
35
36public class ProblemCrossReferenceSerializer extends CrossReferenceSerializer {
37 public static final String AMBIGUOUS_REFERENCE_DIAGNOSTIC = "tools.refinery.language.serializer" +
38 ".ProblemCrossReferenceSerializer.AMBIGUOUS_REFERENCE";
39
40 @Inject
41 private LinkingHelper linkingHelper;
42
43 @Inject
44 private IQualifiedNameConverter qualifiedNameConverter;
45
46 @Inject
47 @SerializerScopeProviderBinding
48 private IScopeProvider scopeProvider;
49
50 @Inject
51 private IValueConverterService valueConverter;
52
53 @Inject
54 private IGrammarAccess grammarAccess;
55
56 @Override
57 public String serializeCrossRef(EObject semanticObject, CrossReference crossref, EObject target, INode node,
58 ISerializationDiagnostic.Acceptor errors) {
59 if ((target == null || target.eIsProxy()) && node != null) {
60 return tokenUtil.serializeNode(node);
61 }
62
63 final EReference ref = GrammarUtil.getReference(crossref, semanticObject.eClass());
64 final IScope scope = scopeProvider.getScope(semanticObject, ref);
65 if (scope == null) {
66 if (errors != null) {
67 errors.accept(diagnostics.getNoScopeFoundDiagnostic(semanticObject, crossref, target));
68 }
69 return null;
70 }
71
72 if (target != null && target.eIsProxy()) {
73 target = handleProxy(target, semanticObject, ref);
74 }
75
76 if (target != null && node != null) {
77 String text = linkingHelper.getCrossRefNodeAsString(node, true);
78 QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(text);
79 URI targetUri = EcoreUtil2.getPlatformResourceOrNormalizedURI(target);
80 if (isUniqueInScope(scope, qualifiedName, targetUri)) {
81 return tokenUtil.serializeNode(node);
82 }
83 }
84
85 return getCrossReferenceNameFromScope(semanticObject, crossref, target, scope, errors);
86 }
87
88 private boolean isUniqueInScope(IScope scope, QualifiedName qualifiedName, URI targetUri) {
89 var iterator = scope.getElements(qualifiedName).iterator();
90 if (!iterator.hasNext()) {
91 return false;
92 }
93 var description = iterator.next();
94 return targetUri.equals(description.getEObjectURI()) && !iterator.hasNext();
95 }
96
97 @Override
98 protected String getCrossReferenceNameFromScope(EObject semanticObject, CrossReference crossref, EObject target,
99 IScope scope, ISerializationDiagnostic.Acceptor errors) {
100 var ruleName = linkingHelper.getRuleNameFrom(crossref);
101 var targetUri = EcoreUtil2.getPlatformResourceOrNormalizedURI(target);
102 FoundName foundName = FoundName.NONE;
103 int shortestNameLength = Integer.MAX_VALUE;
104 String shortestName = null;
105 List<ISerializationDiagnostic> recordedErrors = null;
106 for (var description : scope.getElements(target)) {
107 var qualifiedName = description.getName();
108 var segmentCount = qualifiedName.getSegmentCount();
109 if (shortestName != null && segmentCount >= shortestNameLength) {
110 continue;
111 }
112 if (isUniqueInScope(scope, qualifiedName, targetUri)) {
113 var unconverted = qualifiedNameConverter.toString(qualifiedName);
114 try {
115 shortestName = valueConverter.toString(unconverted, ruleName);
116 shortestNameLength = segmentCount;
117 foundName = FoundName.VALID;
118 } catch (ValueConverterException e) {
119 if (recordedErrors == null) {
120 recordedErrors = Lists.newArrayList();
121 }
122 recordedErrors.add(diagnostics.getValueConversionExceptionDiagnostic(semanticObject, crossref,
123 unconverted, e));
124 }
125 } else if (foundName == FoundName.NONE) {
126 foundName = FoundName.AMBIGUOUS;
127 }
128 }
129 handleErrors(semanticObject, crossref, target, scope, errors, recordedErrors, foundName);
130 return shortestName;
131 }
132
133 private void handleErrors(
134 EObject semanticObject, CrossReference crossref, EObject target, IScope scope,
135 ISerializationDiagnostic.Acceptor errors, List<ISerializationDiagnostic> recordedErrors,
136 FoundName foundName) {
137 if (errors == null) {
138 return;
139 }
140 if (recordedErrors != null) {
141 recordedErrors.forEach(errors::accept);
142 }
143 if (foundName == FoundName.NONE) {
144 errors.accept(diagnostics.getNoEObjectDescriptionFoundDiagnostic(semanticObject, crossref, target,
145 scope));
146 } else if (foundName == FoundName.AMBIGUOUS) {
147 // Computation of reference name copied from
148 // {@link org.eclipse.xtext.serializer.diagnostic.TokenDiagnosticProvider#getFullReferenceName}.
149 var ref = GrammarUtil.getReference(crossref);
150 var clazz = semanticObject.eClass().getName();
151 if (ref.getEContainingClass() != semanticObject.eClass()) {
152 clazz = ref.getEContainingClass().getName() + "(" + clazz + ")";
153 }
154 var message = "No unambiguous name could be found in scope %s.%s for %s"
155 .formatted(clazz, ref.getName(), EmfFormatter.objPath(target));
156 var diagnostic = new SerializationDiagnostic(AMBIGUOUS_REFERENCE_DIAGNOSTIC, semanticObject, crossref,
157 grammarAccess.getGrammar(), message);
158 errors.accept(diagnostic);
159 }
160 }
161
162 private enum FoundName {
163 NONE,
164 AMBIGUOUS,
165 VALID
166 }
167}
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java
index 9f4f2bbf..65675b6b 100644
--- a/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java
+++ b/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java
@@ -74,8 +74,8 @@ class ProblemSerializerTest {
74 } 74 }
75 75
76 @ParameterizedTest 76 @ParameterizedTest
77 @MethodSource 77 @MethodSource("assertionTest")
78 void defaultAssertionTest(LogicValue value, String valueAsString) { 78 void defaultAssertionTest(LogicValue value, String serializedAssertion) {
79 var pred = createPred(); 79 var pred = createPred();
80 var node = ProblemFactory.eINSTANCE.createNode(); 80 var node = ProblemFactory.eINSTANCE.createNode();
81 node.setName("a"); 81 node.setName("a");
@@ -88,12 +88,7 @@ class ProblemSerializerTest {
88 pred foo(node p). 88 pred foo(node p).
89 89
90 indiv a. 90 indiv a.
91 default foo(a):\040""" + valueAsString + ".\n"); 91 default\040""" + serializedAssertion + "\n");
92 }
93
94 static Stream<Arguments> defaultAssertionTest() {
95 return Stream.of(Arguments.of(LogicValue.TRUE, "true"), Arguments.of(LogicValue.FALSE, "false"),
96 Arguments.of(LogicValue.UNKNOWN, "unknown"), Arguments.of(LogicValue.ERROR, "error"));
97 } 92 }
98 93
99 @Test 94 @Test
@@ -161,6 +156,7 @@ class ProblemSerializerTest {
161 problem.getStatements().add(assertion); 156 problem.getStatements().add(assertion);
162 } 157 }
163 158
159
164 @Test 160 @Test
165 void implicitVariableTest() { 161 void implicitVariableTest() {
166 var pred = ProblemFactory.eINSTANCE.createPredicateDefinition(); 162 var pred = ProblemFactory.eINSTANCE.createPredicateDefinition();
@@ -232,20 +228,77 @@ class ProblemSerializerTest {
232 """); 228 """);
233 } 229 }
234 230
231 @Test
232 void unambiguousNameTest() {
233 createClassAndAssertion("Foo", "foo");
234
235 assertSerializedResult("""
236 class Foo {
237 Foo ref
238 }
239
240 ref(foo, foo).
241 """);
242 }
243
244 @Test
245 void ambiguousNameTest() {
246 createClassAndAssertion("Foo", "foo");
247 createClassAndAssertion("Bar", "bar");
248
249 assertSerializedResult("""
250 class Foo {
251 Foo ref
252 }
253
254 Foo::ref(foo, foo).
255
256 class Bar {
257 Bar ref
258 }
259
260 Bar::ref(bar, bar).
261 """);
262 }
263
264 private void createClassAndAssertion(String className, String nodeName) {
265 var classDeclaration = ProblemFactory.eINSTANCE.createClassDeclaration();
266 classDeclaration.setName(className);
267 var referenceDeclaration = ProblemFactory.eINSTANCE.createReferenceDeclaration();
268 referenceDeclaration.setReferenceType(classDeclaration);
269 referenceDeclaration.setName("ref");
270 classDeclaration.getFeatureDeclarations().add(referenceDeclaration);
271 problem.getStatements().add(classDeclaration);
272 var node = ProblemFactory.eINSTANCE.createNode();
273 node.setName(nodeName);
274 problem.getNodes().add(node);
275 createBinaryAssertion(referenceDeclaration, node, node);
276 }
277
278 private void createBinaryAssertion(Relation relation, Node from, Node to) {
279 var assertion = ProblemFactory.eINSTANCE.createAssertion();
280 assertion.setRelation(relation);
281 var fromArgument = ProblemFactory.eINSTANCE.createNodeAssertionArgument();
282 fromArgument.setNode(from);
283 assertion.getArguments().add(fromArgument);
284 var toArgument = ProblemFactory.eINSTANCE.createNodeAssertionArgument();
285 toArgument.setNode(to);
286 assertion.getArguments().add(toArgument);
287 var value = ProblemFactory.eINSTANCE.createLogicConstant();
288 value.setLogicValue(LogicValue.TRUE);
289 assertion.setValue(value);
290 problem.getStatements().add(assertion);
291 }
292
235 private void assertSerializedResult(String expected) { 293 private void assertSerializedResult(String expected) {
236 var outputStream = new ByteArrayOutputStream(); 294 String problemString;
237 try { 295 try (var outputStream = new ByteArrayOutputStream()) {
238 resource.save(outputStream, Map.of()); 296 resource.save(outputStream, Map.of());
297 problemString = outputStream.toString();
239 } catch (IOException e) { 298 } catch (IOException e) {
240 throw new AssertionError("Failed to serialize problem", e); 299 throw new AssertionError("Failed to serialize problem", e);
241 } finally {
242 try {
243 outputStream.close();
244 } catch (IOException e) {
245 // Nothing to handle in a test.
246 }
247 } 300 }
248 var problemString = outputStream.toString(); 301 // Nothing to handle in a test.
249 302
250 assertThat(problemString.replace("\r\n", "\n"), equalTo(expected.replace("\r\n", "\n"))); 303 assertThat(problemString.replace("\r\n", "\n"), equalTo(expected.replace("\r\n", "\n")));
251 } 304 }
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java
index ce3efb21..22f38ca9 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstExplorer.java
@@ -10,10 +10,10 @@ import tools.refinery.store.model.Model;
10import java.util.Random; 10import java.util.Random;
11 11
12public class BestFirstExplorer extends BestFirstWorker { 12public class BestFirstExplorer extends BestFirstWorker {
13 final int id; 13 final long id;
14 Random random; 14 Random random;
15 15
16 public BestFirstExplorer(BestFirstStoreManager storeManager, Model model, int id) { 16 public BestFirstExplorer(BestFirstStoreManager storeManager, Model model, long id) {
17 super(storeManager, model); 17 super(storeManager, model);
18 this.id = id; 18 this.id = id;
19 // The use of a non-cryptographic random generator is safe here, because we only use it to direct the state 19 // The use of a non-cryptographic random generator is safe here, because we only use it to direct the state
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java
index 3d32f84c..c20ab9a0 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/strategy/BestFirstStoreManager.java
@@ -79,7 +79,7 @@ public class BestFirstStoreManager {
79 startExploration(initial, 1); 79 startExploration(initial, 1);
80 } 80 }
81 81
82 public void startExploration(Version initial, int randomSeed) { 82 public void startExploration(Version initial, long randomSeed) {
83 BestFirstExplorer bestFirstExplorer = new BestFirstExplorer(this, modelStore.createModelForState(initial), 83 BestFirstExplorer bestFirstExplorer = new BestFirstExplorer(this, modelStore.createModelForState(initial),
84 randomSeed); 84 randomSeed);
85 bestFirstExplorer.explore(); 85 bestFirstExplorer.explore();
diff --git a/subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java b/subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java
index a2c56a6b..5ee97ce1 100644
--- a/subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java
+++ b/subprojects/store-reasoning-scope/src/test/java/tools/refinery/store/reasoning/scope/PredicateScopeTest.java
@@ -27,7 +27,6 @@ import tools.refinery.store.reasoning.translator.containment.ContainmentHierarch
27import tools.refinery.store.reasoning.translator.metamodel.Metamodel; 27import tools.refinery.store.reasoning.translator.metamodel.Metamodel;
28import tools.refinery.store.reasoning.translator.metamodel.MetamodelTranslator; 28import tools.refinery.store.reasoning.translator.metamodel.MetamodelTranslator;
29import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; 29import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator;
30import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity;
31import tools.refinery.store.representation.TruthValue; 30import tools.refinery.store.representation.TruthValue;
32import tools.refinery.store.representation.cardinality.CardinalityIntervals; 31import tools.refinery.store.representation.cardinality.CardinalityIntervals;
33import tools.refinery.store.statecoding.StateCoderAdapter; 32import tools.refinery.store.statecoding.StateCoderAdapter;
@@ -109,10 +108,16 @@ class PredicateScopeTest {
109 private ModelStore createStore() { 108 private ModelStore createStore() {
110 var metamodel = Metamodel.builder() 109 var metamodel = Metamodel.builder()
111 .type(index) 110 .type(index)
112 .reference(next, index, false, 111 .reference(next, builder -> builder
113 ConstrainedMultiplicity.of(CardinalityIntervals.LONE, nextInvalidMultiplicity), index, prev) 112 .source(index)
114 .reference(prev, index, false, 113 .target(index)
115 ConstrainedMultiplicity.of(CardinalityIntervals.LONE, prevInvalidMultiplicity), index, next) 114 .multiplicity(CardinalityIntervals.LONE, nextInvalidMultiplicity)
115 .opposite(prev))
116 .reference(prev, builder -> builder
117 .source(index)
118 .target(index)
119 .multiplicity(CardinalityIntervals.LONE, prevInvalidMultiplicity)
120 .opposite(next))
116 .build(); 121 .build();
117 return ModelStore.builder() 122 return ModelStore.builder()
118 .with(QueryInterpreterAdapter.builder()) 123 .with(QueryInterpreterAdapter.builder())
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/MapBasedSeed.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/MapBasedSeed.java
index 8b1c3bb3..3b78db02 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/MapBasedSeed.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/MapBasedSeed.java
@@ -12,19 +12,19 @@ import tools.refinery.store.tuple.Tuple;
12import java.util.Map; 12import java.util.Map;
13import java.util.Objects; 13import java.util.Objects;
14 14
15record MapBasedSeed<T>(int arity, Class<T> valueType, T reducedValue, Map<Tuple, T> map) implements Seed<T> { 15record MapBasedSeed<T>(int arity, Class<T> valueType, T majorityValue, Map<Tuple, T> map) implements Seed<T> {
16 @Override 16 @Override
17 public T get(Tuple key) { 17 public T get(Tuple key) {
18 var value = map.get(key); 18 var value = map.get(key);
19 return value == null ? reducedValue : value; 19 return value == null ? majorityValue : value;
20 } 20 }
21 21
22 @Override 22 @Override
23 public Cursor<Tuple, T> getCursor(T defaultValue, int nodeCount) { 23 public Cursor<Tuple, T> getCursor(T defaultValue, int nodeCount) {
24 if (Objects.equals(defaultValue, reducedValue)) { 24 if (Objects.equals(defaultValue, majorityValue)) {
25 return Cursors.of(map); 25 return Cursors.of(map);
26 } 26 }
27 return new CartesianProductCursor<>(arity, nodeCount, reducedValue, defaultValue, map); 27 return new CartesianProductCursor<>(arity, nodeCount, majorityValue, defaultValue, map);
28 } 28 }
29 29
30 private static class CartesianProductCursor<T> implements Cursor<Tuple, T> { 30 private static class CartesianProductCursor<T> implements Cursor<Tuple, T> {
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java
index 732efbcc..d9bad866 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java
@@ -19,7 +19,7 @@ public interface Seed<T> {
19 19
20 Class<T> valueType(); 20 Class<T> valueType();
21 21
22 T reducedValue(); 22 T majorityValue();
23 23
24 T get(Tuple key); 24 T get(Tuple key);
25 25
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInfo.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInfo.java
index d8c6a5ea..7241b032 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInfo.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInfo.java
@@ -7,9 +7,11 @@ package tools.refinery.store.reasoning.translator.crossreference;
7 7
8import tools.refinery.store.reasoning.representation.PartialRelation; 8import tools.refinery.store.reasoning.representation.PartialRelation;
9import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; 9import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity;
10import tools.refinery.store.representation.TruthValue;
10 11
11public record DirectedCrossReferenceInfo(PartialRelation sourceType, Multiplicity sourceMultiplicity, 12public record DirectedCrossReferenceInfo(PartialRelation sourceType, Multiplicity sourceMultiplicity,
12 PartialRelation targetType, Multiplicity targetMultiplicity) { 13 PartialRelation targetType, Multiplicity targetMultiplicity,
14 TruthValue defaultValue) {
13 public boolean isConstrained() { 15 public boolean isConstrained() {
14 return sourceMultiplicity.isConstrained() || targetMultiplicity.isConstrained(); 16 return sourceMultiplicity.isConstrained() || targetMultiplicity.isConstrained();
15 } 17 }
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInitializer.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInitializer.java
new file mode 100644
index 00000000..9347e91e
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceInitializer.java
@@ -0,0 +1,52 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.reasoning.translator.crossreference;
7
8import tools.refinery.store.model.Model;
9import tools.refinery.store.reasoning.ReasoningAdapter;
10import tools.refinery.store.reasoning.refinement.PartialModelInitializer;
11import tools.refinery.store.reasoning.representation.PartialRelation;
12import tools.refinery.store.reasoning.seed.ModelSeed;
13import tools.refinery.store.representation.Symbol;
14import tools.refinery.store.representation.TruthValue;
15import tools.refinery.store.tuple.Tuple;
16
17class DirectedCrossReferenceInitializer implements PartialModelInitializer {
18 private final PartialRelation linkType;
19 private final PartialRelation sourceType;
20 private final PartialRelation targetType;
21 private final Symbol<TruthValue> symbol;
22
23 public DirectedCrossReferenceInitializer(PartialRelation linkType, PartialRelation sourceType,
24 PartialRelation targetType, Symbol<TruthValue> symbol) {
25 this.linkType = linkType;
26 this.sourceType = sourceType;
27 this.targetType = targetType;
28 this.symbol = symbol;
29 }
30
31 @Override
32 public void initialize(Model model, ModelSeed modelSeed) {
33 var reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
34 var sourceRefiner = reasoningAdapter.getRefiner(sourceType);
35 var targetRefiner = reasoningAdapter.getRefiner(targetType);
36 var interpretation = model.getInterpretation(symbol);
37 var cursor = modelSeed.getCursor(linkType, symbol.defaultValue());
38 while (cursor.move()) {
39 var key = cursor.getKey();
40 var value = cursor.getValue();
41 interpretation.put(key, value);
42 if (value.must()) {
43 boolean merged = sourceRefiner.merge(Tuple.of(key.get(0)), TruthValue.TRUE) &&
44 targetRefiner.merge(Tuple.of(key.get(1)), TruthValue.TRUE);
45 if (!merged) {
46 throw new IllegalArgumentException("Failed to merge end types of reference %s for key %s"
47 .formatted(linkType, key));
48 }
49 }
50 }
51 }
52}
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceTranslator.java
index 9028337c..fc7477f1 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceTranslator.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceTranslator.java
@@ -5,6 +5,7 @@
5 */ 5 */
6package tools.refinery.store.reasoning.translator.crossreference; 6package tools.refinery.store.reasoning.translator.crossreference;
7 7
8import tools.refinery.store.dse.propagation.PropagationBuilder;
8import tools.refinery.store.dse.transition.Rule; 9import tools.refinery.store.dse.transition.Rule;
9import tools.refinery.store.model.ModelStoreBuilder; 10import tools.refinery.store.model.ModelStoreBuilder;
10import tools.refinery.store.model.ModelStoreConfiguration; 11import tools.refinery.store.model.ModelStoreConfiguration;
@@ -14,9 +15,9 @@ import tools.refinery.store.query.view.ForbiddenView;
14import tools.refinery.store.reasoning.lifting.DnfLifter; 15import tools.refinery.store.reasoning.lifting.DnfLifter;
15import tools.refinery.store.reasoning.literal.Concreteness; 16import tools.refinery.store.reasoning.literal.Concreteness;
16import tools.refinery.store.reasoning.literal.Modality; 17import tools.refinery.store.reasoning.literal.Modality;
17import tools.refinery.store.reasoning.refinement.RefinementBasedInitializer;
18import tools.refinery.store.reasoning.representation.PartialRelation; 18import tools.refinery.store.reasoning.representation.PartialRelation;
19import tools.refinery.store.reasoning.translator.PartialRelationTranslator; 19import tools.refinery.store.reasoning.translator.PartialRelationTranslator;
20import tools.refinery.store.reasoning.translator.TranslationException;
20import tools.refinery.store.reasoning.translator.multiplicity.InvalidMultiplicityErrorTranslator; 21import tools.refinery.store.reasoning.translator.multiplicity.InvalidMultiplicityErrorTranslator;
21import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; 22import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity;
22import tools.refinery.store.representation.Symbol; 23import tools.refinery.store.representation.Symbol;
@@ -24,6 +25,7 @@ import tools.refinery.store.representation.TruthValue;
24 25
25import static tools.refinery.store.query.literal.Literals.not; 26import static tools.refinery.store.query.literal.Literals.not;
26import static tools.refinery.store.reasoning.actions.PartialActionLiterals.add; 27import static tools.refinery.store.reasoning.actions.PartialActionLiterals.add;
28import static tools.refinery.store.reasoning.actions.PartialActionLiterals.merge;
27import static tools.refinery.store.reasoning.literal.PartialLiterals.*; 29import static tools.refinery.store.reasoning.literal.PartialLiterals.*;
28import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW; 30import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW;
29 31
@@ -35,7 +37,7 @@ public class DirectedCrossReferenceTranslator implements ModelStoreConfiguration
35 public DirectedCrossReferenceTranslator(PartialRelation linkType, DirectedCrossReferenceInfo info) { 37 public DirectedCrossReferenceTranslator(PartialRelation linkType, DirectedCrossReferenceInfo info) {
36 this.linkType = linkType; 38 this.linkType = linkType;
37 this.info = info; 39 this.info = info;
38 symbol = Symbol.of(linkType.name(), 2, TruthValue.class, TruthValue.UNKNOWN); 40 symbol = Symbol.of(linkType.name(), 2, TruthValue.class, info.defaultValue());
39 } 41 }
40 42
41 @Override 43 @Override
@@ -45,41 +47,77 @@ public class DirectedCrossReferenceTranslator implements ModelStoreConfiguration
45 var targetType = info.targetType(); 47 var targetType = info.targetType();
46 var mayNewSource = createMayHelper(sourceType, info.sourceMultiplicity(), false); 48 var mayNewSource = createMayHelper(sourceType, info.sourceMultiplicity(), false);
47 var mayNewTarget = createMayHelper(targetType, info.targetMultiplicity(), true); 49 var mayNewTarget = createMayHelper(targetType, info.targetMultiplicity(), true);
48 var forbiddenView = new ForbiddenView(symbol);
49 var mayName = DnfLifter.decorateName(name, Modality.MAY, Concreteness.PARTIAL); 50 var mayName = DnfLifter.decorateName(name, Modality.MAY, Concreteness.PARTIAL);
50 51
51 storeBuilder.with(PartialRelationTranslator.of(linkType) 52 var defaultValue = info.defaultValue();
52 .symbol(symbol) 53 if (defaultValue.must()) {
53 .may(Query.of(mayName, (builder, source, target) -> { 54 throw new TranslationException(linkType, "Unsupported default value %s for directed cross references %s"
55 .formatted(defaultValue, linkType));
56 }
57
58 var translator = PartialRelationTranslator.of(linkType);
59 translator.symbol(symbol);
60 if (defaultValue.may()) {
61 var forbiddenView = new ForbiddenView(symbol);
62 translator.may(Query.of(mayName, (builder, source, target) -> {
63 builder.clause(
64 mayNewSource.call(source),
65 mayNewTarget.call(target),
66 not(forbiddenView.call(source, target))
67 );
68 if (info.isConstrained()) {
69 // Violation of monotonicity:
70 // Edges violating upper multiplicity will not be marked as {@code ERROR}, but the
71 // corresponding error pattern will already mark the node as invalid.
72 builder.clause(
73 must(linkType.call(source, target)),
74 not(forbiddenView.call(source, target)),
75 may(sourceType.call(source)),
76 may(targetType.call(target))
77 );
78 }
79 }));
80 } else {
81 var propagationBuilder = storeBuilder.getAdapter(PropagationBuilder.class);
82 propagationBuilder.rule(Rule.of(name + "#invalidLink", (builder, p1, p2) -> {
83 builder.clause(
84 may(linkType.call(p1, p2)),
85 not(may(sourceType.call(p1)))
86 );
87 builder.clause(
88 may(linkType.call(p1, p2)),
89 not(may(targetType.call(p2)))
90 );
91 if (info.isConstrained()) {
92 builder.clause(
93 may(linkType.call(p1, p2)),
94 not(must(linkType.call(p1, p2))),
95 not(mayNewSource.call(p1))
96 );
54 builder.clause( 97 builder.clause(
55 mayNewSource.call(source), 98 may(linkType.call(p1, p2)),
56 mayNewTarget.call(target), 99 not(must(linkType.call(p1, p2))),
57 not(forbiddenView.call(source, target)) 100 not(mayNewTarget.call(p2))
58 ); 101 );
59 if (info.isConstrained()) { 102 }
60 // Violation of monotonicity: 103 builder.action(
61 // Edges violating upper multiplicity will not be marked as {@code ERROR}, but the 104 merge(linkType, TruthValue.FALSE, p1, p2)
62 // corresponding error pattern will already mark the node as invalid. 105 );
63 builder.clause( 106 }));
64 must(linkType.call(source, target)), 107 }
65 not(forbiddenView.call(source, target)), 108 translator.refiner(DirectedCrossReferenceRefiner.of(symbol, sourceType, targetType));
66 may(sourceType.call(source)), 109 translator.initializer(new DirectedCrossReferenceInitializer(linkType, sourceType, targetType, symbol));
67 may(targetType.call(target)) 110 translator.decision(Rule.of(linkType.name(), (builder, source, target) -> builder
68 ); 111 .clause(
69 } 112 may(linkType.call(source, target)),
70 })) 113 not(candidateMust(linkType.call(source, target))),
71 .refiner(DirectedCrossReferenceRefiner.of(symbol, sourceType, targetType)) 114 not(MULTI_VIEW.call(source)),
72 .initializer(new RefinementBasedInitializer<>(linkType)) 115 not(MULTI_VIEW.call(target))
73 .decision(Rule.of(linkType.name(), (builder, source, target) -> builder 116 )
74 .clause( 117 .action(
75 may(linkType.call(source, target)), 118 add(linkType, source, target)
76 not(candidateMust(linkType.call(source, target))), 119 )));
77 not(MULTI_VIEW.call(source)), 120 storeBuilder.with(translator);
78 not(MULTI_VIEW.call(target))
79 )
80 .action(
81 add(linkType, source, target)
82 ))));
83 121
84 storeBuilder.with(new InvalidMultiplicityErrorTranslator(sourceType, linkType, false, 122 storeBuilder.with(new InvalidMultiplicityErrorTranslator(sourceType, linkType, false,
85 info.sourceMultiplicity())); 123 info.sourceMultiplicity()));
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInfo.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInfo.java
index fe99bc54..34e9032a 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInfo.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInfo.java
@@ -7,8 +7,9 @@ package tools.refinery.store.reasoning.translator.crossreference;
7 7
8import tools.refinery.store.reasoning.representation.PartialRelation; 8import tools.refinery.store.reasoning.representation.PartialRelation;
9import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; 9import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity;
10import tools.refinery.store.representation.TruthValue;
10 11
11public record UndirectedCrossReferenceInfo(PartialRelation type, Multiplicity multiplicity) { 12public record UndirectedCrossReferenceInfo(PartialRelation type, Multiplicity multiplicity, TruthValue defaultValue) {
12 public boolean isConstrained() { 13 public boolean isConstrained() {
13 return multiplicity.isConstrained(); 14 return multiplicity.isConstrained();
14 } 15 }
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInitializer.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInitializer.java
new file mode 100644
index 00000000..77339aa0
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceInitializer.java
@@ -0,0 +1,84 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.reasoning.translator.crossreference;
7
8import org.jetbrains.annotations.NotNull;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.reasoning.ReasoningAdapter;
11import tools.refinery.store.reasoning.refinement.PartialModelInitializer;
12import tools.refinery.store.reasoning.representation.PartialRelation;
13import tools.refinery.store.reasoning.seed.ModelSeed;
14import tools.refinery.store.reasoning.translator.TranslationException;
15import tools.refinery.store.representation.Symbol;
16import tools.refinery.store.representation.TruthValue;
17import tools.refinery.store.tuple.Tuple;
18
19import java.util.LinkedHashMap;
20
21class UndirectedCrossReferenceInitializer implements PartialModelInitializer {
22 private final PartialRelation linkType;
23 private final PartialRelation sourceType;
24 private final Symbol<TruthValue> symbol;
25
26 UndirectedCrossReferenceInitializer(PartialRelation linkType, PartialRelation sourceType,
27 Symbol<TruthValue> symbol) {
28 this.linkType = linkType;
29 this.sourceType = sourceType;
30 this.symbol = symbol;
31 }
32
33 @Override
34 public void initialize(Model model, ModelSeed modelSeed) {
35 var reasoningAdapter = model.getAdapter(ReasoningAdapter.class);
36 var mergedMap = getMergedMap(modelSeed);
37 var sourceRefiner = reasoningAdapter.getRefiner(sourceType);
38 var interpretation = model.getInterpretation(symbol);
39 for (var entry : mergedMap.entrySet()) {
40 var key = entry.getKey();
41 var value = entry.getValue();
42 interpretation.put(key, value);
43 if (value.must()) {
44 boolean merged = sourceRefiner.merge(Tuple.of(key.get(0)), TruthValue.TRUE) &&
45 sourceRefiner.merge(Tuple.of(key.get(1)), TruthValue.TRUE);
46 if (!merged) {
47 throw new IllegalArgumentException("Failed to merge end types of reference %s for key %s"
48 .formatted(linkType, key));
49 }
50 }
51 }
52 }
53
54 @NotNull
55 private LinkedHashMap<Tuple, TruthValue> getMergedMap(ModelSeed modelSeed) {
56 var defaultValue = symbol.defaultValue();
57 var originalMap = new LinkedHashMap<Tuple, TruthValue>();
58 var cursor = modelSeed.getCursor(linkType, defaultValue);
59 while (cursor.move()) {
60 if (originalMap.put(cursor.getKey(), cursor.getValue()) != null) {
61 throw new TranslationException(linkType, "Duplicate value for key " + cursor.getKey());
62 }
63 }
64 var mergedMap = LinkedHashMap.<Tuple, TruthValue>newLinkedHashMap(originalMap.size());
65 for (var entry : originalMap.entrySet()) {
66 var key = entry.getKey();
67 var value = entry.getValue();
68 int first = key.get(0);
69 int second = key.get(1);
70 var oppositeKey = Tuple.of(second, first);
71 var oppositeValue = originalMap.get(oppositeKey);
72 if (oppositeValue != null && second < first) {
73 // Already processed entry.
74 continue;
75 }
76 var mergedValue = value.merge(oppositeValue == null ? defaultValue : oppositeValue);
77 mergedMap.put(key, mergedValue);
78 if (first != second) {
79 mergedMap.put(oppositeKey, mergedValue);
80 }
81 }
82 return mergedMap;
83 }
84}
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceTranslator.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceTranslator.java
index c554e2a4..b76838b3 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceTranslator.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/UndirectedCrossReferenceTranslator.java
@@ -5,6 +5,7 @@
5 */ 5 */
6package tools.refinery.store.reasoning.translator.crossreference; 6package tools.refinery.store.reasoning.translator.crossreference;
7 7
8import tools.refinery.store.dse.propagation.PropagationBuilder;
8import tools.refinery.store.dse.transition.Rule; 9import tools.refinery.store.dse.transition.Rule;
9import tools.refinery.store.model.ModelStoreBuilder; 10import tools.refinery.store.model.ModelStoreBuilder;
10import tools.refinery.store.model.ModelStoreConfiguration; 11import tools.refinery.store.model.ModelStoreConfiguration;
@@ -13,15 +14,16 @@ import tools.refinery.store.query.view.ForbiddenView;
13import tools.refinery.store.reasoning.lifting.DnfLifter; 14import tools.refinery.store.reasoning.lifting.DnfLifter;
14import tools.refinery.store.reasoning.literal.Concreteness; 15import tools.refinery.store.reasoning.literal.Concreteness;
15import tools.refinery.store.reasoning.literal.Modality; 16import tools.refinery.store.reasoning.literal.Modality;
16import tools.refinery.store.reasoning.refinement.RefinementBasedInitializer;
17import tools.refinery.store.reasoning.representation.PartialRelation; 17import tools.refinery.store.reasoning.representation.PartialRelation;
18import tools.refinery.store.reasoning.translator.PartialRelationTranslator; 18import tools.refinery.store.reasoning.translator.PartialRelationTranslator;
19import tools.refinery.store.reasoning.translator.TranslationException;
19import tools.refinery.store.reasoning.translator.multiplicity.InvalidMultiplicityErrorTranslator; 20import tools.refinery.store.reasoning.translator.multiplicity.InvalidMultiplicityErrorTranslator;
20import tools.refinery.store.representation.Symbol; 21import tools.refinery.store.representation.Symbol;
21import tools.refinery.store.representation.TruthValue; 22import tools.refinery.store.representation.TruthValue;
22 23
23import static tools.refinery.store.query.literal.Literals.not; 24import static tools.refinery.store.query.literal.Literals.not;
24import static tools.refinery.store.reasoning.actions.PartialActionLiterals.add; 25import static tools.refinery.store.reasoning.actions.PartialActionLiterals.add;
26import static tools.refinery.store.reasoning.actions.PartialActionLiterals.merge;
25import static tools.refinery.store.reasoning.literal.PartialLiterals.*; 27import static tools.refinery.store.reasoning.literal.PartialLiterals.*;
26import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW; 28import static tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator.MULTI_VIEW;
27 29
@@ -33,50 +35,77 @@ public class UndirectedCrossReferenceTranslator implements ModelStoreConfigurati
33 public UndirectedCrossReferenceTranslator(PartialRelation linkType, UndirectedCrossReferenceInfo info) { 35 public UndirectedCrossReferenceTranslator(PartialRelation linkType, UndirectedCrossReferenceInfo info) {
34 this.linkType = linkType; 36 this.linkType = linkType;
35 this.info = info; 37 this.info = info;
36 symbol = Symbol.of(linkType.name(), 2, TruthValue.class, TruthValue.UNKNOWN); 38 symbol = Symbol.of(linkType.name(), 2, TruthValue.class, info.defaultValue());
37 } 39 }
38 40
39 @Override 41 @Override
40 public void apply(ModelStoreBuilder storeBuilder) { 42 public void apply(ModelStoreBuilder storeBuilder) {
41 var name = linkType.name(); 43 var name = linkType.name();
42 var type = info.type(); 44 var type = info.type();
43 var forbiddenView = new ForbiddenView(symbol);
44 var mayName = DnfLifter.decorateName(name, Modality.MAY, Concreteness.PARTIAL); 45 var mayName = DnfLifter.decorateName(name, Modality.MAY, Concreteness.PARTIAL);
45 46
47 var defaultValue = info.defaultValue();
48 if (defaultValue.must()) {
49 throw new TranslationException(linkType, "Unsupported default value %s for directed cross references %s"
50 .formatted(defaultValue, linkType));
51 }
52
46 var mayNewSource = CrossReferenceUtils.createMayHelper(linkType, type, info.multiplicity(), false); 53 var mayNewSource = CrossReferenceUtils.createMayHelper(linkType, type, info.multiplicity(), false);
47 54
48 storeBuilder.with(PartialRelationTranslator.of(linkType) 55 var translator = PartialRelationTranslator.of(linkType);
49 .symbol(symbol) 56 translator.symbol(symbol);
50 .may(Query.of(mayName, (builder, source, target) -> { 57 if (defaultValue.may()) {
58 var forbiddenView = new ForbiddenView(symbol);
59 translator.may(Query.of(mayName, (builder, source, target) -> {
60 builder.clause(
61 mayNewSource.call(source),
62 mayNewSource.call(target),
63 not(forbiddenView.call(source, target))
64 );
65 if (info.isConstrained()) {
66 // Violation of monotonicity:
67 // Edges violating upper multiplicity will not be marked as {@code ERROR}, but the
68 // corresponding error pattern will already mark the node as invalid.
69 builder.clause(
70 must(linkType.call(source, target)),
71 not(forbiddenView.call(source, target)),
72 may(type.call(source)),
73 may(type.call(target))
74 );
75 }
76 }));
77 } else {
78 var propagationBuilder = storeBuilder.getAdapter(PropagationBuilder.class);
79 propagationBuilder.rule(Rule.of(name + "#invalidLink", (builder, p1, p2) -> {
80 builder.clause(
81 may(linkType.call(p1, p2)),
82 not(may(type.call(p1)))
83 );
84 if (info.isConstrained()) {
51 builder.clause( 85 builder.clause(
52 mayNewSource.call(source), 86 may(linkType.call(p1, p2)),
53 mayNewSource.call(target), 87 not(must(linkType.call(p1, p2))),
54 not(forbiddenView.call(source, target)) 88 not(mayNewSource.call(p1))
55 ); 89 );
56 if (info.isConstrained()) { 90 }
57 // Violation of monotonicity: 91 builder.action(
58 // Edges violating upper multiplicity will not be marked as {@code ERROR}, but the 92 merge(linkType, TruthValue.FALSE, p1, p2)
59 // corresponding error pattern will already mark the node as invalid. 93 );
60 builder.clause( 94 }));
61 must(linkType.call(source, target)), 95 }
62 not(forbiddenView.call(source, target)), 96 translator.refiner(UndirectedCrossReferenceRefiner.of(symbol, type));
63 may(type.call(source)), 97 translator.initializer(new UndirectedCrossReferenceInitializer(linkType, type, symbol));
64 may(type.call(target)) 98 translator.decision(Rule.of(linkType.name(), (builder, source, target) -> builder
65 ); 99 .clause(
66 } 100 may(linkType.call(source, target)),
67 })) 101 not(candidateMust(linkType.call(source, target))),
68 .refiner(UndirectedCrossReferenceRefiner.of(symbol, type)) 102 not(MULTI_VIEW.call(source)),
69 .initializer(new RefinementBasedInitializer<>(linkType)) 103 not(MULTI_VIEW.call(target))
70 .decision(Rule.of(linkType.name(), (builder, source, target) -> builder 104 )
71 .clause( 105 .action(
72 may(linkType.call(source, target)), 106 add(linkType, source, target)
73 not(candidateMust(linkType.call(source, target))), 107 )));
74 not(MULTI_VIEW.call(source)), 108 storeBuilder.with(translator);
75 not(MULTI_VIEW.call(target))
76 )
77 .action(
78 add(linkType, source, target)
79 ))));
80 109
81 storeBuilder.with(new InvalidMultiplicityErrorTranslator(type, linkType, false, info.multiplicity())); 110 storeBuilder.with(new InvalidMultiplicityErrorTranslator(type, linkType, false, info.multiplicity()));
82 } 111 }
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java
index 74022fc6..a5047768 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java
@@ -16,6 +16,7 @@ import tools.refinery.store.reasoning.translator.multiplicity.UnconstrainedMulti
16import tools.refinery.store.reasoning.translator.typehierarchy.TypeInfo; 16import tools.refinery.store.reasoning.translator.typehierarchy.TypeInfo;
17 17
18import java.util.*; 18import java.util.*;
19import java.util.function.Consumer;
19 20
20public class MetamodelBuilder { 21public class MetamodelBuilder {
21 private final ContainedTypeHierarchyBuilder typeHierarchyBuilder = new ContainedTypeHierarchyBuilder(); 22 private final ContainedTypeHierarchyBuilder typeHierarchyBuilder = new ContainedTypeHierarchyBuilder();
@@ -68,6 +69,12 @@ public class MetamodelBuilder {
68 return this; 69 return this;
69 } 70 }
70 71
72 public MetamodelBuilder reference(PartialRelation linkType, Consumer<ReferenceInfoBuilder> callback) {
73 var builder = ReferenceInfo.builder();
74 callback.accept(builder);
75 return reference(linkType, builder.build());
76 }
77
71 public MetamodelBuilder reference(PartialRelation linkType, ReferenceInfo info) { 78 public MetamodelBuilder reference(PartialRelation linkType, ReferenceInfo info) {
72 if (linkType.arity() != 2) { 79 if (linkType.arity() != 2) {
73 throw new TranslationException(linkType, 80 throw new TranslationException(linkType,
@@ -81,47 +88,6 @@ public class MetamodelBuilder {
81 return this; 88 return this;
82 } 89 }
83 90
84 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType, boolean containment,
85 Multiplicity multiplicity, PartialRelation targetType,
86 PartialRelation opposite) {
87 return reference(linkType, new ReferenceInfo(containment, sourceType, multiplicity, targetType, opposite));
88 }
89
90 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType, Multiplicity multiplicity,
91 PartialRelation targetType, PartialRelation opposite) {
92 return reference(linkType, sourceType, false, multiplicity, targetType, opposite);
93 }
94
95 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType,
96 boolean containment, PartialRelation targetType, PartialRelation opposite) {
97 return reference(linkType, sourceType, containment, UnconstrainedMultiplicity.INSTANCE, targetType, opposite);
98 }
99
100 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType, PartialRelation targetType,
101 PartialRelation opposite) {
102 return reference(linkType, sourceType, UnconstrainedMultiplicity.INSTANCE, targetType, opposite);
103 }
104
105 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType, boolean containment,
106 Multiplicity multiplicity, PartialRelation targetType) {
107 return reference(linkType, sourceType, containment, multiplicity, targetType, null);
108 }
109
110 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType, Multiplicity multiplicity,
111 PartialRelation targetType) {
112 return reference(linkType, sourceType, multiplicity, targetType, null);
113 }
114
115 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType, boolean containment,
116 PartialRelation targetType) {
117 return reference(linkType, sourceType, containment, targetType, null);
118 }
119
120 public MetamodelBuilder reference(PartialRelation linkType, PartialRelation sourceType,
121 PartialRelation targetType) {
122 return reference(linkType, sourceType, targetType, null);
123 }
124
125 public MetamodelBuilder references(Collection<Map.Entry<PartialRelation, ReferenceInfo>> entries) { 91 public MetamodelBuilder references(Collection<Map.Entry<PartialRelation, ReferenceInfo>> entries) {
126 for (var entry : entries) { 92 for (var entry : entries) {
127 reference(entry.getKey(), entry.getValue()); 93 reference(entry.getKey(), entry.getValue());
@@ -160,10 +126,12 @@ public class MetamodelBuilder {
160 var targetType = info.targetType(); 126 var targetType = info.targetType();
161 var opposite = info.opposite(); 127 var opposite = info.opposite();
162 Multiplicity targetMultiplicity = UnconstrainedMultiplicity.INSTANCE; 128 Multiplicity targetMultiplicity = UnconstrainedMultiplicity.INSTANCE;
129 var defaultValue = info.defaultValue();
163 if (opposite != null) { 130 if (opposite != null) {
164 var oppositeInfo = referenceInfoMap.get(opposite); 131 var oppositeInfo = referenceInfoMap.get(opposite);
165 validateOpposite(linkType, info, opposite, oppositeInfo); 132 validateOpposite(linkType, info, opposite, oppositeInfo);
166 targetMultiplicity = oppositeInfo.multiplicity(); 133 targetMultiplicity = oppositeInfo.multiplicity();
134 defaultValue = defaultValue.merge(oppositeInfo.defaultValue());
167 if (oppositeInfo.containment()) { 135 if (oppositeInfo.containment()) {
168 // Skip processing this reference and process it once we encounter its containment opposite. 136 // Skip processing this reference and process it once we encounter its containment opposite.
169 return; 137 return;
@@ -175,7 +143,7 @@ public class MetamodelBuilder {
175 targetType, linkType, sourceType)); 143 targetType, linkType, sourceType));
176 } 144 }
177 undirectedCrossReferences.put(linkType, new UndirectedCrossReferenceInfo(sourceType, 145 undirectedCrossReferences.put(linkType, new UndirectedCrossReferenceInfo(sourceType,
178 info.multiplicity())); 146 info.multiplicity(), defaultValue));
179 return; 147 return;
180 } 148 }
181 oppositeReferences.put(opposite, linkType); 149 oppositeReferences.put(opposite, linkType);
@@ -185,7 +153,7 @@ public class MetamodelBuilder {
185 return; 153 return;
186 } 154 }
187 directedCrossReferences.put(linkType, new DirectedCrossReferenceInfo(sourceType, info.multiplicity(), 155 directedCrossReferences.put(linkType, new DirectedCrossReferenceInfo(sourceType, info.multiplicity(),
188 targetType, targetMultiplicity)); 156 targetType, targetMultiplicity, defaultValue));
189 } 157 }
190 158
191 private void processContainmentInfo(PartialRelation linkType, ReferenceInfo info, 159 private void processContainmentInfo(PartialRelation linkType, ReferenceInfo info,
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfo.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfo.java
index 9a6b4012..9d7fc9c3 100644
--- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfo.java
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfo.java
@@ -7,7 +7,11 @@ package tools.refinery.store.reasoning.translator.metamodel;
7 7
8import tools.refinery.store.reasoning.representation.PartialRelation; 8import tools.refinery.store.reasoning.representation.PartialRelation;
9import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity; 9import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity;
10import tools.refinery.store.representation.TruthValue;
10 11
11public record ReferenceInfo(boolean containment, PartialRelation sourceType, Multiplicity multiplicity, 12public record ReferenceInfo(boolean containment, PartialRelation sourceType, Multiplicity multiplicity,
12 PartialRelation targetType, PartialRelation opposite) { 13 PartialRelation targetType, PartialRelation opposite, TruthValue defaultValue) {
14 public static ReferenceInfoBuilder builder() {
15 return new ReferenceInfoBuilder();
16 }
13} 17}
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfoBuilder.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfoBuilder.java
new file mode 100644
index 00000000..43d01503
--- /dev/null
+++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/ReferenceInfoBuilder.java
@@ -0,0 +1,84 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.reasoning.translator.metamodel;
7
8import org.jetbrains.annotations.NotNull;
9import org.jetbrains.annotations.Nullable;
10import tools.refinery.store.reasoning.representation.PartialRelation;
11import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity;
12import tools.refinery.store.reasoning.translator.multiplicity.Multiplicity;
13import tools.refinery.store.reasoning.translator.multiplicity.UnconstrainedMultiplicity;
14import tools.refinery.store.representation.TruthValue;
15import tools.refinery.store.representation.cardinality.CardinalityInterval;
16
17public final class ReferenceInfoBuilder {
18 private boolean containment;
19 private PartialRelation sourceType;
20 private Multiplicity multiplicity = UnconstrainedMultiplicity.INSTANCE;
21 private PartialRelation targetType;
22 private PartialRelation opposite;
23 private TruthValue defaultValue = TruthValue.UNKNOWN;
24
25 ReferenceInfoBuilder() {
26 }
27
28 public ReferenceInfoBuilder source(@NotNull PartialRelation sourceType) {
29 if (sourceType.arity() != 1) {
30 throw new IllegalArgumentException("Source type %s must be of arity 1".formatted(sourceType));
31 }
32 this.sourceType = sourceType;
33 return this;
34 }
35
36 public ReferenceInfoBuilder target(@NotNull PartialRelation targetType) {
37 if (targetType.arity() != 1) {
38 throw new IllegalArgumentException("Target type %s must be of arity 1".formatted(targetType));
39 }
40 this.targetType = targetType;
41 return this;
42 }
43
44 public ReferenceInfoBuilder containment(boolean containment) {
45 this.containment = containment;
46 return this;
47 }
48
49 public ReferenceInfoBuilder multiplicity(@NotNull Multiplicity multiplicity) {
50 this.multiplicity = multiplicity;
51 return this;
52 }
53
54 public ReferenceInfoBuilder multiplicity(@NotNull CardinalityInterval multiplicityInterval,
55 @NotNull PartialRelation errorSymbol) {
56 return multiplicity(ConstrainedMultiplicity.of(multiplicityInterval, errorSymbol));
57 }
58
59 public ReferenceInfoBuilder opposite(@Nullable PartialRelation opposite) {
60 if (opposite != null && opposite.arity() != 2) {
61 throw new IllegalArgumentException("Opposite %s must be of arity 2".formatted(targetType));
62 }
63 this.opposite = opposite;
64 return this;
65 }
66
67 public ReferenceInfoBuilder defaultValue(@NotNull TruthValue defaultValue) {
68 if (defaultValue.must()) {
69 throw new IllegalArgumentException("Unsupported default value");
70 }
71 this.defaultValue = defaultValue;
72 return this;
73 }
74
75 public ReferenceInfo build() {
76 if (sourceType == null) {
77 throw new IllegalStateException("Source type is required");
78 }
79 if (targetType == null) {
80 throw new IllegalStateException("Target type is required");
81 }
82 return new ReferenceInfo(containment, sourceType, multiplicity, targetType, opposite, defaultValue);
83 }
84}
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java
index 0f1a1006..ba6ba6da 100644
--- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java
+++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilderTest.java
@@ -8,7 +8,6 @@ package tools.refinery.store.reasoning.translator.metamodel;
8import org.junit.jupiter.api.Test; 8import org.junit.jupiter.api.Test;
9import tools.refinery.store.reasoning.representation.PartialRelation; 9import tools.refinery.store.reasoning.representation.PartialRelation;
10import tools.refinery.store.reasoning.translator.TranslationException; 10import tools.refinery.store.reasoning.translator.TranslationException;
11import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity;
12import tools.refinery.store.representation.cardinality.CardinalityIntervals; 11import tools.refinery.store.representation.cardinality.CardinalityIntervals;
13 12
14import static org.junit.jupiter.api.Assertions.assertThrows; 13import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -24,8 +23,13 @@ class MetamodelBuilderTest {
24 var builder = Metamodel.builder() 23 var builder = Metamodel.builder()
25 .type(university) 24 .type(university)
26 .type(course) 25 .type(course)
27 .reference(courses, university, course, location) 26 .reference(courses, referenceBuilder -> referenceBuilder
28 .reference(location, course, university); 27 .source(university)
28 .target(course)
29 .opposite(location))
30 .reference(location, referenceBuilder -> referenceBuilder
31 .source(course)
32 .target(university));
29 33
30 assertThrows(TranslationException.class, builder::build); 34 assertThrows(TranslationException.class, builder::build);
31 } 35 }
@@ -35,8 +39,14 @@ class MetamodelBuilderTest {
35 var builder = Metamodel.builder() 39 var builder = Metamodel.builder()
36 .type(university) 40 .type(university)
37 .type(course) 41 .type(course)
38 .reference(courses, university, course, location) 42 .reference(courses, referenceBuilder -> referenceBuilder
39 .reference(location, course, course, courses); 43 .source(university)
44 .target(course)
45 .opposite(location))
46 .reference(location, referenceBuilder -> referenceBuilder
47 .source(course)
48 .target(course)
49 .opposite(courses));
40 50
41 assertThrows(TranslationException.class, builder::build); 51 assertThrows(TranslationException.class, builder::build);
42 } 52 }
@@ -48,10 +58,16 @@ class MetamodelBuilderTest {
48 var builder = Metamodel.builder() 58 var builder = Metamodel.builder()
49 .type(university) 59 .type(university)
50 .type(course) 60 .type(course)
51 .reference(courses, university, true, course, location) 61 .reference(courses, referenceBuilder -> referenceBuilder
52 .reference(location, course, 62 .containment(true)
53 ConstrainedMultiplicity.of(CardinalityIntervals.atLeast(2), invalidMultiplicity), 63 .source(university)
54 university, courses); 64 .target(course)
65 .opposite(location))
66 .reference(location, referenceBuilder -> referenceBuilder
67 .source(course)
68 .multiplicity(CardinalityIntervals.atLeast(2), invalidMultiplicity)
69 .target(university)
70 .opposite(courses));
55 71
56 assertThrows(TranslationException.class, builder::build); 72 assertThrows(TranslationException.class, builder::build);
57 } 73 }
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java
index 6c2f55af..88e6a4d7 100644
--- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java
+++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelTest.java
@@ -16,7 +16,6 @@ import tools.refinery.store.reasoning.representation.PartialRelation;
16import tools.refinery.store.reasoning.seed.ModelSeed; 16import tools.refinery.store.reasoning.seed.ModelSeed;
17import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; 17import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator;
18import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; 18import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator;
19import tools.refinery.store.reasoning.translator.multiplicity.ConstrainedMultiplicity;
20import tools.refinery.store.representation.TruthValue; 19import tools.refinery.store.representation.TruthValue;
21import tools.refinery.store.representation.cardinality.CardinalityIntervals; 20import tools.refinery.store.representation.cardinality.CardinalityIntervals;
22import tools.refinery.store.tuple.Tuple; 21import tools.refinery.store.tuple.Tuple;
@@ -45,12 +44,23 @@ class MetamodelTest {
45 .type(teacher, person) 44 .type(teacher, person)
46 .type(university) 45 .type(university)
47 .type(course) 46 .type(course)
48 .reference(courses, university, true, course, location) 47 .reference(courses, builder -> builder
49 .reference(location, course, university, courses) 48 .containment(true)
50 .reference(lecturer, course, 49 .source(university)
51 ConstrainedMultiplicity.of(CardinalityIntervals.ONE, invalidLecturerCount), teacher) 50 .target(course)
52 .reference(enrolledStudents, course, 51 .opposite(location))
53 ConstrainedMultiplicity.of(CardinalityIntervals.SOME, invalidStudentCount), student) 52 .reference(location, builder -> builder
53 .source(course)
54 .target(university)
55 .opposite(courses))
56 .reference(lecturer, builder -> builder
57 .source(course)
58 .multiplicity(CardinalityIntervals.ONE, invalidLecturerCount)
59 .target(teacher))
60 .reference(enrolledStudents, builder -> builder
61 .source(course)
62 .multiplicity(CardinalityIntervals.SOME, invalidStudentCount)
63 .target(student))
54 .build(); 64 .build();
55 65
56 var seed = ModelSeed.builder(5) 66 var seed = ModelSeed.builder(5)
@@ -105,10 +115,12 @@ class MetamodelTest {
105 var metamodel = Metamodel.builder() 115 var metamodel = Metamodel.builder()
106 .type(university) 116 .type(university)
107 .type(course) 117 .type(course)
108 .reference(courses, university, true, course) 118 .reference(courses, builder -> builder
119 .containment(true)
120 .source(university)
121 .target(course))
109 .build(); 122 .build();
110 123
111
112 var seed = ModelSeed.builder(4) 124 var seed = ModelSeed.builder(4)
113 .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder 125 .seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder
114 .reducedValue(CardinalityIntervals.ONE) 126 .reducedValue(CardinalityIntervals.ONE)
diff --git a/yarn.lock b/yarn.lock
index 16ac69f0..a99aced7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1234,12 +1234,12 @@ __metadata:
1234 languageName: node 1234 languageName: node
1235 linkType: hard 1235 linkType: hard
1236 1236
1237"@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7": 1237"@babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.5, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7":
1238 version: 7.23.5 1238 version: 7.23.6
1239 resolution: "@babel/runtime@npm:7.23.5" 1239 resolution: "@babel/runtime@npm:7.23.6"
1240 dependencies: 1240 dependencies:
1241 regenerator-runtime: "npm:^0.14.0" 1241 regenerator-runtime: "npm:^0.14.0"
1242 checksum: ca679cc91bb7e424bc2db87bb58cc3b06ade916b9adb21fbbdc43e54cdaacb3eea201ceba2a0464b11d2eb65b9fe6a6ffcf4d7521fa52994f19be96f1af14788 1242 checksum: d886954e985ef8e421222f7a2848884d96a752e0020d3078b920dd104e672fdf23bcc6f51a44313a048796319f1ac9d09c2c88ec8cbb4e1f09174bcd3335b9ff
1243 languageName: node 1243 languageName: node
1244 linkType: hard 1244 linkType: hard
1245 1245
@@ -1348,21 +1348,21 @@ __metadata:
1348 languageName: node 1348 languageName: node
1349 linkType: hard 1349 linkType: hard
1350 1350
1351"@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.1.4, @codemirror/state@npm:^6.2.0, @codemirror/state@npm:^6.3.2": 1351"@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.1.4, @codemirror/state@npm:^6.2.0, @codemirror/state@npm:^6.3.3":
1352 version: 6.3.2 1352 version: 6.3.3
1353 resolution: "@codemirror/state@npm:6.3.2" 1353 resolution: "@codemirror/state@npm:6.3.3"
1354 checksum: d0fa8c78bbccacc6bff5ac661a8e825c21c12fd45294d9a2e181d50af8294165b749094a3fbfc173a0aac72eabc3bf28aa48dfebc330239663680b2ded701ff5 1354 checksum: 97f0174dd6aa43d6293630b0024918ce1bb1f7833de8fa75006de8b7dbd963e2bb8b5e7a805f5a98492a0379d8b60faaee319d42583562b8ea6347ab8b63bf5f
1355 languageName: node 1355 languageName: node
1356 linkType: hard 1356 linkType: hard
1357 1357
1358"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.22.1": 1358"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.22.3":
1359 version: 6.22.1 1359 version: 6.22.3
1360 resolution: "@codemirror/view@npm:6.22.1" 1360 resolution: "@codemirror/view@npm:6.22.3"
1361 dependencies: 1361 dependencies:
1362 "@codemirror/state": "npm:^6.1.4" 1362 "@codemirror/state": "npm:^6.1.4"
1363 style-mod: "npm:^4.1.0" 1363 style-mod: "npm:^4.1.0"
1364 w3c-keyname: "npm:^2.2.4" 1364 w3c-keyname: "npm:^2.2.4"
1365 checksum: 142a861c2bf6d0ba2817eaffdf985c19b556cc98af1bd565b1e9286bfcaf17eb12837ce41633a2462fca1731d043781c21c778fb0d5ae928c03c6a6f42485c78 1365 checksum: ed5e48923f0522d2c55c0bb48eadb06823afaa5fb037b09b53b8eb00acdd4c7cb90816ee023ba90d7c70f7612bb8ab749d232398a6ae8bc2dc4df8d653ba7386
1366 languageName: node 1366 languageName: node
1367 linkType: hard 1367 linkType: hard
1368 1368
@@ -1421,14 +1421,14 @@ __metadata:
1421 languageName: node 1421 languageName: node
1422 linkType: hard 1422 linkType: hard
1423 1423
1424"@emotion/react@npm:^11.11.1": 1424"@emotion/react@npm:^11.11.3":
1425 version: 11.11.1 1425 version: 11.11.3
1426 resolution: "@emotion/react@npm:11.11.1" 1426 resolution: "@emotion/react@npm:11.11.3"
1427 dependencies: 1427 dependencies:
1428 "@babel/runtime": "npm:^7.18.3" 1428 "@babel/runtime": "npm:^7.18.3"
1429 "@emotion/babel-plugin": "npm:^11.11.0" 1429 "@emotion/babel-plugin": "npm:^11.11.0"
1430 "@emotion/cache": "npm:^11.11.0" 1430 "@emotion/cache": "npm:^11.11.0"
1431 "@emotion/serialize": "npm:^1.1.2" 1431 "@emotion/serialize": "npm:^1.1.3"
1432 "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.1" 1432 "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.1"
1433 "@emotion/utils": "npm:^1.2.1" 1433 "@emotion/utils": "npm:^1.2.1"
1434 "@emotion/weak-memoize": "npm:^0.3.1" 1434 "@emotion/weak-memoize": "npm:^0.3.1"
@@ -1438,20 +1438,20 @@ __metadata:
1438 peerDependenciesMeta: 1438 peerDependenciesMeta:
1439 "@types/react": 1439 "@types/react":
1440 optional: true 1440 optional: true
1441 checksum: 1aea4d735b537fbfbeda828bbf929488a7e1b5b7d131f14aeede8737e92bb3b611e15fec353e97f85aed7a65a1c86a695a04ba6e9be905231beef6bd624cb705 1441 checksum: ce995395b8714343715284beb8478afdfa72b89ed83981a15a170ca0f4a2f77d7a4a198fd50c1f9c6efcd0535768d168ff88c5921dc5f90bb33134c7a75f9455
1442 languageName: node 1442 languageName: node
1443 linkType: hard 1443 linkType: hard
1444 1444
1445"@emotion/serialize@npm:^1.1.2": 1445"@emotion/serialize@npm:^1.1.2, @emotion/serialize@npm:^1.1.3":
1446 version: 1.1.2 1446 version: 1.1.3
1447 resolution: "@emotion/serialize@npm:1.1.2" 1447 resolution: "@emotion/serialize@npm:1.1.3"
1448 dependencies: 1448 dependencies:
1449 "@emotion/hash": "npm:^0.9.1" 1449 "@emotion/hash": "npm:^0.9.1"
1450 "@emotion/memoize": "npm:^0.8.1" 1450 "@emotion/memoize": "npm:^0.8.1"
1451 "@emotion/unitless": "npm:^0.8.1" 1451 "@emotion/unitless": "npm:^0.8.1"
1452 "@emotion/utils": "npm:^1.2.1" 1452 "@emotion/utils": "npm:^1.2.1"
1453 csstype: "npm:^3.0.2" 1453 csstype: "npm:^3.0.2"
1454 checksum: d243e0e5abce8d2183d25a32ec89bf650ee741ebadb29e6405abde05d4e2ed446ba5b3f725a29833ad709d0d08f0a5c8d0532fdcd43f4b23d931d8b6d4f218c1 1454 checksum: 875241eafaa30e7d3b7cf9b585d8c1f224cbf627a674e87eb1d7662dafa76a8c8d67f14a79dbf7d1eaa017e9f68389962990fbcc699d5ad65035a1a047432a3f
1455 languageName: node 1455 languageName: node
1456 linkType: hard 1456 linkType: hard
1457 1457
@@ -1701,10 +1701,10 @@ __metadata:
1701 languageName: node 1701 languageName: node
1702 linkType: hard 1702 linkType: hard
1703 1703
1704"@eslint/js@npm:8.55.0": 1704"@eslint/js@npm:8.56.0":
1705 version: 8.55.0 1705 version: 8.56.0
1706 resolution: "@eslint/js@npm:8.55.0" 1706 resolution: "@eslint/js@npm:8.56.0"
1707 checksum: 88ab9fc57a651becd2b32ec40a3958db27fae133b1ae77bebd733aa5bbd00a92f325bb02f20ad680d31c731fa49b22f060a4777dd52eb3e27da013d940bd978d 1707 checksum: 60b3a1cf240e2479cec9742424224465dc50e46d781da1b7f5ef240501b2d1202c225bd456207faac4b34a64f4765833345bc4ddffd00395e1db40fa8c426f5a
1708 languageName: node 1708 languageName: node
1709 linkType: hard 1709 linkType: hard
1710 1710
@@ -1746,28 +1746,28 @@ __metadata:
1746 languageName: node 1746 languageName: node
1747 linkType: hard 1747 linkType: hard
1748 1748
1749"@fontsource-variable/jetbrains-mono@npm:^5.0.18": 1749"@fontsource-variable/jetbrains-mono@npm:^5.0.19":
1750 version: 5.0.18 1750 version: 5.0.19
1751 resolution: "@fontsource-variable/jetbrains-mono@npm:5.0.18" 1751 resolution: "@fontsource-variable/jetbrains-mono@npm:5.0.19"
1752 checksum: c11926a1c55c1f9983a4d94cedad0b5d9b718cd58050c95e2cd14dab165bfba939e3cbecda8dd4652198e7f681e720490914f42b3dfabd1e11796002ba5a2e01 1752 checksum: 93622a6af324be162f028b974bd61f10530df30a1332dded4915509c0a21d80435ad623fb45325dd175afaa095ca6650f2de9da295b2bc9dea85474050d1a46b
1753 languageName: node 1753 languageName: node
1754 linkType: hard 1754 linkType: hard
1755 1755
1756"@fontsource-variable/open-sans@npm:^5.0.18": 1756"@fontsource-variable/open-sans@npm:^5.0.21":
1757 version: 5.0.18 1757 version: 5.0.21
1758 resolution: "@fontsource-variable/open-sans@npm:5.0.18" 1758 resolution: "@fontsource-variable/open-sans@npm:5.0.21"
1759 checksum: ec5e33654d5abfed6d7788bd404f91bab749f69ede1730ab0b958265e1dcc82b77972d0f8e98d477e2f41d3334c73c86a8e7bd90107295b4c44bb17607977b78 1759 checksum: d7a5832751f24ca080355ac51259195dea1910cb4a7f74b5531e993e9892fadfb7784949d5d065d067403db1741bbedcbc96bb5cf1d988449ff647eeba0d4481
1760 languageName: node 1760 languageName: node
1761 linkType: hard 1761 linkType: hard
1762 1762
1763"@hpcc-js/wasm@npm:^2.14.1, @hpcc-js/wasm@npm:^2.15.0": 1763"@hpcc-js/wasm@npm:^2.14.1, @hpcc-js/wasm@npm:^2.15.3":
1764 version: 2.15.0 1764 version: 2.15.3
1765 resolution: "@hpcc-js/wasm@npm:2.15.0" 1765 resolution: "@hpcc-js/wasm@npm:2.15.3"
1766 dependencies: 1766 dependencies:
1767 yargs: "npm:17.7.2" 1767 yargs: "npm:17.7.2"
1768 bin: 1768 bin:
1769 dot-wasm: bin/dot-wasm.js 1769 dot-wasm: bin/dot-wasm.js
1770 checksum: aa3daac878a1c6135fd1eeafa0952e75d37c2664e5ccfb98075a5a901fc898852440a476ab54528cce8a6ae9abea44c810e39695c80149fc60c51f0389288c80 1770 checksum: 9e4474329f191d93cd4029afe4a5e83732bec732a7c83a913fefe64e08a82deb59dbdc33d42c92e4c8eb4df5853c8cbe10d8d53d7db5204d8c9919af082f64b1
1771 languageName: node 1771 languageName: node
1772 linkType: hard 1772 linkType: hard
1773 1773
@@ -1862,10 +1862,10 @@ __metadata:
1862 languageName: node 1862 languageName: node
1863 linkType: hard 1863 linkType: hard
1864 1864
1865"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.1.1": 1865"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.1.2":
1866 version: 1.1.1 1866 version: 1.1.2
1867 resolution: "@lezer/common@npm:1.1.1" 1867 resolution: "@lezer/common@npm:1.1.2"
1868 checksum: 495b76f33164c732461097ee6f8d6f1250a63d21f5c01e58a24f1da49b8d4b392188bbbe972c0c2d7ec48db8e3fd550563bcdefba3b81b4d895e821c1f91fc8e 1868 checksum: ed25e0b05ff073247266f2824d38159b93ab359be23c479ae0cf37131ec0d463a58dc2b78fb989ff9e29f87e0ef16291b2bd6243b082bb4116aed3e386cc069c
1869 languageName: node 1869 languageName: node
1870 linkType: hard 1870 linkType: hard
1871 1871
@@ -1906,14 +1906,14 @@ __metadata:
1906 languageName: node 1906 languageName: node
1907 linkType: hard 1907 linkType: hard
1908 1908
1909"@mui/base@npm:5.0.0-beta.25": 1909"@mui/base@npm:5.0.0-beta.28":
1910 version: 5.0.0-beta.25 1910 version: 5.0.0-beta.28
1911 resolution: "@mui/base@npm:5.0.0-beta.25" 1911 resolution: "@mui/base@npm:5.0.0-beta.28"
1912 dependencies: 1912 dependencies:
1913 "@babel/runtime": "npm:^7.23.4" 1913 "@babel/runtime": "npm:^7.23.5"
1914 "@floating-ui/react-dom": "npm:^2.0.4" 1914 "@floating-ui/react-dom": "npm:^2.0.4"
1915 "@mui/types": "npm:^7.2.10" 1915 "@mui/types": "npm:^7.2.11"
1916 "@mui/utils": "npm:^5.14.19" 1916 "@mui/utils": "npm:^5.15.1"
1917 "@popperjs/core": "npm:^2.11.8" 1917 "@popperjs/core": "npm:^2.11.8"
1918 clsx: "npm:^2.0.0" 1918 clsx: "npm:^2.0.0"
1919 prop-types: "npm:^15.8.1" 1919 prop-types: "npm:^15.8.1"
@@ -1924,22 +1924,22 @@ __metadata:
1924 peerDependenciesMeta: 1924 peerDependenciesMeta:
1925 "@types/react": 1925 "@types/react":
1926 optional: true 1926 optional: true
1927 checksum: 9b1865655cb94b7a40ea31c698f1163d5521a7bb110ddcc1131f83a76428628d11d1582d2e96968734eed17d26e69c6c2b10eb5b9757639e7ddd48be0bd22dc6 1927 checksum: 31479d9548e1b29150e3b94bcb88edce409339ac047e78a8a70173a0fa2c7730b38f28c6b366e2b3dda3964f28e883153cae0dc2957218b1711bb58004ddc2d1
1928 languageName: node 1928 languageName: node
1929 linkType: hard 1929 linkType: hard
1930 1930
1931"@mui/core-downloads-tracker@npm:^5.14.19": 1931"@mui/core-downloads-tracker@npm:^5.15.1":
1932 version: 5.14.19 1932 version: 5.15.1
1933 resolution: "@mui/core-downloads-tracker@npm:5.14.19" 1933 resolution: "@mui/core-downloads-tracker@npm:5.15.1"
1934 checksum: a0851424a067e0e0c266752e34000bcc63121191b93077d6dc01834a71c5defe95e54495f98347e2f8c247cebfe38d142600c71b9a698cf30f114e90598ebb91 1934 checksum: 81e3afca19135336c1122aaa8bd69e411df95389c2654c03ce8a8787f4ee4b14403f58acfbf4eef1b9267685569ee9a0bee4b08cf15782d866e9277792d84657
1935 languageName: node 1935 languageName: node
1936 linkType: hard 1936 linkType: hard
1937 1937
1938"@mui/icons-material@npm:5.14.19": 1938"@mui/icons-material@npm:^5.15.1":
1939 version: 5.14.19 1939 version: 5.15.1
1940 resolution: "@mui/icons-material@npm:5.14.19" 1940 resolution: "@mui/icons-material@npm:5.15.1"
1941 dependencies: 1941 dependencies:
1942 "@babel/runtime": "npm:^7.23.4" 1942 "@babel/runtime": "npm:^7.23.5"
1943 peerDependencies: 1943 peerDependencies:
1944 "@mui/material": ^5.0.0 1944 "@mui/material": ^5.0.0
1945 "@types/react": ^17.0.0 || ^18.0.0 1945 "@types/react": ^17.0.0 || ^18.0.0
@@ -1947,21 +1947,21 @@ __metadata:
1947 peerDependenciesMeta: 1947 peerDependenciesMeta:
1948 "@types/react": 1948 "@types/react":
1949 optional: true 1949 optional: true
1950 checksum: 1af1a14622795dae1b999b49dc27d8d9f32344ccd3bc73a3b9dbce3d8d7ad43e6aa93e100a58ae423c9404fcb91dbdeb7758bd94f5f4614a4843f649645a42a1 1950 checksum: 9ae975f7534094f6e80ffeb3946338a22b9656bb02544fa76e427daeff050c7db0ce83b261bca73a1aab17789d87cc19cc92749d0dc40501f889a9dbfb35709d
1951 languageName: node 1951 languageName: node
1952 linkType: hard 1952 linkType: hard
1953 1953
1954"@mui/material@npm:5.14.19": 1954"@mui/material@npm:^5.15.1":
1955 version: 5.14.19 1955 version: 5.15.1
1956 resolution: "@mui/material@npm:5.14.19" 1956 resolution: "@mui/material@npm:5.15.1"
1957 dependencies: 1957 dependencies:
1958 "@babel/runtime": "npm:^7.23.4" 1958 "@babel/runtime": "npm:^7.23.5"
1959 "@mui/base": "npm:5.0.0-beta.25" 1959 "@mui/base": "npm:5.0.0-beta.28"
1960 "@mui/core-downloads-tracker": "npm:^5.14.19" 1960 "@mui/core-downloads-tracker": "npm:^5.15.1"
1961 "@mui/system": "npm:^5.14.19" 1961 "@mui/system": "npm:^5.15.1"
1962 "@mui/types": "npm:^7.2.10" 1962 "@mui/types": "npm:^7.2.11"
1963 "@mui/utils": "npm:^5.14.19" 1963 "@mui/utils": "npm:^5.15.1"
1964 "@types/react-transition-group": "npm:^4.4.9" 1964 "@types/react-transition-group": "npm:^4.4.10"
1965 clsx: "npm:^2.0.0" 1965 clsx: "npm:^2.0.0"
1966 csstype: "npm:^3.1.2" 1966 csstype: "npm:^3.1.2"
1967 prop-types: "npm:^15.8.1" 1967 prop-types: "npm:^15.8.1"
@@ -1980,16 +1980,16 @@ __metadata:
1980 optional: true 1980 optional: true
1981 "@types/react": 1981 "@types/react":
1982 optional: true 1982 optional: true
1983 checksum: 5ffce28bc26fa5c7ea4409f816698c9f9cb27ae70bcf06bd21aab40ea5b979f17568032a9ec74a9209d11272ee1efc9f4dcbb19f8574e3eec63a622220f58a3f 1983 checksum: d5fc5cba599a691d84424bfa8d8a3dc18ecbf85ea1bd4fc92292b716a4df9facf391d3c164743f83ae8c69905f92c0061cd311d2c6c3a051a277614940b87b1b
1984 languageName: node 1984 languageName: node
1985 linkType: hard 1985 linkType: hard
1986 1986
1987"@mui/private-theming@npm:^5.14.19": 1987"@mui/private-theming@npm:^5.15.1":
1988 version: 5.14.19 1988 version: 5.15.1
1989 resolution: "@mui/private-theming@npm:5.14.19" 1989 resolution: "@mui/private-theming@npm:5.15.1"
1990 dependencies: 1990 dependencies:
1991 "@babel/runtime": "npm:^7.23.4" 1991 "@babel/runtime": "npm:^7.23.5"
1992 "@mui/utils": "npm:^5.14.19" 1992 "@mui/utils": "npm:^5.15.1"
1993 prop-types: "npm:^15.8.1" 1993 prop-types: "npm:^15.8.1"
1994 peerDependencies: 1994 peerDependencies:
1995 "@types/react": ^17.0.0 || ^18.0.0 1995 "@types/react": ^17.0.0 || ^18.0.0
@@ -1997,15 +1997,15 @@ __metadata:
1997 peerDependenciesMeta: 1997 peerDependenciesMeta:
1998 "@types/react": 1998 "@types/react":
1999 optional: true 1999 optional: true
2000 checksum: 06bb5c40f680c037c80fef67404d1181b5775ef38157e12d03c58d1b070e6bb89d82b028d0a544e5d78cbd7822f50d5596e1320cd822c9cfbf185cb3ab2f935c 2000 checksum: 1d5e334601eac1e1f153c91094cd513e98ccb8fef2fcbcf8c048723d171ceda59b8231dcc3daa665e5e5ee7e39aae1b653040efb64320ef89d4ec1ad88eea4de
2001 languageName: node 2001 languageName: node
2002 linkType: hard 2002 linkType: hard
2003 2003
2004"@mui/styled-engine@npm:^5.14.19": 2004"@mui/styled-engine@npm:^5.15.1":
2005 version: 5.14.19 2005 version: 5.15.1
2006 resolution: "@mui/styled-engine@npm:5.14.19" 2006 resolution: "@mui/styled-engine@npm:5.15.1"
2007 dependencies: 2007 dependencies:
2008 "@babel/runtime": "npm:^7.23.4" 2008 "@babel/runtime": "npm:^7.23.5"
2009 "@emotion/cache": "npm:^11.11.0" 2009 "@emotion/cache": "npm:^11.11.0"
2010 csstype: "npm:^3.1.2" 2010 csstype: "npm:^3.1.2"
2011 prop-types: "npm:^15.8.1" 2011 prop-types: "npm:^15.8.1"
@@ -2018,19 +2018,19 @@ __metadata:
2018 optional: true 2018 optional: true
2019 "@emotion/styled": 2019 "@emotion/styled":
2020 optional: true 2020 optional: true
2021 checksum: eaa539b76008d0dbc22cf6b479885f223ca2d71e7338d73f583529ad9b57fe80656cfb5f3779d1c84b7fa7f779b15f3a5df28eb1e1bf797609f78f295b6219f0 2021 checksum: fcfa7cd3ba9ab24ad557ac9e980b46ff4d4dfddab41b1cdd57257a5ad57bf13e3891d771218dca1b1f405609c6e1e9895b80fcd90211a8877279f7774bb70e70
2022 languageName: node 2022 languageName: node
2023 linkType: hard 2023 linkType: hard
2024 2024
2025"@mui/system@npm:^5.14.19": 2025"@mui/system@npm:^5.15.1":
2026 version: 5.14.19 2026 version: 5.15.1
2027 resolution: "@mui/system@npm:5.14.19" 2027 resolution: "@mui/system@npm:5.15.1"
2028 dependencies: 2028 dependencies:
2029 "@babel/runtime": "npm:^7.23.4" 2029 "@babel/runtime": "npm:^7.23.5"
2030 "@mui/private-theming": "npm:^5.14.19" 2030 "@mui/private-theming": "npm:^5.15.1"
2031 "@mui/styled-engine": "npm:^5.14.19" 2031 "@mui/styled-engine": "npm:^5.15.1"
2032 "@mui/types": "npm:^7.2.10" 2032 "@mui/types": "npm:^7.2.11"
2033 "@mui/utils": "npm:^5.14.19" 2033 "@mui/utils": "npm:^5.15.1"
2034 clsx: "npm:^2.0.0" 2034 clsx: "npm:^2.0.0"
2035 csstype: "npm:^3.1.2" 2035 csstype: "npm:^3.1.2"
2036 prop-types: "npm:^15.8.1" 2036 prop-types: "npm:^15.8.1"
@@ -2046,27 +2046,27 @@ __metadata:
2046 optional: true 2046 optional: true
2047 "@types/react": 2047 "@types/react":
2048 optional: true 2048 optional: true
2049 checksum: 8fb45a4bf6ca8736e029bcd42cd085eb3ade8d46c58f1ed2c1ab266cb89397855f1176a7d8dd4317d8ef08045d4e30a28c706b51415c37a8c8ae2589dc1a6d9a 2049 checksum: c8abf92fde14031b0e6af6ef2d947bde9e98ce08bb81550bb08fa56793adf1da086066299a7c09d7f26c6e3a6a780679064ed8e54914ae5d775bb87c44632dc5
2050 languageName: node 2050 languageName: node
2051 linkType: hard 2051 linkType: hard
2052 2052
2053"@mui/types@npm:^7.2.10": 2053"@mui/types@npm:^7.2.11":
2054 version: 7.2.10 2054 version: 7.2.11
2055 resolution: "@mui/types@npm:7.2.10" 2055 resolution: "@mui/types@npm:7.2.11"
2056 peerDependencies: 2056 peerDependencies:
2057 "@types/react": ^17.0.0 || ^18.0.0 2057 "@types/react": ^17.0.0 || ^18.0.0
2058 peerDependenciesMeta: 2058 peerDependenciesMeta:
2059 "@types/react": 2059 "@types/react":
2060 optional: true 2060 optional: true
2061 checksum: 59c8162812581cd1021d319e8828f6220723ffceb13609a99b1ffee6943f81ab07291cc3837c28776ca919dbe74c6416b2014c10e16b19135ff94a80ad7d3270 2061 checksum: 5aecdd9b02ca4537d05ec1809a31e64a3330dc104509bc470ec8e38a00259d36faf2dadee828987b385dff46fbec6fe112ef3a5c0c1b78e60c56755af04d38fa
2062 languageName: node 2062 languageName: node
2063 linkType: hard 2063 linkType: hard
2064 2064
2065"@mui/utils@npm:^5.14.16, @mui/utils@npm:^5.14.19": 2065"@mui/utils@npm:^5.14.16, @mui/utils@npm:^5.15.1":
2066 version: 5.14.19 2066 version: 5.15.1
2067 resolution: "@mui/utils@npm:5.14.19" 2067 resolution: "@mui/utils@npm:5.15.1"
2068 dependencies: 2068 dependencies:
2069 "@babel/runtime": "npm:^7.23.4" 2069 "@babel/runtime": "npm:^7.23.5"
2070 "@types/prop-types": "npm:^15.7.11" 2070 "@types/prop-types": "npm:^15.7.11"
2071 prop-types: "npm:^15.8.1" 2071 prop-types: "npm:^15.8.1"
2072 react-is: "npm:^18.2.0" 2072 react-is: "npm:^18.2.0"
@@ -2076,13 +2076,13 @@ __metadata:
2076 peerDependenciesMeta: 2076 peerDependenciesMeta:
2077 "@types/react": 2077 "@types/react":
2078 optional: true 2078 optional: true
2079 checksum: fb049eed27249dabfba2b3bf3b6d6ebd0a31e837cde6651ab727482e24f3be700103ac04074c348cf8bdc5bed09d6e4c251e7ca46d7bbb66e2e5e9a062ea06cb 2079 checksum: 46a66c488ece0d5be5f179316495220ff95d5276f452ea1cf48836ed6aade63ceb5dd3cd0d3970eb958272eb4455deb657effcf52b7eb2355d9b99bef9d61909
2080 languageName: node 2080 languageName: node
2081 linkType: hard 2081 linkType: hard
2082 2082
2083"@mui/x-data-grid@npm:^6.18.2": 2083"@mui/x-data-grid@npm:^6.18.6":
2084 version: 6.18.2 2084 version: 6.18.6
2085 resolution: "@mui/x-data-grid@npm:6.18.2" 2085 resolution: "@mui/x-data-grid@npm:6.18.6"
2086 dependencies: 2086 dependencies:
2087 "@babel/runtime": "npm:^7.23.2" 2087 "@babel/runtime": "npm:^7.23.2"
2088 "@mui/utils": "npm:^5.14.16" 2088 "@mui/utils": "npm:^5.14.16"
@@ -2094,7 +2094,7 @@ __metadata:
2094 "@mui/system": ^5.4.1 2094 "@mui/system": ^5.4.1
2095 react: ^17.0.0 || ^18.0.0 2095 react: ^17.0.0 || ^18.0.0
2096 react-dom: ^17.0.0 || ^18.0.0 2096 react-dom: ^17.0.0 || ^18.0.0
2097 checksum: 441328df15f1d82651612229bee42c74eda893837bc08edc7c171a85bb755a612395f5abf8b4d09ddf4f70a74914faff221b6001ee8975c0ebe439ab7a1b4be1 2097 checksum: a8931efe1cff8951331223defdf9b17cb501eef85d4b176f36f9b0fb8a9522d6c4d6f5b672ac4f9b710ab95faf98d7a405fb3a739cbe871123798ed82a71dee3
2098 languageName: node 2098 languageName: node
2099 linkType: hard 2099 linkType: hard
2100 2100
@@ -2171,56 +2171,56 @@ __metadata:
2171 "@codemirror/language": "npm:^6.9.3" 2171 "@codemirror/language": "npm:^6.9.3"
2172 "@codemirror/lint": "npm:^6.4.2" 2172 "@codemirror/lint": "npm:^6.4.2"
2173 "@codemirror/search": "npm:^6.5.5" 2173 "@codemirror/search": "npm:^6.5.5"
2174 "@codemirror/state": "npm:^6.3.2" 2174 "@codemirror/state": "npm:^6.3.3"
2175 "@codemirror/view": "npm:^6.22.1" 2175 "@codemirror/view": "npm:^6.22.3"
2176 "@emotion/react": "npm:^11.11.1" 2176 "@emotion/react": "npm:^11.11.3"
2177 "@emotion/styled": "npm:^11.11.0" 2177 "@emotion/styled": "npm:^11.11.0"
2178 "@fontsource-variable/jetbrains-mono": "npm:^5.0.18" 2178 "@fontsource-variable/jetbrains-mono": "npm:^5.0.19"
2179 "@fontsource-variable/open-sans": "npm:^5.0.18" 2179 "@fontsource-variable/open-sans": "npm:^5.0.21"
2180 "@hpcc-js/wasm": "npm:^2.15.0" 2180 "@hpcc-js/wasm": "npm:^2.15.3"
2181 "@lezer/common": "npm:^1.1.1" 2181 "@lezer/common": "npm:^1.1.2"
2182 "@lezer/generator": "npm:^1.5.1" 2182 "@lezer/generator": "npm:^1.5.1"
2183 "@lezer/highlight": "npm:^1.2.0" 2183 "@lezer/highlight": "npm:^1.2.0"
2184 "@lezer/lr": "npm:^1.3.14" 2184 "@lezer/lr": "npm:^1.3.14"
2185 "@material-icons/svg": "npm:^1.0.33" 2185 "@material-icons/svg": "npm:^1.0.33"
2186 "@mui/icons-material": "npm:5.14.19" 2186 "@mui/icons-material": "npm:^5.15.1"
2187 "@mui/material": "npm:5.14.19" 2187 "@mui/material": "npm:^5.15.1"
2188 "@mui/system": "npm:^5.14.19" 2188 "@mui/system": "npm:^5.15.1"
2189 "@mui/x-data-grid": "npm:^6.18.2" 2189 "@mui/x-data-grid": "npm:^6.18.6"
2190 "@types/d3": "npm:^7.4.3" 2190 "@types/d3": "npm:^7.4.3"
2191 "@types/d3-graphviz": "npm:^2.6.10" 2191 "@types/d3-graphviz": "npm:^2.6.10"
2192 "@types/d3-selection": "npm:^3.0.10" 2192 "@types/d3-selection": "npm:^3.0.10"
2193 "@types/d3-zoom": "npm:^3.0.8" 2193 "@types/d3-zoom": "npm:^3.0.8"
2194 "@types/eslint": "npm:^8.44.8" 2194 "@types/eslint": "npm:^8.56.0"
2195 "@types/html-minifier-terser": "npm:^7.0.2" 2195 "@types/html-minifier-terser": "npm:^7.0.2"
2196 "@types/lodash-es": "npm:^4.17.12" 2196 "@types/lodash-es": "npm:^4.17.12"
2197 "@types/micromatch": "npm:^4.0.6" 2197 "@types/micromatch": "npm:^4.0.6"
2198 "@types/ms": "npm:^0.7.34" 2198 "@types/ms": "npm:^0.7.34"
2199 "@types/node": "npm:^20.10.2" 2199 "@types/node": "npm:^20.10.5"
2200 "@types/pnpapi": "npm:^0.0.5" 2200 "@types/pnpapi": "npm:^0.0.5"
2201 "@types/react": "npm:^18.2.41" 2201 "@types/react": "npm:^18.2.45"
2202 "@types/react-dom": "npm:^18.2.17" 2202 "@types/react-dom": "npm:^18.2.18"
2203 "@typescript-eslint/eslint-plugin": "npm:^6.13.1" 2203 "@typescript-eslint/eslint-plugin": "npm:^6.15.0"
2204 "@typescript-eslint/parser": "npm:^6.13.1" 2204 "@typescript-eslint/parser": "npm:^6.15.0"
2205 "@vitejs/plugin-react-swc": "npm:^3.5.0" 2205 "@vitejs/plugin-react-swc": "npm:^3.5.0"
2206 "@xstate/cli": "npm:^0.5.11" 2206 "@xstate/cli": "npm:^0.5.15"
2207 ansi-styles: "npm:^6.2.1" 2207 ansi-styles: "npm:^6.2.1"
2208 cross-env: "npm:^7.0.3" 2208 cross-env: "npm:^7.0.3"
2209 csstype: "npm:^3.1.2" 2209 csstype: "npm:^3.1.3"
2210 d3: "npm:^7.8.5" 2210 d3: "npm:^7.8.5"
2211 d3-graphviz: "patch:d3-graphviz@npm%3A5.2.0#~/.yarn/patches/d3-graphviz-npm-5.2.0-161b1fbad4.patch" 2211 d3-graphviz: "patch:d3-graphviz@npm%3A5.2.0#~/.yarn/patches/d3-graphviz-npm-5.2.0-161b1fbad4.patch"
2212 d3-selection: "npm:^3.0.0" 2212 d3-selection: "npm:^3.0.0"
2213 d3-zoom: "patch:d3-zoom@npm%3A3.0.0#~/.yarn/patches/d3-zoom-npm-3.0.0-18f706a421.patch" 2213 d3-zoom: "patch:d3-zoom@npm%3A3.0.0#~/.yarn/patches/d3-zoom-npm-3.0.0-18f706a421.patch"
2214 escape-string-regexp: "npm:^5.0.0" 2214 escape-string-regexp: "npm:^5.0.0"
2215 eslint: "npm:^8.55.0" 2215 eslint: "npm:^8.56.0"
2216 eslint-config-airbnb: "npm:^19.0.4" 2216 eslint-config-airbnb: "npm:^19.0.4"
2217 eslint-config-airbnb-typescript: "npm:^17.1.0" 2217 eslint-config-airbnb-typescript: "npm:^17.1.0"
2218 eslint-config-prettier: "npm:^9.1.0" 2218 eslint-config-prettier: "npm:^9.1.0"
2219 eslint-import-resolver-typescript: "npm:^3.6.1" 2219 eslint-import-resolver-typescript: "npm:^3.6.1"
2220 eslint-plugin-import: "npm:^2.29.0" 2220 eslint-plugin-import: "npm:^2.29.1"
2221 eslint-plugin-jsx-a11y: "npm:^6.8.0" 2221 eslint-plugin-jsx-a11y: "npm:^6.8.0"
2222 eslint-plugin-mobx: "npm:^0.0.9" 2222 eslint-plugin-mobx: "npm:^0.0.9"
2223 eslint-plugin-prettier: "npm:^5.0.1" 2223 eslint-plugin-prettier: "npm:^5.1.1"
2224 eslint-plugin-react: "npm:^7.33.2" 2224 eslint-plugin-react: "npm:^7.33.2"
2225 eslint-plugin-react-hooks: "npm:^4.6.0" 2225 eslint-plugin-react-hooks: "npm:^4.6.0"
2226 html-minifier-terser: "npm:^7.2.0" 2226 html-minifier-terser: "npm:^7.2.0"
@@ -2234,13 +2234,13 @@ __metadata:
2234 nanoid: "npm:^5.0.4" 2234 nanoid: "npm:^5.0.4"
2235 notistack: "npm:^3.0.1" 2235 notistack: "npm:^3.0.1"
2236 pnpapi: "npm:^0.0.0" 2236 pnpapi: "npm:^0.0.0"
2237 prettier: "npm:^3.1.0" 2237 prettier: "npm:^3.1.1"
2238 react: "npm:^18.2.0" 2238 react: "npm:^18.2.0"
2239 react-dom: "npm:^18.2.0" 2239 react-dom: "npm:^18.2.0"
2240 react-resize-detector: "npm:^9.1.0" 2240 react-resize-detector: "npm:^9.1.1"
2241 typescript: "npm:5.3.2" 2241 typescript: "npm:5.3.3"
2242 vite: "npm:^5.0.4" 2242 vite: "npm:^5.0.10"
2243 vite-plugin-pwa: "npm:^0.17.2" 2243 vite-plugin-pwa: "npm:^0.17.4"
2244 workbox-window: "npm:^7.0.0" 2244 workbox-window: "npm:^7.0.0"
2245 xstate: "npm:^4.38.3" 2245 xstate: "npm:^4.38.3"
2246 zod: "npm:^3.22.4" 2246 zod: "npm:^3.22.4"
@@ -2251,8 +2251,8 @@ __metadata:
2251 version: 0.0.0-use.local 2251 version: 0.0.0-use.local
2252 resolution: "@refinery/root@workspace:." 2252 resolution: "@refinery/root@workspace:."
2253 dependencies: 2253 dependencies:
2254 eslint: "npm:^8.55.0" 2254 eslint: "npm:^8.56.0"
2255 typescript: "npm:5.3.2" 2255 typescript: "npm:5.3.3"
2256 languageName: unknown 2256 languageName: unknown
2257 linkType: soft 2257 linkType: soft
2258 2258
@@ -2879,13 +2879,13 @@ __metadata:
2879 languageName: node 2879 languageName: node
2880 linkType: hard 2880 linkType: hard
2881 2881
2882"@types/eslint@npm:^8.44.8": 2882"@types/eslint@npm:^8.56.0":
2883 version: 8.44.8 2883 version: 8.56.0
2884 resolution: "@types/eslint@npm:8.44.8" 2884 resolution: "@types/eslint@npm:8.56.0"
2885 dependencies: 2885 dependencies:
2886 "@types/estree": "npm:*" 2886 "@types/estree": "npm:*"
2887 "@types/json-schema": "npm:*" 2887 "@types/json-schema": "npm:*"
2888 checksum: 610966753add984f6ac9f00eeb766691e141e66a7e20b724a45ad077f60e8cd8fd7874b7e655e93537e54873cc5711cd6f57728474e08b478407cd942f098263 2888 checksum: afba97b10d02cb7c7e7658de38f626c65b81be0fe45bc479e058ab14bc089911193811dce681edd656fc6b59c91fd8d0c976972476fc98b5e782b2c3b08aaa6c
2889 languageName: node 2889 languageName: node
2890 linkType: hard 2890 linkType: hard
2891 2891
@@ -2963,12 +2963,12 @@ __metadata:
2963 languageName: node 2963 languageName: node
2964 linkType: hard 2964 linkType: hard
2965 2965
2966"@types/node@npm:*, @types/node@npm:^20.10.2": 2966"@types/node@npm:*, @types/node@npm:^20.10.5":
2967 version: 20.10.2 2967 version: 20.10.5
2968 resolution: "@types/node@npm:20.10.2" 2968 resolution: "@types/node@npm:20.10.5"
2969 dependencies: 2969 dependencies:
2970 undici-types: "npm:~5.26.4" 2970 undici-types: "npm:~5.26.4"
2971 checksum: c24630d6bdd237f538d69886868fc29abba8c59f58996b6a6267c42e2253a84a18834c09408b3d887ec74f69e6828e25e3d23cf6fa0daac5902afccaf0568d7e 2971 checksum: be30609aae0bfe492097815f166ccc07f465220cb604647fa4e5ec05a1d16c012a41b82b5f11ecfe2485cbb479d4d20384b95b809ca0bcff6d94d5bbafa645bb
2972 languageName: node 2972 languageName: node
2973 linkType: hard 2973 linkType: hard
2974 2974
@@ -2993,32 +2993,32 @@ __metadata:
2993 languageName: node 2993 languageName: node
2994 linkType: hard 2994 linkType: hard
2995 2995
2996"@types/react-dom@npm:^18.2.17": 2996"@types/react-dom@npm:^18.2.18":
2997 version: 18.2.17 2997 version: 18.2.18
2998 resolution: "@types/react-dom@npm:18.2.17" 2998 resolution: "@types/react-dom@npm:18.2.18"
2999 dependencies: 2999 dependencies:
3000 "@types/react": "npm:*" 3000 "@types/react": "npm:*"
3001 checksum: 33b53078ed7e9e0cfc4dc691e938f7db1cc06353bc345947b41b581c3efe2b980c9e4eb6460dbf5ddc521dd91959194c970221a2bd4bfad9d23ebce338e12938 3001 checksum: 74dba11a1b8156f3a763f3fca1fb4ec1dcd349153279b8bf79210024a69f994bf2cf0728198c047f8130c5318420ea56281b0a4ef84c8ae943cd9a0cac705220
3002 languageName: node 3002 languageName: node
3003 linkType: hard 3003 linkType: hard
3004 3004
3005"@types/react-transition-group@npm:^4.4.9": 3005"@types/react-transition-group@npm:^4.4.10":
3006 version: 4.4.9 3006 version: 4.4.10
3007 resolution: "@types/react-transition-group@npm:4.4.9" 3007 resolution: "@types/react-transition-group@npm:4.4.10"
3008 dependencies: 3008 dependencies:
3009 "@types/react": "npm:*" 3009 "@types/react": "npm:*"
3010 checksum: 279cd319202f7ec24ecad174dffd19fd161250bc438bf3c62951f467093e5664a0c895b185976bf45f55b68ec901e520924216eb8abafe934b66f55337319ff5 3010 checksum: 3eb9bca143abc21eb781aa5cb1bded0c9335689d515bf0513fb8e63217b7a8122c6a323ecd5644a06938727e1f467ee061d8df1c93b68825a80ff1b47ab777a2
3011 languageName: node 3011 languageName: node
3012 linkType: hard 3012 linkType: hard
3013 3013
3014"@types/react@npm:*, @types/react@npm:^18.2.41": 3014"@types/react@npm:*, @types/react@npm:^18.2.45":
3015 version: 18.2.41 3015 version: 18.2.45
3016 resolution: "@types/react@npm:18.2.41" 3016 resolution: "@types/react@npm:18.2.45"
3017 dependencies: 3017 dependencies:
3018 "@types/prop-types": "npm:*" 3018 "@types/prop-types": "npm:*"
3019 "@types/scheduler": "npm:*" 3019 "@types/scheduler": "npm:*"
3020 csstype: "npm:^3.0.2" 3020 csstype: "npm:^3.0.2"
3021 checksum: 5cc72491ce8be95e7bbedd8bf039ca971772ecd22d989feb045af7e73247c7e6cff25a2f1c2200be461fb2f6b5aacef739e1ba9fd83c744209dfd3ce8aa75afe 3021 checksum: 4cc650c47ffb88baac29fb7a74e842e4af4a55f437086ef70250fdc75f0a5f2fcf8adc272d05ab2e00b1de6e14613296881271caee037dadf9130fdeb498c59e
3022 languageName: node 3022 languageName: node
3023 linkType: hard 3023 linkType: hard
3024 3024
@@ -3052,15 +3052,15 @@ __metadata:
3052 languageName: node 3052 languageName: node
3053 linkType: hard 3053 linkType: hard
3054 3054
3055"@typescript-eslint/eslint-plugin@npm:^6.13.1": 3055"@typescript-eslint/eslint-plugin@npm:^6.15.0":
3056 version: 6.13.1 3056 version: 6.15.0
3057 resolution: "@typescript-eslint/eslint-plugin@npm:6.13.1" 3057 resolution: "@typescript-eslint/eslint-plugin@npm:6.15.0"
3058 dependencies: 3058 dependencies:
3059 "@eslint-community/regexpp": "npm:^4.5.1" 3059 "@eslint-community/regexpp": "npm:^4.5.1"
3060 "@typescript-eslint/scope-manager": "npm:6.13.1" 3060 "@typescript-eslint/scope-manager": "npm:6.15.0"
3061 "@typescript-eslint/type-utils": "npm:6.13.1" 3061 "@typescript-eslint/type-utils": "npm:6.15.0"
3062 "@typescript-eslint/utils": "npm:6.13.1" 3062 "@typescript-eslint/utils": "npm:6.15.0"
3063 "@typescript-eslint/visitor-keys": "npm:6.13.1" 3063 "@typescript-eslint/visitor-keys": "npm:6.15.0"
3064 debug: "npm:^4.3.4" 3064 debug: "npm:^4.3.4"
3065 graphemer: "npm:^1.4.0" 3065 graphemer: "npm:^1.4.0"
3066 ignore: "npm:^5.2.4" 3066 ignore: "npm:^5.2.4"
@@ -3073,44 +3073,44 @@ __metadata:
3073 peerDependenciesMeta: 3073 peerDependenciesMeta:
3074 typescript: 3074 typescript:
3075 optional: true 3075 optional: true
3076 checksum: ccbcbf2a16d985348f46f07c90db06d98878632e7e98eb2fe9275dc489e8a3406bbe002e6d5ff0da88f51a5fe44ea0e942ec35488a3f1939e009f0a43997d34a 3076 checksum: 78054afb0d4ab12d82db7a9cb005dfa2be42962341728abf4a81802e1f4c0f5b23de4870287f4b7e32aa4a4bc900bbc218f2d4d0c02aa77452e8e8e0b71fe3de
3077 languageName: node 3077 languageName: node
3078 linkType: hard 3078 linkType: hard
3079 3079
3080"@typescript-eslint/parser@npm:^6.13.1": 3080"@typescript-eslint/parser@npm:^6.15.0":
3081 version: 6.13.1 3081 version: 6.15.0
3082 resolution: "@typescript-eslint/parser@npm:6.13.1" 3082 resolution: "@typescript-eslint/parser@npm:6.15.0"
3083 dependencies: 3083 dependencies:
3084 "@typescript-eslint/scope-manager": "npm:6.13.1" 3084 "@typescript-eslint/scope-manager": "npm:6.15.0"
3085 "@typescript-eslint/types": "npm:6.13.1" 3085 "@typescript-eslint/types": "npm:6.15.0"
3086 "@typescript-eslint/typescript-estree": "npm:6.13.1" 3086 "@typescript-eslint/typescript-estree": "npm:6.15.0"
3087 "@typescript-eslint/visitor-keys": "npm:6.13.1" 3087 "@typescript-eslint/visitor-keys": "npm:6.15.0"
3088 debug: "npm:^4.3.4" 3088 debug: "npm:^4.3.4"
3089 peerDependencies: 3089 peerDependencies:
3090 eslint: ^7.0.0 || ^8.0.0 3090 eslint: ^7.0.0 || ^8.0.0
3091 peerDependenciesMeta: 3091 peerDependenciesMeta:
3092 typescript: 3092 typescript:
3093 optional: true 3093 optional: true
3094 checksum: 83f67374815f330ba96c2129f616ee1c8af3a7282c91e9645371ce4a9acfc2797df345cc65a34efa3ff0e574ac9422921cdac623a37be21e36e45c46d6de4731 3094 checksum: e7f265fd4abd3bc49fa5b304cd4b9c22801ac5a9da4ee342bbab0c117d629ac4aad6998555b61a8c5a0b279c443a44ae99f16669e24e3ef17ccec20c8b7019e7
3095 languageName: node 3095 languageName: node
3096 linkType: hard 3096 linkType: hard
3097 3097
3098"@typescript-eslint/scope-manager@npm:6.13.1": 3098"@typescript-eslint/scope-manager@npm:6.15.0":
3099 version: 6.13.1 3099 version: 6.15.0
3100 resolution: "@typescript-eslint/scope-manager@npm:6.13.1" 3100 resolution: "@typescript-eslint/scope-manager@npm:6.15.0"
3101 dependencies: 3101 dependencies:
3102 "@typescript-eslint/types": "npm:6.13.1" 3102 "@typescript-eslint/types": "npm:6.15.0"
3103 "@typescript-eslint/visitor-keys": "npm:6.13.1" 3103 "@typescript-eslint/visitor-keys": "npm:6.15.0"
3104 checksum: 2b00f087ba9a9940df4cbc96335312737b3a7744b61528e4949ffd8034067d4c419a7b20beeb4c47d0ed5f52ad82490e89622a0de0e33c4bb6af3ede14c680b8 3104 checksum: 3428d99de440f227cbc2afb44cdcb25e44c4b49c5f490392f83e21d2048210a6ec2f2f68133376c842034f5b5ba4ec9721da7caa18e631e23b57e20927b5b6f0
3105 languageName: node 3105 languageName: node
3106 linkType: hard 3106 linkType: hard
3107 3107
3108"@typescript-eslint/type-utils@npm:6.13.1": 3108"@typescript-eslint/type-utils@npm:6.15.0":
3109 version: 6.13.1 3109 version: 6.15.0
3110 resolution: "@typescript-eslint/type-utils@npm:6.13.1" 3110 resolution: "@typescript-eslint/type-utils@npm:6.15.0"
3111 dependencies: 3111 dependencies:
3112 "@typescript-eslint/typescript-estree": "npm:6.13.1" 3112 "@typescript-eslint/typescript-estree": "npm:6.15.0"
3113 "@typescript-eslint/utils": "npm:6.13.1" 3113 "@typescript-eslint/utils": "npm:6.15.0"
3114 debug: "npm:^4.3.4" 3114 debug: "npm:^4.3.4"
3115 ts-api-utils: "npm:^1.0.1" 3115 ts-api-utils: "npm:^1.0.1"
3116 peerDependencies: 3116 peerDependencies:
@@ -3118,23 +3118,23 @@ __metadata:
3118 peerDependenciesMeta: 3118 peerDependenciesMeta:
3119 typescript: 3119 typescript:
3120 optional: true 3120 optional: true
3121 checksum: c958126cb9d28021ae8e3bb2c11d5f427ab09adff5deaf64927f9769b8ba1f7b561dfb30ac2e69f9ef923183566569500a27a188b534e6641a34e0a6fd144773 3121 checksum: 32cb531a4b5e0ccd431cba553ec73b87d4453b48af288a33e359ba4f5278126390d82799b61d3f0fbf135cfde1ac6c2275c2cf37a676e8a2a2811e774e660f16
3122 languageName: node 3122 languageName: node
3123 linkType: hard 3123 linkType: hard
3124 3124
3125"@typescript-eslint/types@npm:6.13.1": 3125"@typescript-eslint/types@npm:6.15.0":
3126 version: 6.13.1 3126 version: 6.15.0
3127 resolution: "@typescript-eslint/types@npm:6.13.1" 3127 resolution: "@typescript-eslint/types@npm:6.15.0"
3128 checksum: 26ea37ec6943859415d683b280e135c20da73281d742aaf123763bf9e10ea0629950422934c4ec3cc77a390a8fa8f33cc4f3914869ffd5af4d1edbbbae834d60 3128 checksum: 6e33529ea301c8c4b8c1f589dadd5d2a66c1b24ec87a577524fbc996d4c7b65d4f4fdfa4a3937b691efee6a10a6b16f7bfcabe98a15e0fc0c0c57aa0d80dcc25
3129 languageName: node 3129 languageName: node
3130 linkType: hard 3130 linkType: hard
3131 3131
3132"@typescript-eslint/typescript-estree@npm:6.13.1": 3132"@typescript-eslint/typescript-estree@npm:6.15.0":
3133 version: 6.13.1 3133 version: 6.15.0
3134 resolution: "@typescript-eslint/typescript-estree@npm:6.13.1" 3134 resolution: "@typescript-eslint/typescript-estree@npm:6.15.0"
3135 dependencies: 3135 dependencies:
3136 "@typescript-eslint/types": "npm:6.13.1" 3136 "@typescript-eslint/types": "npm:6.15.0"
3137 "@typescript-eslint/visitor-keys": "npm:6.13.1" 3137 "@typescript-eslint/visitor-keys": "npm:6.15.0"
3138 debug: "npm:^4.3.4" 3138 debug: "npm:^4.3.4"
3139 globby: "npm:^11.1.0" 3139 globby: "npm:^11.1.0"
3140 is-glob: "npm:^4.0.3" 3140 is-glob: "npm:^4.0.3"
@@ -3143,34 +3143,34 @@ __metadata:
3143 peerDependenciesMeta: 3143 peerDependenciesMeta:
3144 typescript: 3144 typescript:
3145 optional: true 3145 optional: true
3146 checksum: d8aa409464f860f12ddc67ad8d94dcc37dc4da272b1d9d1937b6ccbcf397daa8bb495f409ee5c263053f87a9a0cc7d5ba6926137e5724d4ac6a839d8a481a8c0 3146 checksum: 08955f6e84b8edb855a6769671e85889e52b15b82e00a64f595da867b21ad060e5342787c436d77702b2a1f39d411ac79b81a8d2e2006e9b1886eadb08b626df
3147 languageName: node 3147 languageName: node
3148 linkType: hard 3148 linkType: hard
3149 3149
3150"@typescript-eslint/utils@npm:6.13.1": 3150"@typescript-eslint/utils@npm:6.15.0":
3151 version: 6.13.1 3151 version: 6.15.0
3152 resolution: "@typescript-eslint/utils@npm:6.13.1" 3152 resolution: "@typescript-eslint/utils@npm:6.15.0"
3153 dependencies: 3153 dependencies:
3154 "@eslint-community/eslint-utils": "npm:^4.4.0" 3154 "@eslint-community/eslint-utils": "npm:^4.4.0"
3155 "@types/json-schema": "npm:^7.0.12" 3155 "@types/json-schema": "npm:^7.0.12"
3156 "@types/semver": "npm:^7.5.0" 3156 "@types/semver": "npm:^7.5.0"
3157 "@typescript-eslint/scope-manager": "npm:6.13.1" 3157 "@typescript-eslint/scope-manager": "npm:6.15.0"
3158 "@typescript-eslint/types": "npm:6.13.1" 3158 "@typescript-eslint/types": "npm:6.15.0"
3159 "@typescript-eslint/typescript-estree": "npm:6.13.1" 3159 "@typescript-eslint/typescript-estree": "npm:6.15.0"
3160 semver: "npm:^7.5.4" 3160 semver: "npm:^7.5.4"
3161 peerDependencies: 3161 peerDependencies:
3162 eslint: ^7.0.0 || ^8.0.0 3162 eslint: ^7.0.0 || ^8.0.0
3163 checksum: 6706527c6d979ba0a9756394382e945a2de51f54b8193da03ec2f980d479ffca0f58216c90f510b39601d07b37781af4236384f49afc63713662cd309bd43a1f 3163 checksum: 53519a2027681bdc8f028f9421c65f193f91b5bb1659465fedb8043376c693c2391211f1c01d8ba25bfaa7f7b3a102263d7123f9dfade12032159f4b4490f0fb
3164 languageName: node 3164 languageName: node
3165 linkType: hard 3165 linkType: hard
3166 3166
3167"@typescript-eslint/visitor-keys@npm:6.13.1": 3167"@typescript-eslint/visitor-keys@npm:6.15.0":
3168 version: 6.13.1 3168 version: 6.15.0
3169 resolution: "@typescript-eslint/visitor-keys@npm:6.13.1" 3169 resolution: "@typescript-eslint/visitor-keys@npm:6.15.0"
3170 dependencies: 3170 dependencies:
3171 "@typescript-eslint/types": "npm:6.13.1" 3171 "@typescript-eslint/types": "npm:6.15.0"
3172 eslint-visitor-keys: "npm:^3.4.1" 3172 eslint-visitor-keys: "npm:^3.4.1"
3173 checksum: 68daf60941fc4824f90480787587c9cbb447eeceac5698dfef2b0c2caa6d3c715f604c2357cc20abb6899be3c3e3ae3b5bbee310faccaab9ea98c8bd9137ec1f 3173 checksum: bf9f71af60bd63d1073900e75c5a0aa6eddd672f6c3ac6092c765d67deb7a0c32d2a5f6f3aee9e95f93a93d58563a76da209bd8487aadafd4d013100ffe38520
3174 languageName: node 3174 languageName: node
3175 linkType: hard 3175 linkType: hard
3176 3176
@@ -3192,13 +3192,13 @@ __metadata:
3192 languageName: node 3192 languageName: node
3193 linkType: hard 3193 linkType: hard
3194 3194
3195"@xstate/cli@npm:^0.5.11": 3195"@xstate/cli@npm:^0.5.15":
3196 version: 0.5.11 3196 version: 0.5.15
3197 resolution: "@xstate/cli@npm:0.5.11" 3197 resolution: "@xstate/cli@npm:0.5.15"
3198 dependencies: 3198 dependencies:
3199 "@babel/core": "npm:^7.21.4" 3199 "@babel/core": "npm:^7.21.4"
3200 "@xstate/machine-extractor": "npm:^0.13.0" 3200 "@xstate/machine-extractor": "npm:^0.14.1"
3201 "@xstate/tools-shared": "npm:^4.0.5" 3201 "@xstate/tools-shared": "npm:^4.0.8"
3202 chokidar: "npm:^3.5.3" 3202 chokidar: "npm:^3.5.3"
3203 commander: "npm:^8.0.0" 3203 commander: "npm:^8.0.0"
3204 dotenv: "npm:^16.0.3" 3204 dotenv: "npm:^16.0.3"
@@ -3208,13 +3208,13 @@ __metadata:
3208 xstate-beta: "npm:xstate@beta" 3208 xstate-beta: "npm:xstate@beta"
3209 bin: 3209 bin:
3210 xstate: bin/bin.js 3210 xstate: bin/bin.js
3211 checksum: 02bf9f35661a2b8e93d3618ac1e44c07442e0453861800340c814caee03ce818d0a86e27d0682c6acbeca23d2e7c882713cfadc254c7f7e080c912dd81fe1373 3211 checksum: 85dc3cfcc41328c694817d2aacfbae4fe3d93029fdf55a3fcc2b96e63b5c778abcaf9faf76fd6e2166612c393454b444ca3aa049c26bc9cdfb832b668c7eba2d
3212 languageName: node 3212 languageName: node
3213 linkType: hard 3213 linkType: hard
3214 3214
3215"@xstate/machine-extractor@npm:^0.13.0": 3215"@xstate/machine-extractor@npm:^0.14.1":
3216 version: 0.13.0 3216 version: 0.14.1
3217 resolution: "@xstate/machine-extractor@npm:0.13.0" 3217 resolution: "@xstate/machine-extractor@npm:0.14.1"
3218 dependencies: 3218 dependencies:
3219 "@babel/parser": "npm:^7.21.4" 3219 "@babel/parser": "npm:^7.21.4"
3220 "@babel/traverse": "npm:^7.21.4" 3220 "@babel/traverse": "npm:^7.21.4"
@@ -3222,19 +3222,19 @@ __metadata:
3222 recast: "npm:^0.23.1" 3222 recast: "npm:^0.23.1"
3223 peerDependencies: 3223 peerDependencies:
3224 xstate: ^4 3224 xstate: ^4
3225 checksum: 449cd18e42afccfd7e927683190757b61dd7a74b5ec2a51c786698203370a8348c7b497d6d3b4666ec1a949016792e124d22a65c398ff0a011e82c11b2890453 3225 checksum: bc3ea496bb8974a9431acb318a11684fd7954253539d7d59bcea6af190621f82f6ea729d37bd487ec0e52e90f866401af79d7f1c0ccd396b3ee14916b8519ac9
3226 languageName: node 3226 languageName: node
3227 linkType: hard 3227 linkType: hard
3228 3228
3229"@xstate/tools-shared@npm:^4.0.5": 3229"@xstate/tools-shared@npm:^4.0.8":
3230 version: 4.0.5 3230 version: 4.0.8
3231 resolution: "@xstate/tools-shared@npm:4.0.5" 3231 resolution: "@xstate/tools-shared@npm:4.0.8"
3232 dependencies: 3232 dependencies:
3233 "@xstate/machine-extractor": "npm:^0.13.0" 3233 "@xstate/machine-extractor": "npm:^0.14.1"
3234 peerDependencies: 3234 peerDependencies:
3235 prettier: ^2 3235 prettier: ^2
3236 xstate: ^4 3236 xstate: ^4
3237 checksum: 9af83b255b586c4ee9e9131c41bcdb37377fbd9de2060d4782c0b8f96a89754e86d9101462d4b4dece6b2c82b8df9bb8d6f4c317fed5530d01ab1ceb593a36a1 3237 checksum: 4f1b48b52f415505bb3186bf26cdc94f12630d1718ec4e6a003d5d95885590a6dafc2fbd8ed6c4ab0b7752b21e8357bf07bcd353b078429b55207f6d99217eb4
3238 languageName: node 3238 languageName: node
3239 linkType: hard 3239 linkType: hard
3240 3240
@@ -3741,9 +3741,9 @@ __metadata:
3741 linkType: hard 3741 linkType: hard
3742 3742
3743"caniuse-lite@npm:^1.0.30001517": 3743"caniuse-lite@npm:^1.0.30001517":
3744 version: 1.0.30001565 3744 version: 1.0.30001571
3745 resolution: "caniuse-lite@npm:1.0.30001565" 3745 resolution: "caniuse-lite@npm:1.0.30001571"
3746 checksum: b400e0364651a700e39d59449ca6c65b26e2caceecc4b93ae54a01ed1f62d2a7e1333b1dc640d95fbe620ffa5be38fe4dbacd880cd7a1f42fc72bb8de9a2d0c9 3746 checksum: 632f476e39febbfb5dc91c236981f3d518dc0cf55c42cc2bba431a6b6f4cceae3f9cd74d26312f30e9de65a3cc92ccf80d964ba8de061e25f37b7f0518303dad
3747 languageName: node 3747 languageName: node
3748 linkType: hard 3748 linkType: hard
3749 3749
@@ -3998,10 +3998,10 @@ __metadata:
3998 languageName: node 3998 languageName: node
3999 linkType: hard 3999 linkType: hard
4000 4000
4001"csstype@npm:^3.0.2, csstype@npm:^3.1.2": 4001"csstype@npm:^3.0.2, csstype@npm:^3.1.2, csstype@npm:^3.1.3":
4002 version: 3.1.2 4002 version: 3.1.3
4003 resolution: "csstype@npm:3.1.2" 4003 resolution: "csstype@npm:3.1.3"
4004 checksum: 32c038af259897c807ac738d9eab16b3d86747c72b09d5c740978e06f067f9b7b1737e1b75e407c7ab1fe1543dc95f20e202b4786aeb1b8d3bdf5d5ce655e6c6 4004 checksum: 80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248
4005 languageName: node 4005 languageName: node
4006 linkType: hard 4006 linkType: hard
4007 4007
@@ -4918,9 +4918,9 @@ __metadata:
4918 languageName: node 4918 languageName: node
4919 linkType: hard 4919 linkType: hard
4920 4920
4921"eslint-plugin-import@npm:^2.29.0": 4921"eslint-plugin-import@npm:^2.29.1":
4922 version: 2.29.0 4922 version: 2.29.1
4923 resolution: "eslint-plugin-import@npm:2.29.0" 4923 resolution: "eslint-plugin-import@npm:2.29.1"
4924 dependencies: 4924 dependencies:
4925 array-includes: "npm:^3.1.7" 4925 array-includes: "npm:^3.1.7"
4926 array.prototype.findlastindex: "npm:^1.2.3" 4926 array.prototype.findlastindex: "npm:^1.2.3"
@@ -4938,10 +4938,10 @@ __metadata:
4938 object.groupby: "npm:^1.0.1" 4938 object.groupby: "npm:^1.0.1"
4939 object.values: "npm:^1.1.7" 4939 object.values: "npm:^1.1.7"
4940 semver: "npm:^6.3.1" 4940 semver: "npm:^6.3.1"
4941 tsconfig-paths: "npm:^3.14.2" 4941 tsconfig-paths: "npm:^3.15.0"
4942 peerDependencies: 4942 peerDependencies:
4943 eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 4943 eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
4944 checksum: 761a4e1fbc2cd318e62350bed4c448f8b11ed83091d6bb7776f096556363a09debd9922b39fd2714c895edc9aaea82e08e684eb632283f880c58a91e4bae6733 4944 checksum: 5f35dfbf4e8e67f741f396987de9504ad125c49f4144508a93282b4ea0127e052bde65ab6def1f31b6ace6d5d430be698333f75bdd7dca3bc14226c92a083196
4945 languageName: node 4945 languageName: node
4946 linkType: hard 4946 linkType: hard
4947 4947
@@ -4980,22 +4980,23 @@ __metadata:
4980 languageName: node 4980 languageName: node
4981 linkType: hard 4981 linkType: hard
4982 4982
4983"eslint-plugin-prettier@npm:^5.0.1": 4983"eslint-plugin-prettier@npm:^5.1.1":
4984 version: 5.0.1 4984 version: 5.1.1
4985 resolution: "eslint-plugin-prettier@npm:5.0.1" 4985 resolution: "eslint-plugin-prettier@npm:5.1.1"
4986 dependencies: 4986 dependencies:
4987 prettier-linter-helpers: "npm:^1.0.0" 4987 prettier-linter-helpers: "npm:^1.0.0"
4988 synckit: "npm:^0.8.5" 4988 synckit: "npm:^0.8.5"
4989 peerDependencies: 4989 peerDependencies:
4990 "@types/eslint": ">=8.0.0" 4990 "@types/eslint": ">=8.0.0"
4991 eslint: ">=8.0.0" 4991 eslint: ">=8.0.0"
4992 eslint-config-prettier: "*"
4992 prettier: ">=3.0.0" 4993 prettier: ">=3.0.0"
4993 peerDependenciesMeta: 4994 peerDependenciesMeta:
4994 "@types/eslint": 4995 "@types/eslint":
4995 optional: true 4996 optional: true
4996 eslint-config-prettier: 4997 eslint-config-prettier:
4997 optional: true 4998 optional: true
4998 checksum: 08e2c7bed93d9f7c86e9aa0bd4f5cc51f65233a446ddfda11e821f12819e1e4be62cfbc2a4e17169c76fded1c4de7371e37e5f2525e81695decaf6c652a41fb0 4999 checksum: cb9fb797e3b872864d9bd4a6154cc0aeccdd9b3d7add510b2077f6d5149fb4b681abd180dacb5dafda603defb6089824a7c6f97faf1f099dba4f4e77f86c46c3
4999 languageName: node 5000 languageName: node
5000 linkType: hard 5001 linkType: hard
5001 5002
@@ -5051,14 +5052,14 @@ __metadata:
5051 languageName: node 5052 languageName: node
5052 linkType: hard 5053 linkType: hard
5053 5054
5054"eslint@npm:^8.55.0": 5055"eslint@npm:^8.56.0":
5055 version: 8.55.0 5056 version: 8.56.0
5056 resolution: "eslint@npm:8.55.0" 5057 resolution: "eslint@npm:8.56.0"
5057 dependencies: 5058 dependencies:
5058 "@eslint-community/eslint-utils": "npm:^4.2.0" 5059 "@eslint-community/eslint-utils": "npm:^4.2.0"
5059 "@eslint-community/regexpp": "npm:^4.6.1" 5060 "@eslint-community/regexpp": "npm:^4.6.1"
5060 "@eslint/eslintrc": "npm:^2.1.4" 5061 "@eslint/eslintrc": "npm:^2.1.4"
5061 "@eslint/js": "npm:8.55.0" 5062 "@eslint/js": "npm:8.56.0"
5062 "@humanwhocodes/config-array": "npm:^0.11.13" 5063 "@humanwhocodes/config-array": "npm:^0.11.13"
5063 "@humanwhocodes/module-importer": "npm:^1.0.1" 5064 "@humanwhocodes/module-importer": "npm:^1.0.1"
5064 "@nodelib/fs.walk": "npm:^1.2.8" 5065 "@nodelib/fs.walk": "npm:^1.2.8"
@@ -5095,7 +5096,7 @@ __metadata:
5095 text-table: "npm:^0.2.0" 5096 text-table: "npm:^0.2.0"
5096 bin: 5097 bin:
5097 eslint: bin/eslint.js 5098 eslint: bin/eslint.js
5098 checksum: d28c0b60f19bb7d355cb8393e77b018c8f548dba3f820b799c89bb2e0c436ee26084e700c5e57e1e97e7972ec93065277849141b82e7b0c0d02c2dc1e553a2a1 5099 checksum: 2be598f7da1339d045ad933ffd3d4742bee610515cd2b0d9a2b8b729395a01d4e913552fff555b559fccaefd89d7b37632825789d1b06470608737ae69ab43fb
5099 languageName: node 5100 languageName: node
5100 linkType: hard 5101 linkType: hard
5101 5102
@@ -6687,12 +6688,12 @@ __metadata:
6687 languageName: node 6688 languageName: node
6688 linkType: hard 6689 linkType: hard
6689 6690
6690"nanoid@npm:^3.3.6": 6691"nanoid@npm:^3.3.7":
6691 version: 3.3.6 6692 version: 3.3.7
6692 resolution: "nanoid@npm:3.3.6" 6693 resolution: "nanoid@npm:3.3.7"
6693 bin: 6694 bin:
6694 nanoid: bin/nanoid.cjs 6695 nanoid: bin/nanoid.cjs
6695 checksum: 606b355960d0fcbe3d27924c4c52ef7d47d3b57208808ece73279420d91469b01ec1dce10fae512b6d4a8c5a5432b352b228336a8b2202a6ea68e67fa348e2ee 6696 checksum: e3fb661aa083454f40500473bb69eedb85dc160e763150b9a2c567c7e9ff560ce028a9f833123b618a6ea742e311138b591910e795614a629029e86e180660f3
6696 languageName: node 6697 languageName: node
6697 linkType: hard 6698 linkType: hard
6698 6699
@@ -7080,14 +7081,14 @@ __metadata:
7080 languageName: node 7081 languageName: node
7081 linkType: hard 7082 linkType: hard
7082 7083
7083"postcss@npm:^8.4.31": 7084"postcss@npm:^8.4.32":
7084 version: 8.4.31 7085 version: 8.4.32
7085 resolution: "postcss@npm:8.4.31" 7086 resolution: "postcss@npm:8.4.32"
7086 dependencies: 7087 dependencies:
7087 nanoid: "npm:^3.3.6" 7088 nanoid: "npm:^3.3.7"
7088 picocolors: "npm:^1.0.0" 7089 picocolors: "npm:^1.0.0"
7089 source-map-js: "npm:^1.0.2" 7090 source-map-js: "npm:^1.0.2"
7090 checksum: 748b82e6e5fc34034dcf2ae88ea3d11fd09f69b6c50ecdd3b4a875cfc7cdca435c958b211e2cb52355422ab6fccb7d8f2f2923161d7a1b281029e4a913d59acf 7091 checksum: 39308a9195fa34d4dbdd7b58a896cff0c7809f84f7a4ac1b95b68ca86c9138a395addff33075668ed3983d41b90aac05754c445237a9365eb1c3a5602ebd03ad
7091 languageName: node 7092 languageName: node
7092 linkType: hard 7093 linkType: hard
7093 7094
@@ -7116,12 +7117,12 @@ __metadata:
7116 languageName: node 7117 languageName: node
7117 linkType: hard 7118 linkType: hard
7118 7119
7119"prettier@npm:^3.1.0": 7120"prettier@npm:^3.1.1":
7120 version: 3.1.0 7121 version: 3.1.1
7121 resolution: "prettier@npm:3.1.0" 7122 resolution: "prettier@npm:3.1.1"
7122 bin: 7123 bin:
7123 prettier: bin/prettier.cjs 7124 prettier: bin/prettier.cjs
7124 checksum: a45ea70aa97fde162ea4c4aba3dfc7859aa6a732a1db34458d9535dc3c2c16d3bc3fb5689e6cd76aa835562555303b02d9449fd2e15af3b73c8053557e25c5b6 7125 checksum: facc944ba20e194ff4db765e830ffbcb642803381f0d2033ed397e79904fa4ccc877dc25ad68f42d36985c01d051c990ca1b905fb83d2d7d65fe69e4386fa1a3
7125 languageName: node 7126 languageName: node
7126 linkType: hard 7127 linkType: hard
7127 7128
@@ -7209,15 +7210,15 @@ __metadata:
7209 languageName: node 7210 languageName: node
7210 linkType: hard 7211 linkType: hard
7211 7212
7212"react-resize-detector@npm:^9.1.0": 7213"react-resize-detector@npm:^9.1.1":
7213 version: 9.1.0 7214 version: 9.1.1
7214 resolution: "react-resize-detector@npm:9.1.0" 7215 resolution: "react-resize-detector@npm:9.1.1"
7215 dependencies: 7216 dependencies:
7216 lodash: "npm:^4.17.21" 7217 lodash: "npm:^4.17.21"
7217 peerDependencies: 7218 peerDependencies:
7218 react: ^16.0.0 || ^17.0.0 || ^18.0.0 7219 react: ^16.0.0 || ^17.0.0 || ^18.0.0
7219 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 7220 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0
7220 checksum: ebd45b54ce68368a8d8b6b32ff3b7949e8f56d5cce21fb18b5044612b16ae9adfdd2eefa6494a700aaf6c64b2cec4c3c33d86c464d1772042dbb4d87dd3dafc6 7221 checksum: 6a85892fe46a12fc27b09b5bf5fcc1438f3196f70c75d4685b09eed2c68a2c853dd6eb792bf852038082505a3b4f05dba359055ee0baca3f8b59f022a85a368c
7221 languageName: node 7222 languageName: node
7222 linkType: hard 7223 linkType: hard
7223 7224
@@ -8108,15 +8109,15 @@ __metadata:
8108 languageName: node 8109 languageName: node
8109 linkType: hard 8110 linkType: hard
8110 8111
8111"tsconfig-paths@npm:^3.14.2": 8112"tsconfig-paths@npm:^3.15.0":
8112 version: 3.14.2 8113 version: 3.15.0
8113 resolution: "tsconfig-paths@npm:3.14.2" 8114 resolution: "tsconfig-paths@npm:3.15.0"
8114 dependencies: 8115 dependencies:
8115 "@types/json5": "npm:^0.0.29" 8116 "@types/json5": "npm:^0.0.29"
8116 json5: "npm:^1.0.2" 8117 json5: "npm:^1.0.2"
8117 minimist: "npm:^1.2.6" 8118 minimist: "npm:^1.2.6"
8118 strip-bom: "npm:^3.0.0" 8119 strip-bom: "npm:^3.0.0"
8119 checksum: fdc92bb7b18b31c0e76f8ec4f98d07236b09590fd6578e587ad024792c8b2235d65125a8fd007fa47a84400f84ceccbf33f24e5198d953249e7204f4cef3517c 8120 checksum: 5b4f301a2b7a3766a986baf8fc0e177eb80bdba6e396792ff92dc23b5bca8bb279fc96517dcaaef63a3b49bebc6c4c833653ec58155780bc906bdbcf7dda0ef5
8120 languageName: node 8121 languageName: node
8121 linkType: hard 8122 linkType: hard
8122 8123
@@ -8197,23 +8198,23 @@ __metadata:
8197 languageName: node 8198 languageName: node
8198 linkType: hard 8199 linkType: hard
8199 8200
8200"typescript@npm:5.3.2": 8201"typescript@npm:5.3.3":
8201 version: 5.3.2 8202 version: 5.3.3
8202 resolution: "typescript@npm:5.3.2" 8203 resolution: "typescript@npm:5.3.3"
8203 bin: 8204 bin:
8204 tsc: bin/tsc 8205 tsc: bin/tsc
8205 tsserver: bin/tsserver 8206 tsserver: bin/tsserver
8206 checksum: d7dbe1fbe19039e36a65468ea64b5d338c976550394ba576b7af9c68ed40c0bc5d12ecce390e4b94b287a09a71bd3229f19c2d5680611f35b7c53a3898791159 8207 checksum: e33cef99d82573624fc0f854a2980322714986bc35b9cb4d1ce736ed182aeab78e2cb32b385efa493b2a976ef52c53e20d6c6918312353a91850e2b76f1ea44f
8207 languageName: node 8208 languageName: node
8208 linkType: hard 8209 linkType: hard
8209 8210
8210"typescript@patch:typescript@npm%3A5.3.2#optional!builtin<compat/typescript>": 8211"typescript@patch:typescript@npm%3A5.3.3#optional!builtin<compat/typescript>":
8211 version: 5.3.2 8212 version: 5.3.3
8212 resolution: "typescript@patch:typescript@npm%3A5.3.2#optional!builtin<compat/typescript>::version=5.3.2&hash=e012d7" 8213 resolution: "typescript@patch:typescript@npm%3A5.3.3#optional!builtin<compat/typescript>::version=5.3.3&hash=e012d7"
8213 bin: 8214 bin:
8214 tsc: bin/tsc 8215 tsc: bin/tsc
8215 tsserver: bin/tsserver 8216 tsserver: bin/tsserver
8216 checksum: 73c8bad74e732d93211c9d77f28b03307e2f5fc6a0afc73f4b783261ab567686a16d6ae958bdaef383a00be1b0b8c8b6741dd6ca3d13af4963fa7e47456d49c7 8217 checksum: 1d0a5f4ce496c42caa9a30e659c467c5686eae15d54b027ee7866744952547f1be1262f2d40de911618c242b510029d51d43ff605dba8fb740ec85ca2d3f9500
8217 languageName: node 8218 languageName: node
8218 linkType: hard 8219 linkType: hard
8219 8220
@@ -8360,9 +8361,9 @@ __metadata:
8360 languageName: node 8361 languageName: node
8361 linkType: hard 8362 linkType: hard
8362 8363
8363"vite-plugin-pwa@npm:^0.17.2": 8364"vite-plugin-pwa@npm:^0.17.4":
8364 version: 0.17.2 8365 version: 0.17.4
8365 resolution: "vite-plugin-pwa@npm:0.17.2" 8366 resolution: "vite-plugin-pwa@npm:0.17.4"
8366 dependencies: 8367 dependencies:
8367 debug: "npm:^4.3.4" 8368 debug: "npm:^4.3.4"
8368 fast-glob: "npm:^3.3.2" 8369 fast-glob: "npm:^3.3.2"
@@ -8373,17 +8374,17 @@ __metadata:
8373 vite: ^3.1.0 || ^4.0.0 || ^5.0.0 8374 vite: ^3.1.0 || ^4.0.0 || ^5.0.0
8374 workbox-build: ^7.0.0 8375 workbox-build: ^7.0.0
8375 workbox-window: ^7.0.0 8376 workbox-window: ^7.0.0
8376 checksum: a51ce04ac51df72a26dc84162872b812f5c88bf9683b4a48d1331d9349aa67ebc4602e92e1012a0348777db160142ed921083beccfc9b14bcfe44c88b7f98fb8 8377 checksum: 092da93c53fac8f90028c9412ee647944b59dcd2dbdfabd5c2c4a344dd2e09b1abde66bb8c2dd85022ba0fa68e77f7a8fb67e2659199b4effe549c0d7c46f681
8377 languageName: node 8378 languageName: node
8378 linkType: hard 8379 linkType: hard
8379 8380
8380"vite@npm:^5.0.4": 8381"vite@npm:^5.0.10":
8381 version: 5.0.4 8382 version: 5.0.10
8382 resolution: "vite@npm:5.0.4" 8383 resolution: "vite@npm:5.0.10"
8383 dependencies: 8384 dependencies:
8384 esbuild: "npm:^0.19.3" 8385 esbuild: "npm:^0.19.3"
8385 fsevents: "npm:~2.3.3" 8386 fsevents: "npm:~2.3.3"
8386 postcss: "npm:^8.4.31" 8387 postcss: "npm:^8.4.32"
8387 rollup: "npm:^4.2.0" 8388 rollup: "npm:^4.2.0"
8388 peerDependencies: 8389 peerDependencies:
8389 "@types/node": ^18.0.0 || >=20.0.0 8390 "@types/node": ^18.0.0 || >=20.0.0
@@ -8413,7 +8414,7 @@ __metadata:
8413 optional: true 8414 optional: true
8414 bin: 8415 bin:
8415 vite: bin/vite.js 8416 vite: bin/vite.js
8416 checksum: 67a0df248af042e75b1ecbf20098096df80a1068a832c5c964a20d7c06853e12b7310989c3c273cb88a9a3a37f4bada0a2115018b36df0fc09a6b6dba9a7d5b5 8417 checksum: d666b2760d2a7ea1d0d35f67c042053e562144f80554be4e4dc58e607fd5f62193cd203d73ab2e315df66830d8b9d9a2e3509d0208bdef1b2e92e0a5c364df84
8417 languageName: node 8418 languageName: node
8418 linkType: hard 8419 linkType: hard
8419 8420