Package: UnionTypeTrans$1

UnionTypeTrans$1

nameinstructionbranchcomplexitylinemethod
findType(PType)
M: 0 C: 27
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
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.trans.uniontypes;
23:
24: import java.util.LinkedList;
25: import java.util.List;
26:
27: import org.apache.log4j.Logger;
28: import org.overture.ast.definitions.PDefinition;
29: import org.overture.ast.expressions.AVariableExp;
30: import org.overture.ast.types.ANamedInvariantType;
31: import org.overture.ast.types.AParameterType;
32: import org.overture.ast.types.AUnionType;
33: import org.overture.ast.types.AUnknownType;
34: import org.overture.ast.types.PType;
35: import org.overture.ast.types.SMapType;
36: import org.overture.ast.types.SSeqType;
37: import org.overture.codegen.assistant.AssistantBase;
38: import org.overture.codegen.assistant.DeclAssistantIR;
39: import org.overture.codegen.assistant.ExpAssistantIR;
40: import org.overture.codegen.assistant.TypeAssistantIR;
41: import org.overture.codegen.ir.INode;
42: import org.overture.codegen.ir.SExpIR;
43: import org.overture.codegen.ir.SStmIR;
44: import org.overture.codegen.ir.STypeIR;
45: import org.overture.codegen.ir.SourceNode;
46: import org.overture.codegen.ir.analysis.AnalysisException;
47: import org.overture.codegen.ir.analysis.DepthFirstAnalysisAdaptor;
48: import org.overture.codegen.ir.declarations.ADefaultClassDeclIR;
49: import org.overture.codegen.ir.declarations.AFieldDeclIR;
50: import org.overture.codegen.ir.declarations.AMethodDeclIR;
51: import org.overture.codegen.ir.declarations.ARecordDeclIR;
52: import org.overture.codegen.ir.declarations.AVarDeclIR;
53: import org.overture.codegen.ir.declarations.SClassDeclIR;
54: import org.overture.codegen.ir.expressions.AApplyExpIR;
55: import org.overture.codegen.ir.expressions.ACardUnaryExpIR;
56: import org.overture.codegen.ir.expressions.ACastUnaryExpIR;
57: import org.overture.codegen.ir.expressions.AElemsUnaryExpIR;
58: import org.overture.codegen.ir.expressions.AFieldExpIR;
59: import org.overture.codegen.ir.expressions.AFieldNumberExpIR;
60: import org.overture.codegen.ir.expressions.AHeadUnaryExpIR;
61: import org.overture.codegen.ir.expressions.AIdentifierVarExpIR;
62: import org.overture.codegen.ir.expressions.AIndicesUnaryExpIR;
63: import org.overture.codegen.ir.expressions.AIntDivNumericBinaryExpIR;
64: import org.overture.codegen.ir.expressions.AIsOfClassExpIR;
65: import org.overture.codegen.ir.expressions.ALenUnaryExpIR;
66: import org.overture.codegen.ir.expressions.AMapDomainUnaryExpIR;
67: import org.overture.codegen.ir.expressions.AMissingMemberRuntimeErrorExpIR;
68: import org.overture.codegen.ir.expressions.AModNumericBinaryExpIR;
69: import org.overture.codegen.ir.expressions.ANewExpIR;
70: import org.overture.codegen.ir.expressions.ANotUnaryExpIR;
71: import org.overture.codegen.ir.expressions.ANullExpIR;
72: import org.overture.codegen.ir.expressions.ARemNumericBinaryExpIR;
73: import org.overture.codegen.ir.expressions.ASeqConcatBinaryExpIR;
74: import org.overture.codegen.ir.expressions.AUndefinedExpIR;
75: import org.overture.codegen.ir.expressions.SNumericBinaryExpIR;
76: import org.overture.codegen.ir.expressions.SUnaryExpIR;
77: import org.overture.codegen.ir.expressions.SVarExpBase;
78: import org.overture.codegen.ir.expressions.SVarExpIR;
79: import org.overture.codegen.ir.patterns.AIdentifierPatternIR;
80: import org.overture.codegen.ir.statements.AAssignToExpStmIR;
81: import org.overture.codegen.ir.statements.ABlockStmIR;
82: import org.overture.codegen.ir.statements.ACallObjectExpStmIR;
83: import org.overture.codegen.ir.statements.AElseIfStmIR;
84: import org.overture.codegen.ir.statements.AIfStmIR;
85: import org.overture.codegen.ir.statements.APlainCallStmIR;
86: import org.overture.codegen.ir.statements.ARaiseErrorStmIR;
87: import org.overture.codegen.ir.statements.AReturnStmIR;
88: import org.overture.codegen.ir.statements.ASuperCallStmIR;
89: import org.overture.codegen.ir.statements.SCallStmIR;
90: import org.overture.codegen.ir.types.ABoolBasicTypeIR;
91: import org.overture.codegen.ir.types.AClassTypeIR;
92: import org.overture.codegen.ir.types.AErrorTypeIR;
93: import org.overture.codegen.ir.types.AIntNumericBasicTypeIR;
94: import org.overture.codegen.ir.types.AMethodTypeIR;
95: import org.overture.codegen.ir.types.ARealNumericBasicTypeIR;
96: import org.overture.codegen.ir.types.ARecordTypeIR;
97: import org.overture.codegen.ir.types.ATemplateTypeIR;
98: import org.overture.codegen.ir.types.ATupleTypeIR;
99: import org.overture.codegen.ir.types.AUnionTypeIR;
100: import org.overture.codegen.ir.types.AUnknownTypeIR;
101: import org.overture.codegen.ir.types.SMapTypeIR;
102: import org.overture.codegen.ir.types.SSeqTypeIR;
103: import org.overture.codegen.trans.assistants.TransAssistantIR;
104:
105: public class UnionTypeTrans extends DepthFirstAnalysisAdaptor
106: {
107:         protected Logger log = Logger.getLogger(this.getClass().getName());
108:         
109:         public static final String MISSING_OP_MEMBER = "Missing operation member: ";
110:         public static final String MISSING_MEMBER = "Missing member: ";
111:
112:         private TransAssistantIR transAssistant;
113:
114:         private UnionTypeVarPrefixes unionTypePrefixes;
115:
116:         private List<INode> cloneFreeNodes;
117:
118:         public UnionTypeTrans(TransAssistantIR transAssistant,
119:                         UnionTypeVarPrefixes unionTypePrefixes, List<INode> cloneFreeNodes)
120:         {
121:                 this.transAssistant = transAssistant;
122:                 this.unionTypePrefixes = unionTypePrefixes;
123:                 this.cloneFreeNodes = cloneFreeNodes;
124:         }
125:
126:         private interface TypeFinder<T extends STypeIR>
127:         {
128:                 public T findType(PType type)
129:                                 throws org.overture.ast.analysis.AnalysisException;
130:         }
131:
132:         public <T extends STypeIR> T searchType(SExpIR exp,
133:                         TypeFinder<T> typeFinder)
134:         {
135:                 if (exp == null || exp.getType() == null)
136:                 {
137:                         return null;
138:                 }
139:
140:                 SourceNode sourceNode = exp.getType().getSourceNode();
141:
142:                 if (sourceNode == null)
143:                 {
144:                         return null;
145:                 }
146:
147:                 org.overture.ast.node.INode vdmTypeNode = sourceNode.getVdmNode();
148:
149:                 if (vdmTypeNode instanceof PType)
150:                 {
151:                         try
152:                         {
153:                                 PType vdmType = (PType) vdmTypeNode;
154:
155:                                 return typeFinder.findType(vdmType);
156:
157:                         } catch (org.overture.ast.analysis.AnalysisException e)
158:                         {
159:                         }
160:                 }
161:
162:                 return null;
163:         }
164:
165:         private SExpIR correctTypes(SExpIR exp, STypeIR castedType)
166:                         throws AnalysisException
167:         {
168:                 if ((exp.getType() instanceof AUnknownTypeIR ||
169:                                 exp.getType() instanceof AUnionTypeIR ||
170:                                 castedType instanceof ATemplateTypeIR) &&
171:                                 !(exp instanceof ACastUnaryExpIR) &&
172:                                 !exp.getType().equals(castedType))
173:                 {
174:                         return consCorrection(exp, castedType);
175:                 }
176:                 else
177:                 {
178:                         org.overture.ast.node.INode source = AssistantBase.getVdmNode(exp);
179:                         
180:                         if(source != null)
181:                         {
182:                                 if(source instanceof AVariableExp)
183:                                 {
184:                                         AVariableExp varExp = (AVariableExp) source;
185:                                         PType varDefType = varExp.getVardef().getType();
186:                                         
187:                                         while(varDefType instanceof ANamedInvariantType)
188:                                         {
189:                                                 varDefType = ((ANamedInvariantType) varDefType).getType();
190:                                         }
191:                                         
192:                                         if((varDefType instanceof AUnknownType ||
193:                                                         varDefType instanceof AUnionType ||
194:                                                         castedType instanceof AParameterType) &&
195:                                                         !(exp instanceof ACastUnaryExpIR) &&
196:                                                         !exp.getType().equals(castedType))
197:                                         {
198:                                                 return consCorrection(exp, castedType);
199:                                         }
200:                                 }
201:                         }
202:                 }
203:
204:                 return exp;
205:         }
206:
207:         private SExpIR consCorrection(SExpIR exp, STypeIR castedType) {
208:                 ACastUnaryExpIR casted = new ACastUnaryExpIR();
209:                 casted.setType(castedType.clone());
210:                 casted.setExp(exp.clone());
211:
212:                 transAssistant.replaceNodeWith(exp, casted);
213:
214:                 return casted;
215:         }
216:
217:         private boolean correctArgTypes(List<SExpIR> args, List<STypeIR> paramTypes, boolean sameSize)
218:                         throws AnalysisException
219:         {
220:                 if (sameSize && args.size() != paramTypes.size())
221:                 {
222:                         return false;
223:                 }
224:
225:                 if (transAssistant.getInfo().getAssistantManager().getTypeAssistant().checkArgTypes(transAssistant.getInfo(), args, paramTypes))
226:                 {
227:                         for (int k = 0; k < paramTypes.size(); k++)
228:                         {
229:                                 SExpIR arg = args.get(k);
230:
231:                                 if (!(arg instanceof ANullExpIR))
232:                                 {
233:                                         correctTypes(arg, paramTypes.get(k));
234:                                 }
235:                         }
236:                         return true;
237:                 }
238:
239:                 return false;
240:         }
241:
242:         private boolean handleUnaryExp(SUnaryExpIR exp) throws AnalysisException
243:         {
244:                 STypeIR type = exp.getExp().getType();
245:
246:                 if (type instanceof AUnionTypeIR)
247:                 {
248:                         org.overture.ast.node.INode vdmNode = type.getSourceNode().getVdmNode();
249:
250:                         if (vdmNode instanceof PType)
251:                         {
252:                                 return true;
253:                         }
254:                 }
255:
256:                 return false;
257:         }
258:
259:         private AIsOfClassExpIR consInstanceCheck(SExpIR copy, STypeIR type)
260:         {
261:                 AIsOfClassExpIR check = new AIsOfClassExpIR();
262:                 check.setType(new ABoolBasicTypeIR());
263:                 check.setCheckedType(type.clone());
264:                 check.setExp(copy.clone());
265:
266:                 return check;
267:         }
268:
269:         @Override
270:         public void defaultInSNumericBinaryExpIR(SNumericBinaryExpIR node)
271:                         throws AnalysisException
272:         {
273:                 STypeIR expectedType;
274:
275:                 if (transAssistant.getInfo().getTypeAssistant().isNumericType(node.getType()))
276:                 {
277:                         expectedType = node.getType();
278:                 } else
279:                 {
280:                         expectedType = getExpectedOperandType(node);
281:                 }
282:
283:                 correctTypes(node.getLeft(), expectedType);
284:                 correctTypes(node.getRight(), expectedType);
285:         }
286:
287:         public STypeIR getExpectedOperandType(SNumericBinaryExpIR node)
288:         {
289:                 if (node instanceof AIntDivNumericBinaryExpIR
290:                                 || node instanceof AModNumericBinaryExpIR
291:                                 || node instanceof ARemNumericBinaryExpIR)
292:                 {
293:                         return new AIntNumericBasicTypeIR();
294:                 } else
295:                 {
296:                         return new ARealNumericBasicTypeIR();
297:                 }
298:         }
299:
300:         @Override
301:         public void caseAFieldDeclIR(AFieldDeclIR node) throws AnalysisException
302:         {
303:                 if (node.getInitial() != null)
304:                 {
305:                         if (node.getInitial().getType() instanceof AUnionTypeIR)
306:                         {
307:                                 correctTypes(node.getInitial(), node.getType());
308:                         }
309:
310:                         node.getInitial().apply(this);
311:                 }
312:         }
313:
314:         @Override
315:         public void caseACardUnaryExpIR(ACardUnaryExpIR node)
316:                         throws AnalysisException
317:         {
318:                 STypeIR type = node.getExp().getType();
319:
320:                 if (type instanceof AUnionTypeIR)
321:                 {
322:                         STypeIR expectedType = transAssistant.getInfo().getTypeAssistant().getSetType((AUnionTypeIR) type);
323:                         correctTypes(node.getExp(), expectedType);
324:                 }
325:
326:                 node.getExp().apply(this);
327:                 node.getType().apply(this);
328:         }
329:
330:         @Override
331:         public void caseAHeadUnaryExpIR(AHeadUnaryExpIR node) throws AnalysisException {
332:                 
333:                 processSeqUnaryExp(node);
334:         }
335:         
336:         @Override
337:         public void caseAIndicesUnaryExpIR(AIndicesUnaryExpIR node) throws AnalysisException {
338:                 
339:                 processSeqUnaryExp(node);
340:         }
341:         
342:         @Override
343:         public void caseALenUnaryExpIR(ALenUnaryExpIR node) throws AnalysisException
344:         {
345:                 processSeqUnaryExp(node);
346:         }
347:
348:         private void processSeqUnaryExp(SUnaryExpIR node) throws AnalysisException {
349:                 STypeIR type = node.getExp().getType();
350:
351:                 if (type instanceof AUnionTypeIR)
352:                 {
353:                         STypeIR expectedType = transAssistant.getInfo().getTypeAssistant().getSeqType((AUnionTypeIR) type);
354:                         correctTypes(node.getExp(), expectedType);
355:                 }
356:
357:                 node.getExp().apply(this);
358:                 node.getType().apply(this);
359:         }
360:
361:         @Override
362:         public void caseASeqConcatBinaryExpIR(ASeqConcatBinaryExpIR node)
363:                         throws AnalysisException
364:         {
365:                 node.getLeft().apply(this);
366:                 node.getRight().apply(this);
367:                 node.getType().apply(this);
368:
369:                 if (!transAssistant.getInfo().getTypeAssistant().usesUnionType(node))
370:                 {
371:                         return;
372:                 }
373:
374:                 STypeIR leftType = node.getLeft().getType();
375:
376:                 if (leftType instanceof AUnionTypeIR)
377:                 {
378:                         STypeIR expectedType = transAssistant.getInfo().getTypeAssistant().getSeqType((AUnionTypeIR) leftType);
379:                         correctTypes(node.getLeft(), expectedType);
380:                 }
381:
382:                 STypeIR rightType = node.getRight().getType();
383:
384:                 if (rightType instanceof AUnionTypeIR)
385:                 {
386:                         STypeIR expectedType = transAssistant.getInfo().getTypeAssistant().getSeqType((AUnionTypeIR) rightType);
387:                         correctTypes(node.getRight(), expectedType);
388:                 }
389:         }
390:
391:         @Override
392:         public void caseAFieldNumberExpIR(AFieldNumberExpIR node)
393:                         throws AnalysisException
394:         {
395:                 SExpIR tuple = node.getTuple();
396:                 STypeIR tupleType = tuple.getType();
397:
398:                 if (!(tupleType instanceof AUnionTypeIR))
399:                 {
400:                         tuple.apply(this);
401:                         return;
402:                 }
403:
404:                 handleFieldExp(node, "field number "
405:                                 + node.getField(), tuple, tupleType, node.getType().clone());
406:         }
407:
408:         @Override
409:         public void caseAFieldExpIR(AFieldExpIR node) throws AnalysisException
410:         {
411:                 SExpIR object = node.getObject();
412:                 STypeIR objectType = object.getType();
413:
414:                 if (!(objectType instanceof AUnionTypeIR) && !typeNarrowedByIsCheck(object))
415:                 {
416:                         object.apply(this);
417:                         return;
418:                 }
419:
420:                 STypeIR resultType = getResultType(node, node.parent(), objectType, transAssistant.getInfo().getTypeAssistant());
421:
422:                 handleFieldExp(node, node.getMemberName(), object, objectType, resultType);
423:         }
424:
425:         private boolean typeNarrowedByIsCheck(SExpIR object) {
426:                 
427:                 if(object instanceof SVarExpIR)
428:                 {
429:                         org.overture.ast.node.INode vdmNode = AssistantBase.getVdmNode(object);
430:                 
431:                         if(vdmNode instanceof AVariableExp)
432:                         {
433:                                 AVariableExp vdmVar = (AVariableExp) vdmNode;
434:                                 
435:                                 PDefinition varDef = vdmVar.getVardef();
436:                                 
437:                                 if(varDef != null)
438:                                 {
439:                                         if(varDef.getType() != null)
440:                                         {
441:                                                 if (!varDef.getType().equals(vdmVar.getType())) {
442:                                                         // If the type of the variable expression is narrowed by an 'is_' check, e.g.
443:                                                         // is_(var, R1) then the type of this variable will be different from that of
444:                                                         // the variable definition.
445:                                                         return true;
446:                                                 }
447:                                         }
448:                                         else
449:                                         {
450:                                                 log.warn("Type of variable definition '" + varDef + "' is null. Location: " + varDef.getLocation());
451:                                         }
452:                                 }
453:                         }                        
454:                 }
455:                 
456:                 return false;
457:         }
458:
459:         private void handleFieldExp(SExpIR node, String memberName, SExpIR subject,
460:                         STypeIR fieldObjType, STypeIR resultType) throws AnalysisException
461:         {
462:                 INode parent = node.parent();
463:
464:                 TypeAssistantIR typeAssistant = transAssistant.getInfo().getAssistantManager().getTypeAssistant();
465:
466:                 SStmIR enclosingStatement = transAssistant.getEnclosingStm(node, "field expression");
467:
468:                 String applyResultName = transAssistant.getInfo().getTempVarNameGen().nextVarName(unionTypePrefixes.applyExp());
469:
470:                 AIdentifierPatternIR id = new AIdentifierPatternIR();
471:                 id.setName(applyResultName);
472:
473:                 org.overture.ast.node.INode vdmNode = AssistantBase.getVdmNode(node);
474:                 DeclAssistantIR declAssist = transAssistant.getInfo().getDeclAssistant();
475:                 ExpAssistantIR expAssist = transAssistant.getInfo().getExpAssistant();
476:                 AVarDeclIR resultDecl = declAssist.consLocalVarDecl(vdmNode, resultType, id, expAssist.consUndefinedExp());
477:
478:                 AIdentifierVarExpIR resultVar = new AIdentifierVarExpIR();
479:                 resultVar.setSourceNode(node.getSourceNode());
480:                 resultVar.setIsLambda(false);
481:                 resultVar.setIsLocal(true);
482:                 resultVar.setName(applyResultName);
483:                 resultVar.setType(resultDecl.getType().clone());
484:
485:                 ABlockStmIR replacementBlock = new ABlockStmIR();
486:                 SExpIR obj = null;
487:
488:                 if (!(subject instanceof SVarExpBase))
489:                 {
490:                         String objName = transAssistant.getInfo().getTempVarNameGen().nextVarName(unionTypePrefixes.objExp());
491:
492:                         AIdentifierPatternIR objId = new AIdentifierPatternIR();
493:                         objId.setName(objName);
494:
495:                         AVarDeclIR objectDecl = declAssist.consLocalVarDecl(subject.getType().clone(), objId, subject.clone());
496:
497:                         replacementBlock.getLocalDefs().add(objectDecl);
498:
499:                         AIdentifierVarExpIR objectVar = new AIdentifierVarExpIR();
500:                         objectVar.setIsLambda(false);
501:                         objectVar.setIsLocal(true);
502:                         objectVar.setName(objName);
503:                         objectVar.setType(objectDecl.getType().clone());
504:                         obj = objectVar;
505:                 } else
506:                 {
507:                         obj = subject.clone();
508:                 }
509:
510:                 List<STypeIR> possibleTypes;
511:                 
512:                 if(fieldObjType instanceof AUnionTypeIR)
513:                 {
514:                         possibleTypes = ((AUnionTypeIR) fieldObjType).getTypes();
515:                 }
516:                 else
517:                 {
518:                         possibleTypes = new LinkedList<>();
519:                         possibleTypes.add(fieldObjType);
520:                 }
521:                 
522:                 possibleTypes = typeAssistant.clearDuplicates(possibleTypes);
523:
524:                 AIfStmIR ifChecks = new AIfStmIR();
525:
526:                 int handledTypes = 0;
527:                 for (int i = 0; i < possibleTypes.size(); i++)
528:                 {
529:                         SExpIR fieldExp = (SExpIR) node.clone();
530:                         STypeIR currentType = possibleTypes.get(i);
531:
532:                         if (currentType instanceof AUnknownTypeIR)
533:                         {
534:                                 // If we are accessing an element of (say) the sequence [new A(), new B(), nil] of type A | B | [?]
535:                                 // then the current IR type will be the unknown type at some point. This case is simply skipped.
536:                                 continue;
537:                         }
538:
539:                         if (!(currentType instanceof AClassTypeIR)
540:                                         && !(currentType instanceof ATupleTypeIR)
541:                                         && !(currentType instanceof ARecordTypeIR))
542:                         {
543:                                 // If the field cannot possibly exist then continue
544:                                 continue;
545:                         }
546:
547:                         boolean memberExists = false;
548:
549:                         memberExists = memberExists(memberName, parent, typeAssistant, fieldExp, currentType);
550:
551:                         if (!memberExists)
552:                         {
553:                                 // If the member does not exist then the case should not be treated
554:                                 continue;
555:                         }
556:
557:                         ACastUnaryExpIR castedFieldExp = new ACastUnaryExpIR();
558:                         castedFieldExp.setType(currentType.clone());
559:                         castedFieldExp.setExp(obj.clone());
560:
561:                         setSubject(fieldExp, castedFieldExp);
562:
563:                         AAssignToExpStmIR assignment = new AAssignToExpStmIR();
564:                         cloneFreeNodes.add(assignment);
565:                         assignment.setTarget(resultVar.clone());
566:                         assignment.setExp(getAssignmentExp(node, fieldExp));
567:
568:                         if (handledTypes == 0)
569:                         {
570:                                 ifChecks.setIfExp(consInstanceCheck(obj, currentType));
571:                                 ifChecks.setThenStm(assignment);
572:                         } else
573:                         {
574:                                 AElseIfStmIR elseIf = new AElseIfStmIR();
575:                                 elseIf.setElseIf(consInstanceCheck(obj, currentType));
576:                                 elseIf.setThenStm(assignment);
577:
578:                                 ifChecks.getElseIf().add(elseIf);
579:                         }
580:
581:                         handledTypes++;
582:                 }
583:
584:                 if (handledTypes == 0)
585:                 {
586:                         return;
587:                 }
588:
589:                 ARaiseErrorStmIR raise = consRaiseStm(MISSING_MEMBER, memberName);
590:                 ifChecks.setElseStm(raise);
591:
592:                 if (parent instanceof AApplyExpIR
593:                                 && ((AApplyExpIR) parent).getRoot() == node)
594:                 {
595:                         transAssistant.replaceNodeWith(parent, resultVar);
596:                 } else
597:                 {
598:                         transAssistant.replaceNodeWith(node, resultVar);
599:                 }
600:
601:                 replacementBlock.getLocalDefs().add(resultDecl);
602:                 replacementBlock.getStatements().add(ifChecks);
603:
604:                 transAssistant.replaceNodeWith(enclosingStatement, replacementBlock);
605:                 replacementBlock.getStatements().add(enclosingStatement);
606:
607:                 ifChecks.apply(this);
608:         }
609:
610:         private void setSubject(SExpIR fieldExp, ACastUnaryExpIR castedFieldExp)
611:         {
612:                 if (fieldExp instanceof AFieldExpIR)
613:                 {
614:                         ((AFieldExpIR) fieldExp).setObject(castedFieldExp);
615:                 } else if (fieldExp instanceof AFieldNumberExpIR)
616:                 {
617:                         ((AFieldNumberExpIR) fieldExp).setTuple(castedFieldExp);
618:                 }
619:         }
620:
621:         private boolean memberExists(String memberName, INode parent,
622:                         TypeAssistantIR typeAssistant, SExpIR fieldExp, STypeIR currentType)
623:                         throws AnalysisException
624:         {
625:                 if (fieldExp instanceof AFieldExpIR)
626:                 {
627:                         if (currentType instanceof AClassTypeIR)
628:                         {
629:                                 String className = ((AClassTypeIR) currentType).getName();
630:
631:                                 return memberExists(parent, typeAssistant, className, memberName);
632:                         } else if (currentType instanceof ARecordTypeIR)
633:                         {
634:                                 ARecordTypeIR recordType = (ARecordTypeIR) currentType;
635:
636:                                 return transAssistant.getInfo().getDeclAssistant().getFieldDecl(transAssistant.getInfo().getClasses(), recordType, memberName) != null;
637:                         }
638:                 } else if (fieldExp instanceof AFieldNumberExpIR
639:                                 && currentType instanceof ATupleTypeIR)
640:                 {
641:                         return true;
642:
643:                         // Could possibly be strengthened
644:                         // AFieldNumberExpIR fieldNumberExp = (AFieldNumberExpIR) fieldExp;
645:                         // return fieldNumberExp.getField() <= ((ATupleTypeIR) currentType).getTypes().size();
646:                 }
647:
648:                 return false;
649:         }
650:
651:         private boolean memberExists(INode parent, TypeAssistantIR typeAssistant,
652:                         String className, String memberName) throws AnalysisException
653:         {
654:                 if (typeAssistant.getFieldType(transAssistant.getInfo().getClasses(), className, memberName) != null)
655:                 {
656:                         return true;
657:                 }
658:
659:                 List<SExpIR> args = ((AApplyExpIR) parent).getArgs();
660:
661:                 return typeAssistant.getMethodType(transAssistant.getInfo(), className, memberName, args) != null;
662:         }
663:
664:         @Override
665:         public void caseAApplyExpIR(AApplyExpIR node) throws AnalysisException
666:         {
667:                 for (SExpIR arg : node.getArgs())
668:                 {
669:                         arg.apply(this);
670:                 }
671:
672:                 SExpIR root = node.getRoot();
673:                 root.apply(this);
674:
675:                 if (root.getType() instanceof AUnionTypeIR)
676:                 {
677:                         STypeIR colType = searchType(root, new TypeFinder<SMapTypeIR>()
678:                         {
679:                                 @Override
680:                                 public SMapTypeIR findType(PType type)
681:                                                 throws org.overture.ast.analysis.AnalysisException
682:                                 {
683:                                         SMapType mapType = transAssistant.getInfo().getTcFactory().createPTypeAssistant().getMap(type, null);
684:
685:•                                        return mapType != null
686:                                                         ? (SMapTypeIR) mapType.apply(transAssistant.getInfo().getTypeVisitor(), transAssistant.getInfo())
687:                                                         : null;
688:                                 }
689:                         });
690:
691:                         if (colType == null)
692:                         {
693:                                 colType = searchType(root, new TypeFinder<SSeqTypeIR>()
694:                                 {
695:                                         @Override
696:                                         public SSeqTypeIR findType(PType type)
697:                                                         throws org.overture.ast.analysis.AnalysisException
698:                                         {
699:
700:                                                 SSeqType seqType = transAssistant.getInfo().getTcFactory().createPTypeAssistant().getSeq(type, null);
701:
702:                                                 return seqType != null
703:                                                                 ? (SSeqTypeIR) seqType.apply(transAssistant.getInfo().getTypeVisitor(), transAssistant.getInfo())
704:                                                                 : null;
705:                                         }
706:                                 });
707:                         }
708:
709:                         if (colType != null && node.getArgs().size() == 1)
710:                         {
711:                                 correctTypes(root, colType);
712:                                 return;
713:                         }
714:
715:                 } else if (root.getType() instanceof AMethodTypeIR)
716:                 {
717:                         AMethodTypeIR methodType = (AMethodTypeIR) root.getType();
718:
719:                         LinkedList<STypeIR> paramTypes = methodType.getParams();
720:
721:                         LinkedList<SExpIR> args = node.getArgs();
722:                         correctArgTypes(args, paramTypes, false);
723:                 }
724:         }
725:
726:         @Override
727:         public void inANotUnaryExpIR(ANotUnaryExpIR node) throws AnalysisException
728:         {
729:                 correctTypes(node.getExp(), new ABoolBasicTypeIR());
730:         }
731:
732:         @Override
733:         public void inANewExpIR(ANewExpIR node) throws AnalysisException
734:         {
735:                 LinkedList<SExpIR> args = node.getArgs();
736:
737:                 STypeIR type = node.getType();
738:
739:                 if (type instanceof AClassTypeIR)
740:                 {
741:                         for (SClassDeclIR classCg : transAssistant.getInfo().getClasses())
742:                         {
743:                                 for (AMethodDeclIR method : classCg.getMethods())
744:                                 {
745:                                         if (!method.getIsConstructor())
746:                                         {
747:                                                 continue;
748:                                         }
749:
750:                                         if (correctArgTypes(args, method.getMethodType().getParams(), true))
751:                                         {
752:                                                 return;
753:                                         }
754:                                 }
755:                         }
756:                 } else if (type instanceof ARecordTypeIR)
757:                 {
758:                         ARecordTypeIR recordType = (ARecordTypeIR) type;
759:                         String definingClassName = recordType.getName().getDefiningClass();
760:                         String recordName = recordType.getName().getName();
761:
762:                         SClassDeclIR classDecl = transAssistant.getInfo().getAssistantManager().getDeclAssistant().findClass(transAssistant.getInfo().getClasses(), definingClassName);
763:                         
764:                         if(classDecl == null)
765:                         {
766:                                 return;
767:                         }
768:                         
769:                         ARecordDeclIR record = transAssistant.getInfo().getAssistantManager().getDeclAssistant().findRecord(classDecl, recordName);
770:
771:                         List<STypeIR> fieldTypes = transAssistant.getInfo().getAssistantManager().getTypeAssistant().getFieldTypes(record);
772:
773:                         correctArgTypes(args, fieldTypes, true);
774:                 }
775:         }
776:
777:         @Override
778:         public void inAIfStmIR(AIfStmIR node) throws AnalysisException
779:         {
780:                 ABoolBasicTypeIR expectedType = new ABoolBasicTypeIR();
781:
782:                 correctTypes(node.getIfExp(), expectedType);
783:
784:                 LinkedList<AElseIfStmIR> elseIfs = node.getElseIf();
785:
786:                 for (AElseIfStmIR currentElseIf : elseIfs)
787:                 {
788:                         correctTypes(currentElseIf.getElseIf(), expectedType);
789:                 }
790:         }
791:
792:         @Override
793:         public void caseAPlainCallStmIR(APlainCallStmIR node)
794:                         throws AnalysisException
795:         {
796:                 STypeIR classType = node.getClassType();
797:
798:                 String className = classType instanceof AClassTypeIR
799:                                 ? ((AClassTypeIR) classType).getName()
800:                                 : node.getAncestor(ADefaultClassDeclIR.class).getName();
801:
802:                 handleCallStm(node, className);
803:         }
804:
805:         @Override
806:         public void caseASuperCallStmIR(ASuperCallStmIR node)
807:                         throws AnalysisException
808:         {
809:                 handleCallStm(node, transAssistant.getInfo().getStmAssistant().getSuperClassName(node));
810:         }
811:
812:         private void handleCallStm(SCallStmIR node, String className)
813:                         throws AnalysisException
814:         {
815:                 for (SExpIR arg : node.getArgs())
816:                 {
817:                         arg.apply(this);
818:                 }
819:
820:                 String fieldName = node.getName();
821:                 LinkedList<SExpIR> args = node.getArgs();
822:
823:                 TypeAssistantIR typeAssistant = transAssistant.getInfo().getAssistantManager().getTypeAssistant();
824:                 AMethodTypeIR methodType = typeAssistant.getMethodType(transAssistant.getInfo(), className, fieldName, args);
825:
826:                 if (methodType != null)
827:                 {
828:                         correctArgTypes(args, methodType.getParams(), true);
829:                 }
830:         }
831:
832:         @SuppressWarnings("unchecked")
833:         @Override
834:         public void inACallObjectExpStmIR(ACallObjectExpStmIR node)
835:                         throws AnalysisException
836:         {
837:                 for (SExpIR arg : node.getArgs())
838:                 {
839:                         arg.apply(this);
840:                 }
841:
842:                 SExpIR objExp = node.getObj();
843:
844:                 STypeIR objType = objExp.getType();
845:                 if (!(objType instanceof AUnionTypeIR))
846:                 {
847:                         return;
848:                 }
849:
850:                 STypeIR type = node.getType();
851:                 LinkedList<SExpIR> args = node.getArgs();
852:                 // String className = node.getClassName();
853:                 String fieldName = node.getFieldName();
854:                 SourceNode sourceNode = node.getSourceNode();
855:
856:                 ACallObjectExpStmIR call = new ACallObjectExpStmIR();
857:                 call.setObj(objExp);
858:                 call.setType(type.clone());
859:                 call.setArgs((List<? extends SExpIR>) args.clone());
860:                 // call.setClassName(className);
861:                 call.setFieldName(fieldName);
862:                 call.setSourceNode(sourceNode);
863:
864:                 ABlockStmIR replacementBlock = new ABlockStmIR();
865:
866:                 if (!(objExp instanceof SVarExpIR))
867:                 {
868:                         String callStmObjName = transAssistant.getInfo().getTempVarNameGen().nextVarName(unionTypePrefixes.callStmObj());
869:
870:                         AIdentifierPatternIR id = new AIdentifierPatternIR();
871:                         id.setName(callStmObjName);
872:                         AVarDeclIR objDecl = transAssistant.getInfo().getDeclAssistant().consLocalVarDecl(node.getSourceNode().getVdmNode(), objType.clone(), id, objExp.clone());
873:
874:                         AIdentifierVarExpIR objVar = new AIdentifierVarExpIR();
875:                         objVar.setSourceNode(node.getSourceNode());
876:                         objVar.setIsLambda(false);
877:                         objVar.setIsLocal(true);
878:                         objVar.setName(callStmObjName);
879:                         objVar.setType(objDecl.getType().clone());
880:
881:                         objExp = objVar;
882:
883:                         replacementBlock.getLocalDefs().add(objDecl);
884:                 }
885:
886:                 TypeAssistantIR typeAssistant = transAssistant.getInfo().getAssistantManager().getTypeAssistant();
887:
888:                 LinkedList<STypeIR> possibleTypes = ((AUnionTypeIR) objType).getTypes();
889:                 AIfStmIR ifChecks = new AIfStmIR();
890:
891:                 int handledTypes = 0;
892:                 for (int i = 0; i < possibleTypes.size(); i++)
893:                 {
894:                         ACallObjectExpStmIR callCopy = call.clone();
895:
896:                         AClassTypeIR currentType = (AClassTypeIR) possibleTypes.get(i);
897:
898:                         AMethodTypeIR methodType = typeAssistant.getMethodType(transAssistant.getInfo(), currentType.getName(), fieldName, args);
899:
900:                         if (methodType != null)
901:                         {
902:                                 correctArgTypes(callCopy.getArgs(), methodType.getParams(), true);
903:                         } else
904:                         {
905:                                 // It's possible (due to the way union types work) that the method type for the
906:                                 // field in the object type does not exist. Let's say we are trying to invoke the
907:                                 // operation 'op' for an object type that is either A or B but it might be the
908:                                 // case that only 'A' has the operation 'op' defined.
909:                                 continue;
910:                         }
911:
912:                         ACastUnaryExpIR castedVarExp = new ACastUnaryExpIR();
913:                         castedVarExp.setType(currentType.clone());
914:                         castedVarExp.setExp(objExp.clone());
915:
916:                         callCopy.setObj(castedVarExp);
917:
918:                         if (handledTypes == 0)
919:                         {
920:                                 ifChecks.setIfExp(consInstanceCheck(objExp, currentType));
921:                                 ifChecks.setThenStm(callCopy);
922:                         } else
923:                         {
924:                                 AElseIfStmIR elseIf = new AElseIfStmIR();
925:                                 elseIf.setElseIf(consInstanceCheck(objExp, currentType));
926:                                 elseIf.setThenStm(callCopy);
927:
928:                                 ifChecks.getElseIf().add(elseIf);
929:                         }
930:
931:                         handledTypes++;
932:                 }
933:
934:                 if (handledTypes == 0)
935:                 {
936:                         return;
937:                 }
938:
939:                 ARaiseErrorStmIR raiseStm = consRaiseStm(MISSING_OP_MEMBER, fieldName);
940:                 ifChecks.setElseStm(raiseStm);
941:
942:                 replacementBlock.getStatements().add(ifChecks);
943:                 transAssistant.replaceNodeWith(node, replacementBlock);
944:                 ifChecks.apply(this);
945:         }
946:
947:         private ARaiseErrorStmIR consRaiseStm(String prefix, String fieldName)
948:         {
949:                 AMissingMemberRuntimeErrorExpIR missingMember = new AMissingMemberRuntimeErrorExpIR();
950:                 missingMember.setType(new AErrorTypeIR());
951:                 missingMember.setMessage(prefix + fieldName);
952:
953:                 ARaiseErrorStmIR raise = new ARaiseErrorStmIR();
954:                 raise.setError(missingMember);
955:
956:                 return raise;
957:         }
958:
959:         @Override
960:         public void inAVarDeclIR(AVarDeclIR node) throws AnalysisException
961:         {
962:                 SExpIR exp = node.getExp();
963:
964:                 if (exp != null)
965:                 {
966:                         exp.apply(this);
967:                 }
968:
969:                 STypeIR type = node.getType();
970:
971:                 if (castNotNeeded(exp, type))
972:                 {
973:                         return;
974:                 }
975:
976:                 if (!(type instanceof AUnionTypeIR))
977:                 {
978:                         correctTypes(exp, type);
979:                 }
980:         }
981:
982:         @Override
983:         public void caseAAssignToExpStmIR(AAssignToExpStmIR node)
984:                         throws AnalysisException
985:         {
986:                 handAssignRighHandSide(node);
987:                 handleAssignTarget(node);
988:         }
989:
990:         public void handleAssignTarget(AAssignToExpStmIR node)
991:                         throws AnalysisException
992:         {
993:                 if (node.getTarget() instanceof AFieldExpIR)
994:                 {
995:                         AFieldExpIR field = (AFieldExpIR) node.getTarget();
996:
997:                         if (field.getObject().getType() instanceof AUnionTypeIR)
998:                         {
999:                                 LinkedList<STypeIR> types = ((AUnionTypeIR) field.getObject().getType()).getTypes();
1000:
1001:                                 AIfStmIR ifChecks = new AIfStmIR();
1002:
1003:                                 for (int i = 0; i < types.size(); i++)
1004:                                 {
1005:                                         STypeIR currentType = types.get(i);
1006:                                         
1007:                                         boolean memberExists = false;
1008:
1009:                                         memberExists = memberExists(field.getMemberName(), field.parent(), transAssistant.getInfo().getTypeAssistant(), field, currentType);
1010:
1011:                                         if (!memberExists)
1012:                                         {
1013:                                                 // If the member does not exist then the case should not be treated
1014:                                                 continue;
1015:                                         }
1016:
1017:                                         AIsOfClassExpIR cond = consInstanceCheck(field.getObject(), currentType);
1018:                                         AAssignToExpStmIR castFieldObj = castFieldObj(node, field, currentType);
1019:
1020:                                         if (ifChecks.getIfExp() == null)
1021:                                         {
1022:                                                 ifChecks.setIfExp(cond);
1023:                                                 ifChecks.setThenStm(castFieldObj);
1024:                                         } else
1025:                                         {
1026:                                                 AElseIfStmIR elseIf = new AElseIfStmIR();
1027:                                                 elseIf.setElseIf(cond);
1028:                                                 elseIf.setThenStm(castFieldObj);
1029:
1030:                                                 ifChecks.getElseIf().add(elseIf);
1031:                                         }
1032:                                 }
1033:
1034:                                 ifChecks.setElseStm(consRaiseStm(MISSING_MEMBER, field.getMemberName()));
1035:
1036:                                 transAssistant.replaceNodeWith(node, ifChecks);
1037:                                 ifChecks.apply(this);
1038:                         }
1039:                 }
1040:         }
1041:
1042:         public void handAssignRighHandSide(AAssignToExpStmIR node)
1043:                         throws AnalysisException
1044:         {
1045:                 if (node.getExp() != null)
1046:                 {
1047:                         node.getExp().apply(this);
1048:                 }
1049:
1050:                 if (!castNotNeeded(node.getExp(), node.getTarget().getType()))
1051:                 {
1052:                         if (!(node.getTarget().getType() instanceof AUnionTypeIR))
1053:                         {
1054:                                 correctTypes(node.getExp(), node.getTarget().getType());
1055:                         }
1056:                 }
1057:         }
1058:
1059:         public AAssignToExpStmIR castFieldObj(AAssignToExpStmIR assign,
1060:                         AFieldExpIR target, STypeIR possibleType)
1061:         {
1062:                 ACastUnaryExpIR cast = new ACastUnaryExpIR();
1063:                 cast.setType(possibleType.clone());
1064:                 cast.setExp(target.getObject().clone());
1065:
1066:                 AAssignToExpStmIR assignCopy = assign.clone();
1067:                 AFieldExpIR fieldCopy = target.clone();
1068:
1069:                 transAssistant.replaceNodeWith(fieldCopy.getObject(), cast);
1070:                 transAssistant.replaceNodeWith(assignCopy.getTarget(), fieldCopy);
1071:
1072:                 return assignCopy;
1073:         }
1074:
1075:         private boolean castNotNeeded(SExpIR exp, STypeIR type)
1076:         {
1077:                 return type instanceof AUnknownTypeIR || exp instanceof ANullExpIR
1078:                                 || exp instanceof AUndefinedExpIR;
1079:         }
1080:
1081:         @Override
1082:         public void caseAReturnStmIR(AReturnStmIR node) throws AnalysisException
1083:         {
1084:                 if (node.getExp() == null)
1085:                 {
1086:                         return; // When the return type of the method is 'void'
1087:                 }
1088:
1089:                 if (node.getExp() instanceof ANullExpIR)
1090:                 {
1091:                         return;
1092:                 }
1093:
1094:                 node.getExp().apply(this);
1095:
1096:                 AMethodDeclIR methodDecl = node.getAncestor(AMethodDeclIR.class);
1097:
1098:                 STypeIR expectedType = methodDecl.getMethodType().getResult();
1099:
1100:                 if (expectedType instanceof AUnknownTypeIR)
1101:                 {
1102:                         return;
1103:                 }
1104:
1105:                 if (!(expectedType instanceof AUnionTypeIR))
1106:                 {
1107:                         correctTypes(node.getExp(), expectedType);
1108:                 }
1109:         }
1110:
1111:         @Override
1112:         public void inAElemsUnaryExpIR(AElemsUnaryExpIR node)
1113:                         throws AnalysisException
1114:         {
1115:                 if (handleUnaryExp(node))
1116:                 {
1117:                         SExpIR exp = node.getExp();
1118:                         PType vdmType = (PType) exp.getType().getSourceNode().getVdmNode();
1119:                         SSeqType seqType = transAssistant.getInfo().getTcFactory().createPTypeAssistant().getSeq(vdmType, null);
1120:
1121:                         try
1122:                         {
1123:                                 STypeIR typeCg = seqType.apply(transAssistant.getInfo().getTypeVisitor(), transAssistant.getInfo());
1124:
1125:                                 if (typeCg instanceof SSeqTypeIR)
1126:                                 {
1127:                                         correctTypes(exp, typeCg);
1128:                                 }
1129:
1130:                         } catch (org.overture.ast.analysis.AnalysisException e)
1131:                         {
1132:                         }
1133:                 }
1134:         }
1135:
1136:         @Override
1137:         public void inAMapDomainUnaryExpIR(AMapDomainUnaryExpIR node)
1138:                         throws AnalysisException
1139:         {
1140:                 if (handleUnaryExp(node))
1141:                 {
1142:                         SExpIR exp = node.getExp();
1143:                         PType vdmType = (PType) exp.getType().getSourceNode().getVdmNode();
1144:                         SMapType mapType = transAssistant.getInfo().getTcFactory().createPTypeAssistant().getMap(vdmType, null);
1145:
1146:                         try
1147:                         {
1148:                                 STypeIR typeCg = mapType.apply(transAssistant.getInfo().getTypeVisitor(), transAssistant.getInfo());
1149:
1150:                                 if (typeCg instanceof SMapTypeIR)
1151:                                 {
1152:                                         correctTypes(exp, typeCg);
1153:                                 }
1154:
1155:                         } catch (org.overture.ast.analysis.AnalysisException e)
1156:                         {
1157:                         }
1158:                 }
1159:         }
1160:
1161:         private SExpIR getAssignmentExp(INode node, SExpIR fieldExp)
1162:         {
1163:                 INode parent = node.parent();
1164:
1165:                 if (parent instanceof AApplyExpIR
1166:                                 && ((AApplyExpIR) parent).getRoot() == node)
1167:                 {
1168:                         AApplyExpIR applyExp = (AApplyExpIR) parent.clone();
1169:                         applyExp.setRoot(fieldExp);
1170:
1171:                         return applyExp;
1172:                 } else
1173:                 {
1174:                         return fieldExp;
1175:                 }
1176:         }
1177:
1178:         private STypeIR getResultType(AFieldExpIR node, INode parent,
1179:                         STypeIR fieldObjType, TypeAssistantIR typeAssistant)
1180:         {
1181:                 if (parent instanceof SExpIR)
1182:                 {
1183:                         if (parent instanceof AApplyExpIR
1184:                                         && ((AApplyExpIR) parent).getRoot() == node)
1185:                         {
1186:                                 return ((SExpIR) parent).getType().clone();
1187:                         }
1188:                 }
1189:
1190:                 return fieldType(node, fieldObjType, typeAssistant);
1191:         }
1192:
1193:         private STypeIR fieldType(AFieldExpIR node, STypeIR objectType,
1194:                         TypeAssistantIR typeAssistant)
1195:         {
1196:                 List<STypeIR> fieldTypes = new LinkedList<STypeIR>();
1197:                 
1198:                 List<STypeIR> types;
1199:                 
1200:                 if(objectType instanceof AUnionTypeIR)
1201:                 {
1202:                         types = ((AUnionTypeIR) objectType).getTypes();
1203:                 }
1204:                 else
1205:                 {
1206:                         types = new LinkedList<>();
1207:                         types.add(objectType);
1208:                 }
1209:
1210:                 for (STypeIR currentType : types)
1211:                 {
1212:                         String memberName = node.getMemberName();
1213:                         STypeIR fieldType = null;
1214:
1215:                         if (currentType instanceof AClassTypeIR)
1216:                         {
1217:                                 AClassTypeIR classType = (AClassTypeIR) currentType;
1218:                                 fieldType = typeAssistant.getFieldType(transAssistant.getInfo().getClasses(), classType.getName(), memberName);
1219:                         } else if (currentType instanceof ARecordTypeIR)
1220:                         {
1221:                                 ARecordTypeIR recordType = (ARecordTypeIR) currentType;
1222:                                 fieldType = transAssistant.getInfo().getTypeAssistant().getFieldType(transAssistant.getInfo().getClasses(), recordType, memberName);
1223:                         } else
1224:                         {
1225:                                 // Can be the unknown type
1226:                                 continue;
1227:                         }
1228:
1229:                         if (fieldType == null)
1230:                         {
1231:                                 // The field type may not be found if the member does not exist
1232:                                 // For example:
1233:                                 //
1234:                                 // types
1235:                                 // R1 :: x : int;
1236:                                 // R2 :: y : int;
1237:                                 // ...
1238:                                 // let inlines : seq of Inline = [mk_R1(4), mk_R2(5)]
1239:                                 // in
1240:                                 // return inlines(1).x + inlines(2).y;
1241:                                 continue;
1242:                         }
1243:
1244:                         if (!typeAssistant.containsType(fieldTypes, fieldType))
1245:                         {
1246:                                 fieldTypes.add(fieldType);
1247:                         }
1248:                 }
1249:
1250:                 if (fieldTypes.size() == 1)
1251:                 {
1252:                         return fieldTypes.get(0);
1253:                 } else
1254:                 {
1255:                         AUnionTypeIR unionTypes = new AUnionTypeIR();
1256:                         unionTypes.setTypes(fieldTypes);
1257:
1258:                         return unionTypes;
1259:                 }
1260:         }
1261: }