diff options
author | Kristóf Marussy <kristof@marussy.com> | 2023-11-06 00:38:12 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2023-11-17 12:41:34 +0100 |
commit | 2e0bceb2f25989713f1baf6311d3787c3003d794 (patch) | |
tree | bf4ba62516d4328ac82e5eecb5853e2c3ee244af /subprojects/store-reasoning/src/main | |
parent | feat(language-ide): content assist filtering (diff) | |
download | refinery-2e0bceb2f25989713f1baf6311d3787c3003d794.tar.gz refinery-2e0bceb2f25989713f1baf6311d3787c3003d794.tar.zst refinery-2e0bceb2f25989713f1baf6311d3787c3003d794.zip |
feat: predicates as reference types
Now unary predicates may be used as types for cross-references.
This might create circular references between predicate, but no differently than
when the user manually creates predicates with circular references.
The reference types of containment and container references still have to be
classes, because we use the class hierarchy to encode contained types.
Diffstat (limited to 'subprojects/store-reasoning/src/main')
2 files changed, 27 insertions, 13 deletions
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceRefiner.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceRefiner.java index 0700f9f7..2e804b44 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceRefiner.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/crossreference/DirectedCrossReferenceRefiner.java | |||
@@ -15,15 +15,17 @@ import tools.refinery.store.representation.TruthValue; | |||
15 | import tools.refinery.store.tuple.Tuple; | 15 | import tools.refinery.store.tuple.Tuple; |
16 | 16 | ||
17 | class DirectedCrossReferenceRefiner extends ConcreteSymbolRefiner<TruthValue, Boolean> { | 17 | class DirectedCrossReferenceRefiner extends ConcreteSymbolRefiner<TruthValue, Boolean> { |
18 | private final PartialRelation targetType; | ||
18 | private final PartialInterpretationRefiner<TruthValue, Boolean> sourceRefiner; | 19 | private final PartialInterpretationRefiner<TruthValue, Boolean> sourceRefiner; |
19 | private final PartialInterpretationRefiner<TruthValue, Boolean> targetRefiner; | 20 | private PartialInterpretationRefiner<TruthValue, Boolean> targetRefiner; |
20 | 21 | ||
21 | public DirectedCrossReferenceRefiner(ReasoningAdapter adapter, PartialSymbol<TruthValue, Boolean> partialSymbol, | 22 | public DirectedCrossReferenceRefiner(ReasoningAdapter adapter, PartialSymbol<TruthValue, Boolean> partialSymbol, |
22 | Symbol<TruthValue> concreteSymbol, PartialRelation sourceType, | 23 | Symbol<TruthValue> concreteSymbol, PartialRelation sourceType, |
23 | PartialRelation targetType) { | 24 | PartialRelation targetType) { |
24 | super(adapter, partialSymbol, concreteSymbol); | 25 | super(adapter, partialSymbol, concreteSymbol); |
26 | this.targetType = targetType; | ||
27 | // Source is always a class, so we can rely on the fact that it is always constructed before this refiner. | ||
25 | sourceRefiner = adapter.getRefiner(sourceType); | 28 | sourceRefiner = adapter.getRefiner(sourceType); |
26 | targetRefiner = adapter.getRefiner(targetType); | ||
27 | } | 29 | } |
28 | 30 | ||
29 | @Override | 31 | @Override |
@@ -32,6 +34,10 @@ class DirectedCrossReferenceRefiner extends ConcreteSymbolRefiner<TruthValue, Bo | |||
32 | return false; | 34 | return false; |
33 | } | 35 | } |
34 | if (value.must()) { | 36 | if (value.must()) { |
37 | if (targetRefiner == null) { | ||
38 | // Access the target refinery lazily, since it may be constructed after this refiner. | ||
39 | targetRefiner = getAdapter().getRefiner(targetType); | ||
40 | } | ||
35 | return sourceRefiner.merge(Tuple.of(key.get(0)), TruthValue.TRUE) && | 41 | return sourceRefiner.merge(Tuple.of(key.get(0)), TruthValue.TRUE) && |
36 | targetRefiner.merge(Tuple.of(key.get(1)), TruthValue.TRUE); | 42 | targetRefiner.merge(Tuple.of(key.get(1)), TruthValue.TRUE); |
37 | } | 43 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java index ad0288ed..74022fc6 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/metamodel/MetamodelBuilder.java | |||
@@ -153,15 +153,11 @@ public class MetamodelBuilder { | |||
153 | return; | 153 | return; |
154 | } | 154 | } |
155 | var sourceType = info.sourceType(); | 155 | var sourceType = info.sourceType(); |
156 | var targetType = info.targetType(); | ||
157 | if (typeHierarchyBuilder.isInvalidType(sourceType)) { | 156 | if (typeHierarchyBuilder.isInvalidType(sourceType)) { |
158 | throw new TranslationException(linkType, "Source type %s of %s is not in type hierarchy" | 157 | throw new TranslationException(linkType, "Source type %s of %s is not in type hierarchy" |
159 | .formatted(sourceType, linkType)); | 158 | .formatted(sourceType, linkType)); |
160 | } | 159 | } |
161 | if (typeHierarchyBuilder.isInvalidType(targetType)) { | 160 | var targetType = info.targetType(); |
162 | throw new TranslationException(linkType, "Target type %s of %s is not in type hierarchy" | ||
163 | .formatted(targetType, linkType)); | ||
164 | } | ||
165 | var opposite = info.opposite(); | 161 | var opposite = info.opposite(); |
166 | Multiplicity targetMultiplicity = UnconstrainedMultiplicity.INSTANCE; | 162 | Multiplicity targetMultiplicity = UnconstrainedMultiplicity.INSTANCE; |
167 | if (opposite != null) { | 163 | if (opposite != null) { |
@@ -185,18 +181,30 @@ public class MetamodelBuilder { | |||
185 | oppositeReferences.put(opposite, linkType); | 181 | oppositeReferences.put(opposite, linkType); |
186 | } | 182 | } |
187 | if (info.containment()) { | 183 | if (info.containment()) { |
188 | if (!UnconstrainedMultiplicity.INSTANCE.equals(targetMultiplicity)) { | 184 | processContainmentInfo(linkType, info, targetMultiplicity); |
189 | throw new TranslationException(opposite, "Invalid opposite %s with multiplicity %s of containment %s" | ||
190 | .formatted(opposite, targetMultiplicity, linkType)); | ||
191 | } | ||
192 | containedTypes.add(targetType); | ||
193 | containmentHierarchy.put(linkType, new ContainmentInfo(sourceType, info.multiplicity(), targetType)); | ||
194 | return; | 185 | return; |
195 | } | 186 | } |
196 | directedCrossReferences.put(linkType, new DirectedCrossReferenceInfo(sourceType, info.multiplicity(), | 187 | directedCrossReferences.put(linkType, new DirectedCrossReferenceInfo(sourceType, info.multiplicity(), |
197 | targetType, targetMultiplicity)); | 188 | targetType, targetMultiplicity)); |
198 | } | 189 | } |
199 | 190 | ||
191 | private void processContainmentInfo(PartialRelation linkType, ReferenceInfo info, | ||
192 | Multiplicity targetMultiplicity) { | ||
193 | var sourceType = info.sourceType(); | ||
194 | var targetType = info.targetType(); | ||
195 | var opposite = info.opposite(); | ||
196 | if (typeHierarchyBuilder.isInvalidType(targetType)) { | ||
197 | throw new TranslationException(linkType, "Target type %s of %s is not in type hierarchy" | ||
198 | .formatted(targetType, linkType)); | ||
199 | } | ||
200 | if (!UnconstrainedMultiplicity.INSTANCE.equals(targetMultiplicity)) { | ||
201 | throw new TranslationException(opposite, "Invalid opposite %s with multiplicity %s of containment %s" | ||
202 | .formatted(opposite, targetMultiplicity, linkType)); | ||
203 | } | ||
204 | containedTypes.add(targetType); | ||
205 | containmentHierarchy.put(linkType, new ContainmentInfo(sourceType, info.multiplicity(), targetType)); | ||
206 | } | ||
207 | |||
200 | private static void validateOpposite(PartialRelation linkType, ReferenceInfo info, PartialRelation opposite, | 208 | private static void validateOpposite(PartialRelation linkType, ReferenceInfo info, PartialRelation opposite, |
201 | ReferenceInfo oppositeInfo) { | 209 | ReferenceInfo oppositeInfo) { |
202 | var sourceType = info.sourceType(); | 210 | var sourceType = info.sourceType(); |