Package: TypeAssistantIR$1

TypeAssistantIR$1

nameinstructionbranchcomplexitylinemethod
getElementType(STypeIR)
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%
isCollectionType(STypeIR)
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%
{...}
M: 0 C: 6
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: * VDM Code Generator
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.codegen.assistant;
23:
24: import java.util.LinkedList;
25: import java.util.List;
26:
27: import org.apache.commons.lang.BooleanUtils;
28: import org.overture.ast.analysis.AnalysisException;
29: import org.overture.ast.definitions.PDefinition;
30: import org.overture.ast.definitions.SClassDefinition;
31: import org.overture.ast.factory.AstFactory;
32: import org.overture.ast.intf.lex.ILexNameToken;
33: import org.overture.ast.patterns.ATuplePattern;
34: import org.overture.ast.patterns.PPattern;
35: import org.overture.ast.types.ABracketType;
36: import org.overture.ast.types.ANamedInvariantType;
37: import org.overture.ast.types.AOptionalType;
38: import org.overture.ast.types.AProductType;
39: import org.overture.ast.types.AQuoteType;
40: import org.overture.ast.types.ASeq1SeqType;
41: import org.overture.ast.types.AUnionType;
42: import org.overture.ast.types.AUnknownType;
43: import org.overture.ast.types.PType;
44: import org.overture.ast.types.SSeqTypeBase;
45: import org.overture.ast.util.PTypeSet;
46: import org.overture.codegen.ir.INode;
47: import org.overture.codegen.ir.IRConstants;
48: import org.overture.codegen.ir.IRInfo;
49: import org.overture.codegen.ir.SExpIR;
50: import org.overture.codegen.ir.SObjectDesignatorIR;
51: import org.overture.codegen.ir.STypeIR;
52: import org.overture.codegen.ir.SourceNode;
53: import org.overture.codegen.ir.declarations.AFieldDeclIR;
54: import org.overture.codegen.ir.declarations.AMethodDeclIR;
55: import org.overture.codegen.ir.declarations.ARecordDeclIR;
56: import org.overture.codegen.ir.declarations.SClassDeclIR;
57: import org.overture.codegen.ir.expressions.AApplyExpIR;
58: import org.overture.codegen.ir.expressions.SBinaryExpIR;
59: import org.overture.codegen.ir.statements.AApplyObjectDesignatorIR;
60: import org.overture.codegen.ir.types.*;
61: import org.overture.codegen.trans.conv.ObjectDesignatorToExpIR;
62: import org.overture.typechecker.TypeComparator;
63: import org.overture.typechecker.assistant.definition.PDefinitionAssistantTC;
64: import org.overture.typechecker.assistant.type.PTypeAssistantTC;
65:
66: public class TypeAssistantIR extends AssistantBase
67: {
68:         public TypeAssistantIR(AssistantManager assistantManager)
69:         {
70:                 super(assistantManager);
71:         }
72:
73:         public void removeIllegalQuoteTypes(List<PType> types)
74:         {
75:                 List<Integer> illegalIndices = new LinkedList<>();
76:
77:                 for (int i = 0; i < types.size(); i++)
78:                 {
79:                         PType t = types.get(i);
80:
81:                         if (t instanceof AQuoteType
82:                                         && ((AQuoteType) t).getValue().getValue().equals(IRConstants.ILLEGAL_QUOTE_VALUE))
83:                         {
84:                                 illegalIndices.add(i);
85:                         }
86:                 }
87:
88:                 for (int i = illegalIndices.size() - 1; i >= 0; i--)
89:                 {
90:                         types.remove(i);
91:                 }
92:         }
93:
94:         public STypeIR getFieldExpType(IRInfo info, String fieldName,
95:                         String fieldModule, SObjectDesignatorIR obj, INode parent)
96:                         throws AnalysisException,
97:                         org.overture.codegen.ir.analysis.AnalysisException
98:         {
99:                 if (parent instanceof AApplyObjectDesignatorIR)
100:                 {
101:                         AApplyObjectDesignatorIR apply = (AApplyObjectDesignatorIR) parent;
102:                         LinkedList<SExpIR> args = apply.getArgs();
103:
104:                         if (fieldModule != null)
105:                         {
106:                                 // It is a class
107:                                 SClassDeclIR clazz = info.getDeclAssistant().findClass(info.getClasses(), fieldModule);
108:                                 AFieldDeclIR field = info.getDeclAssistant().getFieldDecl(clazz, fieldModule);
109:
110:                                 if (field != null)
111:                                 {
112:                                         return field.getType().clone();
113:                                 } else
114:                                 {
115:                                         // It must be a method
116:                                         return info.getTypeAssistant().getMethodType(info, fieldModule, fieldName, args);
117:                                 }
118:                         }
119:                 }
120:                 return getFieldType(info, fieldName, fieldModule, obj);
121:         }
122:
123:         private STypeIR getFieldType(IRInfo info, String fieldName,
124:                         String fieldModule, SObjectDesignatorIR obj)
125:         {
126:                 if (fieldModule != null)
127:                 {
128:                         // It is a class
129:                         return info.getTypeAssistant().getFieldType(info.getClasses(), fieldModule, fieldName);
130:                 } else
131:                 {
132:                         // It is a record
133:                         try
134:                         {
135:                                 ObjectDesignatorToExpIR converter = new ObjectDesignatorToExpIR(info);
136:                                 SExpIR objExp = obj.apply(converter);
137:
138:                                 if (objExp.getType() instanceof ARecordTypeIR)
139:                                 {
140:                                         STypeIR fieldExpType = info.getTypeAssistant().getFieldType(info.getClasses(), (ARecordTypeIR) objExp.getType(), fieldName);
141:
142:                                         if (fieldExpType == null)
143:                                         {
144:                                                 log.error("Could not find field type");
145:                                         }
146:
147:                                         return fieldExpType;
148:                                 }
149:                         } catch (org.overture.codegen.ir.analysis.AnalysisException e)
150:                         {
151:                         }
152:                 }
153:
154:                 log.error("Could not determine field type");
155:
156:                 return new AUnknownTypeIR();
157:         }
158:
159:         public AMethodTypeIR getMethodType(IRInfo info, String fieldModule,
160:                         String fieldName, List<SExpIR> args)
161:                         throws org.overture.codegen.ir.analysis.AnalysisException
162:         {
163:                 SClassDeclIR classDecl = assistantManager.getDeclAssistant().findClass(info.getClasses(), fieldModule);
164:                 
165:                 if(classDecl == null)
166:                 {
167:                         return null;
168:                 }
169:
170:                 List<AMethodDeclIR> methods = assistantManager.getDeclAssistant().getAllMethods(classDecl, info.getClasses());
171:
172:                 for (AMethodDeclIR method : methods)
173:                 {
174:                         if (method.getName().equals(fieldName))
175:                         {
176:                                 LinkedList<STypeIR> params = method.getMethodType().getParams();
177:
178:                                 if (assistantManager.getTypeAssistant().checkArgTypes(info, args, params))
179:                                 {
180:                                         return method.getMethodType().clone();
181:                                 }
182:                         }
183:                 }
184:
185:                 // Union type transformations may ask for the method type of a field to find out
186:                 // that it does not exist. Consider for example the (legal) snippet below where
187:                 // class A has an operation 'op()' and B is a completely empty class definition
188:                 //
189:                 // let xs = [new A(), new B()]
190:                 // in
191:                 // for x in xs do
192:                 // x.op();
193:
194:                 // If the field does not exist then the method type does not exist
195:                 return null;
196:         }
197:
198:         public STypeIR getFieldType(SClassDeclIR classDecl, String fieldName,
199:                         List<SClassDeclIR> classes)
200:         {
201:                 for (AFieldDeclIR field : assistantManager.getDeclAssistant().getAllFields(classDecl, classes))
202:                 {
203:                         if (field.getName().equals(fieldName))
204:                         {
205:                                 return field.getType().clone();
206:                         }
207:                 }
208:
209:                 return null;
210:         }
211:
212:         public STypeIR getFieldType(List<SClassDeclIR> classes,
213:                         ARecordTypeIR recordType, String memberName)
214:         {
215:                 AFieldDeclIR field = assistantManager.getDeclAssistant().getFieldDecl(classes, recordType, memberName);
216:
217:                 if (field != null)
218:                 {
219:                         return field.getType().clone();
220:                 }
221:                 return null;
222:         }
223:
224:         public List<STypeIR> getFieldTypes(ARecordDeclIR record)
225:         {
226:                 List<STypeIR> fieldTypes = new LinkedList<STypeIR>();
227:
228:                 for (AFieldDeclIR field : record.getFields())
229:                 {
230:                         fieldTypes.add(field.getType());
231:                 }
232:
233:                 return fieldTypes;
234:         }
235:
236:         public STypeIR getFieldType(List<SClassDeclIR> classes, String moduleName,
237:                         String fieldName)
238:         {
239:                 SClassDeclIR classDecl = assistantManager.getDeclAssistant().findClass(classes, moduleName);
240:                 return getFieldType(classDecl, fieldName, classes);
241:         }
242:
243:         public boolean compatible(IRInfo info, STypeIR left, STypeIR right)
244:         {
245:                 SourceNode leftSource = left.getSourceNode();
246:                 SourceNode rightSource = right.getSourceNode();
247:
248:                 if (leftSource == null || rightSource == null)
249:                 {
250:                         return false;
251:                 }
252:
253:                 org.overture.ast.node.INode leftType = leftSource.getVdmNode();
254:                 org.overture.ast.node.INode rightType = rightSource.getVdmNode();
255:
256:                 if (!(leftType instanceof PType) || !(rightType instanceof PType))
257:                 {
258:                         return false;
259:                 }
260:
261:                 TypeComparator typeComparator = info.getTcFactory().getTypeComparator();
262:
263:                 if (!typeComparator.compatible((PType) leftType, (PType) rightType))
264:                 {
265:                         return false;
266:                 }
267:
268:                 return true;
269:         }
270:
271:         public boolean checkArgTypes(IRInfo info, List<SExpIR> args,
272:                         List<STypeIR> paramTypes)
273:                         throws org.overture.codegen.ir.analysis.AnalysisException
274:         {
275:                 for (int i = 0; i < paramTypes.size(); i++)
276:                 {
277:                         STypeIR paramType = paramTypes.get(i);
278:                         STypeIR argType = args.get(i).getType();
279:
280:                         if (!compatible(info, paramType, argType))
281:                         {
282:                                 return false;
283:                         }
284:                 }
285:
286:                 return true;
287:         }
288:
289:         public PDefinition getTypeDef(ILexNameToken nameToken,
290:                         PDefinitionAssistantTC defAssistant)
291:         {
292:                 PDefinition def = (PDefinition) nameToken.getAncestor(PDefinition.class);
293:
294:                 if (def == null)
295:                 {
296:                         return null;
297:                 }
298:
299:                 SClassDefinition enclosingClass = nameToken.getAncestor(SClassDefinition.class);
300:
301:                 if (enclosingClass == null)
302:                 {
303:                         return null;
304:                 }
305:
306:                 PDefinition typeDef = defAssistant.findType(def, nameToken, enclosingClass.getName().getModule());
307:
308:                 return typeDef;
309:         }
310:
311:         public STypeIR constructSeqType(SSeqTypeBase node, IRInfo question)
312:                         throws AnalysisException
313:         {
314:                 STypeIR seqOfCg = node.getSeqof().apply(question.getTypeVisitor(), question);
315:                 boolean emptyCg = node.getEmpty();
316:
317:                 boolean isSeq1 = node instanceof ASeq1SeqType;
318:
319:                 // This is a special case since sequence of characters are strings
320:                 if (seqOfCg instanceof ACharBasicTypeIR
321:                                 && question.getSettings().getCharSeqAsString())
322:                 {
323:                         AStringTypeIR stringTypeCg = new AStringTypeIR();
324:                         stringTypeCg.setSourceNode(new SourceNode(node));
325:
326:                         return stringTypeCg;
327:                 }
328:
329:                 ASeqSeqTypeIR seqType = new ASeqSeqTypeIR();
330:                 seqType.setSeqOf(seqOfCg);
331:                 seqType.setEmpty(emptyCg);
332:                 seqType.setSeq1(isSeq1);
333:
334:                 return seqType;
335:         }
336:
337:         public boolean isBasicType(STypeIR type)
338:         {
339:                 return type instanceof SBasicTypeIR;
340:         }
341:
342:         public boolean isUnionOfNonCollectionTypes(AUnionTypeIR union)
343:         {
344:                 LinkedList<STypeIR> types = union.getTypes();
345:                 
346:                 for(STypeIR t : types)
347:                 {        
348:                         if(t instanceof AUnionTypeIR)
349:                         {
350:                                 if(!isUnionOfNonCollectionTypes((AUnionTypeIR) t))
351:                                 {
352:                                         return false;
353:                                 }
354:                         }
355:                         else if(!(isBasicType(t) || t instanceof AQuoteTypeIR || t instanceof ARecordTypeIR || t instanceof ATupleTypeIR))
356:                         {
357:                                 return false;
358:                         }
359:                 }
360:                 
361:                 
362:                 return true;
363:         }
364:         
365:         public STypeIR getWrapperType(SBasicTypeIR basicType)
366:         {
367:
368:                 if (basicType instanceof AIntNumericBasicTypeIR)
369:                 {
370:                         return new AIntBasicTypeWrappersTypeIR();
371:                 } else if (basicType instanceof ANat1NumericBasicTypeIR)
372:                 {
373:                         return new ANat1BasicTypeWrappersTypeIR();
374:                 } else if (basicType instanceof ANatNumericBasicTypeIR)
375:                 {
376:                         return new ANatBasicTypeWrappersTypeIR();
377:                 } else if (basicType instanceof ARatNumericBasicTypeIR)
378:                 {
379:                         return new ARatBasicTypeWrappersTypeIR();
380:                 } else if (basicType instanceof ARealNumericBasicTypeIR)
381:                 {
382:                         return new ARealBasicTypeWrappersTypeIR();
383:                 } else if (basicType instanceof ACharBasicTypeIR)
384:                 {
385:                         return new ACharBasicTypeWrappersTypeIR();
386:                 } else if (basicType instanceof ABoolBasicTypeIR)
387:                 {
388:                         return new ABoolBasicTypeWrappersTypeIR();
389:                 } else if (basicType instanceof ATokenBasicTypeIR)
390:                 {
391:                         return basicType;
392:                 } else
393:                 {
394:                         return null;
395:                 }
396:
397:         }
398:
399:         public AMethodTypeIR consMethodType(PType node, List<PType> paramTypes,
400:                         PType resultType, IRInfo question) throws AnalysisException
401:         {
402:                 AMethodTypeIR methodType = new AMethodTypeIR();
403:
404:                 methodType.setEquivalent(node.clone());
405:
406:                 STypeIR resultCg = resultType.apply(question.getTypeVisitor(), question);
407:
408:                 methodType.setResult(resultCg);
409:
410:                 LinkedList<STypeIR> paramsCg = methodType.getParams();
411:                 for (PType paramType : paramTypes)
412:                 {
413:                         paramsCg.add(paramType.apply(question.getTypeVisitor(), question));
414:                 }
415:
416:                 return methodType;
417:         }
418:
419:         public boolean isUnionOfType(AUnionType unionType,
420:                         Class<? extends PType> type, PTypeAssistantTC typeAssistant)
421:         {
422:                 try
423:                 {
424:                         for (PType t : unionType.getTypes())
425:                         {
426:                                 if (!typeAssistant.isType(t, type))
427:                                 {
428:                                         return false;
429:                                 }
430:                         }
431:                 } catch (Error t)// Hack for stackoverflowError
432:                 {
433:                         return false;
434:                 }
435:
436:                 return true;
437:         }
438:
439:         public boolean isUnionOfType(AUnionTypeIR unionType,
440:                                                                  Class<? extends STypeIR> type)
441:         {
442:                 try
443:                 {
444:                         for (STypeIR t : unionType.getTypes())
445:                         {
446:                                 if(t instanceof AUnionTypeIR)
447:                                 {
448:                                         if(!isUnionOfType((AUnionTypeIR) t, type))
449:                                         {
450:                                                 return false;
451:                                         }
452:                                 }
453:                                 else if (!(t instanceof AQuoteTypeIR))
454:                                 {
455:                                         return false;
456:                                 }
457:                         }
458:                 } catch (Error t)// Hack for stackoverflowError
459:                 {
460:                         return false;
461:                 }
462:
463:                 return true;
464:         }
465:
466:         public boolean isProductOfSameSize(AUnionType unionType,
467:                         PTypeAssistantTC typeAssistant)
468:         {
469:                 final int NOT_SET = -1;
470:                 int commonSize = NOT_SET;
471:                 try
472:                 {
473:                         for (PType t : unionType.getTypes())
474:                         {
475:                                 if (!typeAssistant.isType(t, AProductType.class))
476:                                 {
477:                                         return false;
478:                                 } else
479:                                 {
480:                                         AProductType productType = typeAssistant.getProduct(t, null);
481:                                         int currentSize = productType.getTypes().size();
482:
483:                                         if (commonSize == NOT_SET)
484:                                         {
485:                                                 commonSize = currentSize;
486:                                         } else
487:                                         {
488:                                                 if (commonSize != currentSize)
489:                                                 {
490:                                                         return false;
491:                                                 }
492:                                         }
493:                                 }
494:                         }
495:                 } catch (Error t)// Hack for stackoverflowError
496:                 {
497:                         return false;
498:                 }
499:
500:                 return true;
501:         }
502:
503:         public PType getType(IRInfo question, AUnionType unionType,
504:                         PPattern pattern)
505:         {
506:                 PTypeSet possibleTypes = new PTypeSet(question.getTcFactory());
507:                 PType patternType = question.getTcFactory().createPPatternAssistant(null).getPossibleType(pattern);
508:                 TypeComparator comp = question.getTcFactory().getTypeComparator();
509:
510:                 for (PType t : unionType.getTypes())
511:                 {
512:                         if (comp.compatible(patternType, t))
513:                         {
514:                                 possibleTypes.add(t);
515:                         }
516:                 }
517:
518:                 if (possibleTypes.isEmpty())
519:                 {
520:                         log.error("Could not find any possible types for pattern: "
521:                                         + pattern);
522:                         return null;
523:                 } else if (possibleTypes.size() == 1)
524:                 {
525:                         return possibleTypes.pollFirst();
526:                 } else
527:                 // More than one possible type
528:                 {
529:                         unionType.getTypes().clear();
530:                         unionType.getTypes().addAll(possibleTypes);
531:
532:                         PTypeAssistantTC typeAssistant = question.getTcFactory().createPTypeAssistant();
533:
534:                         if (question.getTypeAssistant().isUnionOfType(unionType, AProductType.class, typeAssistant))
535:                         {
536:                                 List<PType> fieldsTypes = new LinkedList<PType>();
537:                                 int noOfFields = ((ATuplePattern) pattern).getPlist().size();
538:                                 for (int i = 0; i < noOfFields; i++)
539:                                 {
540:                                         List<PType> currentFieldTypes = new LinkedList<PType>();
541:
542:                                         for (PType currentPossibleType : possibleTypes)
543:                                         {
544:                                                 AProductType currentProductType = (AProductType) currentPossibleType;
545:                                                 currentFieldTypes.add(currentProductType.getTypes().get(i).clone());
546:                                         }
547:
548:                                         fieldsTypes.add(AstFactory.newAUnionType(pattern.getLocation(), currentFieldTypes));
549:                                 }
550:
551:                                 return AstFactory.newAProductType(pattern.getLocation(), fieldsTypes);
552:                         } else
553:                         {
554:                                 return unionType;
555:                         }
556:                 }
557:         }
558:
559:         public List<STypeIR> clearObjectTypes(List<STypeIR> types)
560:         {
561:                 types = new LinkedList<STypeIR>(types);
562:
563:                 List<AObjectTypeIR> objectTypes = new LinkedList<AObjectTypeIR>();
564:
565:                 for (STypeIR type : types)
566:                 {
567:                         if (type instanceof AObjectTypeIR)
568:                         {
569:                                 objectTypes.add((AObjectTypeIR) type);
570:                         }
571:                 }
572:
573:                 types.removeAll(objectTypes);
574:
575:                 return types;
576:         }
577:
578:         public List<STypeIR> clearDuplicates(List<STypeIR> types)
579:         {
580:                 List<STypeIR> filtered = new LinkedList<STypeIR>();
581:
582:                 for (STypeIR type : types)
583:                 {
584:                         if (!containsType(filtered, type))
585:                         {
586:                                 filtered.add(type);
587:                         }
588:                 }
589:
590:                 return filtered;
591:         }
592:
593:         public boolean isStringType(STypeIR type)
594:         {
595:                 return type instanceof AStringTypeIR;
596:         }
597:
598:         public boolean isStringType(SExpIR exp)
599:         {
600:                 return exp.getType() instanceof AStringTypeIR;
601:         }
602:
603:         public boolean isMapType(SExpIR exp)
604:         {
605:                 return exp.getType() instanceof SMapTypeIR;
606:         }
607:
608:         public boolean isSeqType(SExpIR exp)
609:         {
610:                 return exp.getType() instanceof SSeqTypeIR;
611:         }
612:
613:         public boolean isMapApplication(AApplyExpIR applyExp)
614:         {
615:                 return isMapType(applyExp.getRoot()) && applyExp.getArgs().size() == 1;
616:         }
617:
618:         public boolean isSeqApplication(AApplyExpIR applyExp)
619:         {
620:                 return isSeqType(applyExp.getRoot()) && applyExp.getArgs().size() == 1;
621:         }
622:
623:         public boolean isCharRead(AApplyExpIR applyExp)
624:         {
625:                 return isStringType(applyExp.getRoot())
626:                                 && applyExp.getArgs().size() == 1;
627:         }
628:
629:         public STypeIR findElementType(STypeIR type)
630:         {
631:                 if (type instanceof SSetTypeIR)
632:                 {
633:                         SSetTypeIR setType = (SSetTypeIR) type;
634:
635:                         return setType.getSetOf();
636:                 } else if (type instanceof SSeqTypeIR)
637:                 {
638:                         SSeqTypeIR seqType = (SSeqTypeIR) type;
639:
640:                         return seqType.getSeqOf();
641:                 }
642:
643:                 log.error("Expected set or sequence type in findElementType. Got: "
644:                                 + type);
645:
646:                 return null;
647:         }
648:
649:         public PType resolve(PType type)
650:         {
651:                 while (type instanceof ABracketType
652:                                 || type instanceof ANamedInvariantType
653:                                 || type instanceof AOptionalType)
654:                 {
655:                         if (type instanceof ABracketType)
656:                         {
657:                                 type = ((ABracketType) type).getType();
658:                         }
659:
660:                         if (type instanceof ANamedInvariantType)
661:                         {
662:                                 type = ((ANamedInvariantType) type).getType();
663:                         }
664:
665:                         if (type instanceof AOptionalType)
666:                         {
667:                                 type = ((AOptionalType) type).getType();
668:                         }
669:                 }
670:
671:                 return type;
672:         }
673:         
674:         public STypeIR reduceToSeq(STypeIR type)
675:         {
676:                 if(type instanceof AUnionTypeIR)
677:                 {
678:                         AUnionTypeIR union = (AUnionTypeIR) type;
679:                         List<STypeIR> types = new LinkedList<>();
680:                         
681:                         if(!union.getTypes().isEmpty())
682:                         {
683:                                 for(STypeIR t : union.getTypes())
684:                                 {
685:                                         if(t instanceof SSeqTypeIR)
686:                                         {
687:                                                 types.add(t);
688:                                         }
689:                                 }
690:                                 
691:                                 if(types.size() == 1)
692:                                 {
693:                                         return types.get(0);
694:                                 }
695:                                 
696:                                 AUnionTypeIR newType = union.clone();
697:                                 newType.setTypes(types);
698:                                 return newType;
699:                         }
700:                         else
701:                         {
702:                                 log.error("Received union empty union types: " + type);
703:                                 return type;
704:                         }
705:                 }
706:                 else
707:                 {
708:                         return type;
709:                 }
710:         }
711:
712:         public SSeqTypeIR getSeqType(AUnionTypeIR unionType)
713:         {
714:                 AUnionTypeIR seqOf = new AUnionTypeIR();
715:                 seqOf.setTypes(findElementTypes(unionType, new CollectionTypeStrategy()
716:                 {
717:                         @Override
718:                         public boolean isCollectionType(STypeIR type)
719:                         {
720:                                 return type instanceof SSeqTypeIR;
721:                         }
722:
723:                         @Override
724:                         public STypeIR getElementType(STypeIR type)
725:                         {
726:                                 return ((SSeqTypeIR) type).getSeqOf();
727:                         }
728:                 }));
729:
730:                 ASeqSeqTypeIR seqType = new ASeqSeqTypeIR();
731:                 seqType.setEmpty(false);
732:                 seqType.setSeqOf(seqOf);
733:
734:                 return seqType;
735:         }
736:
737:         public SSetTypeIR getSetType(AUnionTypeIR unionType)
738:         {
739:                 AUnionTypeIR setOf = new AUnionTypeIR();
740:                 setOf.setTypes(findElementTypes(unionType, new CollectionTypeStrategy()
741:                 {
742:                         @Override
743:                         public boolean isCollectionType(STypeIR type)
744:                         {
745:                                 return type instanceof SSetTypeIR;
746:                         }
747:
748:                         @Override
749:                         public STypeIR getElementType(STypeIR type)
750:                         {
751:                                 return ((SSetTypeIR) type).getSetOf();
752:                         }
753:                 }));
754:
755:                 ASetSetTypeIR setType = new ASetSetTypeIR();
756:                 setType.setEmpty(false);
757:                 setType.setSetOf(setOf);
758:
759:                 return setType;
760:         }
761:
762:         public boolean usesUnionType(SBinaryExpIR node)
763:         {
764:                 return node.getLeft().getType() instanceof AUnionTypeIR
765:                                 || node.getRight().getType() instanceof AUnionTypeIR;
766:         }
767:
768:         public List<STypeIR> findElementTypes(AUnionTypeIR unionType,
769:                         CollectionTypeStrategy strategy)
770:         {
771:                 List<STypeIR> elementTypes = new LinkedList<STypeIR>();
772:
773:                 for (int i = 0; i < unionType.getTypes().size(); i++)
774:                 {
775:                         STypeIR type = unionType.getTypes().get(i);
776:
777:                         if (type instanceof AUnionTypeIR)
778:                         {
779:                                 elementTypes.addAll(findElementTypes((AUnionTypeIR) type, strategy));
780:                         } else if (strategy.isCollectionType(type))
781:                         {
782:                                 elementTypes.add(strategy.getElementType(type));
783:                         }
784:                 }
785:
786:                 return elementTypes;
787:         }
788:
789:         public boolean containsType(List<STypeIR> types, STypeIR searchedType)
790:         {
791:                 for (STypeIR currentType : types)
792:                 {
793:                         if (typesEqual(currentType, searchedType))
794:                         {
795:                                 return true;
796:                         }
797:                 }
798:
799:                 return false;
800:         }
801:
802:         private boolean typesEqual(STypeIR left, STypeIR right)
803:         {
804:                 if (left instanceof AClassTypeIR && right instanceof AClassTypeIR)
805:                 {
806:                         AClassTypeIR currentClassType = (AClassTypeIR) left;
807:                         AClassTypeIR searchedClassType = (AClassTypeIR) right;
808:
809:                         return currentClassType.getName().equals(searchedClassType.getName());
810:                 }
811:
812:                 if (left instanceof ARecordTypeIR && right instanceof ARecordTypeIR)
813:                 {
814:                         ARecordTypeIR recordType = (ARecordTypeIR) left;
815:                         ARecordTypeIR searchedRecordType = (ARecordTypeIR) right;
816:
817:                         return recordType.getName().equals(searchedRecordType.getName());
818:                 }
819:
820:                 if (left instanceof ATupleTypeIR && right instanceof ATupleTypeIR)
821:                 {
822:                         ATupleTypeIR currentTupleType = (ATupleTypeIR) left;
823:                         ATupleTypeIR searchedTupleType = (ATupleTypeIR) right;
824:
825:                         if (currentTupleType.getTypes().size() != searchedTupleType.getTypes().size())
826:                         {
827:                                 return false;
828:                         }
829:
830:                         LinkedList<STypeIR> leftTypes = currentTupleType.getTypes();
831:                         LinkedList<STypeIR> rightTypes = searchedTupleType.getTypes();
832:
833:                         for (int i = 0; i < leftTypes.size(); i++)
834:                         {
835:                                 STypeIR currentLeftFieldType = leftTypes.get(i);
836:                                 STypeIR currentRightFieldType = rightTypes.get(i);
837:
838:                                 if (!typesEqual(currentLeftFieldType, currentRightFieldType))
839:                                 {
840:                                         return false;
841:                                 }
842:                         }
843:
844:                         return true;
845:                 }
846:
847:                 if (left.getClass() == right.getClass())
848:                 {
849:                         return true;
850:                 }
851:
852:                 return false;
853:         }
854:
855:         public boolean isNumericType(STypeIR type)
856:         {
857:                 return isInt(type) || isRealOrRat(type);
858:         }
859:
860:         public boolean isRealOrRat(STypeIR type)
861:         {
862:                 return type instanceof ARatNumericBasicTypeIR
863:                                 || type instanceof ARatBasicTypeWrappersTypeIR
864:                                 || type instanceof ARealNumericBasicTypeIR
865:                                 || type instanceof ARealBasicTypeWrappersTypeIR;
866:         }
867:
868:         public boolean isInt(STypeIR type)
869:         {
870:                 return type instanceof AIntNumericBasicTypeIR
871:                                 || type instanceof AIntBasicTypeWrappersTypeIR
872:                                 || type instanceof ANat1NumericBasicTypeIR
873:                                 || type instanceof ANat1BasicTypeWrappersTypeIR
874:                                 || type instanceof ANatNumericBasicTypeIR
875:                                 || type instanceof ANatBasicTypeWrappersTypeIR;
876:         }
877:
878:         public boolean isWrapperType(STypeIR type)
879:         {
880:                 return type instanceof ANatBasicTypeWrappersTypeIR
881:                                 || type instanceof ANat1BasicTypeWrappersTypeIR
882:                                 || type instanceof ARatBasicTypeWrappersTypeIR
883:                                 || type instanceof ARealBasicTypeWrappersTypeIR
884:                                 || type instanceof ACharBasicTypeWrappersTypeIR
885:                                 || type instanceof ABoolBasicTypeWrappersTypeIR;
886:         }
887:
888:         public boolean isOptional(STypeIR type)
889:         {
890:                 return BooleanUtils.isTrue(type.getOptional());
891:         }
892:
893:         public boolean allowsNull(STypeIR type)
894:         {
895:                 if (type instanceof AUnionTypeIR)
896:                 {
897:                         AUnionTypeIR unionType = (AUnionTypeIR) type;
898:
899:                         if (BooleanUtils.isTrue(unionType.getOptional()))
900:                         {
901:                                 return true;
902:                         }
903:
904:                         for (STypeIR t : unionType.getTypes())
905:                         {
906:                                 if (allowsNull(t))
907:                                 {
908:                                         return true;
909:                                 }
910:                         }
911:
912:                         return false;
913:                 } else
914:                 {
915:                         return /* type instanceof AObjectTypeIR || */type != null
916:                                         && (type instanceof AUnknownTypeIR
917:                                                         || BooleanUtils.isTrue(type.getOptional())
918:                                                         || isWrapperType(type));
919:                 }
920:
921:         }
922:
923:         public PType getVdmType(STypeIR type)
924:         {
925:                 SourceNode source = type.getSourceNode();
926:                 if (source != null)
927:                 {
928:                         org.overture.ast.node.INode vdmNode = source.getVdmNode();
929:
930:                         if (vdmNode != null)
931:                         {
932:                                 if (vdmNode instanceof PType)
933:                                 {
934:                                         return (PType) vdmNode;
935:                                 }
936:                         }
937:                 }
938:
939:                 log.error("Could not get VDM type of " + type);
940:                 return new AUnknownType();
941:         }
942:
943:         public boolean isIncompleteRecType(ARecordTypeIR recType)
944:         {
945:                 return recType.getName().getName().equals("?") || recType.getName().getDefiningClass().equals("?");
946:         }
947: }