aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language/src/main/java/tools/refinery/language/typesystem/SignatureProvider.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/language/src/main/java/tools/refinery/language/typesystem/SignatureProvider.java')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/typesystem/SignatureProvider.java107
1 files changed, 107 insertions, 0 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/typesystem/SignatureProvider.java b/subprojects/language/src/main/java/tools/refinery/language/typesystem/SignatureProvider.java
new file mode 100644
index 00000000..3e25a0f5
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/typesystem/SignatureProvider.java
@@ -0,0 +1,107 @@
1/*
2 * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.typesystem;
7
8import com.google.inject.Inject;
9import com.google.inject.Singleton;
10import org.eclipse.xtext.naming.IQualifiedNameProvider;
11import org.eclipse.xtext.util.IResourceScopeCache;
12import tools.refinery.language.model.problem.*;
13
14import java.util.ArrayList;
15import java.util.HashMap;
16import java.util.List;
17
18@Singleton
19public class SignatureProvider {
20 private static final String PREFIX = "tools.refinery.language.typesystem.SignatureProvider.";
21 private static final String SIGNATURE_CACHE = PREFIX + "SIGNATURE_CACHE";
22 private static final String DATATYPE_CACHE = PREFIX + "DATATYPE_CACHE";
23 private static final String AGGREGATOR_CACHE = PREFIX + "AGGREGATOR_CACHE";
24
25 @Inject
26 private IQualifiedNameProvider qualifiedNameProvider;
27
28 @Inject
29 private IResourceScopeCache cache;
30
31 public Signature getSignature(Relation relation) {
32 var signatures = cache.get(SIGNATURE_CACHE, relation.eResource(), () -> new HashMap<Relation, Signature>());
33 return signatures.computeIfAbsent(relation, this::computeSignature);
34 }
35
36 public int getArity(Relation relation) {
37 return getSignature(relation).parameterTypes().size();
38 }
39
40 private Signature computeSignature(Relation relation) {
41 return new Signature(getParameterTypes(relation), getResultType(relation));
42 }
43
44 private List<FixedType> getParameterTypes(Relation relation) {
45 return switch (relation) {
46 case ClassDeclaration ignored -> List.of(ExprType.NODE);
47 case EnumDeclaration ignored -> List.of(ExprType.NODE);
48 case DatatypeDeclaration datatypeDeclaration -> List.of(getDataType(datatypeDeclaration));
49 case ReferenceDeclaration referenceDeclaration -> {
50 if (referenceDeclaration.getReferenceType() instanceof DatatypeDeclaration) {
51 yield List.of(ExprType.NODE);
52 }
53 yield List.of(ExprType.NODE, ExprType.NODE);
54 }
55 case ParametricDefinition parametricDefinition -> {
56 var parameters = parametricDefinition.getParameters();
57 var exprTypes = new ArrayList<FixedType>(parameters.size());
58 for (var parameter : parameters) {
59 if (parameter.getParameterType() instanceof DatatypeDeclaration datatypeDeclaration) {
60 exprTypes.add(getDataType(datatypeDeclaration));
61 } else {
62 exprTypes.add(ExprType.NODE);
63 }
64 }
65 yield List.copyOf(exprTypes);
66 }
67 default -> throw new IllegalArgumentException("Unknown Relation: " + relation);
68 };
69 }
70
71 private FixedType getResultType(Relation relation) {
72 if (relation instanceof ReferenceDeclaration referenceDeclaration &&
73 referenceDeclaration.getReferenceType() instanceof DatatypeDeclaration datatypeDeclaration) {
74 return getDataType(datatypeDeclaration);
75 }
76 return ExprType.LITERAL;
77 }
78
79 public DataExprType getDataType(DatatypeDeclaration datatypeDeclaration) {
80 var dataTypes = cache.get(DATATYPE_CACHE, datatypeDeclaration.eResource(),
81 () -> new HashMap<DatatypeDeclaration, DataExprType>());
82 return dataTypes.computeIfAbsent(datatypeDeclaration, this::computeDataType);
83 }
84
85 private DataExprType computeDataType(DatatypeDeclaration datatypeDeclaration) {
86 var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(datatypeDeclaration);
87 if (qualifiedName == null) {
88 throw new IllegalArgumentException("Datatype declaration has no qualified name: " + datatypeDeclaration);
89 }
90 return new DataExprType(qualifiedName);
91 }
92
93 public AggregatorName getAggregatorName(AggregatorDeclaration aggregatorDeclaration) {
94 var dataTypes = cache.get(AGGREGATOR_CACHE, aggregatorDeclaration.eResource(),
95 () -> new HashMap<AggregatorDeclaration, AggregatorName>());
96 return dataTypes.computeIfAbsent(aggregatorDeclaration, this::computeAggregatorName);
97 }
98
99 private AggregatorName computeAggregatorName(AggregatorDeclaration aggregatorDeclaration) {
100 var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(aggregatorDeclaration);
101 if (qualifiedName == null) {
102 throw new IllegalArgumentException(
103 "Aggregator declaration has no qualified name: " + aggregatorDeclaration);
104 }
105 return new AggregatorName(qualifiedName);
106 }
107}