diff options
author | Kristóf Marussy <marussy@mit.bme.hu> | 2023-11-03 19:24:07 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-03 19:24:07 +0100 |
commit | 62058e085ddf925ae14573379ded2c3333a4fde5 (patch) | |
tree | dcff140c1af411612c2ca61a34471134d762843a | |
parent | refactor(interpreter): aggreagator batching (diff) | |
parent | refactor: smenatics and facades (diff) | |
download | refinery-62058e085ddf925ae14573379ded2c3333a4fde5.tar.gz refinery-62058e085ddf925ae14573379ded2c3333a4fde5.tar.zst refinery-62058e085ddf925ae14573379ded2c3333a4fde5.zip |
Merge pull request #47 from kris7t/generator-facade
Generator facade
45 files changed, 912 insertions, 263 deletions
diff --git a/settings.gradle.kts b/settings.gradle.kts index 0a9d4ca5..40df30ff 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts | |||
@@ -8,6 +8,7 @@ rootProject.name = "refinery" | |||
8 | 8 | ||
9 | include( | 9 | include( |
10 | "frontend", | 10 | "frontend", |
11 | "generator", | ||
11 | "interpreter", | 12 | "interpreter", |
12 | "interpreter-localsearch", | 13 | "interpreter-localsearch", |
13 | "interpreter-rete", | 14 | "interpreter-rete", |
diff --git a/subprojects/generator/build.gradle.kts b/subprojects/generator/build.gradle.kts new file mode 100644 index 00000000..d87ce6de --- /dev/null +++ b/subprojects/generator/build.gradle.kts | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | dependencies { | ||
12 | api(project(":refinery-language-semantics")) | ||
13 | api(libs.eclipseCollections.api) | ||
14 | implementation(project(":refinery-store-query-interpreter")) | ||
15 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java new file mode 100644 index 00000000..a00ddc46 --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelFacade.java | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | import tools.refinery.language.semantics.ProblemTrace; | ||
9 | import tools.refinery.store.model.Model; | ||
10 | import tools.refinery.store.model.ModelStore; | ||
11 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
12 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; | ||
13 | import tools.refinery.store.reasoning.interpretation.PartialInterpretation; | ||
14 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
15 | import tools.refinery.store.reasoning.representation.PartialSymbol; | ||
16 | import tools.refinery.store.reasoning.seed.ModelSeed; | ||
17 | import tools.refinery.store.reasoning.translator.TranslationException; | ||
18 | |||
19 | public abstract class ModelFacade { | ||
20 | private final ProblemTrace problemTrace; | ||
21 | private final ModelStore store; | ||
22 | private final Model model; | ||
23 | private final ReasoningAdapter reasoningAdapter; | ||
24 | private final Concreteness concreteness; | ||
25 | |||
26 | protected ModelFacade(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed, | ||
27 | Concreteness concreteness) { | ||
28 | this.problemTrace = problemTrace; | ||
29 | this.store = store; | ||
30 | try { | ||
31 | model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed); | ||
32 | } catch (TranslationException e) { | ||
33 | throw problemTrace.wrapException(e); | ||
34 | } | ||
35 | reasoningAdapter = model.getAdapter(ReasoningAdapter.class); | ||
36 | this.concreteness = concreteness; | ||
37 | } | ||
38 | |||
39 | public ProblemTrace getProblemTrace() { | ||
40 | return problemTrace; | ||
41 | } | ||
42 | |||
43 | public ModelStore getModelStore() { | ||
44 | return store; | ||
45 | } | ||
46 | |||
47 | public Model getModel() { | ||
48 | return model; | ||
49 | } | ||
50 | |||
51 | public Concreteness getConcreteness() { | ||
52 | return concreteness; | ||
53 | } | ||
54 | |||
55 | public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) { | ||
56 | return reasoningAdapter.getPartialInterpretation(concreteness, partialSymbol); | ||
57 | } | ||
58 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java new file mode 100644 index 00000000..5b44c10a --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGenerator.java | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | import tools.refinery.language.semantics.ProblemTrace; | ||
9 | import tools.refinery.store.dse.strategy.BestFirstStoreManager; | ||
10 | import tools.refinery.store.map.Version; | ||
11 | import tools.refinery.store.model.ModelStore; | ||
12 | import tools.refinery.store.reasoning.interpretation.PartialInterpretation; | ||
13 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
14 | import tools.refinery.store.reasoning.representation.PartialSymbol; | ||
15 | import tools.refinery.store.reasoning.seed.ModelSeed; | ||
16 | |||
17 | public class ModelGenerator extends ModelFacade { | ||
18 | private final Version initialVersion; | ||
19 | |||
20 | private int randomSeed = 0; | ||
21 | |||
22 | private boolean lastGenerationSuccessful; | ||
23 | |||
24 | public ModelGenerator(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) { | ||
25 | super(problemTrace, store, modelSeed, Concreteness.CANDIDATE); | ||
26 | initialVersion = getModel().commit(); | ||
27 | } | ||
28 | |||
29 | public int getRandomSeed() { | ||
30 | return randomSeed; | ||
31 | } | ||
32 | |||
33 | public void setRandomSeed(int randomSeed) { | ||
34 | this.randomSeed = randomSeed; | ||
35 | this.lastGenerationSuccessful = false; | ||
36 | } | ||
37 | |||
38 | public boolean isLastGenerationSuccessful() { | ||
39 | return lastGenerationSuccessful; | ||
40 | } | ||
41 | |||
42 | // This method only makes sense if it returns {@code true} on success. | ||
43 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") | ||
44 | public boolean tryGenerate() { | ||
45 | lastGenerationSuccessful = false; | ||
46 | randomSeed++; | ||
47 | var bestFirst = new BestFirstStoreManager(getModelStore(), 1); | ||
48 | bestFirst.startExploration(initialVersion, randomSeed); | ||
49 | var solutions = bestFirst.getSolutionStore().getSolutions(); | ||
50 | if (solutions.isEmpty()) { | ||
51 | return false; | ||
52 | } | ||
53 | getModel().restore(solutions.get(0).version()); | ||
54 | lastGenerationSuccessful = true; | ||
55 | return true; | ||
56 | } | ||
57 | |||
58 | public void generate() { | ||
59 | if (!tryGenerate()) { | ||
60 | throw new UnsatisfiableProblemException(); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol) { | ||
66 | if (!lastGenerationSuccessful) { | ||
67 | throw new IllegalStateException("No generated model is available"); | ||
68 | } | ||
69 | return super.getPartialInterpretation(partialSymbol); | ||
70 | } | ||
71 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java new file mode 100644 index 00000000..6642d591 --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelGeneratorFactory.java | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import com.google.inject.Provider; | ||
10 | import tools.refinery.language.model.problem.Problem; | ||
11 | import tools.refinery.language.semantics.ModelInitializer; | ||
12 | import tools.refinery.store.dse.propagation.PropagationAdapter; | ||
13 | import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; | ||
14 | import tools.refinery.store.model.ModelStore; | ||
15 | import tools.refinery.store.query.interpreter.QueryInterpreterAdapter; | ||
16 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
17 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
18 | import tools.refinery.store.statecoding.StateCoderAdapter; | ||
19 | import tools.refinery.store.util.CancellationToken; | ||
20 | |||
21 | import java.util.Collection; | ||
22 | import java.util.Set; | ||
23 | |||
24 | public final class ModelGeneratorFactory { | ||
25 | @Inject | ||
26 | private Provider<ModelInitializer> initializerProvider; | ||
27 | |||
28 | private CancellationToken cancellationToken = CancellationToken.NONE; | ||
29 | |||
30 | private boolean debugPartialInterpretations; | ||
31 | |||
32 | public ModelGeneratorFactory cancellationToken(CancellationToken cancellationToken) { | ||
33 | this.cancellationToken = cancellationToken; | ||
34 | return this; | ||
35 | } | ||
36 | |||
37 | public ModelGeneratorFactory debugPartialInterpretations(boolean debugPartialInterpretations) { | ||
38 | this.debugPartialInterpretations = debugPartialInterpretations; | ||
39 | return this; | ||
40 | } | ||
41 | |||
42 | public ModelGenerator createGenerator(Problem problem) { | ||
43 | var initializer = initializerProvider.get(); | ||
44 | initializer.readProblem(problem); | ||
45 | cancellationToken.checkCancelled(); | ||
46 | var storeBuilder = ModelStore.builder() | ||
47 | .cancellationToken(cancellationToken) | ||
48 | .with(QueryInterpreterAdapter.builder()) | ||
49 | .with(PropagationAdapter.builder()) | ||
50 | .with(StateCoderAdapter.builder()) | ||
51 | .with(DesignSpaceExplorationAdapter.builder()) | ||
52 | .with(ReasoningAdapter.builder() | ||
53 | .requiredInterpretations(getRequiredInterpretations())); | ||
54 | initializer.configureStoreBuilder(storeBuilder); | ||
55 | var store = storeBuilder.build(); | ||
56 | return new ModelGenerator(initializer.getProblemTrace(), store, initializer.getModelSeed()); | ||
57 | } | ||
58 | |||
59 | private Collection<Concreteness> getRequiredInterpretations() { | ||
60 | return debugPartialInterpretations ? Set.of(Concreteness.PARTIAL, Concreteness.CANDIDATE) : | ||
61 | Set.of(Concreteness.CANDIDATE); | ||
62 | } | ||
63 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java new file mode 100644 index 00000000..bc02c887 --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemantics.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | import tools.refinery.language.semantics.ProblemTrace; | ||
9 | import tools.refinery.store.model.ModelStore; | ||
10 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
11 | import tools.refinery.store.reasoning.seed.ModelSeed; | ||
12 | |||
13 | public class ModelSemantics extends ModelFacade { | ||
14 | public ModelSemantics(ProblemTrace problemTrace, ModelStore store, ModelSeed modelSeed) { | ||
15 | super(problemTrace, store, modelSeed, Concreteness.PARTIAL); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java new file mode 100644 index 00000000..b6263b37 --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ModelSemanticsFactory.java | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import com.google.inject.Provider; | ||
10 | import tools.refinery.language.model.problem.Problem; | ||
11 | import tools.refinery.language.semantics.ModelInitializer; | ||
12 | import tools.refinery.store.dse.propagation.PropagationAdapter; | ||
13 | import tools.refinery.store.model.ModelStore; | ||
14 | import tools.refinery.store.query.interpreter.QueryInterpreterAdapter; | ||
15 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
16 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
17 | import tools.refinery.store.util.CancellationToken; | ||
18 | |||
19 | import java.util.Set; | ||
20 | |||
21 | public final class ModelSemanticsFactory { | ||
22 | @Inject | ||
23 | private Provider<ModelInitializer> initializerProvider; | ||
24 | |||
25 | private CancellationToken cancellationToken = CancellationToken.NONE; | ||
26 | |||
27 | public ModelSemanticsFactory cancellationToken(CancellationToken cancellationToken) { | ||
28 | this.cancellationToken = cancellationToken; | ||
29 | return this; | ||
30 | } | ||
31 | |||
32 | public ModelSemantics createSemantics(Problem problem) { | ||
33 | var initializer = initializerProvider.get(); | ||
34 | initializer.readProblem(problem); | ||
35 | var storeBuilder = ModelStore.builder() | ||
36 | .cancellationToken(cancellationToken) | ||
37 | .with(QueryInterpreterAdapter.builder()) | ||
38 | .with(PropagationAdapter.builder()) | ||
39 | .with(ReasoningAdapter.builder() | ||
40 | .requiredInterpretations(Set.of(Concreteness.PARTIAL))); | ||
41 | initializer.configureStoreBuilder(storeBuilder); | ||
42 | var store = storeBuilder.build(); | ||
43 | return new ModelSemantics(initializer.getProblemTrace(), store, initializer.getModelSeed()); | ||
44 | } | ||
45 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java new file mode 100644 index 00000000..29f80714 --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ProblemLoader.java | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import com.google.inject.Provider; | ||
10 | import org.eclipse.emf.common.util.URI; | ||
11 | import org.eclipse.emf.ecore.resource.Resource; | ||
12 | import org.eclipse.xtext.diagnostics.Severity; | ||
13 | import org.eclipse.xtext.resource.IResourceFactory; | ||
14 | import org.eclipse.xtext.resource.XtextResourceSet; | ||
15 | import org.eclipse.xtext.util.LazyStringInputStream; | ||
16 | import org.eclipse.xtext.validation.CheckMode; | ||
17 | import org.eclipse.xtext.validation.IResourceValidator; | ||
18 | import tools.refinery.language.model.problem.Problem; | ||
19 | import tools.refinery.store.util.CancellationToken; | ||
20 | |||
21 | import java.io.File; | ||
22 | import java.io.IOException; | ||
23 | import java.io.InputStream; | ||
24 | import java.util.Map; | ||
25 | |||
26 | public class ProblemLoader { | ||
27 | @Inject | ||
28 | private Provider<XtextResourceSet> resourceSetProvider; | ||
29 | |||
30 | @Inject | ||
31 | private IResourceFactory resourceFactory; | ||
32 | |||
33 | @Inject | ||
34 | private IResourceValidator resourceValidator; | ||
35 | |||
36 | private CancellationToken cancellationToken = CancellationToken.NONE; | ||
37 | |||
38 | public ProblemLoader cancellationToken(CancellationToken cancellationToken) { | ||
39 | this.cancellationToken = cancellationToken; | ||
40 | return this; | ||
41 | } | ||
42 | |||
43 | public Problem loadString(String problemString) throws IOException { | ||
44 | try (var stream = new LazyStringInputStream(problemString)) { | ||
45 | return loadStream(stream); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | public Problem loadStream(InputStream inputStream) throws IOException { | ||
50 | var resourceSet = resourceSetProvider.get(); | ||
51 | var resource = resourceFactory.createResource(URI.createFileURI("__synthetic.problem")); | ||
52 | resourceSet.getResources().add(resource); | ||
53 | resource.load(inputStream, Map.of()); | ||
54 | return loadResource(resource); | ||
55 | } | ||
56 | |||
57 | public Problem loadFile(File file) throws IOException { | ||
58 | return loadFile(file.getAbsolutePath()); | ||
59 | } | ||
60 | |||
61 | public Problem loadFile(String filePath) throws IOException { | ||
62 | return loadUri(URI.createFileURI(filePath)); | ||
63 | } | ||
64 | |||
65 | public Problem loadUri(URI uri) throws IOException { | ||
66 | var resourceSet = resourceSetProvider.get(); | ||
67 | var resource = resourceFactory.createResource(uri); | ||
68 | resourceSet.getResources().add(resource); | ||
69 | resource.load(Map.of()); | ||
70 | return loadResource(resource); | ||
71 | } | ||
72 | |||
73 | public Problem loadResource(Resource resource) { | ||
74 | var issues = resourceValidator.validate(resource, CheckMode.ALL, () -> { | ||
75 | cancellationToken.checkCancelled(); | ||
76 | return Thread.interrupted(); | ||
77 | }); | ||
78 | cancellationToken.checkCancelled(); | ||
79 | var errors = issues.stream() | ||
80 | .filter(issue -> issue.getSeverity() == Severity.ERROR) | ||
81 | .toList(); | ||
82 | if (!errors.isEmpty()) { | ||
83 | throw new ValidationErrorsException(resource.getURI(), errors); | ||
84 | } | ||
85 | if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof Problem problem)) { | ||
86 | throw new IllegalArgumentException("Model generation problem not found in resource " + resource.getURI()); | ||
87 | } | ||
88 | return problem; | ||
89 | } | ||
90 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/UnsatisfiableProblemException.java b/subprojects/generator/src/main/java/tools/refinery/generator/UnsatisfiableProblemException.java new file mode 100644 index 00000000..4fb18b90 --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/UnsatisfiableProblemException.java | |||
@@ -0,0 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | public class UnsatisfiableProblemException extends RuntimeException { | ||
9 | public UnsatisfiableProblemException() { | ||
10 | super("Model generation problem was unsatisfiable"); | ||
11 | } | ||
12 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/ValidationErrorsException.java b/subprojects/generator/src/main/java/tools/refinery/generator/ValidationErrorsException.java new file mode 100644 index 00000000..d668e51d --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/ValidationErrorsException.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 | */ | ||
6 | package tools.refinery.generator; | ||
7 | |||
8 | import org.eclipse.emf.common.util.URI; | ||
9 | import org.eclipse.xtext.validation.Issue; | ||
10 | |||
11 | import java.util.List; | ||
12 | |||
13 | public class ValidationErrorsException extends IllegalArgumentException { | ||
14 | private final transient URI resourceUri; | ||
15 | |||
16 | private final String resourceUriString; | ||
17 | |||
18 | private final transient List<Issue> errors; | ||
19 | |||
20 | private final List<String> errorStrings; | ||
21 | |||
22 | public ValidationErrorsException(URI resourceUri, List<Issue> errors) { | ||
23 | this.resourceUri = resourceUri; | ||
24 | resourceUriString = resourceUri.toString(); | ||
25 | this.errors = errors; | ||
26 | errorStrings = errors.stream() | ||
27 | .map(Issue::toString) | ||
28 | .toList(); | ||
29 | } | ||
30 | |||
31 | public URI getResourceUri() { | ||
32 | return resourceUri; | ||
33 | } | ||
34 | |||
35 | public String getResourceUriString() { | ||
36 | return resourceUriString; | ||
37 | } | ||
38 | |||
39 | public List<Issue> getErrors() { | ||
40 | return errors; | ||
41 | } | ||
42 | |||
43 | public List<String> getErrorStrings() { | ||
44 | return errorStrings; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public String getMessage() { | ||
49 | var builder = new StringBuilder(); | ||
50 | builder.append("Validation errors in resource "); | ||
51 | builder.append(resourceUriString); | ||
52 | builder.append(": "); | ||
53 | var iterator = errorStrings.iterator(); | ||
54 | if (!iterator.hasNext()) { | ||
55 | return builder.toString(); | ||
56 | } | ||
57 | builder.append(iterator.next()); | ||
58 | while (iterator.hasNext()) { | ||
59 | builder.append(",\n"); | ||
60 | builder.append(iterator.next()); | ||
61 | } | ||
62 | return builder.toString(); | ||
63 | } | ||
64 | } | ||
diff --git a/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java b/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java new file mode 100644 index 00000000..b444491b --- /dev/null +++ b/subprojects/generator/src/main/java/tools/refinery/generator/standalone/StandaloneRefinery.java | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.generator.standalone; | ||
7 | |||
8 | import com.google.inject.Injector; | ||
9 | import tools.refinery.generator.ModelGeneratorFactory; | ||
10 | import tools.refinery.generator.ModelSemanticsFactory; | ||
11 | import tools.refinery.language.ProblemStandaloneSetup; | ||
12 | import tools.refinery.generator.ProblemLoader; | ||
13 | |||
14 | public final class StandaloneRefinery { | ||
15 | private StandaloneRefinery() { | ||
16 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | ||
17 | } | ||
18 | |||
19 | public static Injector getInjector() { | ||
20 | return LazyHolder.INJECTOR; | ||
21 | } | ||
22 | |||
23 | public static <T> T getInstance(Class<T> type) { | ||
24 | return getInjector().getInstance(type); | ||
25 | } | ||
26 | |||
27 | public static ProblemLoader getProblemLoader() { | ||
28 | return getInstance(ProblemLoader.class); | ||
29 | } | ||
30 | |||
31 | public static ModelGeneratorFactory getGeneratorFactory() { | ||
32 | return getInstance(ModelGeneratorFactory.class); | ||
33 | } | ||
34 | |||
35 | public static ModelSemanticsFactory getSemanticsFactory() { | ||
36 | return getInstance(ModelSemanticsFactory.class); | ||
37 | } | ||
38 | |||
39 | private static final class LazyHolder { | ||
40 | private static final Injector INJECTOR = createInjector(); | ||
41 | |||
42 | private static Injector createInjector() { | ||
43 | return new ProblemStandaloneSetup().createInjectorAndDoEMFRegistration(); | ||
44 | } | ||
45 | } | ||
46 | } | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java index 85c8d701..b3c58366 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java | |||
@@ -3,13 +3,11 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model; | 6 | package tools.refinery.language.semantics; |
7 | 7 | ||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; | ||
10 | import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; | ||
11 | import tools.refinery.language.model.problem.*; | 9 | import tools.refinery.language.model.problem.*; |
12 | import tools.refinery.language.semantics.model.internal.MutableSeed; | 10 | import tools.refinery.language.semantics.internal.MutableSeed; |
13 | import tools.refinery.language.utils.BuiltinSymbols; | 11 | import tools.refinery.language.utils.BuiltinSymbols; |
14 | import tools.refinery.language.utils.ProblemDesugarer; | 12 | import tools.refinery.language.utils.ProblemDesugarer; |
15 | import tools.refinery.language.utils.ProblemUtil; | 13 | import tools.refinery.language.utils.ProblemUtil; |
@@ -23,11 +21,11 @@ import tools.refinery.store.query.literal.*; | |||
23 | import tools.refinery.store.query.term.NodeVariable; | 21 | import tools.refinery.store.query.term.NodeVariable; |
24 | import tools.refinery.store.query.term.Variable; | 22 | import tools.refinery.store.query.term.Variable; |
25 | import tools.refinery.store.reasoning.ReasoningAdapter; | 23 | import tools.refinery.store.reasoning.ReasoningAdapter; |
26 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | ||
27 | import tools.refinery.store.reasoning.representation.PartialRelation; | 24 | import tools.refinery.store.reasoning.representation.PartialRelation; |
28 | import tools.refinery.store.reasoning.scope.ScopePropagator; | 25 | import tools.refinery.store.reasoning.scope.ScopePropagator; |
29 | import tools.refinery.store.reasoning.seed.ModelSeed; | 26 | import tools.refinery.store.reasoning.seed.ModelSeed; |
30 | import tools.refinery.store.reasoning.seed.Seed; | 27 | import tools.refinery.store.reasoning.seed.Seed; |
28 | import tools.refinery.store.reasoning.translator.TranslationException; | ||
31 | import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; | 29 | import tools.refinery.store.reasoning.translator.containment.ContainmentHierarchyTranslator; |
32 | import tools.refinery.store.reasoning.translator.metamodel.Metamodel; | 30 | import tools.refinery.store.reasoning.translator.metamodel.Metamodel; |
33 | import tools.refinery.store.reasoning.translator.metamodel.MetamodelBuilder; | 31 | import tools.refinery.store.reasoning.translator.metamodel.MetamodelBuilder; |
@@ -52,24 +50,19 @@ public class ModelInitializer { | |||
52 | @Inject | 50 | @Inject |
53 | private SemanticsUtils semanticsUtils; | 51 | private SemanticsUtils semanticsUtils; |
54 | 52 | ||
55 | private Problem problem; | 53 | @Inject |
54 | private ProblemTraceImpl problemTrace; | ||
56 | 55 | ||
57 | private ModelStoreBuilder storeBuilder; | 56 | private Problem problem; |
58 | 57 | ||
59 | private BuiltinSymbols builtinSymbols; | 58 | private BuiltinSymbols builtinSymbols; |
60 | 59 | ||
61 | private PartialRelation nodeRelation; | 60 | private PartialRelation nodeRelation; |
62 | 61 | ||
63 | private final MutableObjectIntMap<Node> nodeTrace = ObjectIntMaps.mutable.empty(); | ||
64 | |||
65 | private final Map<Relation, RelationInfo> relationInfoMap = new LinkedHashMap<>(); | 62 | private final Map<Relation, RelationInfo> relationInfoMap = new LinkedHashMap<>(); |
66 | 63 | ||
67 | private final Map<PartialRelation, RelationInfo> partialRelationInfoMap = new HashMap<>(); | 64 | private final Map<PartialRelation, RelationInfo> partialRelationInfoMap = new HashMap<>(); |
68 | 65 | ||
69 | private final Map<AnyPartialSymbol, Relation> inverseTrace = new HashMap<>(); | ||
70 | |||
71 | private Map<Relation, PartialRelation> relationTrace; | ||
72 | |||
73 | private final MetamodelBuilder metamodelBuilder = Metamodel.builder(); | 66 | private final MetamodelBuilder metamodelBuilder = Metamodel.builder(); |
74 | 67 | ||
75 | private Metamodel metamodel; | 68 | private Metamodel metamodel; |
@@ -80,79 +73,89 @@ public class ModelInitializer { | |||
80 | 73 | ||
81 | private ModelSeed modelSeed; | 74 | private ModelSeed modelSeed; |
82 | 75 | ||
83 | public Problem getProblem() { | 76 | public void readProblem(Problem problem) { |
84 | return problem; | 77 | if (this.problem != null) { |
85 | } | 78 | throw new IllegalArgumentException("Problem was already set"); |
86 | 79 | } | |
87 | public int getNodeCount() { | 80 | this.problem = problem; |
88 | return nodeTrace.size(); | 81 | problemTrace.setProblem(problem); |
82 | try { | ||
83 | builtinSymbols = desugarer.getBuiltinSymbols(problem).orElseThrow(() -> new IllegalArgumentException( | ||
84 | "Problem has no builtin library")); | ||
85 | var nodeInfo = collectPartialRelation(builtinSymbols.node(), 1, TruthValue.TRUE, TruthValue.TRUE); | ||
86 | nodeRelation = nodeInfo.partialRelation(); | ||
87 | metamodelBuilder.type(nodeRelation); | ||
88 | putRelationInfo(builtinSymbols.exists(), new RelationInfo(ReasoningAdapter.EXISTS_SYMBOL, null, | ||
89 | TruthValue.TRUE)); | ||
90 | putRelationInfo(builtinSymbols.equals(), new RelationInfo(ReasoningAdapter.EQUALS_SYMBOL, | ||
91 | (TruthValue) null, | ||
92 | null)); | ||
93 | putRelationInfo(builtinSymbols.contained(), | ||
94 | new RelationInfo(ContainmentHierarchyTranslator.CONTAINED_SYMBOL, null, TruthValue.UNKNOWN)); | ||
95 | putRelationInfo(builtinSymbols.contains(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINS_SYMBOL, | ||
96 | null, TruthValue.UNKNOWN)); | ||
97 | putRelationInfo(builtinSymbols.invalidContainer(), | ||
98 | new RelationInfo(ContainmentHierarchyTranslator.INVALID_CONTAINER, TruthValue.FALSE, | ||
99 | TruthValue.FALSE)); | ||
100 | collectNodes(); | ||
101 | collectPartialSymbols(); | ||
102 | collectMetamodel(); | ||
103 | metamodel = metamodelBuilder.build(); | ||
104 | problemTrace.setMetamodel(metamodel); | ||
105 | collectAssertions(); | ||
106 | int nodeCount = problemTrace.getNodeTrace().size(); | ||
107 | var modelSeedBuilder = ModelSeed.builder(nodeCount); | ||
108 | for (var entry : relationInfoMap.entrySet()) { | ||
109 | var info = entry.getValue(); | ||
110 | var partialRelation = info.partialRelation(); | ||
111 | modelSeedBuilder.seed(partialRelation, info.toSeed(nodeCount)); | ||
112 | } | ||
113 | collectScopes(); | ||
114 | modelSeedBuilder.seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
115 | .reducedValue(CardinalityIntervals.SET) | ||
116 | .putAll(countSeed)); | ||
117 | modelSeed = modelSeedBuilder.build(); | ||
118 | } catch (TranslationException e) { | ||
119 | throw problemTrace.wrapException(e); | ||
120 | } | ||
89 | } | 121 | } |
90 | 122 | ||
91 | public MutableObjectIntMap<Node> getNodeTrace() { | 123 | public void configureStoreBuilder(ModelStoreBuilder storeBuilder) { |
92 | return nodeTrace; | 124 | checkProblem(); |
125 | try { | ||
126 | storeBuilder.with(new MultiObjectTranslator()); | ||
127 | storeBuilder.with(new MetamodelTranslator(metamodel)); | ||
128 | if (scopePropagator != null) { | ||
129 | if (storeBuilder.tryGetAdapter(PropagationBuilder.class).isEmpty()) { | ||
130 | throw new TracedException(problem, "Type scopes require a PropagationBuilder"); | ||
131 | } | ||
132 | storeBuilder.with(scopePropagator); | ||
133 | } | ||
134 | collectPredicates(storeBuilder); | ||
135 | } catch (TranslationException e) { | ||
136 | throw problemTrace.wrapException(e); | ||
137 | } | ||
93 | } | 138 | } |
94 | 139 | ||
95 | public Map<Relation, PartialRelation> getRelationTrace() { | 140 | private void checkProblem() { |
96 | return relationTrace; | 141 | if (problem == null) { |
142 | throw new IllegalStateException("Problem is not set"); | ||
143 | } | ||
97 | } | 144 | } |
98 | 145 | ||
99 | public Relation getInverseTrace(AnyPartialSymbol partialRelation) { | 146 | public ModelSeed createModel(Problem problem, ModelStoreBuilder storeBuilder) { |
100 | return inverseTrace.get(partialRelation); | 147 | readProblem(problem); |
148 | configureStoreBuilder(storeBuilder); | ||
149 | return getModelSeed(); | ||
101 | } | 150 | } |
102 | 151 | ||
103 | public Metamodel getMetamodel() { | 152 | public ProblemTrace getProblemTrace() { |
104 | return metamodel; | 153 | checkProblem(); |
154 | return problemTrace; | ||
105 | } | 155 | } |
106 | 156 | ||
107 | public ModelSeed createModel(Problem problem, ModelStoreBuilder storeBuilder) { | 157 | public ModelSeed getModelSeed() { |
108 | this.problem = problem; | 158 | checkProblem(); |
109 | this.storeBuilder = storeBuilder; | ||
110 | builtinSymbols = desugarer.getBuiltinSymbols(problem).orElseThrow(() -> new IllegalArgumentException( | ||
111 | "Problem has no builtin library")); | ||
112 | var nodeInfo = collectPartialRelation(builtinSymbols.node(), 1, TruthValue.TRUE, TruthValue.TRUE); | ||
113 | nodeRelation = nodeInfo.partialRelation(); | ||
114 | metamodelBuilder.type(nodeRelation); | ||
115 | putRelationInfo(builtinSymbols.exists(), new RelationInfo(ReasoningAdapter.EXISTS_SYMBOL, null, | ||
116 | TruthValue.TRUE)); | ||
117 | putRelationInfo(builtinSymbols.equals(), new RelationInfo(ReasoningAdapter.EQUALS_SYMBOL, | ||
118 | (TruthValue) null, | ||
119 | null)); | ||
120 | putRelationInfo(builtinSymbols.contained(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINED_SYMBOL, | ||
121 | null, TruthValue.UNKNOWN)); | ||
122 | putRelationInfo(builtinSymbols.contains(), new RelationInfo(ContainmentHierarchyTranslator.CONTAINS_SYMBOL, | ||
123 | null, TruthValue.UNKNOWN)); | ||
124 | putRelationInfo(builtinSymbols.invalidContainer(), | ||
125 | new RelationInfo(ContainmentHierarchyTranslator.INVALID_CONTAINER, TruthValue.FALSE, | ||
126 | TruthValue.FALSE)); | ||
127 | collectNodes(); | ||
128 | collectPartialSymbols(); | ||
129 | collectMetamodel(); | ||
130 | metamodel = metamodelBuilder.build(); | ||
131 | collectAssertions(); | ||
132 | storeBuilder.with(new MultiObjectTranslator()); | ||
133 | storeBuilder.with(new MetamodelTranslator(metamodel)); | ||
134 | relationTrace = new LinkedHashMap<>(relationInfoMap.size()); | ||
135 | int nodeCount = getNodeCount(); | ||
136 | var modelSeedBuilder = ModelSeed.builder(nodeCount); | ||
137 | for (var entry : relationInfoMap.entrySet()) { | ||
138 | var relation = entry.getKey(); | ||
139 | var info = entry.getValue(); | ||
140 | var partialRelation = info.partialRelation(); | ||
141 | relationTrace.put(relation, partialRelation); | ||
142 | modelSeedBuilder.seed(partialRelation, info.toSeed(nodeCount)); | ||
143 | } | ||
144 | collectScopes(); | ||
145 | if (scopePropagator != null) { | ||
146 | if (storeBuilder.tryGetAdapter(PropagationBuilder.class).isEmpty()) { | ||
147 | throw new TracedException(problem, "Type scopes require a PropagationBuilder"); | ||
148 | } | ||
149 | storeBuilder.with(scopePropagator); | ||
150 | } | ||
151 | modelSeedBuilder.seed(MultiObjectTranslator.COUNT_SYMBOL, builder -> builder | ||
152 | .reducedValue(CardinalityIntervals.SET) | ||
153 | .putAll(countSeed)); | ||
154 | modelSeed = modelSeedBuilder.build(); | ||
155 | collectPredicates(); | ||
156 | return modelSeed; | 159 | return modelSeed; |
157 | } | 160 | } |
158 | 161 | ||
@@ -179,7 +182,7 @@ public class ModelInitializer { | |||
179 | } | 182 | } |
180 | 183 | ||
181 | private void collectNode(Node node) { | 184 | private void collectNode(Node node) { |
182 | nodeTrace.getIfAbsentPut(node, this::getNodeCount); | 185 | problemTrace.collectNode(node); |
183 | } | 186 | } |
184 | 187 | ||
185 | private void collectPartialSymbols() { | 188 | private void collectPartialSymbols() { |
@@ -221,7 +224,7 @@ public class ModelInitializer { | |||
221 | private void putRelationInfo(Relation relation, RelationInfo info) { | 224 | private void putRelationInfo(Relation relation, RelationInfo info) { |
222 | relationInfoMap.put(relation, info); | 225 | relationInfoMap.put(relation, info); |
223 | partialRelationInfoMap.put(info.partialRelation(), info); | 226 | partialRelationInfoMap.put(info.partialRelation(), info); |
224 | inverseTrace.put(info.partialRelation(), relation); | 227 | problemTrace.putRelation(relation, info.partialRelation()); |
225 | } | 228 | } |
226 | 229 | ||
227 | private RelationInfo collectPartialRelation(Relation relation, int arity, TruthValue value, | 230 | private RelationInfo collectPartialRelation(Relation relation, int arity, TruthValue value, |
@@ -230,7 +233,7 @@ public class ModelInitializer { | |||
230 | var name = getName(relation); | 233 | var name = getName(relation); |
231 | var info = new RelationInfo(name, arity, value, defaultValue); | 234 | var info = new RelationInfo(name, arity, value, defaultValue); |
232 | partialRelationInfoMap.put(info.partialRelation(), info); | 235 | partialRelationInfoMap.put(info.partialRelation(), info); |
233 | inverseTrace.put(info.partialRelation(), relation); | 236 | problemTrace.putRelation(relation, info.partialRelation()); |
234 | return info; | 237 | return info; |
235 | }); | 238 | }); |
236 | } | 239 | } |
@@ -410,7 +413,7 @@ public class ModelInitializer { | |||
410 | } | 413 | } |
411 | 414 | ||
412 | private int getNodeId(Node node) { | 415 | private int getNodeId(Node node) { |
413 | return nodeTrace.getOrThrow(node); | 416 | return problemTrace.getNodeId(node); |
414 | } | 417 | } |
415 | 418 | ||
416 | private Tuple getTuple(Assertion assertion) { | 419 | private Tuple getTuple(Assertion assertion) { |
@@ -442,17 +445,18 @@ public class ModelInitializer { | |||
442 | }; | 445 | }; |
443 | } | 446 | } |
444 | 447 | ||
445 | private void collectPredicates() { | 448 | private void collectPredicates(ModelStoreBuilder storeBuilder) { |
446 | for (var statement : problem.getStatements()) { | 449 | for (var statement : problem.getStatements()) { |
447 | if (statement instanceof PredicateDefinition predicateDefinition) { | 450 | if (statement instanceof PredicateDefinition predicateDefinition) { |
448 | collectPredicateDefinitionTraced(predicateDefinition); | 451 | collectPredicateDefinitionTraced(predicateDefinition, storeBuilder); |
449 | } | 452 | } |
450 | } | 453 | } |
451 | } | 454 | } |
452 | 455 | ||
453 | private void collectPredicateDefinitionTraced(PredicateDefinition predicateDefinition) { | 456 | private void collectPredicateDefinitionTraced(PredicateDefinition predicateDefinition, |
457 | ModelStoreBuilder storeBuilder) { | ||
454 | try { | 458 | try { |
455 | collectPredicateDefinition(predicateDefinition); | 459 | collectPredicateDefinition(predicateDefinition, storeBuilder); |
456 | } catch (InvalidClauseException e) { | 460 | } catch (InvalidClauseException e) { |
457 | int clauseIndex = e.getClauseIndex(); | 461 | int clauseIndex = e.getClauseIndex(); |
458 | var bodies = predicateDefinition.getBodies(); | 462 | var bodies = predicateDefinition.getBodies(); |
@@ -466,7 +470,7 @@ public class ModelInitializer { | |||
466 | } | 470 | } |
467 | } | 471 | } |
468 | 472 | ||
469 | private void collectPredicateDefinition(PredicateDefinition predicateDefinition) { | 473 | private void collectPredicateDefinition(PredicateDefinition predicateDefinition, ModelStoreBuilder storeBuilder) { |
470 | var partialRelation = getPartialRelation(predicateDefinition); | 474 | var partialRelation = getPartialRelation(predicateDefinition); |
471 | var query = toQuery(partialRelation.name(), predicateDefinition); | 475 | var query = toQuery(partialRelation.name(), predicateDefinition); |
472 | boolean mutable; | 476 | boolean mutable; |
@@ -477,7 +481,7 @@ public class ModelInitializer { | |||
477 | } else { | 481 | } else { |
478 | var seed = modelSeed.getSeed(partialRelation); | 482 | var seed = modelSeed.getSeed(partialRelation); |
479 | defaultValue = seed.reducedValue() == TruthValue.FALSE ? TruthValue.FALSE : TruthValue.UNKNOWN; | 483 | defaultValue = seed.reducedValue() == TruthValue.FALSE ? TruthValue.FALSE : TruthValue.UNKNOWN; |
480 | var cursor = seed.getCursor(defaultValue, getNodeCount()); | 484 | var cursor = seed.getCursor(defaultValue, problemTrace.getNodeTrace().size()); |
481 | // The symbol should be mutable if there is at least one non-default entry in the seed. | 485 | // The symbol should be mutable if there is at least one non-default entry in the seed. |
482 | mutable = cursor.move(); | 486 | mutable = cursor.move(); |
483 | } | 487 | } |
@@ -641,8 +645,8 @@ public class ModelInitializer { | |||
641 | if (newNode == null) { | 645 | if (newNode == null) { |
642 | throw new TracedException(typeScope, "Target of incremental type scope must be concrete class"); | 646 | throw new TracedException(typeScope, "Target of incremental type scope must be concrete class"); |
643 | } | 647 | } |
644 | int newNodeId = nodeTrace.get(newNode); | 648 | int newNodeId = getNodeId(newNode); |
645 | var type = relationTrace.get(classDeclaration); | 649 | var type = problemTrace.getPartialRelation(classDeclaration); |
646 | var typeInfo = metamodel.typeHierarchy().getAnalysisResult(type); | 650 | var typeInfo = metamodel.typeHierarchy().getAnalysisResult(type); |
647 | if (!typeInfo.getDirectSubtypes().isEmpty()) { | 651 | if (!typeInfo.getDirectSubtypes().isEmpty()) { |
648 | throw new TracedException(typeScope, "Target of incremental type scope cannot have any subclasses"); | 652 | throw new TracedException(typeScope, "Target of incremental type scope cannot have any subclasses"); |
@@ -653,10 +657,7 @@ public class ModelInitializer { | |||
653 | } | 657 | } |
654 | 658 | ||
655 | private void collectTypeScope(TypeScope typeScope) { | 659 | private void collectTypeScope(TypeScope typeScope) { |
656 | var type = relationTrace.get(typeScope.getTargetType()); | 660 | var type = problemTrace.getPartialRelation(typeScope.getTargetType()); |
657 | if (type == null) { | ||
658 | throw new TracedException(typeScope, "Unknown target type"); | ||
659 | } | ||
660 | var interval = getCardinalityInterval(typeScope.getMultiplicity()); | 661 | var interval = getCardinalityInterval(typeScope.getMultiplicity()); |
661 | if (scopePropagator == null) { | 662 | if (scopePropagator == null) { |
662 | scopePropagator = new ScopePropagator(); | 663 | scopePropagator = new ScopePropagator(); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java new file mode 100644 index 00000000..b8d0b804 --- /dev/null +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTrace.java | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.semantics; | ||
7 | |||
8 | import org.eclipse.collections.api.map.primitive.ObjectIntMap; | ||
9 | import org.eclipse.xtext.naming.QualifiedName; | ||
10 | import tools.refinery.language.model.problem.Node; | ||
11 | import tools.refinery.language.model.problem.Problem; | ||
12 | import tools.refinery.language.model.problem.Relation; | ||
13 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | ||
14 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
15 | import tools.refinery.store.reasoning.translator.TranslationException; | ||
16 | import tools.refinery.store.reasoning.translator.metamodel.Metamodel; | ||
17 | |||
18 | import java.util.Map; | ||
19 | |||
20 | public interface ProblemTrace { | ||
21 | Problem getProblem(); | ||
22 | |||
23 | Metamodel getMetamodel(); | ||
24 | |||
25 | ObjectIntMap<Node> getNodeTrace(); | ||
26 | |||
27 | int getNodeId(Node node); | ||
28 | |||
29 | int getNodeId(QualifiedName qualifiedName); | ||
30 | |||
31 | int getNodeId(String qualifiedName); | ||
32 | |||
33 | Map<Relation, PartialRelation> getRelationTrace(); | ||
34 | |||
35 | Map<AnyPartialSymbol, Relation> getInverseRelationTrace(); | ||
36 | |||
37 | Relation getRelation(AnyPartialSymbol partialSymbol); | ||
38 | |||
39 | RuntimeException wrapException(TranslationException translationException); | ||
40 | |||
41 | PartialRelation getPartialRelation(Relation relation); | ||
42 | |||
43 | PartialRelation getPartialRelation(QualifiedName qualifiedName); | ||
44 | |||
45 | PartialRelation getPartialRelation(String qualifiedName); | ||
46 | } | ||
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 new file mode 100644 index 00000000..cc634949 --- /dev/null +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.semantics; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import org.eclipse.collections.api.factory.primitive.ObjectIntMaps; | ||
10 | import org.eclipse.collections.api.map.primitive.MutableObjectIntMap; | ||
11 | import org.eclipse.collections.api.map.primitive.ObjectIntMap; | ||
12 | import org.eclipse.emf.ecore.util.EcoreUtil; | ||
13 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
14 | import org.eclipse.xtext.naming.QualifiedName; | ||
15 | import org.eclipse.xtext.scoping.IScope; | ||
16 | import org.eclipse.xtext.scoping.IScopeProvider; | ||
17 | import tools.refinery.language.model.problem.Node; | ||
18 | import tools.refinery.language.model.problem.Problem; | ||
19 | import tools.refinery.language.model.problem.ProblemPackage; | ||
20 | import tools.refinery.language.model.problem.Relation; | ||
21 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | ||
22 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
23 | import tools.refinery.store.reasoning.translator.TranslationException; | ||
24 | import tools.refinery.store.reasoning.translator.metamodel.Metamodel; | ||
25 | |||
26 | import java.util.Collections; | ||
27 | import java.util.HashMap; | ||
28 | import java.util.LinkedHashMap; | ||
29 | import java.util.Map; | ||
30 | |||
31 | public class ProblemTraceImpl implements ProblemTrace { | ||
32 | @Inject | ||
33 | private IQualifiedNameConverter qualifiedNameConverter; | ||
34 | |||
35 | @Inject | ||
36 | private SemanticsUtils semanticsUtils; | ||
37 | |||
38 | @Inject | ||
39 | private IScopeProvider scopeProvider; | ||
40 | |||
41 | private Problem problem; | ||
42 | private Metamodel metamodel; | ||
43 | private final MutableObjectIntMap<Node> mutableNodeTrace = ObjectIntMaps.mutable.empty(); | ||
44 | private final ObjectIntMap<Node> nodeTrace = mutableNodeTrace.asUnmodifiable(); | ||
45 | private final Map<Relation, PartialRelation> mutableRelationTrace = new LinkedHashMap<>(); | ||
46 | private final Map<Relation, PartialRelation> relationTrace = | ||
47 | Collections.unmodifiableMap(mutableRelationTrace); | ||
48 | private final Map<AnyPartialSymbol, Relation> mutableInverseTrace = new HashMap<>(); | ||
49 | private final Map<AnyPartialSymbol, Relation> inverseTrace = Collections.unmodifiableMap(mutableInverseTrace); | ||
50 | |||
51 | @Override | ||
52 | public Problem getProblem() { | ||
53 | return problem; | ||
54 | } | ||
55 | |||
56 | void setProblem(Problem problem) { | ||
57 | this.problem = problem; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public Metamodel getMetamodel() { | ||
62 | return metamodel; | ||
63 | } | ||
64 | |||
65 | void setMetamodel(Metamodel metamodel) { | ||
66 | this.metamodel = metamodel; | ||
67 | } | ||
68 | |||
69 | @Override | ||
70 | public ObjectIntMap<Node> getNodeTrace() { | ||
71 | return nodeTrace; | ||
72 | } | ||
73 | |||
74 | void collectNode(Node node) { | ||
75 | mutableNodeTrace.getIfAbsentPut(node, mutableNodeTrace.size()); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public int getNodeId(Node node) { | ||
80 | try { | ||
81 | return nodeTrace.getOrThrow(node); | ||
82 | } catch (IllegalStateException e) { | ||
83 | var qualifiedName = semanticsUtils.getName(node); | ||
84 | throw new TracedException(node, "No node ID for " + qualifiedName, e); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | @Override | ||
89 | public int getNodeId(QualifiedName qualifiedName) { | ||
90 | var nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); | ||
91 | return getNodeId(getElement(nodeScope, qualifiedName, Node.class)); | ||
92 | } | ||
93 | |||
94 | @Override | ||
95 | public int getNodeId(String qualifiedName) { | ||
96 | var convertedName = qualifiedNameConverter.toQualifiedName(qualifiedName); | ||
97 | return getNodeId(convertedName); | ||
98 | } | ||
99 | |||
100 | @Override | ||
101 | public Map<Relation, PartialRelation> getRelationTrace() { | ||
102 | return relationTrace; | ||
103 | } | ||
104 | |||
105 | void putRelation(Relation relation, PartialRelation partialRelation) { | ||
106 | var oldPartialRelation = mutableRelationTrace.put(relation, partialRelation); | ||
107 | if (oldPartialRelation != null) { | ||
108 | throw new TracedException(relation, "Relation already mapped to partial relation: " + oldPartialRelation); | ||
109 | } | ||
110 | var oldRelation = mutableInverseTrace.put(partialRelation, relation); | ||
111 | if (oldRelation != null) { | ||
112 | throw new TracedException(oldRelation, "Partial relation %s was already mapped to relation" | ||
113 | .formatted(partialRelation)); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public Map<AnyPartialSymbol, Relation> getInverseRelationTrace() { | ||
119 | return inverseTrace; | ||
120 | } | ||
121 | |||
122 | @Override | ||
123 | public Relation getRelation(AnyPartialSymbol partialSymbol) { | ||
124 | var relation = mutableInverseTrace.get(partialSymbol); | ||
125 | if (relation == null) { | ||
126 | throw new IllegalArgumentException("No relation for partial symbol: " + partialSymbol); | ||
127 | } | ||
128 | return relation; | ||
129 | } | ||
130 | |||
131 | @Override | ||
132 | public RuntimeException wrapException(TranslationException translationException) { | ||
133 | var partialSymbol = translationException.getPartialSymbol(); | ||
134 | if (partialSymbol == null) { | ||
135 | return translationException; | ||
136 | } | ||
137 | var relation = mutableInverseTrace.get(partialSymbol); | ||
138 | if (relation == null) { | ||
139 | return translationException; | ||
140 | } | ||
141 | return new TracedException(relation, translationException); | ||
142 | } | ||
143 | |||
144 | @Override | ||
145 | public PartialRelation getPartialRelation(Relation relation) { | ||
146 | var partialRelation = mutableRelationTrace.get(relation); | ||
147 | if (partialRelation == null) { | ||
148 | var qualifiedName = semanticsUtils.getName(relation); | ||
149 | throw new TracedException(relation, "No partial relation for " + qualifiedName); | ||
150 | } | ||
151 | return partialRelation; | ||
152 | } | ||
153 | |||
154 | @Override | ||
155 | public PartialRelation getPartialRelation(QualifiedName qualifiedName) { | ||
156 | var relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION); | ||
157 | return getPartialRelation(getElement(relationScope, qualifiedName, Relation.class)); | ||
158 | } | ||
159 | |||
160 | @Override | ||
161 | public PartialRelation getPartialRelation(String qualifiedName) { | ||
162 | var convertedName = qualifiedNameConverter.toQualifiedName(qualifiedName); | ||
163 | return getPartialRelation(convertedName); | ||
164 | } | ||
165 | |||
166 | private <T> T getElement(IScope scope, QualifiedName qualifiedName, Class<T> type) { | ||
167 | var iterator = scope.getElements(qualifiedName).iterator(); | ||
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 | } | ||
187 | } | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java index 47c89e9b..b195a8e7 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/SemanticsUtils.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model; | 6 | package tools.refinery.language.semantics; |
7 | 7 | ||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import com.google.inject.Singleton; | 9 | import com.google.inject.Singleton; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/TracedException.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/TracedException.java index 38fd8a67..8636bdab 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/TracedException.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/TracedException.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model; | 6 | package tools.refinery.language.semantics; |
7 | 7 | ||
8 | import org.eclipse.emf.ecore.EObject; | 8 | import org.eclipse.emf.ecore.EObject; |
9 | 9 | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java index 32112e61..c732f784 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTree.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | 8 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; |
9 | import tools.refinery.store.map.Cursor; | 9 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeCursor.java index a9fc644a..71b54cbd 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeCursor.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
9 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.store.representation.TruthValue; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java index 3c54e3c5..ebca2634 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeNode.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import org.eclipse.collections.api.LazyIntIterable; | 8 | import org.eclipse.collections.api.LazyIntIterable; |
9 | import tools.refinery.store.tuple.Tuple; | 9 | import tools.refinery.store.tuple.Tuple; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeValue.java index 915ae2bf..5053e7ac 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/DecisionTreeValue.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import tools.refinery.store.representation.TruthValue; | 8 | import tools.refinery.store.representation.TruthValue; |
9 | 9 | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java index e6f01d48..0e2f5d18 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/IntermediateNode.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import org.eclipse.collections.api.LazyIntIterable; | 8 | import org.eclipse.collections.api.LazyIntIterable; |
9 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | 9 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/MutableSeed.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/MutableSeed.java index 99019e2a..693b9e1f 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/MutableSeed.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/MutableSeed.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import tools.refinery.store.reasoning.seed.Seed; | 8 | import tools.refinery.store.reasoning.seed.Seed; |
9 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.store.representation.TruthValue; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/NullaryMutableSeed.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java index 80644b1f..7a72c656 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/NullaryMutableSeed.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/NullaryMutableSeed.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
9 | import tools.refinery.store.map.Cursors; | 9 | import tools.refinery.store.map.Cursors; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java index ce49aa62..d3dd757c 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/internal/TerminalNode.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import org.eclipse.collections.api.LazyIntIterable; | 8 | import org.eclipse.collections.api.LazyIntIterable; |
9 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | 9 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; |
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/CountPropagationTest.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/CountPropagationTest.java index 6beae93a..b679c1ef 100644 --- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/CountPropagationTest.java +++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/CountPropagationTest.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model; | 6 | package tools.refinery.language.semantics; |
7 | 7 | ||
8 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
9 | import tools.refinery.store.dse.propagation.PropagationAdapter; | 9 | import tools.refinery.store.dse.propagation.PropagationAdapter; |
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/ModelGenerationTest.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/ModelGenerationTest.java index c8a79c37..899e3cb3 100644 --- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/ModelGenerationTest.java +++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/ModelGenerationTest.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model; | 6 | package tools.refinery.language.semantics; |
7 | 7 | ||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import org.eclipse.xtext.testing.InjectWith; | 9 | import org.eclipse.xtext.testing.InjectWith; |
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/internal/DecisionTreeTests.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java index 5d039308..2320de2c 100644 --- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/internal/DecisionTreeTests.java +++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/internal/DecisionTreeTests.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.internal; |
7 | 7 | ||
8 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
9 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.store.representation.TruthValue; |
diff --git a/subprojects/language-web/build.gradle.kts b/subprojects/language-web/build.gradle.kts index 2370794d..c3a0b7e9 100644 --- a/subprojects/language-web/build.gradle.kts +++ b/subprojects/language-web/build.gradle.kts | |||
@@ -15,11 +15,9 @@ val webapp: Configuration by configurations.creating { | |||
15 | } | 15 | } |
16 | 16 | ||
17 | dependencies { | 17 | dependencies { |
18 | implementation(project(":refinery-generator")) | ||
18 | implementation(project(":refinery-language")) | 19 | implementation(project(":refinery-language")) |
19 | implementation(project(":refinery-language-ide")) | 20 | implementation(project(":refinery-language-ide")) |
20 | implementation(project(":refinery-language-semantics")) | ||
21 | implementation(project(":refinery-store-query-interpreter")) | ||
22 | implementation(project(":refinery-store-reasoning-scope")) | ||
23 | implementation(libs.gson) | 21 | implementation(libs.gson) |
24 | implementation(libs.jetty.server) | 22 | implementation(libs.jetty.server) |
25 | implementation(libs.jetty.servlet) | 23 | implementation(libs.jetty.servlet) |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java index 21be4e08..0abe116e 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationSuccessResult.java | |||
@@ -6,8 +6,8 @@ | |||
6 | package tools.refinery.language.web.generator; | 6 | package tools.refinery.language.web.generator; |
7 | 7 | ||
8 | import com.google.gson.JsonObject; | 8 | import com.google.gson.JsonObject; |
9 | import tools.refinery.language.semantics.metadata.NodeMetadata; | 9 | import tools.refinery.language.web.semantics.metadata.NodeMetadata; |
10 | import tools.refinery.language.semantics.metadata.RelationMetadata; | 10 | import tools.refinery.language.web.semantics.metadata.RelationMetadata; |
11 | 11 | ||
12 | import java.util.List; | 12 | import java.util.List; |
13 | import java.util.UUID; | 13 | import java.util.UUID; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java index 1fce10a4..a3b6ca82 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/generator/ModelGenerationWorker.java | |||
@@ -6,36 +6,20 @@ | |||
6 | package tools.refinery.language.web.generator; | 6 | package tools.refinery.language.web.generator; |
7 | 7 | ||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import com.google.inject.Provider; | ||
10 | import org.eclipse.emf.common.util.URI; | ||
11 | import org.eclipse.xtext.diagnostics.Severity; | ||
12 | import org.eclipse.xtext.resource.IResourceFactory; | ||
13 | import org.eclipse.xtext.resource.XtextResourceSet; | ||
14 | import org.eclipse.xtext.service.OperationCanceledManager; | 9 | import org.eclipse.xtext.service.OperationCanceledManager; |
15 | import org.eclipse.xtext.util.LazyStringInputStream; | ||
16 | import org.eclipse.xtext.validation.CheckMode; | ||
17 | import org.eclipse.xtext.validation.IResourceValidator; | ||
18 | import org.slf4j.Logger; | 10 | import org.slf4j.Logger; |
19 | import org.slf4j.LoggerFactory; | 11 | import org.slf4j.LoggerFactory; |
20 | import tools.refinery.language.model.problem.Problem; | 12 | import tools.refinery.generator.ModelGenerator; |
21 | import tools.refinery.language.semantics.metadata.MetadataCreator; | 13 | import tools.refinery.generator.ModelGeneratorFactory; |
22 | import tools.refinery.language.semantics.model.ModelInitializer; | 14 | import tools.refinery.language.web.semantics.metadata.MetadataCreator; |
15 | import tools.refinery.generator.ProblemLoader; | ||
16 | import tools.refinery.generator.ValidationErrorsException; | ||
23 | import tools.refinery.language.web.semantics.PartialInterpretation2Json; | 17 | import tools.refinery.language.web.semantics.PartialInterpretation2Json; |
24 | import tools.refinery.language.web.xtext.server.ThreadPoolExecutorServiceProvider; | 18 | import tools.refinery.language.web.xtext.server.ThreadPoolExecutorServiceProvider; |
25 | import tools.refinery.language.web.xtext.server.push.PushWebDocument; | 19 | import tools.refinery.language.web.xtext.server.push.PushWebDocument; |
26 | import tools.refinery.store.dse.propagation.PropagationAdapter; | ||
27 | import tools.refinery.store.dse.strategy.BestFirstStoreManager; | ||
28 | import tools.refinery.store.dse.transition.DesignSpaceExplorationAdapter; | ||
29 | import tools.refinery.store.model.ModelStore; | ||
30 | import tools.refinery.store.query.interpreter.QueryInterpreterAdapter; | ||
31 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
32 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; | ||
33 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
34 | import tools.refinery.store.statecoding.StateCoderAdapter; | ||
35 | import tools.refinery.store.util.CancellationToken; | 20 | import tools.refinery.store.util.CancellationToken; |
36 | 21 | ||
37 | import java.io.IOException; | 22 | import java.io.IOException; |
38 | import java.util.Map; | ||
39 | import java.util.UUID; | 23 | import java.util.UUID; |
40 | import java.util.concurrent.*; | 24 | import java.util.concurrent.*; |
41 | 25 | ||
@@ -56,16 +40,10 @@ public class ModelGenerationWorker implements Runnable { | |||
56 | private OperationCanceledManager operationCanceledManager; | 40 | private OperationCanceledManager operationCanceledManager; |
57 | 41 | ||
58 | @Inject | 42 | @Inject |
59 | private Provider<XtextResourceSet> resourceSetProvider; | 43 | private ProblemLoader problemLoader; |
60 | 44 | ||
61 | @Inject | 45 | @Inject |
62 | private IResourceFactory resourceFactory; | 46 | private ModelGeneratorFactory generatorFactory; |
63 | |||
64 | @Inject | ||
65 | private IResourceValidator resourceValidator; | ||
66 | |||
67 | @Inject | ||
68 | private ModelInitializer initializer; | ||
69 | 47 | ||
70 | @Inject | 48 | @Inject |
71 | private MetadataCreator metadataCreator; | 49 | private MetadataCreator metadataCreator; |
@@ -157,57 +135,30 @@ public class ModelGenerationWorker implements Runnable { | |||
157 | 135 | ||
158 | public ModelGenerationResult doRun() throws IOException { | 136 | public ModelGenerationResult doRun() throws IOException { |
159 | cancellationToken.checkCancelled(); | 137 | cancellationToken.checkCancelled(); |
160 | var resourceSet = resourceSetProvider.get(); | 138 | var problem = problemLoader.cancellationToken(cancellationToken).loadString(text); |
161 | var uri = URI.createURI("__synthetic_" + uuid + ".problem"); | 139 | ModelGenerator generator; |
162 | var resource = resourceFactory.createResource(uri); | 140 | try { |
163 | resourceSet.getResources().add(resource); | 141 | generator = generatorFactory.cancellationToken(cancellationToken).createGenerator(problem); |
164 | var inputStream = new LazyStringInputStream(text); | 142 | } catch (ValidationErrorsException e) { |
165 | resource.load(inputStream, Map.of()); | 143 | var errors = e.getErrors(); |
166 | cancellationToken.checkCancelled(); | 144 | if (errors != null && !errors.isEmpty()) { |
167 | var issues = resourceValidator.validate(resource, CheckMode.ALL, () -> cancelled || Thread.interrupted()); | 145 | return new ModelGenerationErrorResult(uuid, "Validation error: " + errors.get(0).getMessage()); |
168 | cancellationToken.checkCancelled(); | ||
169 | for (var issue : issues) { | ||
170 | if (issue.getSeverity() == Severity.ERROR) { | ||
171 | return new ModelGenerationErrorResult(uuid, "Validation error: " + issue.getMessage()); | ||
172 | } | 146 | } |
147 | throw e; | ||
173 | } | 148 | } |
174 | if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof Problem problem)) { | ||
175 | return new ModelGenerationErrorResult(uuid, "Model generation problem not found"); | ||
176 | } | ||
177 | cancellationToken.checkCancelled(); | ||
178 | var storeBuilder = ModelStore.builder() | ||
179 | .cancellationToken(cancellationToken) | ||
180 | .with(QueryInterpreterAdapter.builder()) | ||
181 | .with(PropagationAdapter.builder()) | ||
182 | .with(StateCoderAdapter.builder()) | ||
183 | .with(DesignSpaceExplorationAdapter.builder()) | ||
184 | .with(ReasoningAdapter.builder() | ||
185 | .requiredInterpretations(Concreteness.CANDIDATE)); | ||
186 | var modelSeed = initializer.createModel(problem, storeBuilder); | ||
187 | var store = storeBuilder.build(); | ||
188 | cancellationToken.checkCancelled(); | ||
189 | var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed); | ||
190 | var initialVersion = model.commit(); | ||
191 | cancellationToken.checkCancelled(); | ||
192 | notifyResult(new ModelGenerationStatusResult(uuid, "Generating model")); | 149 | notifyResult(new ModelGenerationStatusResult(uuid, "Generating model")); |
193 | var bestFirst = new BestFirstStoreManager(store, 1); | 150 | generator.setRandomSeed(randomSeed); |
194 | bestFirst.startExploration(initialVersion, randomSeed); | 151 | if (!generator.tryGenerate()) { |
195 | cancellationToken.checkCancelled(); | ||
196 | var solutionStore = bestFirst.getSolutionStore(); | ||
197 | if (solutionStore.getSolutions().isEmpty()) { | ||
198 | return new ModelGenerationErrorResult(uuid, "Problem is unsatisfiable"); | 152 | return new ModelGenerationErrorResult(uuid, "Problem is unsatisfiable"); |
199 | } | 153 | } |
200 | notifyResult(new ModelGenerationStatusResult(uuid, "Saving generated model")); | 154 | notifyResult(new ModelGenerationStatusResult(uuid, "Saving generated model")); |
201 | model.restore(solutionStore.getSolutions().get(0).version()); | ||
202 | cancellationToken.checkCancelled(); | 155 | cancellationToken.checkCancelled(); |
203 | metadataCreator.setInitializer(initializer); | 156 | metadataCreator.setProblemTrace(generator.getProblemTrace()); |
204 | var nodesMetadata = metadataCreator.getNodesMetadata(model.getAdapter(ReasoningAdapter.class).getNodeCount(), | 157 | var nodesMetadata = metadataCreator.getNodesMetadata(generator.getModel(), false); |
205 | false); | ||
206 | cancellationToken.checkCancelled(); | 158 | cancellationToken.checkCancelled(); |
207 | var relationsMetadata = metadataCreator.getRelationsMetadata(); | 159 | var relationsMetadata = metadataCreator.getRelationsMetadata(); |
208 | cancellationToken.checkCancelled(); | 160 | cancellationToken.checkCancelled(); |
209 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(initializer, model, | 161 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(generator, cancellationToken); |
210 | Concreteness.CANDIDATE, cancellationToken); | ||
211 | return new ModelGenerationSuccessResult(uuid, nodesMetadata, relationsMetadata, partialInterpretation); | 162 | return new ModelGenerationSuccessResult(uuid, nodesMetadata, relationsMetadata, partialInterpretation); |
212 | } | 163 | } |
213 | 164 | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java index 5d5da8fe..efe04592 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java | |||
@@ -9,12 +9,10 @@ import com.google.gson.JsonArray; | |||
9 | import com.google.gson.JsonObject; | 9 | import com.google.gson.JsonObject; |
10 | import com.google.inject.Inject; | 10 | import com.google.inject.Inject; |
11 | import com.google.inject.Singleton; | 11 | import com.google.inject.Singleton; |
12 | import tools.refinery.language.semantics.model.ModelInitializer; | 12 | import tools.refinery.generator.ModelFacade; |
13 | import tools.refinery.language.semantics.model.SemanticsUtils; | 13 | import tools.refinery.language.semantics.SemanticsUtils; |
14 | import tools.refinery.store.map.Cursor; | 14 | import tools.refinery.store.map.Cursor; |
15 | import tools.refinery.store.model.Model; | 15 | import tools.refinery.store.model.Model; |
16 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
17 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
18 | import tools.refinery.store.reasoning.representation.PartialRelation; | 16 | import tools.refinery.store.reasoning.representation.PartialRelation; |
19 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; | 17 | import tools.refinery.store.reasoning.translator.multiobject.MultiObjectTranslator; |
20 | import tools.refinery.store.tuple.Tuple; | 18 | import tools.refinery.store.tuple.Tuple; |
@@ -27,14 +25,13 @@ public class PartialInterpretation2Json { | |||
27 | @Inject | 25 | @Inject |
28 | private SemanticsUtils semanticsUtils; | 26 | private SemanticsUtils semanticsUtils; |
29 | 27 | ||
30 | public JsonObject getPartialInterpretation(ModelInitializer initializer, Model model, Concreteness concreteness, | 28 | public JsonObject getPartialInterpretation(ModelFacade facade, CancellationToken cancellationToken) { |
31 | CancellationToken cancellationToken) { | 29 | var model = facade.getModel(); |
32 | var adapter = model.getAdapter(ReasoningAdapter.class); | ||
33 | var json = new JsonObject(); | 30 | var json = new JsonObject(); |
34 | for (var entry : initializer.getRelationTrace().entrySet()) { | 31 | for (var entry : facade.getProblemTrace().getRelationTrace().entrySet()) { |
35 | var relation = entry.getKey(); | 32 | var relation = entry.getKey(); |
36 | var partialSymbol = entry.getValue(); | 33 | var partialSymbol = entry.getValue(); |
37 | var tuples = getTuplesJson(adapter, concreteness, partialSymbol); | 34 | var tuples = getTuplesJson(facade, partialSymbol); |
38 | var name = semanticsUtils.getName(relation).orElse(partialSymbol.name()); | 35 | var name = semanticsUtils.getName(relation).orElse(partialSymbol.name()); |
39 | json.add(name, tuples); | 36 | json.add(name, tuples); |
40 | cancellationToken.checkCancelled(); | 37 | cancellationToken.checkCancelled(); |
@@ -43,9 +40,8 @@ public class PartialInterpretation2Json { | |||
43 | return json; | 40 | return json; |
44 | } | 41 | } |
45 | 42 | ||
46 | private static JsonArray getTuplesJson(ReasoningAdapter adapter, Concreteness concreteness, | 43 | private static JsonArray getTuplesJson(ModelFacade facade, PartialRelation partialSymbol) { |
47 | PartialRelation partialSymbol) { | 44 | var interpretation = facade.getPartialInterpretation(partialSymbol); |
48 | var interpretation = adapter.getPartialInterpretation(concreteness, partialSymbol); | ||
49 | var cursor = interpretation.getAll(); | 45 | var cursor = interpretation.getAll(); |
50 | return getTuplesJson(cursor); | 46 | return getTuplesJson(cursor); |
51 | } | 47 | } |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java index 350b0b2b..f26fa2b2 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsSuccessResult.java | |||
@@ -6,8 +6,8 @@ | |||
6 | package tools.refinery.language.web.semantics; | 6 | package tools.refinery.language.web.semantics; |
7 | 7 | ||
8 | import com.google.gson.JsonObject; | 8 | import com.google.gson.JsonObject; |
9 | import tools.refinery.language.semantics.metadata.NodeMetadata; | 9 | import tools.refinery.language.web.semantics.metadata.NodeMetadata; |
10 | import tools.refinery.language.semantics.metadata.RelationMetadata; | 10 | import tools.refinery.language.web.semantics.metadata.RelationMetadata; |
11 | 11 | ||
12 | import java.util.List; | 12 | import java.util.List; |
13 | 13 | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java index fb89bea6..44974869 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java | |||
@@ -15,16 +15,11 @@ import org.eclipse.xtext.validation.FeatureBasedDiagnostic; | |||
15 | import org.eclipse.xtext.validation.IDiagnosticConverter; | 15 | import org.eclipse.xtext.validation.IDiagnosticConverter; |
16 | import org.eclipse.xtext.validation.Issue; | 16 | import org.eclipse.xtext.validation.Issue; |
17 | import org.eclipse.xtext.web.server.validation.ValidationResult; | 17 | import org.eclipse.xtext.web.server.validation.ValidationResult; |
18 | import tools.refinery.generator.ModelSemantics; | ||
19 | import tools.refinery.generator.ModelSemanticsFactory; | ||
18 | import tools.refinery.language.model.problem.Problem; | 20 | import tools.refinery.language.model.problem.Problem; |
19 | import tools.refinery.language.semantics.metadata.MetadataCreator; | 21 | import tools.refinery.language.web.semantics.metadata.MetadataCreator; |
20 | import tools.refinery.language.semantics.model.ModelInitializer; | 22 | import tools.refinery.language.semantics.TracedException; |
21 | import tools.refinery.language.semantics.model.TracedException; | ||
22 | import tools.refinery.store.dse.propagation.PropagationAdapter; | ||
23 | import tools.refinery.store.model.ModelStore; | ||
24 | import tools.refinery.store.query.interpreter.QueryInterpreterAdapter; | ||
25 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
26 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; | ||
27 | import tools.refinery.store.reasoning.literal.Concreteness; | ||
28 | import tools.refinery.store.reasoning.translator.TranslationException; | 23 | import tools.refinery.store.reasoning.translator.TranslationException; |
29 | import tools.refinery.store.util.CancellationToken; | 24 | import tools.refinery.store.util.CancellationToken; |
30 | 25 | ||
@@ -35,20 +30,20 @@ class SemanticsWorker implements Callable<SemanticsResult> { | |||
35 | private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError"; | 30 | private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError"; |
36 | 31 | ||
37 | @Inject | 32 | @Inject |
38 | private PartialInterpretation2Json partialInterpretation2Json; | ||
39 | |||
40 | @Inject | ||
41 | private OperationCanceledManager operationCanceledManager; | 33 | private OperationCanceledManager operationCanceledManager; |
42 | 34 | ||
43 | @Inject | 35 | @Inject |
44 | private IDiagnosticConverter diagnosticConverter; | 36 | private IDiagnosticConverter diagnosticConverter; |
45 | 37 | ||
46 | @Inject | 38 | @Inject |
47 | private ModelInitializer initializer; | 39 | private ModelSemanticsFactory semanticsFactory; |
48 | 40 | ||
49 | @Inject | 41 | @Inject |
50 | private MetadataCreator metadataCreator; | 42 | private MetadataCreator metadataCreator; |
51 | 43 | ||
44 | @Inject | ||
45 | private PartialInterpretation2Json partialInterpretation2Json; | ||
46 | |||
52 | private Problem problem; | 47 | private Problem problem; |
53 | 48 | ||
54 | private CancellationToken cancellationToken; | 49 | private CancellationToken cancellationToken; |
@@ -64,36 +59,26 @@ class SemanticsWorker implements Callable<SemanticsResult> { | |||
64 | 59 | ||
65 | @Override | 60 | @Override |
66 | public SemanticsResult call() { | 61 | public SemanticsResult call() { |
67 | var builder = ModelStore.builder() | ||
68 | .cancellationToken(cancellationToken) | ||
69 | .with(QueryInterpreterAdapter.builder()) | ||
70 | .with(PropagationAdapter.builder()) | ||
71 | .with(ReasoningAdapter.builder() | ||
72 | .requiredInterpretations(Concreteness.PARTIAL)); | ||
73 | cancellationToken.checkCancelled(); | 62 | cancellationToken.checkCancelled(); |
63 | ModelSemantics semantics; | ||
74 | try { | 64 | try { |
75 | var modelSeed = initializer.createModel(problem, builder); | 65 | semantics = semanticsFactory.cancellationToken(cancellationToken).createSemantics(problem); |
76 | cancellationToken.checkCancelled(); | ||
77 | metadataCreator.setInitializer(initializer); | ||
78 | cancellationToken.checkCancelled(); | ||
79 | var nodesMetadata = metadataCreator.getNodesMetadata(); | ||
80 | cancellationToken.checkCancelled(); | ||
81 | var relationsMetadata = metadataCreator.getRelationsMetadata(); | ||
82 | cancellationToken.checkCancelled(); | ||
83 | var store = builder.build(); | ||
84 | cancellationToken.checkCancelled(); | ||
85 | var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed); | ||
86 | cancellationToken.checkCancelled(); | ||
87 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(initializer, model, | ||
88 | Concreteness.PARTIAL, cancellationToken); | ||
89 | |||
90 | return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation); | ||
91 | } catch (TracedException e) { | ||
92 | return getTracedErrorResult(e.getSourceElement(), e.getMessage()); | ||
93 | } catch (TranslationException e) { | 66 | } catch (TranslationException e) { |
94 | var sourceElement = initializer.getInverseTrace(e.getPartialSymbol()); | 67 | return new SemanticsInternalErrorResult(e.getMessage()); |
95 | return getTracedErrorResult(sourceElement, e.getMessage()); | 68 | } catch (TracedException e) { |
69 | var cause = e.getCause(); | ||
70 | // Suppress the type of the cause exception. | ||
71 | var message = cause == null ? e.getMessage() : cause.getMessage(); | ||
72 | return getTracedErrorResult(e.getSourceElement(), message); | ||
96 | } | 73 | } |
74 | cancellationToken.checkCancelled(); | ||
75 | metadataCreator.setProblemTrace(semantics.getProblemTrace()); | ||
76 | var nodesMetadata = metadataCreator.getNodesMetadata(semantics.getModel(), true); | ||
77 | cancellationToken.checkCancelled(); | ||
78 | var relationsMetadata = metadataCreator.getRelationsMetadata(); | ||
79 | cancellationToken.checkCancelled(); | ||
80 | var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(semantics, cancellationToken); | ||
81 | return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation); | ||
97 | } | 82 | } |
98 | 83 | ||
99 | private SemanticsResult getTracedErrorResult(EObject sourceElement, String message) { | 84 | private SemanticsResult getTracedErrorResult(EObject sourceElement, String message) { |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/BuiltInDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java index 6f706069..27eb7ad7 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/BuiltInDetail.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/BuiltInDetail.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public record BuiltInDetail() implements RelationDetail { | 8 | public record BuiltInDetail() implements RelationDetail { |
9 | public static final BuiltInDetail INSTANCE = new BuiltInDetail(); | 9 | public static final BuiltInDetail INSTANCE = new BuiltInDetail(); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ClassDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java index 1d3190f5..42495950 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ClassDetail.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ClassDetail.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public record ClassDetail(boolean abstractClass) implements RelationDetail { | 8 | public record ClassDetail(boolean abstractClass) implements RelationDetail { |
9 | public static final ClassDetail CONCRETE_CLASS = new ClassDetail(false); | 9 | public static final ClassDetail CONCRETE_CLASS = new ClassDetail(false); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/Metadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java index d2dcb43a..5e1fac05 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/Metadata.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/Metadata.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public sealed interface Metadata permits NodeMetadata, RelationMetadata { | 8 | public sealed interface Metadata permits NodeMetadata, RelationMetadata { |
9 | String name(); | 9 | String name(); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/MetadataCreator.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java index 3694f5f4..3fbc5d2d 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/MetadataCreator.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import org.eclipse.emf.ecore.EObject; | 9 | import org.eclipse.emf.ecore.EObject; |
@@ -13,12 +13,17 @@ import org.eclipse.xtext.naming.QualifiedName; | |||
13 | import org.eclipse.xtext.scoping.IScope; | 13 | import org.eclipse.xtext.scoping.IScope; |
14 | import org.eclipse.xtext.scoping.IScopeProvider; | 14 | import org.eclipse.xtext.scoping.IScopeProvider; |
15 | import tools.refinery.language.model.problem.*; | 15 | import tools.refinery.language.model.problem.*; |
16 | import tools.refinery.language.semantics.model.ModelInitializer; | 16 | import tools.refinery.language.semantics.ProblemTrace; |
17 | import tools.refinery.language.semantics.model.TracedException; | 17 | import tools.refinery.language.semantics.TracedException; |
18 | import tools.refinery.language.utils.ProblemUtil; | 18 | import tools.refinery.language.utils.ProblemUtil; |
19 | import tools.refinery.store.model.Model; | ||
20 | import tools.refinery.store.reasoning.ReasoningAdapter; | ||
19 | import tools.refinery.store.reasoning.representation.PartialRelation; | 21 | import tools.refinery.store.reasoning.representation.PartialRelation; |
20 | 22 | ||
21 | import java.util.*; | 23 | import java.util.ArrayList; |
24 | import java.util.Collections; | ||
25 | import java.util.Comparator; | ||
26 | import java.util.List; | ||
22 | 27 | ||
23 | public class MetadataCreator { | 28 | public class MetadataCreator { |
24 | @Inject | 29 | @Inject |
@@ -30,18 +35,18 @@ public class MetadataCreator { | |||
30 | @Inject | 35 | @Inject |
31 | private IQualifiedNameConverter qualifiedNameConverter; | 36 | private IQualifiedNameConverter qualifiedNameConverter; |
32 | 37 | ||
33 | private ModelInitializer initializer; | 38 | private ProblemTrace problemTrace; |
34 | 39 | ||
35 | private IScope nodeScope; | 40 | private IScope nodeScope; |
36 | 41 | ||
37 | private IScope relationScope; | 42 | private IScope relationScope; |
38 | 43 | ||
39 | public void setInitializer(ModelInitializer initializer) { | 44 | public void setProblemTrace(ProblemTrace problemTrace) { |
40 | if (initializer == null) { | 45 | if (this.problemTrace != null) { |
41 | throw new IllegalArgumentException("Initializer was already set"); | 46 | throw new IllegalArgumentException("Problem trace was already set"); |
42 | } | 47 | } |
43 | this.initializer = initializer; | 48 | this.problemTrace = problemTrace; |
44 | var problem = initializer.getProblem(); | 49 | var problem = problemTrace.getProblem(); |
45 | nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); | 50 | nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE); |
46 | relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION); | 51 | relationScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__RELATION); |
47 | } | 52 | } |
@@ -50,13 +55,11 @@ public class MetadataCreator { | |||
50 | return "::" + nodeId; | 55 | return "::" + nodeId; |
51 | } | 56 | } |
52 | 57 | ||
53 | public List<NodeMetadata> getNodesMetadata() { | 58 | public List<NodeMetadata> getNodesMetadata(Model model, boolean preserveNewNodes) { |
54 | return getNodesMetadata(initializer.getNodeCount(), true); | 59 | int nodeCount = model.getAdapter(ReasoningAdapter.class).getNodeCount(); |
55 | } | 60 | var nodeTrace = problemTrace.getNodeTrace(); |
56 | 61 | var nodes = new NodeMetadata[Math.max(nodeTrace.size(), nodeCount)]; | |
57 | public List<NodeMetadata> getNodesMetadata(int nodeCount, boolean preserveNewNodes) { | 62 | for (var entry : nodeTrace.keyValuesView()) { |
58 | var nodes = new NodeMetadata[Math.max(initializer.getNodeCount(), nodeCount)]; | ||
59 | for (var entry : initializer.getNodeTrace().keyValuesView()) { | ||
60 | var node = entry.getOne(); | 63 | var node = entry.getOne(); |
61 | var id = entry.getTwo(); | 64 | var id = entry.getTwo(); |
62 | nodes[id] = getNodeMetadata(id, node, preserveNewNodes); | 65 | nodes[id] = getNodeMetadata(id, node, preserveNewNodes); |
@@ -95,7 +98,7 @@ public class MetadataCreator { | |||
95 | } | 98 | } |
96 | 99 | ||
97 | public List<RelationMetadata> getRelationsMetadata() { | 100 | public List<RelationMetadata> getRelationsMetadata() { |
98 | var relationTrace = initializer.getRelationTrace(); | 101 | var relationTrace = problemTrace.getRelationTrace(); |
99 | var relations = new ArrayList<RelationMetadata>(relationTrace.size()); | 102 | var relations = new ArrayList<RelationMetadata>(relationTrace.size()); |
100 | for (var entry : relationTrace.entrySet()) { | 103 | for (var entry : relationTrace.entrySet()) { |
101 | var relation = entry.getKey(); | 104 | var relation = entry.getKey(); |
@@ -142,7 +145,7 @@ public class MetadataCreator { | |||
142 | } | 145 | } |
143 | 146 | ||
144 | private RelationDetail getReferenceDetail(PartialRelation partialRelation) { | 147 | private RelationDetail getReferenceDetail(PartialRelation partialRelation) { |
145 | var metamodel = initializer.getMetamodel(); | 148 | var metamodel = problemTrace.getMetamodel(); |
146 | var opposite = metamodel.oppositeReferences().get(partialRelation); | 149 | var opposite = metamodel.oppositeReferences().get(partialRelation); |
147 | if (opposite == null) { | 150 | if (opposite == null) { |
148 | boolean isContainment = metamodel.containmentHierarchy().containsKey(partialRelation); | 151 | boolean isContainment = metamodel.containmentHierarchy().containsKey(partialRelation); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeKind.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java index 01f0cd09..fa863bc2 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeKind.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeKind.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public enum NodeKind { | 8 | public enum NodeKind { |
9 | IMPLICIT, | 9 | IMPLICIT, |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeMetadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java index 812952c0..5da28acf 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/NodeMetadata.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/NodeMetadata.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public record NodeMetadata(String name, String simpleName, NodeKind kind) implements Metadata { | 8 | public record NodeMetadata(String name, String simpleName, NodeKind kind) implements Metadata { |
9 | } | 9 | } |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/OppositeReferenceDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java index 26d7461c..98e7fec8 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/OppositeReferenceDetail.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/OppositeReferenceDetail.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public record OppositeReferenceDetail(boolean container, String opposite) implements RelationDetail { | 8 | public record OppositeReferenceDetail(boolean container, String opposite) implements RelationDetail { |
9 | } | 9 | } |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/PredicateDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java index ca397eca..d4ac4b65 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/PredicateDetail.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/PredicateDetail.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public record PredicateDetail(boolean error) implements RelationDetail { | 8 | public record PredicateDetail(boolean error) implements RelationDetail { |
9 | public static final PredicateDetail PREDICATE = new PredicateDetail(false); | 9 | public static final PredicateDetail PREDICATE = new PredicateDetail(false); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ReferenceDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java index 36771566..42799417 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/ReferenceDetail.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/ReferenceDetail.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public record ReferenceDetail(boolean containment) implements RelationDetail { | 8 | public record ReferenceDetail(boolean containment) implements RelationDetail { |
9 | public static final ReferenceDetail CROSS_REFERENCE = new ReferenceDetail(false); | 9 | public static final ReferenceDetail CROSS_REFERENCE = new ReferenceDetail(false); |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationDetail.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java index 105179fd..bbe563cd 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationDetail.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationDetail.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public sealed interface RelationDetail permits ClassDetail, ReferenceDetail, PredicateDetail, OppositeReferenceDetail, | 8 | public sealed interface RelationDetail permits ClassDetail, ReferenceDetail, PredicateDetail, OppositeReferenceDetail, |
9 | BuiltInDetail { | 9 | BuiltInDetail { |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationMetadata.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java index 5abcc253..e5d3a091 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/metadata/RelationMetadata.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/RelationMetadata.java | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.semantics.metadata; | 6 | package tools.refinery.language.web.semantics.metadata; |
7 | 7 | ||
8 | public record RelationMetadata(String name, String simpleName, int arity, RelationDetail detail) implements Metadata { | 8 | public record RelationMetadata(String name, String simpleName, int arity, RelationDetail detail) implements Metadata { |
9 | } | 9 | } |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java index 1fde1be5..818bd80e 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java | |||
@@ -17,7 +17,7 @@ import org.eclipse.xtext.resource.IResourceServiceProvider; | |||
17 | import org.eclipse.xtext.web.server.ISession; | 17 | import org.eclipse.xtext.web.server.ISession; |
18 | import org.slf4j.Logger; | 18 | import org.slf4j.Logger; |
19 | import org.slf4j.LoggerFactory; | 19 | import org.slf4j.LoggerFactory; |
20 | import tools.refinery.language.semantics.metadata.*; | 20 | import tools.refinery.language.web.semantics.metadata.*; |
21 | import tools.refinery.language.web.xtext.server.ResponseHandler; | 21 | import tools.refinery.language.web.xtext.server.ResponseHandler; |
22 | import tools.refinery.language.web.xtext.server.ResponseHandlerException; | 22 | import tools.refinery.language.web.xtext.server.ResponseHandlerException; |
23 | import tools.refinery.language.web.xtext.server.TransactionExecutor; | 23 | import tools.refinery.language.web.xtext.server.TransactionExecutor; |