diff options
author | 2023-07-18 20:18:48 +0200 | |
---|---|---|
committer | 2023-07-20 15:54:49 +0200 | |
commit | bc742b20fa187200def2809e5aef71547f75c65a (patch) | |
tree | f12e0344805501118410520ee8a60905a6541210 /subprojects/store/src/main/java | |
parent | feat: use base index for local search (diff) | |
download | refinery-bc742b20fa187200def2809e5aef71547f75c65a.tar.gz refinery-bc742b20fa187200def2809e5aef71547f75c65a.tar.zst refinery-bc742b20fa187200def2809e5aef71547f75c65a.zip |
feat: basic partial interpretation infrastructure
Diffstat (limited to 'subprojects/store/src/main/java')
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 | */ |
6 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
7 | 7 | ||
8 | import java.util.Iterator; | ||
9 | import java.util.Map; | ||
10 | |||
8 | public final class Cursors { | 11 | public 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 | */ | ||
6 | package tools.refinery.store.map; | ||
7 | |||
8 | import java.util.Iterator; | ||
9 | import java.util.Map; | ||
10 | |||
11 | public 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 | */ | ||
6 | package tools.refinery.store.model; | ||
7 | |||
8 | @FunctionalInterface | ||
9 | public 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; | |||
9 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | 9 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; |
10 | import org.eclipse.collections.api.map.MutableMap; | 10 | import org.eclipse.collections.api.map.MutableMap; |
11 | import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; | 11 | import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; |
12 | import tools.refinery.store.map.AnyVersionedMap; | 12 | import tools.refinery.store.map.*; |
13 | import tools.refinery.store.map.Cursor; | ||
14 | import tools.refinery.store.map.Cursors; | ||
15 | import tools.refinery.store.map.VersionedMap; | ||
16 | import tools.refinery.store.tuple.Tuple; | 13 | import tools.refinery.store.tuple.Tuple; |
17 | 14 | ||
18 | import java.util.Iterator; | ||
19 | import java.util.Map; | ||
20 | import java.util.Set; | 15 | import java.util.Set; |
21 | 16 | ||
22 | class BaseIndexer<T> { | 17 | class 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; | |||
11 | import tools.refinery.store.map.VersionedMapStoreImpl; | 11 | import tools.refinery.store.map.VersionedMapStoreImpl; |
12 | import tools.refinery.store.model.ModelStore; | 12 | import tools.refinery.store.model.ModelStore; |
13 | import tools.refinery.store.model.ModelStoreBuilder; | 13 | import tools.refinery.store.model.ModelStoreBuilder; |
14 | import tools.refinery.store.model.ModelStoreConfiguration; | ||
14 | import tools.refinery.store.model.TupleHashProvider; | 15 | import tools.refinery.store.model.TupleHashProvider; |
15 | import tools.refinery.store.representation.AnySymbol; | 16 | import tools.refinery.store.representation.AnySymbol; |
16 | import tools.refinery.store.representation.Symbol; | 17 | import 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 | */ |
6 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
7 | 7 | ||
8 | import java.util.Objects; | ||
8 | import java.util.Optional; | 9 | import java.util.Optional; |
9 | 10 | ||
10 | public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain { | 11 | public 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 | ||
8 | import java.util.Optional; | 8 | import java.util.Optional; |
9 | 9 | ||
10 | // Singleton pattern, because there is only one domain for truth values. | ||
11 | @SuppressWarnings("squid:S6548") | ||
10 | public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolean> { | 12 | public 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) |