diff options
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.java | 107 |
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 | */ | ||
6 | package tools.refinery.language.typesystem; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import com.google.inject.Singleton; | ||
10 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | ||
11 | import org.eclipse.xtext.util.IResourceScopeCache; | ||
12 | import tools.refinery.language.model.problem.*; | ||
13 | |||
14 | import java.util.ArrayList; | ||
15 | import java.util.HashMap; | ||
16 | import java.util.List; | ||
17 | |||
18 | @Singleton | ||
19 | public 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 | } | ||