aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2024-05-20 17:29:07 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2024-05-26 17:22:33 +0200
commit42214746edac8bdc992a52ca8624f996871e2842 (patch)
tree2e8cf18ab0a9b12fcba96b2eb7511cd84131cb57
parentfeat(dse): detect stuch propagation rules (diff)
downloadrefinery-42214746edac8bdc992a52ca8624f996871e2842.tar.gz
refinery-42214746edac8bdc992a52ca8624f996871e2842.tar.zst
refinery-42214746edac8bdc992a52ca8624f996871e2842.zip
feat(language): node constants in rule actions
-rw-r--r--subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java8
-rw-r--r--subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java23
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java18
-rw-r--r--subprojects/logic/src/main/java/tools/refinery/logic/literal/ConstantLiteral.java3
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java4
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java4
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ConstantActionLiteral.java45
7 files changed, 89 insertions, 16 deletions
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java
index 06f0e758..58d6748a 100644
--- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java
+++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java
@@ -125,7 +125,7 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli
125 classesBuilder.add(ERROR_CLASS); 125 classesBuilder.add(ERROR_CLASS);
126 } 126 }
127 if (eObject instanceof Node node) { 127 if (eObject instanceof Node node) {
128 highlightNode(node, reference, classesBuilder); 128 highlightNode(node, classesBuilder);
129 } 129 }
130 if (eObject instanceof Relation relation) { 130 if (eObject instanceof Relation relation) {
131 var typeHash = typeHashProvider.getTypeHash(relation); 131 var typeHash = typeHashProvider.getTypeHash(relation);
@@ -137,10 +137,8 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli
137 return classes.toArray(new String[0]); 137 return classes.toArray(new String[0]);
138 } 138 }
139 139
140 private static void highlightNode(Node node, EReference reference, ImmutableList.Builder<String> classesBuilder) { 140 private static void highlightNode(Node node, ImmutableList.Builder<String> classesBuilder) {
141 if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE) { 141 classesBuilder.add(NODE_CLASS);
142 classesBuilder.add(NODE_CLASS);
143 }
144 if (ProblemUtil.isAtomNode(node)) { 142 if (ProblemUtil.isAtomNode(node)) {
145 classesBuilder.add(ATOM_NODE_CLASS); 143 classesBuilder.add(ATOM_NODE_CLASS);
146 } 144 }
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
index a86e2c47..02b2f920 100644
--- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
+++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java
@@ -31,6 +31,7 @@ import tools.refinery.store.dse.transition.DesignSpaceExplorationBuilder;
31import tools.refinery.store.dse.transition.Rule; 31import tools.refinery.store.dse.transition.Rule;
32import tools.refinery.store.dse.transition.RuleBuilder; 32import tools.refinery.store.dse.transition.RuleBuilder;
33import tools.refinery.store.dse.transition.actions.ActionLiteral; 33import tools.refinery.store.dse.transition.actions.ActionLiteral;
34import tools.refinery.store.dse.transition.actions.ActionLiterals;
34import tools.refinery.store.model.ModelStoreBuilder; 35import tools.refinery.store.model.ModelStoreBuilder;
35import tools.refinery.store.reasoning.ReasoningAdapter; 36import tools.refinery.store.reasoning.ReasoningAdapter;
36import tools.refinery.store.reasoning.actions.PartialActionLiterals; 37import tools.refinery.store.reasoning.actions.PartialActionLiterals;
@@ -968,7 +969,7 @@ public class ModelInitializer {
968 } 969 }
969 } 970 }
970 for (var action : body.getActions()) { 971 for (var action : body.getActions()) {
971 actionLiterals.add(toActionLiteral(action, localScope)); 972 toActionLiterals(action, localScope, actionLiterals);
972 } 973 }
973 builder.action(actionLiterals); 974 builder.action(actionLiterals);
974 } catch (RuntimeException e) { 975 } catch (RuntimeException e) {
@@ -976,8 +977,9 @@ public class ModelInitializer {
976 } 977 }
977 } 978 }
978 979
979 private ActionLiteral toActionLiteral( 980 private void toActionLiterals(
980 Action action, HashMap<tools.refinery.language.model.problem.Variable, NodeVariable> localScope) { 981 Action action, HashMap<tools.refinery.language.model.problem.Variable, NodeVariable> localScope,
982 List<ActionLiteral> actionLiterals) {
981 if (!(action instanceof AssertionAction assertionAction)) { 983 if (!(action instanceof AssertionAction assertionAction)) {
982 throw new TracedException(action, "Unknown action"); 984 throw new TracedException(action, "Unknown action");
983 } 985 }
@@ -991,11 +993,18 @@ public class ModelInitializer {
991 throw new TracedException(problemArgument, "Invalid argument"); 993 throw new TracedException(problemArgument, "Invalid argument");
992 } 994 }
993 var variableOrNode = nodeAssertionArgument.getNode(); 995 var variableOrNode = nodeAssertionArgument.getNode();
994 if (!(variableOrNode instanceof tools.refinery.language.model.problem.Variable problemVariable)) { 996 switch (variableOrNode) {
995 throw new TracedException(problemArgument, "Invalid argument"); 997 case tools.refinery.language.model.problem.Variable problemVariable ->
998 arguments[i] = localScope.get(problemVariable);
999 case Node node -> {
1000 int nodeId = getNodeId(node);
1001 var tempVariable = Variable.of(semanticsUtils.getNameWithoutRootPrefix(node).orElse("_" + nodeId));
1002 actionLiterals.add(ActionLiterals.constant(tempVariable, nodeId));
1003 arguments[i] = tempVariable;
1004 }
1005 default -> throw new TracedException(problemArgument, "Invalid argument");
996 } 1006 }
997 arguments[i] = localScope.get(problemVariable);
998 } 1007 }
999 return PartialActionLiterals.merge(partialRelation, truthValue, arguments); 1008 actionLiterals.add(PartialActionLiterals.merge(partialRelation, truthValue, arguments));
1000 } 1009 }
1001} 1010}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java b/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java
index 7b392182..84af4ee6 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java
@@ -153,6 +153,22 @@ public class ProblemValidator extends AbstractProblemValidator {
153 } 153 }
154 154
155 @Check 155 @Check
156 public void checkNodeAssertionArgumentConstants(NodeAssertionArgument argument) {
157 var rule = EcoreUtil2.getContainerOfType(argument, RuleDefinition.class);
158 if (rule == null) {
159 return;
160 }
161 var variableOrNode = argument.getNode();
162 if (variableOrNode instanceof Node node && !ProblemUtil.isAtomNode(node)) {
163 var name = node.getName();
164 var message = ("Only atoms can be referenced in rule actions. " +
165 "Mark '%s' as an atom with the declaration 'atom %s.'").formatted(name, name);
166 error(message, argument, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE,
167 INSIGNIFICANT_INDEX, NODE_CONSTANT_ISSUE);
168 }
169 }
170
171 @Check
156 public void checkUniqueDeclarations(Problem problem) { 172 public void checkUniqueDeclarations(Problem problem) {
157 var relations = new ArrayList<Relation>(); 173 var relations = new ArrayList<Relation>();
158 var nodes = new ArrayList<Node>(); 174 var nodes = new ArrayList<Node>();
@@ -360,7 +376,7 @@ public class ProblemValidator extends AbstractProblemValidator {
360 INVALID_MODALITY_ISSUE); 376 INVALID_MODALITY_ISSUE);
361 } 377 }
362 if (parameter.getBinding() != ParameterBinding.SINGLE) { 378 if (parameter.getBinding() != ParameterBinding.SINGLE) {
363 acceptError("Parameter binding annotations are only supported in rule definitions.", parameter, 379 acceptError("Parameter binding annotations are only supported in decision rules.", parameter,
364 ProblemPackage.PARAMETER__BINDING, 0, INVALID_MODALITY_ISSUE); 380 ProblemPackage.PARAMETER__BINDING, 0, INVALID_MODALITY_ISSUE);
365 } 381 }
366 } 382 }
diff --git a/subprojects/logic/src/main/java/tools/refinery/logic/literal/ConstantLiteral.java b/subprojects/logic/src/main/java/tools/refinery/logic/literal/ConstantLiteral.java
index 688ddfa0..36cf4226 100644
--- a/subprojects/logic/src/main/java/tools/refinery/logic/literal/ConstantLiteral.java
+++ b/subprojects/logic/src/main/java/tools/refinery/logic/literal/ConstantLiteral.java
@@ -14,6 +14,8 @@ import tools.refinery.logic.term.Variable;
14import java.util.Objects; 14import java.util.Objects;
15import java.util.Set; 15import java.util.Set;
16 16
17// {@link Object#equals(Object)} is implemented by {@link AbstractLiteral}.
18@SuppressWarnings("squid:S2160")
17public class ConstantLiteral extends AbstractLiteral { 19public class ConstantLiteral extends AbstractLiteral {
18 private final NodeVariable variable; 20 private final NodeVariable variable;
19 private final int nodeId; 21 private final int nodeId;
@@ -31,7 +33,6 @@ public class ConstantLiteral extends AbstractLiteral {
31 return nodeId; 33 return nodeId;
32 } 34 }
33 35
34
35 @Override 36 @Override
36 public Set<Variable> getOutputVariables() { 37 public Set<Variable> getOutputVariables() {
37 return Set.of(variable); 38 return Set.of(variable);
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java
index 0ce0c3a4..edcf9526 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/Action.java
@@ -1,5 +1,5 @@
1/* 1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> 2 * SPDX-FileCopyrightText: 2023-2024 The Refinery Authors <https://refinery.tools/>
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
@@ -67,7 +67,7 @@ public class Action {
67 var outputVariables = actionLiteral.getOutputVariables(); 67 var outputVariables = actionLiteral.getOutputVariables();
68 int size = outputVariables.size(); 68 int size = outputVariables.size();
69 if (size == 0) { 69 if (size == 0) {
70 // Identity mappings use a {@code null} allocation to avoid iterating over the output tuple. 70 // Empty mappings use a {@code null} allocation to avoid iterating over the output tuple.
71 return; 71 return;
72 } 72 }
73 if (size >= 2 && new HashSet<>(outputVariables).size() != size) { 73 if (size >= 2 && new HashSet<>(outputVariables).size() != size) {
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java
index d06e2479..6bd5075b 100644
--- a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ActionLiterals.java
@@ -16,6 +16,10 @@ public final class ActionLiterals {
16 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); 16 throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly");
17 } 17 }
18 18
19 public static ConstantActionLiteral constant(NodeVariable variable, int nodeId) {
20 return new ConstantActionLiteral(variable, nodeId);
21 }
22
19 public static <T> PutActionLiteral<T> put(Symbol<T> symbol, T value, NodeVariable... parameters) { 23 public static <T> PutActionLiteral<T> put(Symbol<T> symbol, T value, NodeVariable... parameters) {
20 return new PutActionLiteral<>(symbol, value, List.of(parameters)); 24 return new PutActionLiteral<>(symbol, value, List.of(parameters));
21 } 25 }
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ConstantActionLiteral.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ConstantActionLiteral.java
new file mode 100644
index 00000000..fecb2960
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/ConstantActionLiteral.java
@@ -0,0 +1,45 @@
1/*
2 * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.actions;
7
8import tools.refinery.logic.term.NodeVariable;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.tuple.Tuple;
11
12import java.util.List;
13
14public class ConstantActionLiteral extends AbstractActionLiteral {
15 private final NodeVariable variable;
16 private final int nodeId;
17
18 public ConstantActionLiteral(NodeVariable variable, int nodeId) {
19 this.variable = variable;
20 this.nodeId = nodeId;
21 }
22
23 public NodeVariable getVariable() {
24 return variable;
25 }
26
27 public int getNodeId() {
28 return nodeId;
29 }
30
31 @Override
32 public List<NodeVariable> getInputVariables() {
33 return List.of();
34 }
35
36 @Override
37 public List<NodeVariable> getOutputVariables() {
38 return List.of(variable);
39 }
40
41 @Override
42 public BoundActionLiteral bindToModel(Model model) {
43 return ignoredTuple -> Tuple.of(nodeId);
44 }
45}