Package: TypeCheckerImportsVisitor

TypeCheckerImportsVisitor

nameinstructionbranchcomplexitylinemethod
TypeCheckerImportsVisitor(IQuestionAnswer)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
caseAAllImport(AAllImport, TypeCheckInfo)
M: 0 C: 2
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
caseAFunctionValueImport(AFunctionValueImport, TypeCheckInfo)
M: 34 C: 272
89%
M: 9 C: 23
72%
M: 9 C: 8
47%
M: 2 C: 40
95%
M: 0 C: 1
100%
caseAOperationValueImport(AOperationValueImport, TypeCheckInfo)
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
caseATypeImport(ATypeImport, TypeCheckInfo)
M: 27 C: 112
81%
M: 8 C: 8
50%
M: 7 C: 2
22%
M: 3 C: 19
86%
M: 0 C: 1
100%
checkKind(ITypeCheckerAssistantFactory, PDefinition, boolean, String, PImport)
M: 28 C: 5
15%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 2 C: 2
50%
M: 0 C: 1
100%
defaultSValueImport(SValueImport, TypeCheckInfo)
M: 25 C: 132
84%
M: 4 C: 14
78%
M: 4 C: 6
60%
M: 3 C: 27
90%
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.List;
25: import java.util.Vector;
26:
27: import org.overture.ast.analysis.AnalysisException;
28: import org.overture.ast.analysis.intf.IQuestionAnswer;
29: import org.overture.ast.definitions.AExplicitFunctionDefinition;
30: import org.overture.ast.definitions.AImplicitFunctionDefinition;
31: import org.overture.ast.definitions.AStateDefinition;
32: import org.overture.ast.definitions.PDefinition;
33: import org.overture.ast.factory.AstFactory;
34: import org.overture.ast.intf.lex.ILexNameToken;
35: import org.overture.ast.modules.AAllImport;
36: import org.overture.ast.modules.AFunctionValueImport;
37: import org.overture.ast.modules.AModuleModules;
38: import org.overture.ast.modules.AOperationValueImport;
39: import org.overture.ast.modules.ATypeImport;
40: import org.overture.ast.modules.PImport;
41: import org.overture.ast.modules.SValueImport;
42: import org.overture.ast.typechecker.NameScope;
43: import org.overture.ast.types.PType;
44: import org.overture.ast.types.SInvariantType;
45: import org.overture.typechecker.FlatCheckedEnvironment;
46: import org.overture.typechecker.TypeCheckInfo;
47: import org.overture.typechecker.TypeCheckerErrors;
48: import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
49:
50: public class TypeCheckerImportsVisitor extends AbstractTypeCheckVisitor
51: {
52:
53:         public TypeCheckerImportsVisitor(
54:                         IQuestionAnswer<TypeCheckInfo, PType> typeCheckVisitor)
55:         {
56:                 super(typeCheckVisitor);
57:         }
58:
59:         @Override
60:         public PType caseAAllImport(AAllImport node, TypeCheckInfo question)
61:         {
62:                 return null; // Implicitly OK.
63:         }
64:
65:         @Override
66:         public PType caseATypeImport(ATypeImport node, TypeCheckInfo question) throws AnalysisException
67:         {
68:                 PDefinition expdef = null;
69:                 
70:•                if (node.getFrom() != null)
71:                 {
72:                         expdef = question.assistantFactory.createPDefinitionListAssistant().findType(node.getFrom().getExportdefs(), node.getName(), null);
73:                         
74:•                        if (expdef != null)
75:                         {
76:•                                boolean istype = question.assistantFactory.createPDefinitionAssistant().isTypeDefinition(expdef)
77:                                                 || expdef instanceof AStateDefinition;        // State record imports are allowed
78:                                 checkKind(question.assistantFactory, expdef, istype, "type", node);
79:                         }
80:                 }
81:
82:•                if (node.getDef() != null && node.getFrom() != null)
83:                 {
84:                         PDefinition def = node.getDef();
85:                         ILexNameToken name = node.getName();
86:                         AModuleModules from = node.getFrom();
87:                         def.setType((SInvariantType) question.assistantFactory.createPTypeAssistant().typeResolve(question.assistantFactory.createPDefinitionAssistant().getType(def), null, THIS, question));
88:
89:•                        if (expdef != null)
90:                         {
91:                                 boolean istype = question.assistantFactory.createPDefinitionAssistant().isTypeDefinition(expdef);
92:                                 checkKind(question.assistantFactory, expdef, istype, "type", node);
93:                                 PType exptype = question.assistantFactory.createPTypeAssistant().typeResolve(expdef.getType(), null, THIS, question);
94:
95:                                 // if (!question.assistantFactory.getTypeComparator().compatible(def.getType(), exptype))
96:                                 String detail1 = question.assistantFactory.createPTypeAssistant().toDetailedString(def.getType());
97:                                 String detail2 = question.assistantFactory.createPTypeAssistant().toDetailedString(exptype);
98:                                 
99:•                                if (!detail1.equals(detail2))
100:                                 {
101:                                         TypeCheckerErrors.report(3192, "Type import of " + name
102:                                                         + " does not match export from " + from.getName(), node.getLocation(), node);
103:                                         TypeCheckerErrors.detail2("Import", detail1, "Export", detail2);
104:                                 }
105:                         }
106:                 }
107:                 return null;
108:         }
109:
110:         @Override
111:         public PType defaultSValueImport(SValueImport node, TypeCheckInfo question) throws AnalysisException
112:         {
113:                 PDefinition expdef = null;
114:                 
115:•                if (node.getFrom() != null)
116:                 {
117:                         expdef = question.assistantFactory.createPDefinitionListAssistant().findName(node.getFrom().getExportdefs(), node.getName(), NameScope.NAMES);
118:
119:•                 if (expdef != null)
120:                 {
121:                         boolean expected = false;
122:                         String expkind = "";
123:                         
124:•                         if (node instanceof SValueImport)
125:                         {
126:                                 expected = question.assistantFactory.createPDefinitionAssistant().isValueDefinition(expdef);
127:                                 expkind = "value";
128:                         }
129:•                         if (node instanceof AFunctionValueImport)
130:                         {
131:                                 expected = question.assistantFactory.createPTypeAssistant().isFunction(expdef.getType(), question.fromModule);
132:                                 expkind = "function";
133:                         }
134:•                         else if (node instanceof AOperationValueImport)
135:                         {
136:                                 expected = question.assistantFactory.createPTypeAssistant().isOperation(expdef.getType(), question.fromModule);
137:                                 expkind = "operation";
138:                         }
139:                         
140:                         checkKind(question.assistantFactory, expdef, expected, expkind, node);
141:                 }
142:                 }
143:                 
144:                 PType type = node.getImportType();
145:                 AModuleModules from = node.getFrom();
146:                 ILexNameToken name = node.getName();
147:
148:•                if (type != null && from != null && expdef != null)
149:                 {
150:                         type = question.assistantFactory.createPTypeAssistant().typeResolve(type, null, THIS, question);
151:                                 
152:                         PType exptype = question.assistantFactory.createPTypeAssistant().typeResolve(expdef.getType(), null, THIS, question);
153:                         
154:                         // Temporarily tweak the module to look like it is the exporting module
155:                         String m = question.assistantFactory.getTypeComparator().getCurrentModule();
156:                         question.assistantFactory.getTypeComparator().setCurrentModule(exptype.getLocation().getModule());
157:
158:•                        if (!question.assistantFactory.getTypeComparator().compatible(type, exptype))
159:                         {
160:                                 TypeCheckerErrors.report(3194, "Type of import "
161:                                                 + name + " does not match export from "
162:                                                 + from.getName(), node.getLocation(), node);
163:                                 TypeCheckerErrors.detail2("Import", type.toString(), "Export", exptype.toString());
164:                         }
165:                         
166:                         question.assistantFactory.getTypeComparator().setCurrentModule(m);                // Restore it
167:                 }
168:         
169:                 return null;
170:         }
171:
172:         @Override
173:         public PType caseAFunctionValueImport(AFunctionValueImport node,
174:                         TypeCheckInfo question) throws AnalysisException
175:         {
176:                 PDefinition expdef = null;
177:                 
178:•                if (node.getFrom() != null)
179:                 {
180:                         expdef = question.assistantFactory.createPDefinitionListAssistant().findName(node.getFrom().getExportdefs(), node.getName(), NameScope.NAMES);
181:                         
182:•                        if (expdef != null)
183:                         {
184:                                 boolean isfunc = question.assistantFactory.createPDefinitionAssistant().isFunction(expdef);
185:                                 checkKind(question.assistantFactory, expdef, isfunc, "function", node);
186:                         }
187:                 }
188:
189:•                if (node.getTypeParams().size() == 0)
190:                 {
191:                         return defaultSValueImport(node, question);
192:                 }
193:                 else
194:                 {
195:                         List<PDefinition> defs = new Vector<PDefinition>();
196:
197:•                        for (ILexNameToken pname : node.getTypeParams())
198:                         {
199:                                 ILexNameToken pnameClone = pname.clone();
200:                                 PDefinition p = AstFactory.newALocalDefinition(pname.getLocation(), pnameClone, NameScope.NAMES, AstFactory.newAParameterType(pnameClone));
201:
202:                                 question.assistantFactory.createPDefinitionAssistant().markUsed(p);
203:                                 defs.add(p);
204:                         }
205:
206:                         FlatCheckedEnvironment params = new FlatCheckedEnvironment(question.assistantFactory, defs, question.env, NameScope.NAMES);
207:                         PType rtype = question.assistantFactory.createPTypeAssistant().typeResolve(node.getImportType(), null, THIS, question.newInfo(params));
208:                         node.setImportType(rtype);
209:                         
210:•                        if (expdef instanceof AExplicitFunctionDefinition)
211:                         {
212:                                 AExplicitFunctionDefinition efd = (AExplicitFunctionDefinition)expdef;
213:                                 
214:•                                if (efd.getTypeParams() == null || efd.getTypeParams().isEmpty())
215:                                 {
216:                                         TypeCheckerErrors.report(3352, "Imported " + node.getName() + " function has no type paramaters", node.getLocation(), node);
217:                                 }
218:•                                else if (!efd.getTypeParams().toString().equals(node.getTypeParams().toString()))
219:                                 {
220:                                         TypeCheckerErrors.report(3353, "Imported " + node.getName() + " function type parameters incorrect", node.getLocation(), node);
221:                                         TypeCheckerErrors.detail2("Imported", node.getTypeParams(), "Actual", efd.getTypeParams());
222:                                 }
223:                                 
224:•                                if (efd.getType() != null && !efd.getType().toString().equals(node.getImportType().toString()))
225:                                 {
226:                                         TypeCheckerErrors.report(3184, "Imported " + node.getName() + " function type incorrect", node.getLocation(), node);
227:                                         TypeCheckerErrors.detail2("Imported", node.getImportType(), "Actual", efd.getType());
228:                                 }
229:                                 
230:                                 node.setImportType(efd.getType().clone());
231:                         }
232:•                        else if (expdef instanceof AImplicitFunctionDefinition)
233:                         {
234:                                 AImplicitFunctionDefinition ifd = (AImplicitFunctionDefinition)expdef;
235:                                 
236:•                                if (ifd.getTypeParams() == null || ifd.getTypeParams().isEmpty())
237:                                 {
238:                                         TypeCheckerErrors.report(3352, "Imported " + node.getName() + " function has no type paramaters", node.getLocation(), node);
239:                                 }
240:•                                else if (!ifd.getTypeParams().toString().equals(node.getTypeParams().toString()))
241:                                 {
242:                                         TypeCheckerErrors.report(3353, "Imported " + node.getName() + " function type parameters incorrect", node.getLocation(), node);
243:                                         TypeCheckerErrors.detail2("Imported", node.getTypeParams(), "Actual", ifd.getTypeParams());
244:                                 }
245:                                 
246:•                                if (ifd.getType() != null && !ifd.getType().toString().equals(node.getImportType().toString()))
247:                                 {
248:                                         TypeCheckerErrors.report(3184, "Imported " + node.getName() + " function type incorrect", node.getLocation(), node);
249:                                         TypeCheckerErrors.detail2("Imported", node.getImportType(), "Actual", ifd.getType());
250:                                 }
251:                                 
252:                                 node.setImportType(ifd.getType().clone());
253:                         }
254:                 }
255:
256:                 return null;
257:         }
258:
259:         @Override
260:         public PType caseAOperationValueImport(AOperationValueImport node,
261:                         TypeCheckInfo question) throws AnalysisException
262:         {
263:                 return defaultSValueImport(node, question);
264:         }
265:         
266:         private void checkKind(ITypeCheckerAssistantFactory af, PDefinition actual, boolean expected, String expkind, PImport node) throws AnalysisException
267:         {
268:•                if (actual != null && !expected)
269:                 {
270:                 String actkind = actual.apply(af.getKindFinder());
271:                         TypeCheckerErrors.report(3356, "Import of " + expkind + " " + actual.getName() + " is " + actkind, node.getLocation(), node);
272:                 }
273:         }
274: }