diff options
Diffstat (limited to 'subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java')
-rw-r--r-- | subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java | 255 |
1 files changed, 0 insertions, 255 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java b/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java deleted file mode 100644 index a4ea1113..00000000 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java +++ /dev/null | |||
@@ -1,255 +0,0 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.utils; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import org.eclipse.emf.ecore.EObject; | ||
10 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
11 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | ||
12 | import tools.refinery.language.model.problem.*; | ||
13 | |||
14 | import java.util.LinkedHashMap; | ||
15 | import java.util.List; | ||
16 | import java.util.Map; | ||
17 | |||
18 | class SymbolCollector { | ||
19 | @Inject | ||
20 | private IQualifiedNameProvider qualifiedNameProvider; | ||
21 | |||
22 | @Inject | ||
23 | private IQualifiedNameConverter qualifiedNameConverter; | ||
24 | |||
25 | @Inject | ||
26 | private ProblemDesugarer desugarer; | ||
27 | |||
28 | private BuiltinSymbols builtinSymbols; | ||
29 | |||
30 | private final Map<Node, NodeInfo> nodes = new LinkedHashMap<>(); | ||
31 | |||
32 | private final Map<Relation, RelationInfo> relations = new LinkedHashMap<>(); | ||
33 | |||
34 | public CollectedSymbols collectSymbols(Problem problem) { | ||
35 | builtinSymbols = desugarer.getBuiltinSymbols(problem).orElseThrow(() -> new IllegalArgumentException( | ||
36 | "Problem has no associated built-in library")); | ||
37 | collectOwnSymbols(builtinSymbols.problem()); | ||
38 | collectOwnSymbols(problem); | ||
39 | return new CollectedSymbols(nodes, relations); | ||
40 | } | ||
41 | |||
42 | public void collectOwnSymbols(Problem problem) { | ||
43 | collectOwnRelations(problem); | ||
44 | collectOwnNodes(problem); | ||
45 | collectOwnAssertions(problem); | ||
46 | } | ||
47 | |||
48 | private void collectOwnRelations(Problem problem) { | ||
49 | for (var statement : problem.getStatements()) { | ||
50 | if (statement instanceof PredicateDefinition predicateDefinition) { | ||
51 | collectPredicate(predicateDefinition); | ||
52 | } else if (statement instanceof ClassDeclaration classDeclaration) { | ||
53 | collectClass(classDeclaration); | ||
54 | } else if (statement instanceof EnumDeclaration enumDeclaration) { | ||
55 | collectEnum(enumDeclaration); | ||
56 | } else if (statement instanceof RuleDefinition) { | ||
57 | throw new UnsupportedOperationException("Rules are not currently supported"); | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | |||
62 | private void collectPredicate(PredicateDefinition predicateDefinition) { | ||
63 | var predicateKind = predicateDefinition.getKind(); | ||
64 | var info = new RelationInfo(getQualifiedNameString(predicateDefinition), | ||
65 | ContainmentRole.fromPredicateKind(predicateKind), predicateDefinition.getParameters(), null, null, | ||
66 | predicateDefinition.getBodies()); | ||
67 | relations.put(predicateDefinition, info); | ||
68 | } | ||
69 | |||
70 | private void collectClass(ClassDeclaration classDeclaration) { | ||
71 | var contained = classDeclaration != builtinSymbols.node(); | ||
72 | var containmentRole = contained ? ContainmentRole.CONTAINED : ContainmentRole.NONE; | ||
73 | var instanceParameter = ProblemFactory.eINSTANCE.createParameter(); | ||
74 | instanceParameter.setName("instance"); | ||
75 | var classInfo = new RelationInfo(getQualifiedNameString(classDeclaration), containmentRole, | ||
76 | List.of(instanceParameter), null, null, List.of()); | ||
77 | relations.put(classDeclaration, classInfo); | ||
78 | collectFeatures(classDeclaration); | ||
79 | } | ||
80 | |||
81 | private void collectFeatures(ClassDeclaration classDeclaration) { | ||
82 | for (var featureDeclaration : classDeclaration.getFeatureDeclarations()) { | ||
83 | if (featureDeclaration instanceof ReferenceDeclaration referenceDeclaration) { | ||
84 | collectReference(classDeclaration, referenceDeclaration); | ||
85 | } else if (featureDeclaration instanceof AttributeDeclaration attributeDeclaration) { | ||
86 | collectAttribute(classDeclaration, attributeDeclaration); | ||
87 | } else if (featureDeclaration instanceof FlagDeclaration flagDeclaration) { | ||
88 | collectFlag(classDeclaration, flagDeclaration); | ||
89 | } else { | ||
90 | throw new IllegalArgumentException("Unknown FeatureDeclaration: " + featureDeclaration); | ||
91 | } | ||
92 | } | ||
93 | } | ||
94 | |||
95 | private void collectReference(ClassDeclaration classDeclaration, ReferenceDeclaration referenceDeclaration) { | ||
96 | var referenceRole = desugarer.isContainmentReference(referenceDeclaration) ? | ||
97 | ContainmentRole.CONTAINMENT : | ||
98 | ContainmentRole.NONE; | ||
99 | var sourceParameter = ProblemFactory.eINSTANCE.createParameter(); | ||
100 | sourceParameter.setName("source"); | ||
101 | sourceParameter.setParameterType(classDeclaration); | ||
102 | var targetParameter = ProblemFactory.eINSTANCE.createParameter(); | ||
103 | targetParameter.setName("target"); | ||
104 | var multiplicity = referenceDeclaration.getMultiplicity(); | ||
105 | if (multiplicity == null) { | ||
106 | var exactMultiplicity = ProblemFactory.eINSTANCE.createExactMultiplicity(); | ||
107 | exactMultiplicity.setExactValue(1); | ||
108 | multiplicity = exactMultiplicity; | ||
109 | } | ||
110 | targetParameter.setParameterType(referenceDeclaration.getReferenceType()); | ||
111 | var referenceInfo = new RelationInfo(getQualifiedNameString(referenceDeclaration), referenceRole, | ||
112 | List.of(sourceParameter, targetParameter), multiplicity, referenceDeclaration.getOpposite(), | ||
113 | List.of()); | ||
114 | this.relations.put(referenceDeclaration, referenceInfo); | ||
115 | } | ||
116 | |||
117 | private void collectAttribute(ClassDeclaration classDeclaration, AttributeDeclaration attributeDeclaration) { | ||
118 | // TODO Implement attribute handling. | ||
119 | } | ||
120 | |||
121 | private void collectFlag(ClassDeclaration classDeclaration, FlagDeclaration flagDeclaration) { | ||
122 | var parameter = ProblemFactory.eINSTANCE.createParameter(); | ||
123 | parameter.setName("object"); | ||
124 | parameter.setParameterType(classDeclaration); | ||
125 | var referenceInfo = new RelationInfo(getQualifiedNameString(flagDeclaration), ContainmentRole.NONE, | ||
126 | List.of(parameter), null, null, List.of()); | ||
127 | this.relations.put(flagDeclaration, referenceInfo); | ||
128 | } | ||
129 | |||
130 | private void collectEnum(EnumDeclaration enumDeclaration) { | ||
131 | var instanceParameter = ProblemFactory.eINSTANCE.createParameter(); | ||
132 | instanceParameter.setName("instance"); | ||
133 | var info = new RelationInfo(getQualifiedNameString(enumDeclaration), ContainmentRole.NONE, | ||
134 | List.of(instanceParameter), null, null, List.of()); | ||
135 | this.relations.put(enumDeclaration, info); | ||
136 | } | ||
137 | |||
138 | private void collectOwnNodes(Problem problem) { | ||
139 | for (var statement : problem.getStatements()) { | ||
140 | if (statement instanceof IndividualDeclaration individualDeclaration) { | ||
141 | collectIndividuals(individualDeclaration); | ||
142 | } else if (statement instanceof ClassDeclaration classDeclaration) { | ||
143 | collectNewNode(classDeclaration); | ||
144 | } else if (statement instanceof EnumDeclaration enumDeclaration) { | ||
145 | collectEnumLiterals(enumDeclaration); | ||
146 | } | ||
147 | } | ||
148 | for (var node : problem.getNodes()) { | ||
149 | addNode(node, false); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | private void collectIndividuals(IndividualDeclaration individualDeclaration) { | ||
154 | for (var individual : individualDeclaration.getNodes()) { | ||
155 | addNode(individual, true); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | private void collectNewNode(ClassDeclaration classDeclaration) { | ||
160 | var newNode = classDeclaration.getNewNode(); | ||
161 | if (newNode != null) { | ||
162 | addNode(newNode, false); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | private void collectEnumLiterals(EnumDeclaration enumDeclaration) { | ||
167 | for (var literal : enumDeclaration.getLiterals()) { | ||
168 | addNode(literal, true); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | private void addNode(Node node, boolean individual) { | ||
173 | var info = new NodeInfo(getQualifiedNameString(node), individual); | ||
174 | this.nodes.put(node, info); | ||
175 | } | ||
176 | |||
177 | private String getQualifiedNameString(EObject eObject) { | ||
178 | var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(eObject); | ||
179 | if (qualifiedName == null) { | ||
180 | return null; | ||
181 | } | ||
182 | return qualifiedNameConverter.toString(qualifiedName); | ||
183 | } | ||
184 | |||
185 | private void collectOwnAssertions(Problem problem) { | ||
186 | for (var statement : problem.getStatements()) { | ||
187 | if (statement instanceof Assertion assertion) { | ||
188 | collectAssertion(assertion); | ||
189 | } else if (statement instanceof PredicateDefinition predicateDefinition) { | ||
190 | collectPredicateAssertion(predicateDefinition); | ||
191 | } else if (statement instanceof ClassDeclaration classDeclaration) { | ||
192 | collectClassAssertion(classDeclaration); | ||
193 | } else if (statement instanceof EnumDeclaration enumDeclaration) { | ||
194 | collectEnumAssertions(enumDeclaration); | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | private void collectAssertion(Assertion assertion) { | ||
200 | var relationInfo = this.relations.get(assertion.getRelation()); | ||
201 | if (relationInfo == null) { | ||
202 | throw new IllegalStateException("Assertion refers to unknown relation"); | ||
203 | } | ||
204 | if (assertion.getArguments().size() != relationInfo.parameters().size()) { | ||
205 | // Silently ignoring assertions of invalid arity helps when SymbolCollector is called on an invalid | ||
206 | // Problem during editing. The errors can still be detected by the Problem validator. | ||
207 | return; | ||
208 | } | ||
209 | relationInfo.assertions().add(assertion); | ||
210 | } | ||
211 | |||
212 | private void collectPredicateAssertion(PredicateDefinition predicateDefinition) { | ||
213 | if (predicateDefinition.getKind() != PredicateKind.ERROR) { | ||
214 | return; | ||
215 | } | ||
216 | int arity = predicateDefinition.getParameters().size(); | ||
217 | addAssertion(predicateDefinition, LogicValue.FALSE, new Node[arity]); | ||
218 | } | ||
219 | |||
220 | private void collectClassAssertion(ClassDeclaration classDeclaration) { | ||
221 | var node = classDeclaration.getNewNode(); | ||
222 | if (node == null) { | ||
223 | return; | ||
224 | } | ||
225 | addAssertion(classDeclaration, LogicValue.TRUE, node); | ||
226 | addAssertion(builtinSymbols.exists(), LogicValue.UNKNOWN, node); | ||
227 | addAssertion(builtinSymbols.equals(), LogicValue.UNKNOWN, node, node); | ||
228 | } | ||
229 | |||
230 | private void collectEnumAssertions(EnumDeclaration enumDeclaration) { | ||
231 | for (var literal : enumDeclaration.getLiterals()) { | ||
232 | addAssertion(enumDeclaration, LogicValue.TRUE, literal); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | private void addAssertion(Relation relation, LogicValue logicValue, Node... nodes) { | ||
237 | var assertion = ProblemFactory.eINSTANCE.createAssertion(); | ||
238 | assertion.setRelation(relation); | ||
239 | for (var node : nodes) { | ||
240 | AssertionArgument argument; | ||
241 | if (node == null) { | ||
242 | argument = ProblemFactory.eINSTANCE.createWildcardAssertionArgument(); | ||
243 | } else { | ||
244 | var nodeArgument = ProblemFactory.eINSTANCE.createNodeAssertionArgument(); | ||
245 | nodeArgument.setNode(node); | ||
246 | argument = nodeArgument; | ||
247 | } | ||
248 | assertion.getArguments().add(argument); | ||
249 | } | ||
250 | var value = ProblemFactory.eINSTANCE.createLogicConstant(); | ||
251 | value.setLogicValue(logicValue); | ||
252 | assertion.setValue(value); | ||
253 | collectAssertion(assertion); | ||
254 | } | ||
255 | } | ||