aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-18 20:18:48 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-07-20 15:54:49 +0200
commitbc742b20fa187200def2809e5aef71547f75c65a (patch)
treef12e0344805501118410520ee8a60905a6541210 /subprojects/store
parentfeat: use base index for local search (diff)
downloadrefinery-bc742b20fa187200def2809e5aef71547f75c65a.tar.gz
refinery-bc742b20fa187200def2809e5aef71547f75c65a.tar.zst
refinery-bc742b20fa187200def2809e5aef71547f75c65a.zip
feat: basic partial interpretation infrastructure
Diffstat (limited to 'subprojects/store')
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java11
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/map/IteratorBasedCursor.java44
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java4
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreConfiguration.java11
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/BaseIndexer.java41
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java19
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java5
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java17
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java29
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java2
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java5
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java8
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java9
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java10
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java11
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java10
16 files changed, 176 insertions, 60 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java
index 1080a248..5e69e7af 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java
@@ -5,6 +5,9 @@
5 */ 5 */
6package tools.refinery.store.map; 6package tools.refinery.store.map;
7 7
8import java.util.Iterator;
9import java.util.Map;
10
8public final class Cursors { 11public final class Cursors {
9 private Cursors() { 12 private Cursors() {
10 throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); 13 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
@@ -18,6 +21,14 @@ public final class Cursors {
18 return new Singleton<>(key, value); 21 return new Singleton<>(key, value);
19 } 22 }
20 23
24 public static <K, V> Cursor<K, V> of(Iterator<Map.Entry<K, V>> iterator) {
25 return new IteratorBasedCursor<>(iterator);
26 }
27
28 public static <K, V> Cursor<K, V> of(Map<K, V> map) {
29 return of(map.entrySet().iterator());
30 }
31
21 private static class Empty<K, V> implements Cursor<K, V> { 32 private static class Empty<K, V> implements Cursor<K, V> {
22 private boolean terminated = false; 33 private boolean terminated = false;
23 34
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/IteratorBasedCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/IteratorBasedCursor.java
new file mode 100644
index 00000000..0ed9b730
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/map/IteratorBasedCursor.java
@@ -0,0 +1,44 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.map;
7
8import java.util.Iterator;
9import java.util.Map;
10
11public class IteratorBasedCursor<K, V> implements Cursor<K, V> {
12 private final Iterator<Map.Entry<K, V>> iterator;
13 private Map.Entry<K, V> entry;
14 private boolean terminated;
15
16 public IteratorBasedCursor(Iterator<Map.Entry<K, V>> iterator) {
17 this.iterator = iterator;
18 }
19
20 @Override
21 public K getKey() {
22 return entry.getKey();
23 }
24
25 @Override
26 public V getValue() {
27 return entry.getValue();
28 }
29
30 @Override
31 public boolean isTerminated() {
32 return terminated;
33 }
34
35 @Override
36 public boolean move() {
37 if (!terminated && iterator.hasNext()) {
38 entry = iterator.next();
39 return true;
40 }
41 terminated = true;
42 return false;
43 }
44}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java
index 3a4024b5..8f652762 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java
@@ -29,7 +29,9 @@ public interface ModelStoreBuilder {
29 29
30 <T> ModelStoreBuilder symbol(Symbol<T> symbol); 30 <T> ModelStoreBuilder symbol(Symbol<T> symbol);
31 31
32 <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder); 32 ModelStoreBuilder with(ModelAdapterBuilder adapterBuilder);
33
34 ModelStoreBuilder with(ModelStoreConfiguration configuration);
33 35
34 <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType); 36 <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType);
35 37
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreConfiguration.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreConfiguration.java
new file mode 100644
index 00000000..e94af5f8
--- /dev/null
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreConfiguration.java
@@ -0,0 +1,11 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.model;
7
8@FunctionalInterface
9public interface ModelStoreConfiguration {
10 void apply(ModelStoreBuilder storeBuilder);
11}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/BaseIndexer.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/BaseIndexer.java
index d9245c1d..3d7f59d7 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/BaseIndexer.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/BaseIndexer.java
@@ -9,14 +9,9 @@ import org.eclipse.collections.api.factory.Maps;
9import org.eclipse.collections.api.factory.primitive.IntObjectMaps; 9import org.eclipse.collections.api.factory.primitive.IntObjectMaps;
10import org.eclipse.collections.api.map.MutableMap; 10import org.eclipse.collections.api.map.MutableMap;
11import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; 11import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
12import tools.refinery.store.map.AnyVersionedMap; 12import tools.refinery.store.map.*;
13import tools.refinery.store.map.Cursor;
14import tools.refinery.store.map.Cursors;
15import tools.refinery.store.map.VersionedMap;
16import tools.refinery.store.tuple.Tuple; 13import tools.refinery.store.tuple.Tuple;
17 14
18import java.util.Iterator;
19import java.util.Map;
20import java.util.Set; 15import java.util.Set;
21 16
22class BaseIndexer<T> { 17class BaseIndexer<T> {
@@ -91,40 +86,12 @@ class BaseIndexer<T> {
91 return new IndexCursor<>(adjacentTuples, versionedMap); 86 return new IndexCursor<>(adjacentTuples, versionedMap);
92 } 87 }
93 88
94 private static class IndexCursor<T> implements Cursor<Tuple, T> { 89 private static class IndexCursor<T> extends IteratorBasedCursor<Tuple, T> {
95 private final Set<AnyVersionedMap> dependingMaps; 90 private final Set<AnyVersionedMap> dependingMaps;
96 private final Iterator<Map.Entry<Tuple, T>> iterator;
97 private Map.Entry<Tuple, T> entry;
98 private boolean terminated;
99 91
100 public IndexCursor(MutableMap<Tuple, T> adjacentTuples, VersionedMap<Tuple, T> versionedMap) { 92 public IndexCursor(MutableMap<Tuple, T> map, VersionedMap<Tuple, T> versionedMap) {
93 super(map.entrySet().iterator());
101 dependingMaps = versionedMap == null ? Set.of() : Set.of(versionedMap); 94 dependingMaps = versionedMap == null ? Set.of() : Set.of(versionedMap);
102 iterator = adjacentTuples.entrySet().iterator();
103 }
104
105 @Override
106 public Tuple getKey() {
107 return entry.getKey();
108 }
109
110 @Override
111 public T getValue() {
112 return entry.getValue();
113 }
114
115 @Override
116 public boolean isTerminated() {
117 return terminated;
118 }
119
120 @Override
121 public boolean move() {
122 if (!terminated && iterator.hasNext()) {
123 entry = iterator.next();
124 return true;
125 }
126 terminated = true;
127 return false;
128 } 95 }
129 96
130 @Override 97 @Override
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
index aafbe130..5c688178 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java
@@ -11,6 +11,7 @@ import tools.refinery.store.map.VersionedMapStore;
11import tools.refinery.store.map.VersionedMapStoreImpl; 11import tools.refinery.store.map.VersionedMapStoreImpl;
12import tools.refinery.store.model.ModelStore; 12import tools.refinery.store.model.ModelStore;
13import tools.refinery.store.model.ModelStoreBuilder; 13import tools.refinery.store.model.ModelStoreBuilder;
14import tools.refinery.store.model.ModelStoreConfiguration;
14import tools.refinery.store.model.TupleHashProvider; 15import tools.refinery.store.model.TupleHashProvider;
15import tools.refinery.store.representation.AnySymbol; 16import tools.refinery.store.representation.AnySymbol;
16import tools.refinery.store.representation.Symbol; 17import tools.refinery.store.representation.Symbol;
@@ -26,7 +27,8 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
26 @Override 27 @Override
27 public <T> ModelStoreBuilder symbol(Symbol<T> symbol) { 28 public <T> ModelStoreBuilder symbol(Symbol<T> symbol) {
28 if (!allSymbols.add(symbol)) { 29 if (!allSymbols.add(symbol)) {
29 throw new IllegalArgumentException("Symbol %s already added".formatted(symbol)); 30 // No need to add symbol twice.
31 return this;
30 } 32 }
31 var equivalenceClass = new SymbolEquivalenceClass<>(symbol); 33 var equivalenceClass = new SymbolEquivalenceClass<>(symbol);
32 var symbolsInEquivalenceClass = equivalenceClasses.computeIfAbsent(equivalenceClass, 34 var symbolsInEquivalenceClass = equivalenceClasses.computeIfAbsent(equivalenceClass,
@@ -36,7 +38,7 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
36 } 38 }
37 39
38 @Override 40 @Override
39 public <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder) { 41 public ModelStoreBuilder with(ModelAdapterBuilder adapterBuilder) {
40 for (var existingAdapter : adapters) { 42 for (var existingAdapter : adapters) {
41 if (existingAdapter.getClass().equals(adapterBuilder.getClass())) { 43 if (existingAdapter.getClass().equals(adapterBuilder.getClass())) {
42 throw new IllegalArgumentException("%s adapter was already configured for store builder" 44 throw new IllegalArgumentException("%s adapter was already configured for store builder"
@@ -48,6 +50,12 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
48 } 50 }
49 51
50 @Override 52 @Override
53 public ModelStoreBuilder with(ModelStoreConfiguration configuration) {
54 configuration.apply(this);
55 return this;
56 }
57
58 @Override
51 public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { 59 public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType) {
52 return AdapterUtils.tryGetAdapter(adapters, adapterType); 60 return AdapterUtils.tryGetAdapter(adapters, adapterType);
53 } 61 }
@@ -59,13 +67,14 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder {
59 67
60 @Override 68 @Override
61 public ModelStore build() { 69 public ModelStore build() {
70 // First configure adapters and let them register any symbols we don't know about yet.
71 for (int i = adapters.size() - 1; i >= 0; i--) {
72 adapters.get(i).configure(this);
73 }
62 var stores = new HashMap<AnySymbol, VersionedMapStore<Tuple, ?>>(allSymbols.size()); 74 var stores = new HashMap<AnySymbol, VersionedMapStore<Tuple, ?>>(allSymbols.size());
63 for (var entry : equivalenceClasses.entrySet()) { 75 for (var entry : equivalenceClasses.entrySet()) {
64 createStores(stores, entry.getKey(), entry.getValue()); 76 createStores(stores, entry.getKey(), entry.getValue());
65 } 77 }
66 for (int i = adapters.size() - 1; i >= 0; i--) {
67 adapters.get(i).configure(this);
68 }
69 var modelStore = new ModelStoreImpl(stores, adapters.size()); 78 var modelStore = new ModelStoreImpl(stores, adapters.size());
70 for (var adapterBuilder : adapters) { 79 for (var adapterBuilder : adapters) {
71 var storeAdapter = adapterBuilder.build(modelStore); 80 var storeAdapter = adapterBuilder.build(modelStore);
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java
index 52c740e8..dfdb43bd 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java
@@ -5,6 +5,7 @@
5 */ 5 */
6package tools.refinery.store.representation; 6package tools.refinery.store.representation;
7 7
8import java.util.Objects;
8import java.util.Optional; 9import java.util.Optional;
9 10
10public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain { 11public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain {
@@ -22,7 +23,9 @@ public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain {
22 return toConcrete(abstractValue).isPresent(); 23 return toConcrete(abstractValue).isPresent();
23 } 24 }
24 25
25 boolean isRefinement(A originalValue, A refinedValue); 26 default boolean isRefinement(A originalValue, A refinedValue) {
27 return Objects.equals(commonRefinement(originalValue, refinedValue), refinedValue);
28 }
26 29
27 A commonRefinement(A leftValue, A rightValue); 30 A commonRefinement(A leftValue, A rightValue);
28 31
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java
index 40baf9a5..f81ee9a4 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java
@@ -36,6 +36,10 @@ public enum TruthValue {
36 return this != UNKNOWN; 36 return this != UNKNOWN;
37 } 37 }
38 38
39 public boolean isConcrete() {
40 return this == TRUE || this == FALSE;
41 }
42
39 public boolean must() { 43 public boolean must() {
40 return this == TRUE || this == ERROR; 44 return this == TRUE || this == ERROR;
41 } 45 }
@@ -55,9 +59,18 @@ public enum TruthValue {
55 public TruthValue merge(TruthValue other) { 59 public TruthValue merge(TruthValue other) {
56 return switch (this) { 60 return switch (this) {
57 case TRUE -> other == UNKNOWN || other == TRUE ? TRUE : ERROR; 61 case TRUE -> other == UNKNOWN || other == TRUE ? TRUE : ERROR;
58 case FALSE -> other == TruthValue.UNKNOWN || other == TruthValue.FALSE ? FALSE : ERROR; 62 case FALSE -> other == UNKNOWN || other == FALSE ? FALSE : ERROR;
59 case UNKNOWN -> other; 63 case UNKNOWN -> other;
60 default -> ERROR; 64 case ERROR -> ERROR;
65 };
66 }
67
68 public TruthValue join(TruthValue other) {
69 return switch (this) {
70 case TRUE -> other == ERROR || other == TRUE ? TRUE : UNKNOWN;
71 case FALSE -> other == ERROR || other == FALSE ? FALSE : UNKNOWN;
72 case UNKNOWN -> UNKNOWN;
73 case ERROR -> other;
61 }; 74 };
62 } 75 }
63} 76}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java
index 89f8dd19..61696dca 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java
@@ -7,6 +7,8 @@ package tools.refinery.store.representation;
7 7
8import java.util.Optional; 8import java.util.Optional;
9 9
10// Singleton pattern, because there is only one domain for truth values.
11@SuppressWarnings("squid:S6548")
10public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolean> { 12public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolean> {
11 public static final TruthValueDomain INSTANCE = new TruthValueDomain(); 13 public static final TruthValueDomain INSTANCE = new TruthValueDomain();
12 14
@@ -15,51 +17,50 @@ public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolea
15 17
16 @Override 18 @Override
17 public Class<TruthValue> abstractType() { 19 public Class<TruthValue> abstractType() {
18 return null; 20 return TruthValue.class;
19 } 21 }
20 22
21 @Override 23 @Override
22 public Class<Boolean> concreteType() { 24 public Class<Boolean> concreteType() {
23 return null; 25 return Boolean.class;
24 } 26 }
25 27
26 @Override 28 @Override
27 public TruthValue toAbstract(Boolean concreteValue) { 29 public TruthValue toAbstract(Boolean concreteValue) {
28 return null; 30 return TruthValue.toTruthValue(concreteValue);
29 } 31 }
30 32
31 @Override 33 @Override
32 public Optional<Boolean> toConcrete(TruthValue abstractValue) { 34 public Optional<Boolean> toConcrete(TruthValue abstractValue) {
33 return Optional.empty(); 35 return switch (abstractValue) {
36 case TRUE -> Optional.of(true);
37 case FALSE -> Optional.of(false);
38 default -> Optional.empty();
39 };
34 } 40 }
35 41
36 @Override 42 @Override
37 public boolean isConcrete(TruthValue abstractValue) { 43 public boolean isConcrete(TruthValue abstractValue) {
38 return AbstractDomain.super.isConcrete(abstractValue); 44 return abstractValue.isConcrete();
39 }
40
41 @Override
42 public boolean isRefinement(TruthValue originalValue, TruthValue refinedValue) {
43 return false;
44 } 45 }
45 46
46 @Override 47 @Override
47 public TruthValue commonRefinement(TruthValue leftValue, TruthValue rightValue) { 48 public TruthValue commonRefinement(TruthValue leftValue, TruthValue rightValue) {
48 return null; 49 return leftValue.merge(rightValue);
49 } 50 }
50 51
51 @Override 52 @Override
52 public TruthValue commonAncestor(TruthValue leftValue, TruthValue rightValue) { 53 public TruthValue commonAncestor(TruthValue leftValue, TruthValue rightValue) {
53 return null; 54 return leftValue.join(rightValue);
54 } 55 }
55 56
56 @Override 57 @Override
57 public TruthValue unknown() { 58 public TruthValue unknown() {
58 return null; 59 return TruthValue.UNKNOWN;
59 } 60 }
60 61
61 @Override 62 @Override
62 public boolean isError(TruthValue abstractValue) { 63 public boolean isError(TruthValue abstractValue) {
63 return false; 64 return !abstractValue.isConsistent();
64 } 65 }
65} 66}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java
index aae7b344..e9761763 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java
@@ -12,6 +12,8 @@ public sealed interface Tuple extends Comparable<Tuple> permits Tuple0, Tuple1,
12 12
13 int get(int element); 13 int get(int element);
14 14
15 Tuple set(int element, int value);
16
15 @Override 17 @Override
16 default int compareTo(@NotNull Tuple other) { 18 default int compareTo(@NotNull Tuple other) {
17 int size = getSize(); 19 int size = getSize();
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java
index a9aa9bf2..5f525798 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java
@@ -29,6 +29,11 @@ public final class Tuple0 implements Tuple {
29 } 29 }
30 30
31 @Override 31 @Override
32 public Tuple set(int element, int value) {
33 throw new IndexOutOfBoundsException(element);
34 }
35
36 @Override
32 public String toString() { 37 public String toString() {
33 return TUPLE_BEGIN + TUPLE_END; 38 return TUPLE_BEGIN + TUPLE_END;
34 } 39 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java
index 388ee3a9..fb9497d2 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java
@@ -38,6 +38,14 @@ public final class Tuple1 implements Tuple {
38 } 38 }
39 39
40 @Override 40 @Override
41 public Tuple set(int element, int value) {
42 if (element == 0) {
43 return Tuple.of(value);
44 }
45 throw new IndexOutOfBoundsException(element);
46 }
47
48 @Override
41 public String toString() { 49 public String toString() {
42 return TUPLE_BEGIN + value0 + TUPLE_END; 50 return TUPLE_BEGIN + value0 + TUPLE_END;
43 } 51 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java
index 6d886fd3..2213df97 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java
@@ -25,6 +25,15 @@ public record Tuple2(int value0, int value1) implements Tuple {
25 } 25 }
26 26
27 @Override 27 @Override
28 public Tuple set(int element, int value) {
29 return switch (element) {
30 case 0 -> Tuple.of(value, value1);
31 case 1 -> Tuple.of(value0, value);
32 default -> throw new ArrayIndexOutOfBoundsException(element);
33 };
34 }
35
36 @Override
28 public String toString() { 37 public String toString() {
29 return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_END; 38 return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_END;
30 } 39 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java
index 734e45c2..417770e8 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java
@@ -26,6 +26,16 @@ public record Tuple3(int value0, int value1, int value2) implements Tuple {
26 } 26 }
27 27
28 @Override 28 @Override
29 public Tuple set(int element, int value) {
30 return switch (element) {
31 case 0 -> Tuple.of(value, value1, value2);
32 case 1 -> Tuple.of(value0, value, value2);
33 case 2 -> Tuple.of(value0, value1, value);
34 default -> throw new ArrayIndexOutOfBoundsException(element);
35 };
36 }
37
38 @Override
29 public String toString() { 39 public String toString() {
30 return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_END; 40 return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_END;
31 } 41 }
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java
index e1b93e7b..c4915198 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java
@@ -27,6 +27,17 @@ public record Tuple4(int value0, int value1, int value2, int value3) implements
27 } 27 }
28 28
29 @Override 29 @Override
30 public Tuple set(int element, int value) {
31 return switch (element) {
32 case 0 -> Tuple.of(value, value1, value2, value3);
33 case 1 -> Tuple.of(value0, value, value2, value3);
34 case 2 -> Tuple.of(value0, value1, value, value3);
35 case 3 -> Tuple.of(value0, value1, value2, value);
36 default -> throw new ArrayIndexOutOfBoundsException(element);
37 };
38 }
39
40 @Override
30 public String toString() { 41 public String toString() {
31 return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_SEPARATOR + value3 + 42 return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_SEPARATOR + value3 +
32 TUPLE_END; 43 TUPLE_END;
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java
index b66af491..b42b4b6a 100644
--- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java
+++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java
@@ -32,6 +32,16 @@ public final class TupleN implements Tuple {
32 } 32 }
33 33
34 @Override 34 @Override
35 public Tuple set(int element, int value) {
36 int size = getSize();
37 var newValues = new int[size];
38 for (int i = 0; i < size; i++) {
39 newValues[i] = element == i ? value : values[i];
40 }
41 return Tuple.of(newValues);
42 }
43
44 @Override
35 public String toString() { 45 public String toString() {
36 var valuesString = Arrays.stream(values) 46 var valuesString = Arrays.stream(values)
37 .mapToObj(Integer::toString) 47 .mapToObj(Integer::toString)