aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java')
-rw-r--r--subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java119
1 files changed, 119 insertions, 0 deletions
diff --git a/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java
new file mode 100644
index 00000000..4da609fa
--- /dev/null
+++ b/subprojects/store-dse/src/main/java/tools/refinery/store/dse/transition/actions/BoundAction.java
@@ -0,0 +1,119 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.dse.transition.actions;
7
8import org.jetbrains.annotations.Nullable;
9import tools.refinery.store.model.Model;
10import tools.refinery.store.tuple.Tuple;
11
12public class BoundAction {
13 private final Action action;
14 private final Model model;
15 private BoundActionLiteral @Nullable [] boundLiterals;
16 private Tuple activation;
17 private final int[] localVariables;
18
19 BoundAction(Action action, Model model) {
20 this.action = action;
21 this.model = model;
22 localVariables = new int[action.getLocalVariables().size()];
23 }
24
25 public boolean fire(Tuple activation) {
26 model.checkCancelled();
27 if (this.activation != null) {
28 throw new IllegalStateException("Reentrant firing is not allowed");
29 }
30 this.activation = activation;
31 if (boundLiterals == null) {
32 boundLiterals = bindLiterals();
33 }
34 try {
35 int size = boundLiterals.length;
36 for (int i = 0; i < size; i++) {
37 var inputAllocation = action.getInputAllocation(i);
38 var boundLiteral = boundLiterals[i];
39 var input = getInputTuple(inputAllocation);
40 var output = boundLiteral.fire(input);
41 if (output == null) {
42 return false;
43 }
44 var outputAllocation = this.action.getOutputAllocation(i);
45 setOutputTuple(outputAllocation, output);
46 }
47 } finally {
48 this.activation = null;
49 }
50 return true;
51 }
52
53 private BoundActionLiteral[] bindLiterals() {
54 var actionLiterals = action.getActionLiterals();
55 int size = actionLiterals.size();
56 var boundLiteralsArray = new BoundActionLiteral[size];
57 for (int i = 0; i < size; i++) {
58 boundLiteralsArray[i] = actionLiterals.get(i).bindToModel(model);
59 }
60 return boundLiteralsArray;
61 }
62
63 private Tuple getInputTuple(int @Nullable [] inputAllocation) {
64 if (inputAllocation == null) {
65 // Identity allocation.
66 return activation;
67 }
68 return switch (inputAllocation.length) {
69 case 0 -> Tuple.of();
70 case 1 -> Tuple.of(getInput(inputAllocation[0]));
71 case 2 -> Tuple.of(getInput(inputAllocation[0]), getInput(inputAllocation[1]));
72 case 3 -> Tuple.of(getInput(inputAllocation[0]), getInput(inputAllocation[1]),
73 getInput(inputAllocation[2]));
74 case 4 -> Tuple.of(getInput(inputAllocation[0]), getInput(inputAllocation[1]),
75 getInput(inputAllocation[2]), getInput(inputAllocation[3]));
76 default -> {
77 var elements = new int[inputAllocation.length];
78 for (var i = 0; i < inputAllocation.length; i++) {
79 elements[i] = getInput(inputAllocation[i]);
80 }
81 yield Tuple.of(elements);
82 }
83 };
84 }
85
86 private int getInput(int index) {
87 int arity = action.getArity();
88 return index < arity ? activation.get(index) : localVariables[index - arity];
89 }
90
91 private void setOutputTuple(int @Nullable [] outputAllocation, Tuple output) {
92 if (outputAllocation == null || outputAllocation.length == 0) {
93 return;
94 }
95 switch (outputAllocation.length) {
96 case 1 -> localVariables[outputAllocation[0]] = output.get(0);
97 case 2 -> {
98 localVariables[outputAllocation[0]] = output.get(0);
99 localVariables[outputAllocation[1]] = output.get(1);
100 }
101 case 3 -> {
102 localVariables[outputAllocation[0]] = output.get(0);
103 localVariables[outputAllocation[1]] = output.get(1);
104 localVariables[outputAllocation[2]] = output.get(2);
105 }
106 case 4 -> {
107 localVariables[outputAllocation[0]] = output.get(0);
108 localVariables[outputAllocation[1]] = output.get(1);
109 localVariables[outputAllocation[2]] = output.get(2);
110 localVariables[outputAllocation[3]] = output.get(3);
111 }
112 default -> {
113 for (int i = 0; i < outputAllocation.length; i++) {
114 localVariables[outputAllocation[i]] = output.get(i);
115 }
116 }
117 }
118 }
119}