diff options
Diffstat (limited to 'subprojects')
9 files changed, 349 insertions, 9 deletions
diff --git a/subprojects/store/build.gradle.kts b/subprojects/store/build.gradle.kts index 2c485020..d653f01d 100644 --- a/subprojects/store/build.gradle.kts +++ b/subprojects/store/build.gradle.kts | |||
@@ -8,3 +8,8 @@ plugins { | |||
8 | id("tools.refinery.gradle.java-library") | 8 | id("tools.refinery.gradle.java-library") |
9 | id("tools.refinery.gradle.jmh") | 9 | id("tools.refinery.gradle.jmh") |
10 | } | 10 | } |
11 | |||
12 | dependencies { | ||
13 | implementation(libs.eclipseCollections) | ||
14 | implementation(libs.eclipseCollections.api) | ||
15 | } | ||
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 0a94d449..1080a248 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 | |||
@@ -14,6 +14,10 @@ public final class Cursors { | |||
14 | return new Empty<>(); | 14 | return new Empty<>(); |
15 | } | 15 | } |
16 | 16 | ||
17 | public static <K, V> Cursor<K, V> singleton(K key, V value) { | ||
18 | return new Singleton<>(key, value); | ||
19 | } | ||
20 | |||
17 | private static class Empty<K, V> implements Cursor<K, V> { | 21 | private static class Empty<K, V> implements Cursor<K, V> { |
18 | private boolean terminated = false; | 22 | private boolean terminated = false; |
19 | 23 | ||
@@ -38,4 +42,53 @@ public final class Cursors { | |||
38 | return false; | 42 | return false; |
39 | } | 43 | } |
40 | } | 44 | } |
45 | |||
46 | private static class Singleton<K, V> implements Cursor<K, V> { | ||
47 | private State state = State.INITIAL; | ||
48 | private final K key; | ||
49 | private final V value; | ||
50 | |||
51 | public Singleton(K key, V value) { | ||
52 | this.key = key; | ||
53 | this.value = value; | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public K getKey() { | ||
58 | if (state == State.STARTED) { | ||
59 | return key; | ||
60 | } | ||
61 | return null; | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public V getValue() { | ||
66 | if (state == State.STARTED) { | ||
67 | return value; | ||
68 | } | ||
69 | return null; | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public boolean isTerminated() { | ||
74 | return state == State.TERMINATED; | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public boolean move() { | ||
79 | if (state == State.INITIAL) { | ||
80 | state = State.STARTED; | ||
81 | return true; | ||
82 | } | ||
83 | state = State.TERMINATED; | ||
84 | return false; | ||
85 | } | ||
86 | |||
87 | |||
88 | private enum State { | ||
89 | INITIAL, | ||
90 | STARTED, | ||
91 | TERMINATED | ||
92 | } | ||
93 | } | ||
41 | } | 94 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java index f906b48a..d650bd06 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java | |||
@@ -13,4 +13,6 @@ public sealed interface AnyInterpretation permits Interpretation { | |||
13 | AnySymbol getSymbol(); | 13 | AnySymbol getSymbol(); |
14 | 14 | ||
15 | long getSize(); | 15 | long getSize(); |
16 | |||
17 | int getAdjacentSize(int slot, int node); | ||
16 | } | 18 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java index 26ad9a69..ea670cbc 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java | |||
@@ -18,6 +18,8 @@ public non-sealed interface Interpretation<T> extends AnyInterpretation { | |||
18 | 18 | ||
19 | Cursor<Tuple, T> getAll(); | 19 | Cursor<Tuple, T> getAll(); |
20 | 20 | ||
21 | Cursor<Tuple, T> getAdjacent(int slot, int node); | ||
22 | |||
21 | T put(Tuple key, T value); | 23 | T put(Tuple key, T value); |
22 | 24 | ||
23 | void putAll(Cursor<Tuple, T> cursor); | 25 | void putAll(Cursor<Tuple, T> cursor); |
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 new file mode 100644 index 00000000..d9245c1d --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/BaseIndexer.java | |||
@@ -0,0 +1,135 @@ | |||
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.internal; | ||
7 | |||
8 | import org.eclipse.collections.api.factory.Maps; | ||
9 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | ||
10 | import org.eclipse.collections.api.map.MutableMap; | ||
11 | import org.eclipse.collections.api.map.primitive.MutableIntObjectMap; | ||
12 | import tools.refinery.store.map.AnyVersionedMap; | ||
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; | ||
17 | |||
18 | import java.util.Iterator; | ||
19 | import java.util.Map; | ||
20 | import java.util.Set; | ||
21 | |||
22 | class BaseIndexer<T> { | ||
23 | private final MutableIntObjectMap<MutableMap<Tuple, T>>[] maps; | ||
24 | private final VersionedMap<Tuple, T> versionedMap; | ||
25 | |||
26 | public BaseIndexer(int arity, VersionedMap<Tuple, T> map) { | ||
27 | if (arity < 2) { | ||
28 | throw new IllegalArgumentException("Only arity >= 2 symbols need to be indexed"); | ||
29 | } | ||
30 | // There is no way in Java to create a generic array in a checked way. | ||
31 | @SuppressWarnings({"unchecked", "squid:S1905"}) | ||
32 | var uncheckedMaps = (MutableIntObjectMap<MutableMap<Tuple, T>>[]) new MutableIntObjectMap[arity]; | ||
33 | maps = uncheckedMaps; | ||
34 | for (int i = 0; i < arity; i++) { | ||
35 | maps[i] = IntObjectMaps.mutable.empty(); | ||
36 | } | ||
37 | this.versionedMap = map; | ||
38 | if (map != null) { | ||
39 | var cursor = map.getAll(); | ||
40 | while (cursor.move()) { | ||
41 | put(cursor.getKey(), cursor.getValue()); | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | |||
46 | public void put(Tuple key, T value) { | ||
47 | for (int i = 0; i < maps.length; i++) { | ||
48 | var map = maps[i]; | ||
49 | int element = key.get(i); | ||
50 | var adjacentTuples = map.getIfAbsentPut(element, Maps.mutable::empty); | ||
51 | adjacentTuples.put(key, value); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | public void remove(Tuple key) { | ||
56 | for (int i = 0; i < maps.length; i++) { | ||
57 | var map = maps[i]; | ||
58 | int element = key.get(i); | ||
59 | var adjacentTuples = map.get(element); | ||
60 | if (adjacentTuples == null) { | ||
61 | continue; | ||
62 | } | ||
63 | adjacentTuples.remove(key); | ||
64 | if (adjacentTuples.isEmpty()) { | ||
65 | map.remove(element); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | private MutableMap<Tuple, T> getAdjacentMap(int slot, int node) { | ||
71 | if (slot < 0 || slot >= maps.length) { | ||
72 | throw new IllegalArgumentException("Invalid index: " + slot); | ||
73 | } | ||
74 | var map = maps[slot]; | ||
75 | return map.get(node); | ||
76 | } | ||
77 | |||
78 | public int getAdjacentSize(int slot, int node) { | ||
79 | var adjacentTuples = getAdjacentMap(slot, node); | ||
80 | if (adjacentTuples == null) { | ||
81 | return 0; | ||
82 | } | ||
83 | return adjacentTuples.size(); | ||
84 | } | ||
85 | |||
86 | public Cursor<Tuple, T> getAdjacent(int slot, int node) { | ||
87 | var adjacentTuples = getAdjacentMap(slot, node); | ||
88 | if (adjacentTuples == null) { | ||
89 | return Cursors.empty(); | ||
90 | } | ||
91 | return new IndexCursor<>(adjacentTuples, versionedMap); | ||
92 | } | ||
93 | |||
94 | private static class IndexCursor<T> implements Cursor<Tuple, T> { | ||
95 | 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 | |||
100 | public IndexCursor(MutableMap<Tuple, T> adjacentTuples, VersionedMap<Tuple, T> versionedMap) { | ||
101 | 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 | } | ||
129 | |||
130 | @Override | ||
131 | public Set<AnyVersionedMap> getDependingMaps() { | ||
132 | return dependingMaps; | ||
133 | } | ||
134 | } | ||
135 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/IndexedVersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/IndexedVersionedInterpretation.java new file mode 100644 index 00000000..e0a371de --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/IndexedVersionedInterpretation.java | |||
@@ -0,0 +1,50 @@ | |||
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.internal; | ||
7 | |||
8 | import tools.refinery.store.map.Cursor; | ||
9 | import tools.refinery.store.map.VersionedMap; | ||
10 | import tools.refinery.store.map.VersionedMapStore; | ||
11 | import tools.refinery.store.representation.Symbol; | ||
12 | import tools.refinery.store.tuple.Tuple; | ||
13 | |||
14 | import java.util.Objects; | ||
15 | |||
16 | class IndexedVersionedInterpretation<T> extends VersionedInterpretation<T> { | ||
17 | private final BaseIndexer<T> indexer; | ||
18 | |||
19 | public IndexedVersionedInterpretation(ModelImpl model, Symbol<T> symbol, VersionedMapStore<Tuple, T> store, | ||
20 | VersionedMap<Tuple, T> map) { | ||
21 | super(model, symbol, store, map); | ||
22 | indexer = new BaseIndexer<>(symbol.arity(), map); | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public Cursor<Tuple, T> getAdjacent(int slot, int node) { | ||
27 | return indexer.getAdjacent(slot, node); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public int getAdjacentSize(int slot, int node) { | ||
32 | return indexer.getAdjacentSize(slot, node); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | protected boolean shouldNotifyRestoreListeners() { | ||
37 | // Always call the {@code valueChanged} method to update the index. | ||
38 | return true; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | protected void valueChanged(Tuple key, T fromValue, T toValue, boolean restoring) { | ||
43 | if (Objects.equals(toValue, getSymbol().defaultValue())) { | ||
44 | indexer.remove(key); | ||
45 | } else { | ||
46 | indexer.put(key, toValue); | ||
47 | } | ||
48 | super.valueChanged(key, fromValue, toValue, restoring); | ||
49 | } | ||
50 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/NullaryVersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/NullaryVersionedInterpretation.java new file mode 100644 index 00000000..96639a8e --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/NullaryVersionedInterpretation.java | |||
@@ -0,0 +1,29 @@ | |||
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.internal; | ||
7 | |||
8 | import tools.refinery.store.map.Cursor; | ||
9 | import tools.refinery.store.map.VersionedMap; | ||
10 | import tools.refinery.store.map.VersionedMapStore; | ||
11 | import tools.refinery.store.representation.Symbol; | ||
12 | import tools.refinery.store.tuple.Tuple; | ||
13 | |||
14 | class NullaryVersionedInterpretation<T> extends VersionedInterpretation<T> { | ||
15 | public NullaryVersionedInterpretation(ModelImpl model, Symbol<T> symbol, VersionedMapStore<Tuple, T> store, | ||
16 | VersionedMap<Tuple, T> map) { | ||
17 | super(model, symbol, store, map); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public Cursor<Tuple, T> getAdjacent(int slot, int node) { | ||
22 | throw new IllegalArgumentException("Invalid index: " + slot); | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public int getAdjacentSize(int slot, int node) { | ||
27 | throw new IllegalArgumentException("Invalid index: " + slot); | ||
28 | } | ||
29 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/UnaryVersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/UnaryVersionedInterpretation.java new file mode 100644 index 00000000..4ec04358 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/UnaryVersionedInterpretation.java | |||
@@ -0,0 +1,50 @@ | |||
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.internal; | ||
7 | |||
8 | import tools.refinery.store.map.Cursor; | ||
9 | import tools.refinery.store.map.Cursors; | ||
10 | import tools.refinery.store.map.VersionedMap; | ||
11 | import tools.refinery.store.map.VersionedMapStore; | ||
12 | import tools.refinery.store.representation.Symbol; | ||
13 | import tools.refinery.store.tuple.Tuple; | ||
14 | |||
15 | import java.util.Objects; | ||
16 | |||
17 | class UnaryVersionedInterpretation<T> extends VersionedInterpretation<T> { | ||
18 | public UnaryVersionedInterpretation(ModelImpl model, Symbol<T> symbol, VersionedMapStore<Tuple, T> store, | ||
19 | VersionedMap<Tuple, T> map) { | ||
20 | super(model, symbol, store, map); | ||
21 | } | ||
22 | |||
23 | private void validateSlot(int slot) { | ||
24 | if (slot != 0) { | ||
25 | throw new IllegalArgumentException("Invalid index: " + slot); | ||
26 | } | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public Cursor<Tuple, T> getAdjacent(int slot, int node) { | ||
31 | validateSlot(slot); | ||
32 | var key = Tuple.of(node); | ||
33 | var value = get(key); | ||
34 | if (Objects.equals(value, getSymbol().defaultValue())) { | ||
35 | return Cursors.empty(); | ||
36 | } | ||
37 | return Cursors.singleton(key, value); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public int getAdjacentSize(int slot, int node) { | ||
42 | validateSlot(slot); | ||
43 | var key = Tuple.of(node); | ||
44 | var value = get(key); | ||
45 | if (Objects.equals(value, getSymbol().defaultValue())) { | ||
46 | return 0; | ||
47 | } | ||
48 | return 1; | ||
49 | } | ||
50 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java index 86101ce3..877028cc 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java | |||
@@ -21,7 +21,7 @@ import tools.refinery.store.tuple.Tuple; | |||
21 | import java.util.ArrayList; | 21 | import java.util.ArrayList; |
22 | import java.util.List; | 22 | import java.util.List; |
23 | 23 | ||
24 | public class VersionedInterpretation<T> implements Interpretation<T> { | 24 | public abstract class VersionedInterpretation<T> implements Interpretation<T> { |
25 | private final ModelImpl model; | 25 | private final ModelImpl model; |
26 | private final Symbol<T> symbol; | 26 | private final Symbol<T> symbol; |
27 | private final VersionedMapStore<Tuple, T> store; | 27 | private final VersionedMapStore<Tuple, T> store; |
@@ -29,8 +29,8 @@ public class VersionedInterpretation<T> implements Interpretation<T> { | |||
29 | private final List<InterpretationListener<T>> listeners = new ArrayList<>(); | 29 | private final List<InterpretationListener<T>> listeners = new ArrayList<>(); |
30 | private final List<InterpretationListener<T>> restoreListeners = new ArrayList<>(); | 30 | private final List<InterpretationListener<T>> restoreListeners = new ArrayList<>(); |
31 | 31 | ||
32 | private VersionedInterpretation(ModelImpl model, Symbol<T> symbol, VersionedMapStore<Tuple, T> store, | 32 | protected VersionedInterpretation(ModelImpl model, Symbol<T> symbol, VersionedMapStore<Tuple, T> store, |
33 | VersionedMap<Tuple, T> map) { | 33 | VersionedMap<Tuple, T> map) { |
34 | this.model = model; | 34 | this.model = model; |
35 | this.symbol = symbol; | 35 | this.symbol = symbol; |
36 | this.store = store; | 36 | this.store = store; |
@@ -58,6 +58,7 @@ public class VersionedInterpretation<T> implements Interpretation<T> { | |||
58 | .formatted(symbol, symbol.arity())); | 58 | .formatted(symbol, symbol.arity())); |
59 | } | 59 | } |
60 | } | 60 | } |
61 | |||
61 | @Override | 62 | @Override |
62 | public T get(Tuple key) { | 63 | public T get(Tuple key) { |
63 | checkKey(key); | 64 | checkKey(key); |
@@ -69,7 +70,7 @@ public class VersionedInterpretation<T> implements Interpretation<T> { | |||
69 | return map.getAll(); | 70 | return map.getAll(); |
70 | } | 71 | } |
71 | 72 | ||
72 | private void notifyListeners(Tuple key, T fromValue, T toValue, boolean restoring) { | 73 | protected void valueChanged(Tuple key, T fromValue, T toValue, boolean restoring) { |
73 | var listenerList = restoring ? restoreListeners : listeners; | 74 | var listenerList = restoring ? restoreListeners : listeners; |
74 | int listenerCount = listenerList.size(); | 75 | int listenerCount = listenerList.size(); |
75 | // Use a for loop instead of a for-each loop to avoid <code>Iterator</code> allocation overhead. | 76 | // Use a for loop instead of a for-each loop to avoid <code>Iterator</code> allocation overhead. |
@@ -84,7 +85,7 @@ public class VersionedInterpretation<T> implements Interpretation<T> { | |||
84 | checkKey(key); | 85 | checkKey(key); |
85 | model.markAsChanged(); | 86 | model.markAsChanged(); |
86 | var oldValue = map.put(key, value); | 87 | var oldValue = map.put(key, value); |
87 | notifyListeners(key, oldValue, value, false); | 88 | valueChanged(key, oldValue, value, false); |
88 | return oldValue; | 89 | return oldValue; |
89 | } | 90 | } |
90 | 91 | ||
@@ -125,11 +126,15 @@ public class VersionedInterpretation<T> implements Interpretation<T> { | |||
125 | return map.commit(); | 126 | return map.commit(); |
126 | } | 127 | } |
127 | 128 | ||
129 | protected boolean shouldNotifyRestoreListeners() { | ||
130 | return !restoreListeners.isEmpty(); | ||
131 | } | ||
132 | |||
128 | public void restore(long state) { | 133 | public void restore(long state) { |
129 | if (!restoreListeners.isEmpty()) { | 134 | if (shouldNotifyRestoreListeners()) { |
130 | var diffCursor = getDiffCursor(state); | 135 | var diffCursor = getDiffCursor(state); |
131 | while (diffCursor.move()) { | 136 | while (diffCursor.move()) { |
132 | notifyListeners(diffCursor.getKey(), diffCursor.getFromValue(), diffCursor.getToValue(), true); | 137 | valueChanged(diffCursor.getKey(), diffCursor.getFromValue(), diffCursor.getToValue(), true); |
133 | } | 138 | } |
134 | } | 139 | } |
135 | map.restore(state); | 140 | map.restore(state); |
@@ -153,7 +158,7 @@ public class VersionedInterpretation<T> implements Interpretation<T> { | |||
153 | @SuppressWarnings("unchecked") | 158 | @SuppressWarnings("unchecked") |
154 | var typedSymbol = (Symbol<T>) symbol; | 159 | var typedSymbol = (Symbol<T>) symbol; |
155 | var map = store.createMap(); | 160 | var map = store.createMap(); |
156 | return new VersionedInterpretation<>(model, typedSymbol, store, map); | 161 | return of(model, typedSymbol, store, map); |
157 | } | 162 | } |
158 | 163 | ||
159 | static <T> VersionedInterpretation<T> of(ModelImpl model, AnySymbol symbol, VersionedMapStore<Tuple, T> store, | 164 | static <T> VersionedInterpretation<T> of(ModelImpl model, AnySymbol symbol, VersionedMapStore<Tuple, T> store, |
@@ -161,6 +166,15 @@ public class VersionedInterpretation<T> implements Interpretation<T> { | |||
161 | @SuppressWarnings("unchecked") | 166 | @SuppressWarnings("unchecked") |
162 | var typedSymbol = (Symbol<T>) symbol; | 167 | var typedSymbol = (Symbol<T>) symbol; |
163 | var map = store.createMap(state); | 168 | var map = store.createMap(state); |
164 | return new VersionedInterpretation<>(model, typedSymbol, store, map); | 169 | return of(model, typedSymbol, store, map); |
170 | } | ||
171 | |||
172 | private static <T> VersionedInterpretation<T> of(ModelImpl model, Symbol<T> typedSymbol, | ||
173 | VersionedMapStore<Tuple, T> store, VersionedMap<Tuple, T> map) { | ||
174 | return switch (typedSymbol.arity()) { | ||
175 | case 0 -> new NullaryVersionedInterpretation<>(model, typedSymbol, store, map); | ||
176 | case 1 -> new UnaryVersionedInterpretation<>(model, typedSymbol, store, map); | ||
177 | default -> new IndexedVersionedInterpretation<>(model, typedSymbol, store, map); | ||
178 | }; | ||
165 | } | 179 | } |
166 | } | 180 | } |