Package: ModuleTypeChecker

ModuleTypeChecker

nameinstructionbranchcomplexitylinemethod
ModuleTypeChecker(List)
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
typeCheck()
M: 117 C: 603
84%
M: 26 C: 70
73%
M: 21 C: 28
57%
M: 24 C: 113
82%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: *
3: *        Copyright (c) 2008 Fujitsu Services Ltd.
4: *
5: *        Author: Nick Battle
6: *
7: *        This file is part of VDMJ.
8: *
9: *        VDMJ is free software: you can redistribute it and/or modify
10: *        it under the terms of the GNU General Public License as published by
11: *        the Free Software Foundation, either version 3 of the License, or
12: *        (at your option) any later version.
13: *
14: *        VDMJ is distributed in the hope that it will be useful,
15: *        but WITHOUT ANY WARRANTY; without even the implied warranty of
16: *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: *        GNU General Public License for more details.
18: *
19: *        You should have received a copy of the GNU General Public License
20: *        along with VDMJ. If not, see <http://www.gnu.org/licenses/>.
21: *
22: ******************************************************************************/
23:
24: package org.overture.typechecker;
25:
26: import java.util.List;
27: import java.util.Vector;
28:
29: import org.overture.ast.analysis.AnalysisException;
30: import org.overture.ast.annotations.Annotation;
31: import org.overture.ast.annotations.PAnnotation;
32: import org.overture.ast.definitions.PDefinition;
33: import org.overture.ast.modules.AModuleModules;
34: import org.overture.ast.typechecker.NameScope;
35: import org.overture.ast.typechecker.Pass;
36: import org.overture.ast.util.modules.CombinedDefaultModule;
37: import org.overture.config.Release;
38: import org.overture.config.Settings;
39: import org.overture.typechecker.annotations.TCAnnotation;
40: import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
41: import org.overture.typechecker.assistant.TypeCheckerAssistantFactory;
42: import org.overture.typechecker.assistant.definition.PDefinitionAssistantTC;
43: import org.overture.typechecker.visitor.TypeCheckVisitor;
44:
45: /**
46: * A class to coordinate all module type checking processing.
47: */
48:
49: public class ModuleTypeChecker extends TypeChecker
50: {
51:         /** The list of modules to check. */
52:         private final List<AModuleModules> modules;
53:
54:         /**
55:          * Create a type checker with the list of modules passed. The warnings flag indicates whether warnings should be
56:          * printed or just counted.
57:          */
58:
59:         public final ITypeCheckerAssistantFactory assistantFactory;
60:
61:         /**
62:          * VDM-only constructor. <b>NOT</b> for use by extensions.
63:          *
64:          * @param modules
65:          */
66:         public ModuleTypeChecker(List<AModuleModules> modules)
67:         {
68:                 super();
69:                 assistantFactory = new TypeCheckerAssistantFactory();
70:                 this.modules = modules;
71:         }
72:
73:         /**
74:          * Perform the type checking for the set of modules. This is a complicated process.
75:          * <p>
76:          * First the module names are checked for uniqueness. Then each module generates its implicit definitions (eg. for
77:          * pre_ and post_ functions). Then export definitions for each module are generated, and the import definitions
78:          * linked to them. Next all the definition in the set of modules are type resolved by creating a list of all
79:          * modules' definitions and calling their typeResolve methods. Then the type checking of the modules' definitions
80:          * can proceed, covering the types, values and remaining definitions in that order. Next, the declared types of the
81:          * imports for each module are compared with the (now determined) types of the exports. Finally the usage of the
82:          * imports and definitions for each module are checked.
83:          */
84:
85:         @Override
86:         public void typeCheck()
87:         {
88:                 // Check for module name duplication
89:
90:                 boolean nothing = true;
91:                 boolean hasFlat = false;
92:
93:•                for (AModuleModules m1 : modules)
94:                 {
95:•                        for (AModuleModules m2 : modules)
96:                         {
97:•                                if (m1 != m2 && m1.getName().equals(m2.getName()))
98:                                 {
99:                                         TypeChecker.report(3429, "Module " + m1.getName()
100:                                                         + " duplicates " + m2.getName(), m1.getName().getLocation());
101:                                 }
102:                         }
103:
104:•                        if (m1.getIsFlat())
105:                         {
106:                                 hasFlat = true;
107:                         } else
108:                         {
109:•                                if (hasFlat && Settings.release == Release.CLASSIC)
110:                                 {
111:                                         TypeChecker.report(3308, "Cannot mix modules and flat specifications", m1.getName().getLocation());
112:                                 }
113:                         }
114:
115:•                        if (!m1.getTypeChecked())
116:                         {
117:                                 nothing = false;
118:                         }
119:                 }
120:
121:•                if (nothing)
122:                 {
123:                         return;
124:                 }
125:
126:                 // Mark top level definitions of flat specifications as used
127:                 new PDefinitionAssistantTC(new TypeCheckerAssistantFactory());
128:
129:•                for (AModuleModules module : modules)
130:                 {
131:•                        if (module instanceof CombinedDefaultModule)
132:                         {
133:•                                for (PDefinition definition : module.getDefs())
134:                                 {
135:                                         assistantFactory.createPDefinitionAssistant().markUsed(definition);
136:                                 }
137:                         }
138:                 }
139:
140:                 // Generate implicit definitions for pre_, post_, inv_ functions etc.
141:
142:•                for (AModuleModules m : modules)
143:                 {
144:•                        if (!m.getTypeChecked())
145:                         {
146:                                 Environment env = new ModuleEnvironment(assistantFactory, m);
147:                                 assistantFactory.createPDefinitionListAssistant().implicitDefinitions(m.getDefs(), env);
148:                         }
149:                 }
150:
151:                 // Exports have to be identified before imports can be processed.
152:
153:•                for (AModuleModules m : modules)
154:                 {
155:•                        if (!m.getTypeChecked())
156:                         {
157:                                 assistantFactory.getTypeComparator().setCurrentModule(m.getName().getName());
158:                                 assistantFactory.createAModuleModulesAssistant().processExports(m); // Populate exportDefs
159:                         }
160:                 }
161:
162:                 // Process the imports early because renamed imports create definitions
163:                 // which can affect type resolution.
164:
165:•                for (AModuleModules m : modules)
166:                 {
167:•                        if (!m.getTypeChecked())
168:                         {
169:                                 assistantFactory.getTypeComparator().setCurrentModule(m.getName().getName());
170:                                 assistantFactory.createAModuleModulesAssistant().processImports(m, modules); // Populate importDefs
171:                         }
172:                 }
173:
174:                 // Create a list of all definitions from all modules, including
175:                 // imports of renamed definitions.
176:
177:                 List<PDefinition> alldefs = new Vector<PDefinition>();
178:                 List<PDefinition> checkDefs = new Vector<PDefinition>();
179:
180:•                for (AModuleModules m : modules)
181:                 {
182:•                        for (PDefinition d : m.getImportdefs())
183:                         {
184:                                 alldefs.add(d);
185:•                                if (!m.getTypeChecked())
186:                                 {
187:                                         checkDefs.add(d);
188:                                 }
189:                         }
190:                 }
191:
192:•                for (AModuleModules m : modules)
193:                 {
194:•                        for (PDefinition d : m.getDefs())
195:                         {
196:                                 alldefs.add(d);
197:•                                if (!m.getTypeChecked())
198:                                 {
199:                                         checkDefs.add(d);
200:                                 }
201:                         }
202:                 }
203:
204:                 // Attempt type resolution of unchecked definitions from all modules.
205:                 Environment env = new FlatCheckedEnvironment(assistantFactory, alldefs, NameScope.NAMESANDSTATE);
206:                 TypeCheckVisitor tc = new TypeCheckVisitor();
207:•                for (PDefinition d : checkDefs)
208:                 {
209:                         try
210:                         {
211:                                 assistantFactory.createPDefinitionAssistant().typeResolve(d, tc,
212:                                                 new TypeCheckInfo(assistantFactory, env).newModule(d.getLocation().getModule()));
213:                         } catch (TypeCheckException te)
214:                         {
215:                                 report(3430, te.getMessage(), te.location);
216:                                 
217:•                                if (te.extras != null)
218:                                 {
219:•                                        for (TypeCheckException e: te.extras)
220:                                         {
221:                                                 report(3430, e.getMessage(), e.location);
222:                                         }
223:                                 }
224:                         } catch (AnalysisException te)
225:                         {
226:                                 report(3431, te.getMessage(), null);// FIXME: internal error
227:                         }
228:                 }
229:
230:                 // Initialise any annotations
231:                 Annotation.init(TCAnnotation.class);
232:
233:•                for (AModuleModules m: modules)
234:                 {
235:•                        for (PAnnotation annotation: m.getAnnotations())
236:                         {
237:•                                if (annotation.getImpl() instanceof TCAnnotation)
238:                                 {
239:                                         TCAnnotation impl = (TCAnnotation)annotation.getImpl();
240:                                         impl.tcBefore(m, null);
241:                                 }
242:                         }
243:                 }
244:
245:                 // Prepare to look for recursive loops
246:                 RecursiveLoops.getInstance().reset();
247:
248:                 // Proceed to type check all definitions, considering types, values
249:                 // and remaining definitions, in that order.
250:
251:•                for (Pass pass : Pass.values())
252:                 {
253:•                        for (AModuleModules m : modules)
254:                         {
255:•                                if (!m.getTypeChecked())
256:                                 {
257:                                         assistantFactory.getTypeComparator().setCurrentModule(m.getName().getName());
258:                                         Environment e = new ModuleEnvironment(assistantFactory, m);
259:
260:•                                        for (PDefinition d : m.getDefs())
261:                                         {
262:                                                 // System.out.println("Number of Defs: " + m.getDefs().size());
263:                                                 // System.out.println("Def to typecheck: " + d.getName());
264:•                                                if (d.getPass() == pass)
265:                                                 {
266:                                                         try
267:                                                         {
268:                                                                 d.apply(tc, new TypeCheckInfo(assistantFactory, e, NameScope.NAMES).newModule(m.getName().getName()));
269:                                                                 // System.out.println();
270:                                                         } catch (TypeCheckException te)
271:                                                         {
272:                                                                 report(3431, te.getMessage(), te.location);
273:                                                                 
274:•                                                                if (te.extras != null)
275:                                                                 {
276:•                                                                        for (TypeCheckException ex: te.extras)
277:                                                                         {
278:                                                                                 report(3431, ex.getMessage(), ex.location);
279:                                                                         }
280:                                                                 }
281:                                                         } catch (AnalysisException te)
282:                                                         {
283:                                                                 report(3431, te.getMessage(), null);// FIXME: internal error
284:                                                         }
285:                                                 }
286:                                                 // System.out.println("Number of Defs: " + m.getDefs().size());
287:                                         }
288:                                 }
289:                         }
290:                 }
291:
292:                 // Prepare to look for recursive loops
293:                 RecursiveLoops.getInstance().typeCheckModules(modules, assistantFactory);
294:
295:•                for (AModuleModules m: modules)
296:                 {
297:•                        for (PAnnotation annotation: m.getAnnotations())
298:                         {
299:•                                if (annotation.getImpl() instanceof TCAnnotation)
300:                                 {
301:                                         TCAnnotation impl = (TCAnnotation)annotation.getImpl();
302:                                         impl.tcAfter(m, null);
303:                                 }
304:                         }
305:                 }
306:
307:                 // Report any discrepancies between the final checked types of
308:                 // definitions and their explicit imported types. Rebuild the import/export lists first.
309:
310:•                for (AModuleModules m : modules)
311:                 {
312:                         assistantFactory.getTypeComparator().setCurrentModule(m.getName().getName());
313:                         assistantFactory.createAModuleModulesAssistant().processExports(m);
314:                 }
315:
316:•                for (AModuleModules m : modules)
317:                 {
318:                         assistantFactory.getTypeComparator().setCurrentModule(m.getName().getName());
319:                         assistantFactory.createAModuleModulesAssistant().processImports(m, modules);
320:                 }
321:
322:•                for (AModuleModules m : modules)
323:                 {
324:•                        if (!m.getTypeChecked())
325:                         {
326:                                 assistantFactory.getTypeComparator().setCurrentModule(m.getName().getName());
327:                                 assistantFactory.createAModuleModulesAssistant().processImports(m, modules); // Re-populate importDefs
328:
329:                                 try
330:                                 {
331:                                         assistantFactory.createAModuleModulesAssistant().typeCheckExports(m);
332:                                         assistantFactory.createAModuleModulesAssistant().typeCheckImports(m);
333:                                 }
334:                                 catch (TypeCheckException te)
335:                                 {
336:                                         report(3432, te.getMessage(), te.location);
337:                                         
338:•                                        if (te.extras != null)
339:                                         {
340:•                                                for (TypeCheckException e: te.extras)
341:                                                 {
342:                                                         report(3432, e.getMessage(), e.location);
343:                                                 }
344:                                         }
345:                                 }
346:                                 catch (AnalysisException te)
347:                                 {
348:                                         report(3431, te.getMessage(), null);// FIXME: internal error
349:                                 }
350:                         }
351:                 }
352:
353:                 // Any names that have not been referenced or exported produce "unused"
354:                 // warnings.
355:
356:•                for (AModuleModules m : modules)
357:                 {
358:•                        if (!m.getTypeChecked())
359:                         {
360:                                 assistantFactory.createPDefinitionListAssistant().unusedCheck(m.getImportdefs());
361:                                 assistantFactory.createPDefinitionListAssistant().unusedCheck(m.getDefs());
362:                         }
363:                 }
364:
365:                 // Check for inter-definition cyclic dependencies before initialization
366:         cyclicDependencyCheck(checkDefs);
367:         }
368: }