aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java130
1 files changed, 130 insertions, 0 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java b/subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java
new file mode 100644
index 00000000..f0baf35f
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/resource/state/DerivedVariableComputer.java
@@ -0,0 +1,130 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.resource.state;
7
8import com.google.inject.Inject;
9import com.google.inject.Singleton;
10import com.google.inject.name.Named;
11import org.eclipse.xtext.linking.impl.LinkingHelper;
12import org.eclipse.xtext.naming.IQualifiedNameConverter;
13import org.eclipse.xtext.scoping.IScopeProvider;
14import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
15import tools.refinery.language.model.problem.*;
16
17import java.util.*;
18
19@Singleton
20public class DerivedVariableComputer {
21 @Inject
22 private LinkingHelper linkingHelper;
23
24 @Inject
25 private IQualifiedNameConverter qualifiedNameConverter;
26
27 @Inject
28 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
29 private IScopeProvider scopeProvider;
30
31 public void installDerivedVariables(Problem problem, Set<String> nodeNames) {
32 for (Statement statement : problem.getStatements()) {
33 if (statement instanceof ParametricDefinition definition) {
34 installDerivedParametricDefinitionState(definition, nodeNames);
35 }
36 }
37 }
38
39 protected void installDerivedParametricDefinitionState(ParametricDefinition definition, Set<String> nodeNames) {
40 Set<String> knownVariables = new HashSet<>(nodeNames);
41 for (Parameter parameter : definition.getParameters()) {
42 String name = parameter.getName();
43 if (name != null) {
44 knownVariables.add(name);
45 }
46 }
47 if (definition instanceof PredicateDefinition predicateDefinition) {
48 installDerivedPredicateDefinitionState(predicateDefinition, knownVariables);
49 } else if (definition instanceof FunctionDefinition functionDefinition) {
50 installDerivedFunctionDefinitionState(functionDefinition, knownVariables);
51 } else if (definition instanceof RuleDefinition ruleDefinition) {
52 installDerivedRuleDefinitionState(ruleDefinition, knownVariables);
53 } else {
54 throw new IllegalArgumentException("Unknown ParametricDefinition: " + definition);
55 }
56 }
57
58 protected void installDerivedPredicateDefinitionState(PredicateDefinition definition, Set<String> knownVariables) {
59 for (Conjunction body : definition.getBodies()) {
60 createVariablesForScope(new ImplicitVariableScope(body, knownVariables));
61 }
62 }
63
64 protected void installDerivedFunctionDefinitionState(FunctionDefinition definition, Set<String> knownVariables) {
65 for (Case body : definition.getCases()) {
66 if (body instanceof Conjunction conjunction) {
67 createVariablesForScope(new ImplicitVariableScope(conjunction, knownVariables));
68 } else if (body instanceof Match match) {
69 var condition = match.getCondition();
70 if (condition != null) {
71 createVariablesForScope(new ImplicitVariableScope(match, match.getCondition(), knownVariables));
72 }
73 } else {
74 throw new IllegalArgumentException("Unknown Case: " + body);
75 }
76 }
77 }
78
79 protected void installDerivedRuleDefinitionState(RuleDefinition definition, Set<String> knownVariables) {
80 for (Conjunction precondition : definition.getPreconditions()) {
81 createVariablesForScope(new ImplicitVariableScope(precondition, knownVariables));
82 }
83 }
84
85 protected void createVariablesForScope(ImplicitVariableScope scope) {
86 var queue = new ArrayDeque<ImplicitVariableScope>();
87 queue.addLast(scope);
88 while (!queue.isEmpty()) {
89 var nextScope = queue.removeFirst();
90 nextScope.createVariables(scopeProvider, linkingHelper, qualifiedNameConverter, queue);
91 }
92 }
93
94 public void discardDerivedVariables(Problem problem) {
95 for (Statement statement : problem.getStatements()) {
96 if (statement instanceof ParametricDefinition parametricDefinition) {
97 discardParametricDefinitionState(parametricDefinition);
98 }
99 }
100 }
101
102 protected void discardParametricDefinitionState(ParametricDefinition definition) {
103 List<ExistentialQuantifier> existentialQuantifiers = new ArrayList<>();
104 List<VariableOrNodeExpr> variableOrNodeExprs = new ArrayList<>();
105 var treeIterator = definition.eAllContents();
106 // We must collect the nodes where we are discarding derived state and only discard them after the iteration,
107 // because modifying the containment hierarchy during iteration causes the TreeIterator to fail with
108 // IndexOutOfBoundsException.
109 while (treeIterator.hasNext()) {
110 var child = treeIterator.next();
111 var containingFeature = child.eContainingFeature();
112 if (containingFeature == ProblemPackage.Literals.EXISTENTIAL_QUANTIFIER__IMPLICIT_VARIABLES ||
113 containingFeature == ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__SINGLETON_VARIABLE) {
114 treeIterator.prune();
115 } else if (child instanceof ExistentialQuantifier existentialQuantifier &&
116 !existentialQuantifier.getImplicitVariables().isEmpty()) {
117 existentialQuantifiers.add(existentialQuantifier);
118 } else if (child instanceof VariableOrNodeExpr variableOrNodeExpr &&
119 variableOrNodeExpr.getSingletonVariable() != null) {
120 variableOrNodeExprs.add(variableOrNodeExpr);
121 }
122 }
123 for (var existentialQuantifier : existentialQuantifiers) {
124 existentialQuantifier.getImplicitVariables().clear();
125 }
126 for (var variableOrNodeExpr : variableOrNodeExprs) {
127 variableOrNodeExpr.setSingletonVariable(null);
128 }
129 }
130}