Package: NameFinder$Newquestion

NameFinder$Newquestion

nameinstructionbranchcomplexitylinemethod
NameFinder.Newquestion(ILexNameToken, NameScope)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * #%~
3: * The VDM Type Checker
4: * %%
5: * Copyright (C) 2008 - 2014 Overture
6: * %%
7: * This program is free software: you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation, either version 3 of the
10: * License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program. If not, see
19: * <http://www.gnu.org/licenses/gpl-3.0.html>.
20: * #~%
21: */
22: package org.overture.typechecker.utilities;
23:
24: import java.util.List;
25:
26: import org.overture.ast.analysis.AnalysisException;
27: import org.overture.ast.analysis.QuestionAnswerAdaptor;
28: import org.overture.ast.definitions.AEqualsDefinition;
29: import org.overture.ast.definitions.AExplicitFunctionDefinition;
30: import org.overture.ast.definitions.AExplicitOperationDefinition;
31: import org.overture.ast.definitions.AExternalDefinition;
32: import org.overture.ast.definitions.AImplicitFunctionDefinition;
33: import org.overture.ast.definitions.AImplicitOperationDefinition;
34: import org.overture.ast.definitions.AImportedDefinition;
35: import org.overture.ast.definitions.AInheritedDefinition;
36: import org.overture.ast.definitions.AInstanceVariableDefinition;
37: import org.overture.ast.definitions.AMultiBindListDefinition;
38: import org.overture.ast.definitions.AMutexSyncDefinition;
39: import org.overture.ast.definitions.APerSyncDefinition;
40: import org.overture.ast.definitions.ARenamedDefinition;
41: import org.overture.ast.definitions.AStateDefinition;
42: import org.overture.ast.definitions.AThreadDefinition;
43: import org.overture.ast.definitions.ATypeDefinition;
44: import org.overture.ast.definitions.AValueDefinition;
45: import org.overture.ast.definitions.PDefinition;
46: import org.overture.ast.definitions.SClassDefinition;
47: import org.overture.ast.intf.lex.ILexNameToken;
48: import org.overture.ast.lex.Dialect;
49: import org.overture.ast.node.INode;
50: import org.overture.ast.typechecker.NameScope;
51: import org.overture.config.Release;
52: import org.overture.config.Settings;
53: import org.overture.typechecker.TypeCheckerErrors;
54: import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
55:
56: /**
57: * This class implements a way to find type from a node in the AST
58: *
59: * @author kel
60: */
61: public class NameFinder extends
62:                 QuestionAnswerAdaptor<NameFinder.Newquestion, PDefinition>
63: {
64:         public static class Newquestion
65:         {
66:                 public final ILexNameToken sought;
67:                 public final NameScope scope;
68:
69:                 public Newquestion(ILexNameToken sought, NameScope scope)
70:                 {
71:                         this.scope = scope;
72:                         this.sought = sought;
73:                 }
74:
75:         }
76:
77:         protected ITypeCheckerAssistantFactory af;
78:
79:         public NameFinder(ITypeCheckerAssistantFactory af)
80:         {
81:                 this.af = af;
82:         }
83:
84:         @Override
85:         public PDefinition defaultSClassDefinition(SClassDefinition node,
86:                         Newquestion question) throws AnalysisException
87:         {
88:                 PDefinition def = null;
89:
90:                 for (PDefinition d : node.getDefinitions())
91:                 {
92:                         PDefinition found = d.apply(this, question);// PDefinitionAssistantTC.findName(d, question.sought,
93:                                                                                                                 // question.scope);
94:
95:                         // It is possible to have an ambiguous name if the name has
96:                         // type qualifiers that are a union of types that match several
97:                         // overloaded functions/ops (even though they themselves are
98:                         // distinguishable).
99:
100:                         if (found != null)
101:                         {
102:                                 if (def == null)
103:                                 {
104:                                         def = found;
105:
106:                                         if (question.sought.getTypeQualifier() == null)
107:                                         {
108:                                                 break; // Can't be ambiguous
109:                                         }
110:                                 } else
111:                                 {
112:                                         if (!def.getLocation().equals(found.getLocation())
113:                                                         && af.createPDefinitionAssistant().isFunctionOrOperation(def))
114:                                         {
115:                                                 TypeCheckerErrors.report(3010, "Name "
116:                                                                 + question.sought + " is ambiguous", question.sought.getLocation(), question.sought);
117:                                                 TypeCheckerErrors.detail2("1", def.getLocation(), "2", found.getLocation());
118:                                                 break;
119:                                         }
120:                                 }
121:                         }
122:                 }
123:
124:                 if (def == null)
125:                 {
126:                         for (PDefinition d : node.getAllInheritedDefinitions())
127:                         {
128:                                 PDefinition indef = d.apply(this, question);// PDefinitionAssistantTC.findName(d, question.sought,
129:                                                                                                                         // question.scope);
130:
131:                                 // See above for the following...
132:
133:                                 if (indef != null)
134:                                 {
135:                                         if (def == null)
136:                                         {
137:                                                 def = indef;
138:
139:                                                 if (question.sought.getTypeQualifier() == null)
140:                                                 {
141:                                                         break; // Can't be ambiguous
142:                                                 }
143:                                         } else if (def.equals(indef)
144:                                                         && // Compares qualified names
145:                                                         !def.getLocation().equals(indef.getLocation())
146:                                                         && !af.createPDefinitionAssistant().hasSupertype(def.getClassDefinition(), indef.getClassDefinition().getType())
147:                                                         && af.createPDefinitionAssistant().isFunctionOrOperation(def))
148:                                         {
149:                                                 TypeCheckerErrors.report(3011, "Name "
150:                                                                 + question.sought
151:                                                                 + " is multiply defined in class", question.sought.getLocation(), question.sought);
152:                                                 TypeCheckerErrors.detail2("1", def.getLocation(), "2", indef.getLocation());
153:                                                 break;
154:                                         }
155:                                 }
156:                         }
157:                 }
158:
159:                 return def;
160:         }
161:
162:         @Override
163:         public PDefinition caseAEqualsDefinition(AEqualsDefinition node,
164:                         Newquestion question) throws AnalysisException
165:         {
166:                 List<PDefinition> defs = node.getDefs();
167:
168:                 if (defs != null)
169:                 {
170:                         PDefinition def = af.createPDefinitionListAssistant().findName(defs, question.sought, question.scope);
171:
172:                         if (def != null)
173:                         {
174:                                 return def;
175:                         }
176:                 }
177:                 return null;
178:         }
179:
180:         @Override
181:         public PDefinition caseAExplicitFunctionDefinition(
182:                         AExplicitFunctionDefinition node, Newquestion question)
183:                         throws AnalysisException
184:         {
185:                 if (af.createPDefinitionAssistant().findNameBaseCase(node, question.sought, question.scope) != null)
186:                 {
187:                         return node;
188:                 }
189:
190:                 PDefinition predef = node.getPredef();
191:                 if (predef != null && predef.apply(this, question) != null)// PDefinitionAssistantTC.findName(predef, sought,
192:                                                                                                                                         // scope) != null)
193:                 {
194:                         return predef;
195:                 }
196:
197:                 PDefinition postdef = node.getPostdef();
198:                 if (postdef != null && postdef.apply(this, question) != null)// PDefinitionAssistantTC.findName(postdef, sought,
199:                                                                                                                                                 // scope) != null)
200:                 {
201:                         return postdef;
202:                 }
203:                 
204:                 PDefinition measureDef = node.getMeasureDef();
205:                 if (measureDef != null && measureDef.apply(this, question) != null)
206:                 {
207:                         return measureDef;
208:                 }
209:
210:                 return null;
211:         }
212:
213:         @Override
214:         public PDefinition caseAExplicitOperationDefinition(
215:                         AExplicitOperationDefinition node, Newquestion question)
216:                         throws AnalysisException
217:         {
218:                 if (af.createPDefinitionAssistant().findNameBaseCase(node, question.sought, question.scope) != null)
219:                 {
220:                         return node;
221:                 }
222:
223:                 if (Settings.dialect == Dialect.VDM_SL || Settings.release == Release.CLASSIC)
224:                 {
225:                 PDefinition predef = node.getPredef();
226:                 if (predef != null && predef.apply(this, question) != null)
227:                 {
228:                         return predef;
229:                 }
230:
231:                 PDefinition postdef = node.getPostdef();
232:                 if (postdef != null && postdef.apply(this, question) != null)
233:                 {
234:                         return postdef;
235:                 }
236:                 }
237:
238:                 return null;
239:         }
240:
241:         @Override
242:         public PDefinition caseAExternalDefinition(AExternalDefinition node,
243:                         Newquestion question) throws AnalysisException
244:         {
245:                 if (question.sought.getOld() && question.scope == NameScope.NAMESANDANYSTATE)
246:                 {
247:                         return question.sought.equals(node.getOldname()) ? node : null;
248:                 }
249:
250:                 // return question.sought.equals(node.getState().getName()) ? node : null;
251:                 return defaultPDefinition(node, question) != null ? node : null;
252:         }
253:
254:         @Override
255:         public PDefinition caseAImplicitFunctionDefinition(
256:                         AImplicitFunctionDefinition node, Newquestion question)
257:                         throws AnalysisException
258:         {
259:                 if (af.createPDefinitionAssistant().findNameBaseCase(node, question.sought, question.scope) != null)
260:                 {
261:                         return node;
262:                 }
263:
264:                 PDefinition predef = node.getPredef();
265:                 if (predef != null && predef.apply(this, question) != null)// PDefinitionAssistantTC.findName(predef, sought,
266:                                                                                                                                         // scope) != null)
267:                 {
268:                         return predef;
269:                 }
270:
271:                 PDefinition postdef = node.getPostdef();
272:                 if (postdef != null && postdef.apply(this, question) != null) // PDefinitionAssistantTC.findName(postdef,
273:                                                                                                                                                 // sought, scope) != null)
274:                 {
275:                         return postdef;
276:                 }
277:                 
278:                 PDefinition measureDef = node.getMeasureDef();
279:                 if (measureDef != null && measureDef.apply(this, question) != null)
280:                 {
281:                         return measureDef;
282:                 }
283:
284:                 return null;
285:         }
286:
287:         @Override
288:         public PDefinition caseAImplicitOperationDefinition(
289:                         AImplicitOperationDefinition node, Newquestion question)
290:                         throws AnalysisException
291:         {
292:                 if (af.createPDefinitionAssistant().findNameBaseCase(node, question.sought, question.scope) != null)
293:                 {
294:                         return node;
295:                 }
296:
297:                 if (Settings.dialect == Dialect.VDM_SL || Settings.release == Release.CLASSIC)
298:                 {
299:                 PDefinition predef = node.getPredef();
300:                 if (predef != null && predef.apply(this, question) != null)
301:                 {
302:                         return predef;
303:                 }
304:
305:                 PDefinition postdef = node.getPostdef();
306:                 if (postdef != null && postdef.apply(this, question) != null)
307:                 {
308:                         return postdef;
309:                 }
310:                 }
311:
312:                 return null;
313:         }
314:
315:         @Override
316:         public PDefinition caseAImportedDefinition(AImportedDefinition node,
317:                         Newquestion question) throws AnalysisException
318:         {
319:                 PDefinition def = node.getDef().apply(this, question);// PDefinitionAssistantTC.findName(d.getDef(), sought,
320:                                                                                                                                 // scope);
321:
322:                 if (def != null)
323:                 {
324:                         af.createPDefinitionAssistant().markUsed(node);
325:                 }
326:
327:                 return def;
328:         }
329:
330:         @Override
331:         public PDefinition caseAInheritedDefinition(AInheritedDefinition node,
332:                         Newquestion question) throws AnalysisException
333:         {
334:                 // The problem is, when the InheritedDefinition is created, we
335:                 // don't know its fully qualified name.
336:                 
337:                 if (node.getSuperdef() instanceof AInheritedDefinition)
338:                 {
339:                         node.getSuperdef().apply(this, question);
340:                 }
341:
342:                 ILexNameToken name = node.getName();
343:                 name.setTypeQualifier(node.getSuperdef().getName().getTypeQualifier());
344:
345:                 if (af.getLexNameTokenAssistant().isEqual(name, question.sought))
346:                 {
347:                         return node;
348:                 } else if (question.scope.matches(NameScope.OLDSTATE)
349:                                 && node.getOldname().equals(question.sought))
350:                 {
351:                         return node;
352:                 }
353:
354:                 return null;
355:         }
356:
357:         @Override
358:         public PDefinition caseAInstanceVariableDefinition(
359:                         AInstanceVariableDefinition node, Newquestion question)
360:                         throws AnalysisException
361:         {
362:                 PDefinition found = af.createPDefinitionAssistant().findNameBaseCase(node, question.sought, question.scope);
363:                 if (found != null)
364:                 {
365:                         return found;
366:                 }
367:                 return question.scope.matches(NameScope.OLDSTATE)
368:                                 && node.getOldname().equals(question.sought) ? node : null;
369:         }
370:
371:         @Override
372:         public PDefinition caseAMultiBindListDefinition(
373:                         AMultiBindListDefinition node, Newquestion question)
374:                         throws AnalysisException
375:         {
376:                 if (node.getDefs() != null)
377:                 {
378:                         PDefinition def = af.createPDefinitionListAssistant().findName(node.getDefs(), question.sought, question.scope);
379:
380:                         if (def != null)
381:                         {
382:                                 return def;
383:                         }
384:                 }
385:
386:                 return null;
387:         }
388:
389:         @Override
390:         public PDefinition caseAMutexSyncDefinition(AMutexSyncDefinition node,
391:                         Newquestion question) throws AnalysisException
392:         {
393:                 return null;
394:         }
395:
396:         @Override
397:         public PDefinition caseAPerSyncDefinition(APerSyncDefinition node,
398:                         Newquestion question) throws AnalysisException
399:         {
400:                 return null;
401:         }
402:
403:         @Override
404:         public PDefinition caseARenamedDefinition(ARenamedDefinition node,
405:                         Newquestion question) throws AnalysisException
406:         {
407:                 PDefinition renamed = af.createPDefinitionAssistant().findNameBaseCase(node, question.sought, question.scope);
408:
409:                 if (renamed != null)
410:                 {
411:                         af.createPDefinitionAssistant().markUsed(node.getDef());
412:                         return renamed;
413:                 } else
414:                 {
415:                         // Renamed definitions hide the original name
416:                         return null;// PDefinitionAssistantTC.findName(d.getDef(),sought, scope);
417:                 }
418:         }
419:
420:         @Override
421:         public PDefinition caseAStateDefinition(AStateDefinition node,
422:                         Newquestion question) throws AnalysisException
423:         {
424:                 if (question.scope.matches(NameScope.NAMES))
425:                 {
426:                         PDefinition invdef = node.getInvdef();
427:
428:                         if (invdef != null && invdef.apply(this, question) != null)// PDefinitionAssistantTC.findName(invdef,
429:                                                                                                                                                 // sought, scope) != null)
430:                         {
431:                                 return invdef;
432:                         }
433:
434:                         PDefinition initdef = node.getInitdef();
435:                         if (initdef != null && initdef.apply(this, question) != null)// PDefinitionAssistantTC.findName(initdef,
436:                                                                                                                                                         // sought, scope) != null)
437:                         {
438:                                 return initdef;
439:                         }
440:                 }
441:
442:                 // if ( PDefinitionAssistantTC.findName(definition.getRecordDefinition(), sought, scope) != null)
443:                 // {
444:                 // return definition.getRecordDefinition();
445:                 // }
446:
447:                 for (PDefinition d : node.getStateDefs())
448:                 {
449:                         PDefinition def = d.apply(this, question);// PDefinitionAssistantTC.findName(d, sought, scope);
450:
451:                         if (def != null)
452:                         {
453:                                 return def;
454:                         }
455:                 }
456:
457:                 return null;
458:         }
459:
460:         @Override
461:         public PDefinition caseAThreadDefinition(AThreadDefinition node,
462:                         Newquestion question) throws AnalysisException
463:         {
464:                 return node.getOperationDef().apply(this, question); // PDefinitionAssistantTC.findName(definition.getOperationDef(),
465:                                                                                                                                 // sought, scope);
466:         }
467:
468:         @Override
469:         public PDefinition caseATypeDefinition(ATypeDefinition node,
470:                                                                                  Newquestion question) throws AnalysisException
471:         {
472:                 PDefinition invdef = node.getInvdef();
473:
474:                 if (invdef != null && invdef.apply(this, question) != null)// PDefinitionAssistantTC.findName(invdef, sought,
475:                 // scope) != null)
476:                 {
477:                         return invdef;
478:                 }
479:
480:                 PDefinition eqdef = node.getEqRelation() == null ? null : node.getEqRelation().getRelDef();
481:
482:                 if (eqdef != null && eqdef.apply(this, question) != null)
483:                 {
484:                         return eqdef;
485:                 }
486:
487:                 PDefinition orddef = node.getOrdRelation() == null ? null : node.getOrdRelation().getRelDef();
488:
489:                 if (orddef != null && orddef.apply(this, question) != null)
490:                 {
491:                         return orddef;
492:                 }
493:
494:                 PDefinition mindef = node.getOrdRelation() == null ? null : node.getOrdRelation().getMinDef();
495:
496:                 if (mindef != null && mindef.apply(this, question) != null)
497:                 {
498:                         return mindef;
499:                 }
500:
501:                 PDefinition maxdef = node.getOrdRelation() == null ? null : node.getOrdRelation().getMaxDef();
502:
503:                 if (maxdef != null && maxdef.apply(this, question) != null)
504:                 {
505:                         return maxdef;
506:                 }
507:
508:                 return null;
509:         }
510:
511:         @Override
512:         public PDefinition caseAValueDefinition(AValueDefinition node,
513:                         Newquestion question) throws AnalysisException
514:         {
515:                 return af.createPDefinitionListAssistant().findName(node.getDefs(), question.sought, question.scope);
516:         }
517:
518:         // @Override
519:         // public PDefinition caseAClassType(AClassType node, Newquestion question)
520:         // throws AnalysisException
521:         // {
522:         // return node.apply(THIS, question);
523:         // }
524:
525:         @Override
526:         public PDefinition defaultPDefinition(PDefinition node, Newquestion question)
527:                         throws AnalysisException
528:         {
529:                 return af.createPDefinitionAssistant().findNameBaseCase(node, question.sought, question.scope);
530:         }
531:
532:         @Override
533:         public PDefinition createNewReturnValue(INode node, Newquestion question)
534:         {
535:                 assert false : "should not happen";
536:                 return null;
537:         }
538:
539:         @Override
540:         public PDefinition createNewReturnValue(Object node, Newquestion question)
541:         {
542:                 assert false : "should not happen";
543:                 return null;
544:         }
545: }