1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package io.github.tonywasher.joceanus.themis.solver.mapper;
19
20 import io.github.tonywasher.joceanus.oceanus.base.OceanusException;
21 import io.github.tonywasher.joceanus.themis.exc.ThemisDataException;
22 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance;
23 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisClassInstance;
24 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisDeclarationInstance;
25 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisId;
26 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisNodeInstance;
27 import io.github.tonywasher.joceanus.themis.parser.base.ThemisInstance.ThemisTypeInstance;
28 import io.github.tonywasher.joceanus.themis.parser.base.ThemisModifierList;
29 import io.github.tonywasher.joceanus.themis.parser.decl.ThemisDeclEnum;
30 import io.github.tonywasher.joceanus.themis.parser.decl.ThemisDeclEnumValue;
31 import io.github.tonywasher.joceanus.themis.parser.decl.ThemisDeclField;
32 import io.github.tonywasher.joceanus.themis.parser.decl.ThemisDeclaration;
33 import io.github.tonywasher.joceanus.themis.parser.expr.ThemisExprTypePattern;
34 import io.github.tonywasher.joceanus.themis.parser.node.ThemisNodeParameter;
35 import io.github.tonywasher.joceanus.themis.parser.node.ThemisNodeVariable;
36 import io.github.tonywasher.joceanus.themis.parser.stmt.ThemisStatement;
37 import io.github.tonywasher.joceanus.themis.parser.type.ThemisTypeClassInterface;
38 import io.github.tonywasher.joceanus.themis.solver.reflect.ThemisReflectExternal;
39
40 import java.util.ArrayDeque;
41 import java.util.Deque;
42 import java.util.HashMap;
43 import java.util.Map;
44
45
46
47
48 public class ThemisMapperNameState {
49
50
51
52 private final Deque<ThemisMapperNameMap> theStack;
53
54
55
56
57 private ThemisMapperNameMap theName;
58
59
60
61
62 ThemisMapperNameState() {
63
64 theStack = new ArrayDeque<>();
65
66
67 theName = new ThemisMapperNameMap();
68 }
69
70
71
72
73 void reset() {
74 theStack.clear();
75 theName = new ThemisMapperNameMap();
76 }
77
78
79
80
81
82
83
84
85 boolean processInstance(final ThemisInstance pInstance) throws OceanusException {
86
87 final boolean doBump = bumpStack(pInstance);
88 if (doBump) {
89 bumpStack();
90 }
91
92
93 if (pInstance instanceof ThemisClassInstance myClass) {
94 processClass(myClass);
95 }
96 if (pInstance instanceof ThemisDeclEnum myEnum) {
97 return processEnum(myEnum);
98 }
99 if (pInstance instanceof ThemisNodeVariable myVar) {
100 return processVariable(myVar);
101 }
102 if (pInstance instanceof ThemisNodeParameter myParam) {
103 return processParameter(myParam);
104 }
105 if (pInstance instanceof ThemisExprTypePattern myPattern) {
106 return processPattern(myPattern);
107 }
108
109
110 return doBump;
111 }
112
113
114
115
116 private void bumpStack() {
117 theStack.push(theName);
118 theName = new ThemisMapperNameMap(theName);
119 }
120
121
122
123
124 void cleanUpAfterInstance() {
125 theName = theStack.pop();
126 }
127
128
129
130
131
132
133
134 ThemisTypeInstance lookUpName(final String pName) {
135 return theName.lookUpName(pName);
136 }
137
138
139
140
141
142
143
144 private boolean processEnum(final ThemisDeclEnum pElement) {
145 final ThemisMapperTypeRef myRef = new ThemisMapperTypeRef(pElement);
146 for (ThemisDeclarationInstance myInstance : pElement.getValues()) {
147 final ThemisDeclEnumValue myValue = (ThemisDeclEnumValue) myInstance;
148 theName.declareEnum(myRef, myValue);
149 }
150 return false;
151 }
152
153
154
155
156
157
158
159 private boolean processVariable(final ThemisNodeVariable pElement) {
160 theName.declareVariable(pElement);
161 return false;
162 }
163
164
165
166
167
168
169
170 private boolean processParameter(final ThemisNodeParameter pElement) {
171 theName.declareParameter(pElement);
172 return false;
173 }
174
175
176
177
178
179
180
181 private boolean processPattern(final ThemisExprTypePattern pElement) {
182 theName.declarePattern(pElement);
183 return false;
184 }
185
186
187
188
189
190
191
192 private void processClass(final ThemisClassInstance pClass) throws OceanusException {
193 for (ThemisTypeInstance myClass : pClass.getExtends()) {
194 final ThemisTypeClassInterface myExtend = (ThemisTypeClassInterface) myClass;
195 ThemisClassInstance myClassInstance = myExtend.getClassInstance();
196 if (myClassInstance instanceof ThemisReflectExternal myExternal) {
197 myClassInstance = myExternal.getClassInstance();
198 }
199 if (myClassInstance == null) {
200 throw new ThemisDataException("Class Instance not found: " + pClass.getFullName());
201 }
202
203
204 for (ThemisInstance myChild : myClassInstance.getBody()) {
205 if (myChild instanceof ThemisDeclField myField) {
206 processField(myField);
207 }
208 }
209
210
211 processClass(myClassInstance);
212 }
213 }
214
215
216
217
218
219
220 private void processField(final ThemisDeclField pField) {
221
222 final ThemisModifierList myModifiers = pField.getModifiers();
223 if (myModifiers.isProtected() || myModifiers.isPublic()) {
224 for (ThemisNodeInstance myVarNode : pField.getVariables()) {
225 final ThemisNodeVariable myVar = (ThemisNodeVariable) myVarNode;
226 processVariable(myVar);
227 }
228 }
229 }
230
231
232
233
234
235
236
237 private boolean bumpStack(final ThemisInstance pInstance) {
238
239 final ThemisId myId = pInstance.getId();
240 if (myId instanceof ThemisDeclaration myDeclType) {
241 return bumpStack(myDeclType);
242 }
243 if (myId instanceof ThemisStatement myStmtType) {
244 return bumpStack(myStmtType);
245 }
246 return false;
247 }
248
249
250
251
252
253
254
255 private boolean bumpStack(final ThemisDeclaration pDeclType) {
256 return switch (pDeclType) {
257 case CLASSINTERFACE, ENUM, RECORD, METHOD, CONSTRUCTOR -> true;
258 default -> false;
259 };
260 }
261
262
263
264
265
266
267
268 private boolean bumpStack(final ThemisStatement pStmtType) {
269 return switch (pStmtType) {
270 case BLOCK, FOR, FOREACH, TRY -> true;
271 default -> false;
272 };
273 }
274
275
276
277
278 private static class ThemisMapperNameMap {
279
280
281
282 private final ThemisMapperNameMap theParent;
283
284
285
286
287 private final Map<String, ThemisTypeInstance> theNames;
288
289
290
291
292 ThemisMapperNameMap() {
293 this(null);
294 }
295
296
297
298
299
300
301 ThemisMapperNameMap(final ThemisMapperNameMap pParent) {
302 theParent = pParent;
303 theNames = new HashMap<>();
304 }
305
306
307
308
309
310
311
312 void declareEnum(final ThemisMapperTypeRef pRef,
313 final ThemisDeclEnumValue pEnum) {
314 theNames.put(pEnum.getName().toString(), pRef);
315 }
316
317
318
319
320
321
322 void declareVariable(final ThemisNodeVariable pVar) {
323 theNames.put(pVar.getName().toString(), pVar.getType());
324 }
325
326
327
328
329
330
331 void declareParameter(final ThemisNodeParameter pParam) {
332 theNames.put(pParam.getName().toString(), pParam.getType());
333 }
334
335
336
337
338
339
340 void declarePattern(final ThemisExprTypePattern pPattern) {
341 theNames.put(pPattern.getName().toString(), pPattern.getType());
342 }
343
344
345
346
347
348
349
350 ThemisTypeInstance lookUpName(final String pName) {
351
352 final ThemisTypeInstance myType = theNames.get(pName);
353 if (myType != null) {
354 return myType;
355 }
356
357
358 return theParent == null ? null : theParent.lookUpName(pName);
359 }
360 }
361 }