Package: AbstractTypeCheckVisitor$1

AbstractTypeCheckVisitor$1

nameinstructionbranchcomplexitylinemethod
getKey()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getValue()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
setValue(AMultiBindListDefinition)
M: 2 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
{...}
M: 0 C: 12
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
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.visitor;
23:
24: import java.util.LinkedList;
25: import java.util.List;
26: import java.util.Map;
27: import java.util.Vector;
28:
29: import org.overture.ast.analysis.AnalysisException;
30: import org.overture.ast.analysis.QuestionAnswerAdaptor;
31: import org.overture.ast.analysis.intf.IQuestionAnswer;
32: import org.overture.ast.annotations.PAnnotation;
33: import org.overture.ast.definitions.AExplicitFunctionDefinition;
34: import org.overture.ast.definitions.AMultiBindListDefinition;
35: import org.overture.ast.definitions.PDefinition;
36: import org.overture.ast.definitions.SClassDefinition;
37: import org.overture.ast.expressions.PExp;
38: import org.overture.ast.factory.AstFactory;
39: import org.overture.ast.intf.lex.ILexLocation;
40: import org.overture.ast.modules.AModuleModules;
41: import org.overture.ast.node.INode;
42: import org.overture.ast.patterns.PMultipleBind;
43: import org.overture.ast.statements.PStm;
44: import org.overture.ast.typechecker.NameScope;
45: import org.overture.ast.types.ABooleanBasicType;
46: import org.overture.ast.types.PType;
47: import org.overture.ast.util.PTypeSet;
48: import org.overture.config.Settings;
49: import org.overture.typechecker.Environment;
50: import org.overture.typechecker.FlatCheckedEnvironment;
51: import org.overture.typechecker.FlatEnvironment;
52: import org.overture.typechecker.TypeCheckInfo;
53: import org.overture.typechecker.TypeCheckerErrors;
54: import org.overture.typechecker.annotations.TCAnnotation;
55: import org.overture.typechecker.utilities.type.QualifiedDefinition;
56:
57: public class AbstractTypeCheckVisitor extends
58:                 QuestionAnswerAdaptor<TypeCheckInfo, PType>
59: {
60:
61:         public AbstractTypeCheckVisitor(
62:                         IQuestionAnswer<TypeCheckInfo, PType> visitor)
63:         {
64:                 super(visitor);
65:         }
66:
67:         public AbstractTypeCheckVisitor()
68:         {
69:                 super();
70:         }
71:
72:         @Override
73:         public PType createNewReturnValue(INode node, TypeCheckInfo question)
74:         {
75:                 return null;
76:         }
77:
78:         @Override
79:         public PType createNewReturnValue(Object node, TypeCheckInfo question)
80:         {
81:                 return null;
82:         }
83:
84:         @Override
85:         public PType defaultINode(INode node, TypeCheckInfo question)
86:                         throws AnalysisException
87:         {
88:                 return THIS.defaultINode(node, question);
89:         }
90:
91:         protected PType typeCheckIf(ILexLocation ifLocation, PExp testExp,
92:                         INode thenNode, List<? extends INode> elseIfNodeList,
93:                         INode elseNode, TypeCheckInfo question) throws AnalysisException
94:         {
95:                 boolean isExpression = testExp.parent() instanceof PExp;
96:
97:                 question.qualifiers = null;
98:
99:                 PType test = testExp.apply(THIS, question.newConstraint(null));
100:
101:                 if (!question.assistantFactory.createPTypeAssistant().isType(test, ABooleanBasicType.class))
102:                 {
103:                         TypeCheckerErrors.report((isExpression ? 3108 : 3224), "If expression is not boolean", testExp.getLocation(), testExp);
104:                 }
105:
106:                 List<QualifiedDefinition> qualified = testExp.apply(question.assistantFactory.getQualificationVisitor(), question);
107:
108:                 for (QualifiedDefinition qdef : qualified)
109:                 {
110:                         qdef.qualifyType();
111:                 }
112:
113:                 PTypeSet rtypes = new PTypeSet(question.assistantFactory);
114:                 question.qualifiers = null;
115:                 rtypes.add(thenNode.apply(THIS, question));
116:
117:                 for (QualifiedDefinition qdef : qualified)
118:                 {
119:                         qdef.resetType();
120:                 }
121:
122:                 if (elseIfNodeList != null)
123:                 {
124:                         for (INode stmt : elseIfNodeList)
125:                         {
126:                                 question.qualifiers = null;
127:                                 rtypes.add(stmt.apply(THIS, question));
128:                         }
129:                 }
130:
131:                 if (elseNode != null)
132:                 {
133:                         question.qualifiers = null;
134:                         rtypes.add(elseNode.apply(THIS, question));
135:                 } else
136:                 {
137:                         // If the else case is empty then it is a statement and its type is void
138:                         rtypes.add(AstFactory.newAVoidType(ifLocation));
139:                         question.assistantFactory.createPTypeAssistant().checkReturnType(question.returnType, rtypes.getType(ifLocation), question.mandatory, ifLocation);
140:                 }
141:
142:                 return rtypes.getType(ifLocation);
143:
144:         }
145:
146:         /**
147:          * Type checks a AElseIf node
148:          *
149:          * @param elseIfNode
150:          * @param elseIfLocation
151:          * @param test
152:          * @param thenNode
153:          * @param question
154:          * @return
155:          * @throws AnalysisException
156:          */
157:         PType typeCheckAElseIf(INode elseIfNode, ILexLocation elseIfLocation,
158:                         INode test, INode thenNode, TypeCheckInfo question)
159:                         throws AnalysisException
160:         {
161:                 if (!question.assistantFactory.createPTypeAssistant().isType(test.apply(THIS, question.newConstraint(null)), ABooleanBasicType.class))
162:                 {
163:                         boolean isExpression = elseIfNode.parent() instanceof PExp;
164:                         TypeCheckerErrors.report((isExpression ? 3086 : 3218), "Expression is not boolean", elseIfLocation, elseIfNode);
165:                 }
166:
167:                 List<QualifiedDefinition> qualified = test.apply(question.assistantFactory.getQualificationVisitor(), question);
168:
169:                 for (QualifiedDefinition qdef : qualified)
170:                 {
171:                         qdef.qualifyType();
172:                 }
173:
174:                 PType type = thenNode.apply(THIS, question);
175:
176:                 for (QualifiedDefinition qdef : qualified)
177:                 {
178:                         qdef.resetType();
179:                 }
180:
181:                 return type;
182:         }
183:
184:         PType typeCheckANotYetSpecifiedExp(INode node, ILexLocation location)
185:         {
186:                 return AstFactory.newAUnknownType(location);// Because we terminate anyway
187:         }
188:
189:         /**
190:          * Type checks a let node
191:          *
192:          * @param node
193:          * @param localDefs
194:          * @param body
195:          * @param question
196:          * @return
197:          * @throws AnalysisException
198:          */
199:         protected PType typeCheckLet(INode node, LinkedList<PDefinition> localDefs,
200:                         INode body, TypeCheckInfo question, boolean statement) throws AnalysisException
201:         {
202:                 Environment local = null;
203:
204:                 if (statement && Settings.strict)
205:                 {
206:                         local = new FlatEnvironment(question.assistantFactory, question.env, true, false);
207:                 }
208:                 else
209:                 {
210:                         local = question.env;
211:                 }
212:
213:                 for (PDefinition d : localDefs)
214:                 {
215:                         if (d instanceof AExplicitFunctionDefinition)
216:                         {
217:                                 // Functions' names are in scope in their bodies, whereas
218:                                 // simple variable declarations aren't
219:
220:                                 local = new FlatCheckedEnvironment(question.assistantFactory, d, local, question.scope); // cumulative
221:                                 question.assistantFactory.createPDefinitionAssistant().implicitDefinitions(d, local);
222:
223:                                 question.assistantFactory.createPDefinitionAssistant().typeResolve(d, THIS, new TypeCheckInfo(question.assistantFactory, local, question.scope, question.qualifiers));
224:
225:                                 if (question.env.isVDMPP())
226:                                 {
227:                                         SClassDefinition cdef = question.env.findClassDefinition();
228:                                         // question.assistantFactory.createPDefinitionAssistant().setClassDefinition(d, cdef);
229:                                         d.setClassDefinition(cdef);
230:                                         d.setAccess(question.assistantFactory.createPAccessSpecifierAssistant().getStatic(d, true));
231:                                 }
232:
233:                                 d.apply(THIS, new TypeCheckInfo(question.assistantFactory, local, question.scope, question.qualifiers));
234:                         } else
235:                         {
236:                                 question.assistantFactory.createPDefinitionAssistant().implicitDefinitions(d, local);
237:                                 question.assistantFactory.createPDefinitionAssistant().typeResolve(d, THIS, new TypeCheckInfo(question.assistantFactory, local, question.scope, question.qualifiers));
238:                                 d.apply(THIS, new TypeCheckInfo(question.assistantFactory, local, question.scope).newModule(question.fromModule));
239:                                 local = new FlatCheckedEnvironment(question.assistantFactory, d, local, question.scope); // cumulative
240:                         }
241:                 }
242:                 
243:                 if (statement)
244:                 {
245:                         local = new FlatEnvironment(question.assistantFactory, local, false, false);
246:                 }
247:
248:                 PType r = body.apply(THIS, new TypeCheckInfo(question.assistantFactory, local, question.scope, null, question.constraint, null, question.fromModule, question.mandatory));
249:                 local.unusedCheck(question.env);
250:                 return r;
251:         }
252:
253:         /**
254:          * Type check method for let be such that
255:          * @param node
256:          * @param nodeLocation
257:          * @param bind
258:          * @param suchThat
259:          * @param body
260:          * @param question
261:          * @return a pair of the type and definition
262:          * @throws AnalysisException
263:          */
264:         protected Map.Entry<PType, AMultiBindListDefinition> typecheckLetBeSt(
265:                         INode node, ILexLocation nodeLocation, PMultipleBind bind,
266:                         PExp suchThat, INode body, TypeCheckInfo question, boolean statement)
267:                         throws AnalysisException
268:         {
269:                 final PDefinition def = AstFactory.newAMultiBindListDefinition(nodeLocation, question.assistantFactory.createPMultipleBindAssistant().getMultipleBindList((PMultipleBind) bind));
270:
271:                 Environment funcEnv = null;
272:
273:                 if (statement && Settings.strict)
274:                 {
275:                         funcEnv = new FlatEnvironment(question.assistantFactory, question.env, true, false);
276:                 }
277:                 else
278:                 {
279:                         funcEnv = question.env;
280:                 }
281:
282:                 def.apply(THIS, question.newConstraint(null).newInfo(funcEnv));
283:
284:                 List<PDefinition> qualified = new Vector<PDefinition>();
285:
286:                 for (PDefinition d: question.assistantFactory.createPDefinitionAssistant().getDefinitions(def))
287:                 {
288:                         PDefinition copy = d.clone();
289:                         copy.setNameScope(NameScope.LOCAL);
290:                         qualified.add(copy);
291:                 }
292:                 
293:                 Environment local = new FlatCheckedEnvironment(question.assistantFactory, qualified, question.env, question.scope);
294:
295:                 TypeCheckInfo newInfo = new TypeCheckInfo(question.assistantFactory, local, question.scope, question.qualifiers, question.constraint, null, question.fromModule, question.mandatory);
296:
297:                 if (suchThat != null
298:                                 && !question.assistantFactory.createPTypeAssistant().isType(suchThat.apply(THIS, newInfo.newConstraint(null)), ABooleanBasicType.class))
299:                 {
300:                         boolean isExpression = node instanceof PExp;
301:                         TypeCheckerErrors.report((isExpression ? 3117 : 3225), "Such that clause is not boolean", nodeLocation, node);
302:                 }
303:
304:                 newInfo.qualifiers = null;
305:                 final PType r = body.apply(THIS, newInfo);
306:                 local.unusedCheck();
307:
308:                 return new Map.Entry<PType, AMultiBindListDefinition>()
309:                 {
310:
311:                         @Override
312:                         public AMultiBindListDefinition setValue(
313:                                         AMultiBindListDefinition value)
314:                         {
315:                                 return null;
316:                         }
317:
318:                         @Override
319:                         public AMultiBindListDefinition getValue()
320:                         {
321:                                 return (AMultiBindListDefinition) def;
322:                         }
323:
324:                         @Override
325:                         public PType getKey()
326:                         {
327:                                 return r;
328:                         }
329:                 };
330:         }
331:         
332:         /**
333:          * Annotation before processing.
334:          */
335:         
336:         protected void beforeAnnotations(List<PAnnotation> annotations, INode node, TypeCheckInfo question) throws AnalysisException
337:         {
338:                 for (PAnnotation annotation: annotations)
339:                 {
340:                         beforeAnnotation(annotation, node, question);
341:                 }
342:         }
343:         
344:         protected void beforeAnnotation(PAnnotation annotation, INode node, TypeCheckInfo question)
345:         {
346:                 if (annotation.getImpl() instanceof TCAnnotation)
347:                 {
348:                         TCAnnotation impl = (TCAnnotation)annotation.getImpl();
349:                         
350:                         // This is not as ugly as multiple overloaded beforeAnotation and beforeAnnotations!
351:                         if (node instanceof PDefinition)
352:                         {
353:                                 impl.tcBefore((PDefinition)node, question);
354:                         }
355:                         else if (node instanceof PExp)
356:                         {
357:                                 impl.tcBefore((PExp)node, question);
358:                         }
359:                         else if (node instanceof PStm)
360:                         {
361:                                 impl.tcBefore((PStm)node, question);
362:                         }
363:                         else if (node instanceof AModuleModules)
364:                         {
365:                                 impl.tcBefore((AModuleModules)node, question);
366:                         }
367:                         else if (node instanceof SClassDefinition)
368:                         {
369:                                 impl.tcBefore((SClassDefinition)node, question);
370:                         }
371:                         else
372:                         {
373:                                 System.err.println("Cannot apply annoation to " + node.getClass().getSimpleName());
374:                         }
375:                 }
376:         }
377:         
378:         /**
379:          * After annotation processing.
380:          */
381:         
382:         protected void afterAnnotations(List<PAnnotation> annotations, INode node, TypeCheckInfo question) throws AnalysisException
383:         {
384:                 for (PAnnotation annotation: annotations)
385:                 {
386:                         afterAnnotation(annotation, node, question);
387:                 }
388:         }
389:
390:         protected void afterAnnotation(PAnnotation annotation, INode node, TypeCheckInfo question)
391:         {
392:                 if (annotation.getImpl() instanceof TCAnnotation)
393:                 {
394:                         TCAnnotation impl = (TCAnnotation)annotation.getImpl();
395:                         
396:                         // This is not as ugly as multiple overloaded beforeAnotation and beforeAnnotations!
397:                         if (node instanceof PDefinition)
398:                         {
399:                                 impl.tcAfter((PDefinition)node, question);
400:                         }
401:                         else if (node instanceof PExp)
402:                         {
403:                                 impl.tcAfter((PExp)node, question);
404:                         }
405:                         else if (node instanceof PStm)
406:                         {
407:                                 impl.tcAfter((PStm)node, question);
408:                         }
409:                         else if (node instanceof AModuleModules)
410:                         {
411:                                 impl.tcAfter((AModuleModules)node, question);
412:                         }
413:                         else if (node instanceof SClassDefinition)
414:                         {
415:                                 impl.tcAfter((SClassDefinition)node, question);
416:                         }
417:                         else
418:                         {
419:                                 System.err.println("Cannot apply annoation to " + node.getClass().getSimpleName());
420:                         }
421:                 }
422:         }
423: }