Method: caseASetMultipleBind(ASetMultipleBind, TypeCheckInfo)
1: /*
2: * #%~
3: * The VDM Type Checker
4: * %%
5: * Copyright (C) 2008 - 2014 Overture
6: * %%
7: * This program is free software: you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as
9: * published by the Free Software Foundation, either version 3 of the
10: * License, or (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public
18: * License along with this program. If not, see
19: * <http://www.gnu.org/licenses/gpl-3.0.html>.
20: * #~%
21: */
22: package org.overture.typechecker.visitor;
23:
24: import org.overture.ast.analysis.AnalysisException;
25: import org.overture.ast.analysis.intf.IQuestionAnswer;
26: import org.overture.ast.definitions.PDefinition;
27: import org.overture.ast.factory.AstFactory;
28: import org.overture.ast.patterns.ANamePatternPair;
29: import org.overture.ast.patterns.AObjectPattern;
30: import org.overture.ast.patterns.ASeqMultipleBind;
31: import org.overture.ast.patterns.ASetMultipleBind;
32: import org.overture.ast.patterns.ATypeMultipleBind;
33: import org.overture.ast.typechecker.NameScope;
34: import org.overture.ast.types.AClassType;
35: import org.overture.ast.types.SSeqType;
36: import org.overture.ast.types.SSetType;
37: import org.overture.ast.types.PType;
38: import org.overture.typechecker.TypeCheckInfo;
39: import org.overture.typechecker.TypeCheckerErrors;
40: import org.overture.typechecker.assistant.type.PTypeAssistantTC;
41:
42: public class TypeCheckerPatternVisitor extends AbstractTypeCheckVisitor
43: {
44:
45:         public TypeCheckerPatternVisitor(
46:                         IQuestionAnswer<TypeCheckInfo, PType> typeCheckVisitor)
47:         {
48:                 super(typeCheckVisitor);
49:         }
50:
51:         @Override
52:         public PType caseASetMultipleBind(ASetMultipleBind node,
53:                         TypeCheckInfo question) throws AnalysisException
54:         {
55:
56:                 question.assistantFactory.createPPatternListAssistant().typeResolve(node.getPlist(), THIS, question);
57:                 question.qualifiers = null;
58:                 PType type = node.getSet().apply(THIS, question);
59:                 PType result = AstFactory.newAUnknownType(node.getLocation());
60:
61:•                if (!question.assistantFactory.createPTypeAssistant().isSet(type, question.fromModule))
62:                 {
63:                         TypeCheckerErrors.report(3197, "Expression matching set bind is not a set", node.getSet().getLocation(), node.getSet());
64:                         TypeCheckerErrors.detail("Actual type", type);
65:                 } else
66:                 {
67:                         SSetType st = question.assistantFactory.createPTypeAssistant().getSet(type, question.fromModule);
68:
69:•                        if (!st.getEmpty())
70:                         {
71:                                 result = st.getSetof();
72:                                 PType ptype = question.assistantFactory.createPMultipleBindAssistant().getPossibleType(node);
73:
74:•                                if (!question.assistantFactory.getTypeComparator().compatible(ptype, result))
75:                                 {
76:                                         TypeCheckerErrors.report(3264, "At least one bind cannot match set", node.getSet().getLocation(), node.getSet());
77:                                         TypeCheckerErrors.detail2("Binds", ptype, "Set of", st);
78:                                 }
79:                         } else
80:                         {
81:                                 TypeCheckerErrors.warning(5009, "Empty set used in bind", node.getSet().getLocation(), node.getSet());
82:                         }
83:                 }
84:
85:                 return result;
86:         }
87:
88:         @Override
89:         public PType caseASeqMultipleBind(ASeqMultipleBind node,
90:                         TypeCheckInfo question) throws AnalysisException
91:         {
92:                 question.assistantFactory.createPPatternListAssistant().typeResolve(node.getPlist(), THIS, question);
93:                 question.qualifiers = null;
94:                 PType type = node.getSeq().apply(THIS, question);
95:                 PType result = AstFactory.newAUnknownType(node.getLocation());
96:
97:                 if (!question.assistantFactory.createPTypeAssistant().isSeq(type, question.fromModule))
98:                 {
99:                         TypeCheckerErrors.report(3197, "Expression matching seq bind is not a sequence", node.getSeq().getLocation(), node.getSeq());
100:                         TypeCheckerErrors.detail("Actual type", type);
101:                 }
102:                 else
103:                 {
104:                         SSeqType st = question.assistantFactory.createPTypeAssistant().getSeq(type, question.fromModule);
105:
106:                         if (!st.getEmpty())
107:                         {
108:                                 result = st.getSeqof();
109:                                 PType ptype = question.assistantFactory.createPMultipleBindAssistant().getPossibleType(node);
110:
111:                                 if (!question.assistantFactory.getTypeComparator().compatible(ptype, result))
112:                                 {
113:                                         TypeCheckerErrors.report(3264, "At least one bind cannot match sequence", node.getSeq().getLocation(), node.getSeq());
114:                                         TypeCheckerErrors.detail2("Binds", ptype, "Seq of", st);
115:                                 }
116:                         } else
117:                         {
118:                                 TypeCheckerErrors.warning(5009, "Empty squence used in bind", node.getSeq().getLocation(), node.getSeq());
119:                         }
120:                 }
121:
122:                 return result;
123:         }
124:
125:         @Override
126:         public PType caseATypeMultipleBind(ATypeMultipleBind node,
127:                         TypeCheckInfo question) throws AnalysisException
128:         {
129:
130:                 question.assistantFactory.createPPatternListAssistant().typeResolve(node.getPlist(), THIS, question);
131:                 PType type = question.assistantFactory.createPTypeAssistant().typeResolve(node.getType(), null, THIS, question);
132:                 PType ptype = question.assistantFactory.createPPatternListAssistant().getPossibleType(node.getPlist(), node.getLocation());
133:
134:                 if (!question.assistantFactory.getTypeComparator().compatible(ptype, type))
135:                 {
136:                         TypeCheckerErrors.report(3265, "At least one bind cannot match this type", type.getLocation(), type);
137:                         TypeCheckerErrors.detail2("Binds", ptype, "Type", type);
138:                 }
139:
140:                 node.setType(type);
141:                 return type;
142:         }
143:
144:         @Override
145:         public PType caseAObjectPattern(AObjectPattern pattern, TypeCheckInfo question) throws AnalysisException
146:         {
147:                 PTypeAssistantTC typeAssistant = question.assistantFactory.createPTypeAssistant();
148:                 
149:                 if (!typeAssistant.isClass(pattern.getType(), question.env, question.fromModule))
150:                 {
151:                         TypeCheckerErrors.report(3331, "obj_ expression is not an object type", pattern.getLocation(), pattern);
152:                         TypeCheckerErrors.detail("Type", pattern.getType());
153:                 }
154:                 else
155:                 {
156:                         // Check whether the field access is permitted from here.
157:                         AClassType cls = typeAssistant.getClassType(pattern.getType(), question.env, question.fromModule);
158:         
159:                         for (ANamePatternPair npp: pattern.getFields())
160:                         {
161:                                 PDefinition fdef = question.assistantFactory.createAClassTypeAssistant().findName(cls, npp.getName(), NameScope.STATE);
162:         
163:                                 if (fdef == null)
164:                                 {
165:                                         TypeCheckerErrors.report(3091, "Unknown member " + npp.getName() + " of class " + cls.getName().getName(), npp.getName().getLocation(), npp.getName());
166:                                 }
167:                                 else if (!question.assistantFactory.createSClassDefinitionAssistant().isAccessible(question.env, fdef, false))
168:                                 {
169:                                         TypeCheckerErrors.report(3092, "Inaccessible member " + npp.getName() + " of class " + cls.getName().getName(), npp.getName().getLocation(), npp.getName());
170:                                 }
171:                         }
172:         
173:                         if (question.env.isFunctional())
174:                         {
175:                                 TypeCheckerErrors.report(3332, "Object pattern cannot be used from a function", pattern.getLocation(), pattern);
176:                         }
177:                 }
178:                 
179:                 return pattern.getType();
180:         }
181: }