Package: SFunctionDefinitionAssistantTC

SFunctionDefinitionAssistantTC

nameinstructionbranchcomplexitylinemethod
SFunctionDefinitionAssistantTC(ITypeCheckerAssistantFactory)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
checkCycleMeasures(List)
M: 17 C: 45
73%
M: 3 C: 5
63%
M: 2 C: 3
60%
M: 3 C: 9
75%
M: 0 C: 1
100%
findClassDefinition(ILexNameToken, List)
M: 0 C: 35
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
findClassDefinitions(Stack, List)
M: 2 C: 28
93%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 5
100%
M: 0 C: 1
100%
findModuleDefinition(ILexNameToken, List)
M: 0 C: 35
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
findModuleDefinitions(Stack, List)
M: 0 C: 30
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
getParamDefinitions(SFunctionDefinition, AFunctionType, List, ILexLocation)
M: 0 C: 103
100%
M: 0 C: 10
100%
M: 0 C: 6
100%
M: 0 C: 22
100%
M: 0 C: 1
100%
measureType(PDefinition, StringBuilder)
M: 33 C: 31
48%
M: 7 C: 5
42%
M: 4 C: 3
43%
M: 5 C: 4
44%
M: 0 C: 1
100%
typeCheckCycles(AApplyExp, PDefinition, PDefinition)
M: 20 C: 131
87%
M: 6 C: 24
80%
M: 5 C: 11
69%
M: 4 C: 34
89%
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.assistant.definition;
23:
24: import java.util.ArrayList;
25: import java.util.Iterator;
26: import java.util.List;
27: import java.util.Stack;
28: import java.util.Vector;
29:
30: import org.overture.ast.assistant.IAstAssistant;
31: import org.overture.ast.definitions.AExplicitFunctionDefinition;
32: import org.overture.ast.definitions.AImplicitFunctionDefinition;
33: import org.overture.ast.definitions.PDefinition;
34: import org.overture.ast.definitions.SClassDefinition;
35: import org.overture.ast.definitions.SFunctionDefinition;
36: import org.overture.ast.expressions.AApplyExp;
37: import org.overture.ast.factory.AstFactory;
38: import org.overture.ast.intf.lex.ILexLocation;
39: import org.overture.ast.intf.lex.ILexNameToken;
40: import org.overture.ast.modules.AModuleModules;
41: import org.overture.ast.patterns.PPattern;
42: import org.overture.ast.typechecker.NameScope;
43: import org.overture.ast.types.AFunctionType;
44: import org.overture.ast.types.PType;
45: import org.overture.typechecker.RecursiveLoops;
46: import org.overture.typechecker.TypeChecker;
47: import org.overture.typechecker.assistant.ITypeCheckerAssistantFactory;
48:
49: public class SFunctionDefinitionAssistantTC implements IAstAssistant
50: {
51:         protected ITypeCheckerAssistantFactory af;
52:
53:         public SFunctionDefinitionAssistantTC(
54:                         ITypeCheckerAssistantFactory af)
55:         {
56:                 this.af = af;
57:         }
58:
59:         public List<List<PDefinition>> getParamDefinitions(
60:                         SFunctionDefinition node, AFunctionType type,
61:                         List<List<PPattern>> paramPatternList, ILexLocation location)
62:         {
63:                 List<List<PDefinition>> defList = new ArrayList<List<PDefinition>>(); // new Vector<DefinitionList>();
64:                 AFunctionType ftype = type; // Start with the overall function
65:                 Iterator<List<PPattern>> piter = paramPatternList.iterator();
66:
67:•                while (piter.hasNext())
68:                 {
69:                         List<PPattern> plist = piter.next();
70:                         List<PDefinition> defs = new Vector<PDefinition>();
71:                         List<PType> ptypes = ftype.getParameters();
72:                         Iterator<PType> titer = ptypes.iterator();
73:
74:•                        if (plist.size() != ptypes.size())
75:                         {
76:                                 // This is a type/param mismatch, reported elsewhere. But we
77:                                 // have to create definitions to avoid a cascade of errors.
78:
79:                                 PType unknown = AstFactory.newAUnknownType(location);
80:
81:•                                for (PPattern p : plist)
82:                                 {
83:                                         defs.addAll(af.createPPatternAssistant(location.getModule()).getDefinitions(p, unknown, NameScope.LOCAL));
84:
85:                                 }
86:                         } else
87:                         {
88:•                                for (PPattern p : plist)
89:                                 {
90:                                         defs.addAll(af.createPPatternAssistant(location.getModule()).getDefinitions(p, titer.next(), NameScope.LOCAL));
91:                                 }
92:                         }
93:
94:                         defList.add(af.createPDefinitionAssistant().checkDuplicatePatterns(node, defs));
95:
96:•                        if (ftype.getResult() instanceof AFunctionType) // else???
97:                         {
98:                                 ftype = (AFunctionType) ftype.getResult();
99:                         }
100:                 }
101:
102:                 return defList;
103:         }
104:
105:         public List<PDefinition> findModuleDefinitions(Stack<ILexNameToken> stack, List<AModuleModules> modules)
106:         {
107:                 List<PDefinition> list = new Vector<PDefinition>();
108:
109:•                for (ILexNameToken name: stack)
110:                 {
111:                         list.add(findModuleDefinition(name, modules));
112:                 }
113:
114:•                return list.contains(null) ? null : list;        // Usually local func definitions
115:         }
116:
117:         public PDefinition findModuleDefinition(ILexNameToken sought, List<AModuleModules> modules)
118:         {
119:•                for (AModuleModules module: modules)
120:                 {
121:•                        for (PDefinition def: module.getDefs())
122:                         {
123:•                                if (def.getName() != null && def.getName().equals(sought))
124:                                 {
125:                                         return def;
126:                                 }
127:                         }
128:                 }
129:
130:                 return null;
131:         }
132:
133:         public List<PDefinition> findClassDefinitions(Stack<ILexNameToken> stack, List<SClassDefinition> classes)
134:         {
135:                 List<PDefinition> list = new Vector<PDefinition>();
136:
137:•                for (ILexNameToken name: stack)
138:                 {
139:                         list.add(findClassDefinition(name, classes));
140:                 }
141:
142:•                return list.contains(null) ? null : list;        // Usually local func definitions
143:         }
144:
145:         public PDefinition findClassDefinition(ILexNameToken sought, List<SClassDefinition> classes)
146:         {
147:•                for (SClassDefinition clazz: classes)
148:                 {
149:•                        for (PDefinition def: clazz.getDefinitions())
150:                         {
151:•                                if (def.getName() != null && def.getName().equals(sought))
152:                                 {
153:                                         return def;
154:                                 }
155:                         }
156:                 }
157:
158:                 return null;
159:         }
160:
161:         public void typeCheckCycles(AApplyExp apply, PDefinition parent, PDefinition called)
162:         {
163:                 List<List<PDefinition>> cycles = RecursiveLoops.getInstance().getCycles(parent.getName());
164:
165:•                if (cycles != null)
166:                 {
167:                         List<List<String>> cycleNames = new Vector<List<String>>();
168:                         List<List<PDefinition>> recursiveCycles = new Vector<List<PDefinition>>();
169:                         boolean mutuallyRecursive = false;
170:
171:•                        for (List<PDefinition> cycle: cycles)
172:                         {
173:•                                if (cycle.size() >= 2)
174:                                 {
175:•                                        if (cycle.get(1).equals(called))        // The parent cycle involves this apply call
176:                                         {
177:                                                 recursiveCycles.add(cycle);
178:                                                 cycleNames.add(RecursiveLoops.getInstance().getCycleNames(cycle));
179:•                                                mutuallyRecursive = mutuallyRecursive || cycle.size() > 2;        // eg. [f, g, f] not [f, f]
180:                                                 checkCycleMeasures(cycle);
181:                                         }
182:                                 }
183:                         }
184:
185:•                        if (cycleNames.isEmpty())
186:                         {
187:                                 // No recursion via this "called" apply
188:                                 return;
189:                         }
190:                         
191:•                        if (parent instanceof AExplicitFunctionDefinition)
192:                         {
193:                                 AExplicitFunctionDefinition def = (AExplicitFunctionDefinition)parent;
194:                                 def.setRecursive(true);
195:
196:•                                 if (def.getMeasure() == null)
197:                                 {
198:•                                         if (mutuallyRecursive)
199:                                         {
200:                                                 TypeChecker.warning(5013, "Mutually recursive cycle has no measure", def.getLocation());
201:
202:•                                                 for (List<String> cycleName: cycleNames)
203:                                                 {
204:                                                         TypeChecker.detail("Cycle", cycleName);
205:                                                 }
206:                                         }
207:                                         else
208:                                         {
209:                                                 TypeChecker.warning(5012, "Recursive function has no measure", def.getLocation());
210:                                         }
211:                                 }
212:                         }
213:•                        else if (parent instanceof AImplicitFunctionDefinition)
214:                         {
215:                                 AImplicitFunctionDefinition def = (AImplicitFunctionDefinition)parent;
216:                                 def.setRecursive(true);
217:
218:•                                 if (def.getMeasure() == null)
219:                                 {
220:•                                         if (mutuallyRecursive)
221:                                         {
222:                                                 TypeChecker.warning(5013, "Mutually recursive cycle has no measure", def.getLocation());
223:
224:•                                                 for (List<String> cycleName: cycleNames)
225:                                                 {
226:                                                         TypeChecker.detail("Cycle", cycleName);
227:                                                 }
228:                                         }
229:                                         else
230:                                         {
231:                                                 TypeChecker.warning(5012, "Recursive function has no measure", def.getLocation());
232:                                         }
233:                                 }
234:                         }
235:
236:                         apply.setRecursiveCycles(recursiveCycles);
237:                 }
238:         }
239:
240:         private void checkCycleMeasures(List<PDefinition> cycle)
241:         {
242:•                for (int i = 0; i < cycle.size()-2; i++)
243:                 {
244:                         PDefinition d1 = cycle.get(i);
245:                         PDefinition d2 = cycle.get(i+1);
246:                         StringBuilder sb1 = new StringBuilder();
247:                         StringBuilder sb2 = new StringBuilder();
248:
249:                         PType a = measureType(d1, sb1);
250:                         PType b = measureType(d2, sb2);
251:
252:•                        if (a != null && b != null && !a.equals(b))
253:                         {
254:                                 TypeChecker.report(3364, "Recursive cycle measures return different types", d1.getLocation());
255:                                 TypeChecker.detail(sb1.toString(), a);
256:                                 TypeChecker.detail(sb2.toString(), b);
257:                         }
258:                 }
259:         }
260:
261:         private PType measureType(PDefinition def, StringBuilder mname)
262:         {
263:•                if (def instanceof AExplicitFunctionDefinition)
264:                 {
265:                         AExplicitFunctionDefinition expl = (AExplicitFunctionDefinition)def;
266:•                        if (expl.getMeasureName() != null) mname.append(expl.getMeasureName()); else mname.append(def.getName().toString());
267:•                        return expl.getMeasureDef() != null ? expl.getMeasureDef().getType().getResult() : null;
268:                 }
269:•                else if (def instanceof AImplicitFunctionDefinition)
270:                 {
271:                         AImplicitFunctionDefinition impl = (AImplicitFunctionDefinition)def;
272:•                        if (impl.getMeasureName() != null) mname.append(impl.getMeasureName()); else mname.append(def.getName().toString());
273:•                        return impl.getMeasureDef() != null ? impl.getMeasureDef().getType().getResult() : null;
274:                 }
275:                 else
276:                 {
277:                         return null;
278:                 }
279:         }
280: }