Line data Source code
1 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_case.h"
2 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_default.h"
3 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_elseIf.h"
4 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_if.h"
5 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_switch.h"
6 : #include "../../../inc/parsingAnalysis/ast/conditionals/ast_ternary.h"
7 : #include "../../../inc/visitors/typeAnalysis/typeAnalysis.h"
8 : #include <cstddef>
9 : #include <memory>
10 :
11 : namespace nicole {
12 :
13 : /*
14 : - codition debe ser bool
15 : - body lo mismo que el resto
16 : - else if lo mismo que if
17 : - else lo mismo que body
18 : */
19 : std::expected<std::shared_ptr<Type>, Error>
20 0 : TypeAnalysis::visit(const AST_IF *node) const noexcept {
21 0 : if (!node) {
22 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_IF");
23 0 : }
24 0 : auto condition = node->condition()->accept(*this);
25 0 : if (!condition)
26 0 : return createError(condition.error());
27 0 : auto condType = condition.value();
28 :
29 0 : if (auto constCond = std::dynamic_pointer_cast<ConstType>(condType))
30 0 : condType = constCond->baseType();
31 :
32 0 : bool isGeneric{false};
33 0 : if (insideDeclWithGenerics &&
34 0 : typeTable_->isGenericType(condType, currentGenericList_)) {
35 0 : isGeneric = true;
36 : // return condType;
37 0 : }
38 :
39 0 : if (!isGeneric) {
40 0 : if (!typeTable_->areSameType(condType, typeTable_->boolType()))
41 0 : return createError(ERROR_TYPE::TYPE, "a condition must be boolean");
42 0 : }
43 :
44 0 : auto mainBody = node->body()->accept(*this);
45 0 : if (!mainBody)
46 0 : return createError(mainBody.error());
47 :
48 0 : std::vector<std::shared_ptr<Type>> branchTypes;
49 :
50 0 : if (!typeTable_->areSameType(mainBody.value(),
51 0 : typeTable_->noPropagateType()) &&
52 0 : !typeTable_->areSameType(mainBody.value(), typeTable_->breakType())) {
53 0 : branchTypes.push_back(mainBody.value());
54 0 : }
55 :
56 0 : for (const auto &elseIf : node->elseIf()) {
57 0 : auto elseIfResult = elseIf->accept(*this);
58 0 : if (!elseIfResult)
59 0 : return createError(elseIfResult.error());
60 0 : if (!typeTable_->areSameType(elseIfResult.value(),
61 0 : typeTable_->noPropagateType()) &&
62 0 : !typeTable_->areSameType(elseIfResult.value(),
63 0 : typeTable_->breakType())) {
64 0 : branchTypes.push_back(elseIfResult.value());
65 0 : }
66 0 : }
67 :
68 0 : if (node->elseBody()) {
69 0 : auto elseBody = node->elseBody()->accept(*this);
70 0 : if (!elseBody)
71 0 : return createError(elseBody.error());
72 0 : if (!typeTable_->areSameType(elseBody.value(),
73 0 : typeTable_->noPropagateType()) &&
74 0 : !typeTable_->areSameType(elseBody.value(), typeTable_->breakType())) {
75 0 : branchTypes.push_back(elseBody.value());
76 0 : }
77 0 : }
78 :
79 0 : if (!branchTypes.empty()) {
80 0 : auto commonType = branchTypes.front();
81 0 : for (size_t i = 1; i < branchTypes.size(); ++i) {
82 0 : if (!typeTable_->areSameType(commonType, branchTypes[i])) {
83 0 : if (!typeTable_->haveCommonAncestor(commonType, branchTypes[i])) {
84 0 : return createError(ERROR_TYPE::TYPE,
85 0 : "inconsistent return types in if branches");
86 0 : }
87 0 : }
88 0 : }
89 0 : node->setReturnedFromAnalysis(commonType);
90 0 : return commonType;
91 0 : }
92 0 : node->setReturnedFromAnalysis(typeTable_->noPropagateType());
93 0 : return typeTable_->noPropagateType();
94 0 : }
95 :
96 : /*
97 : - lo mismo que if
98 : */
99 : std::expected<std::shared_ptr<Type>, Error>
100 0 : TypeAnalysis::visit(const AST_ELSE_IF *node) const noexcept {
101 0 : if (!node) {
102 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_ELSE_IF");
103 0 : }
104 0 : auto condition = node->condition()->accept(*this);
105 0 : if (!condition)
106 0 : return createError(condition.error());
107 0 : auto condType = condition.value();
108 :
109 0 : if (auto constCond = std::dynamic_pointer_cast<ConstType>(condType))
110 0 : condType = constCond->baseType();
111 :
112 0 : bool isGeneric{false};
113 0 : if (insideDeclWithGenerics &&
114 0 : typeTable_->isGenericType(condType, currentGenericList_)) {
115 0 : isGeneric = true;
116 : // return condType;
117 0 : }
118 :
119 0 : if (!isGeneric) {
120 0 : if (!typeTable_->areSameType(condType, typeTable_->boolType()))
121 0 : return createError(ERROR_TYPE::TYPE, "a condition must be boolean");
122 0 : }
123 :
124 0 : auto body = node->body()->accept(*this);
125 0 : if (!body)
126 0 : return createError(body.error());
127 0 : auto bodyType = body.value();
128 :
129 0 : if (!typeTable_->areSameType(bodyType, typeTable_->noPropagateType()) &&
130 0 : !typeTable_->areSameType(bodyType, typeTable_->breakType())) {
131 0 : node->setReturnedFromAnalysis(bodyType);
132 0 : return bodyType;
133 0 : }
134 0 : node->setReturnedFromAnalysis(typeTable_->noPropagateType());
135 0 : return typeTable_->noPropagateType();
136 0 : }
137 :
138 : /*
139 : - match solo bool, int, char
140 : - Lo mismo que if
141 : */
142 : std::expected<std::shared_ptr<Type>, Error>
143 0 : TypeAnalysis::visit(const AST_SWITCH *node) const noexcept {
144 0 : if (!node) {
145 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_SWITCH");
146 0 : }
147 0 : auto condition = node->condition()->accept(*this);
148 0 : if (!condition)
149 0 : return createError(condition.error());
150 0 : auto condType = condition.value();
151 0 : if (auto constCond = std::dynamic_pointer_cast<ConstType>(condType))
152 0 : condType = constCond->baseType();
153 :
154 0 : bool isGeneric{false};
155 0 : if (insideDeclWithGenerics &&
156 0 : typeTable_->isGenericType(condType, currentGenericList_)) {
157 0 : isGeneric = true;
158 : // return condType;
159 0 : }
160 :
161 0 : if (!isGeneric) {
162 0 : bool isEnum = (std::dynamic_pointer_cast<EnumType>(condType) != nullptr);
163 0 : if (!(typeTable_->areSameType(condType, typeTable_->boolType()) ||
164 0 : typeTable_->areSameType(condType, typeTable_->intType()) ||
165 0 : typeTable_->areSameType(condType, typeTable_->charType()) ||
166 0 : isEnum)) {
167 0 : return createError(ERROR_TYPE::TYPE,
168 0 : "switch condition must be bool, int, char, or enum");
169 0 : }
170 0 : }
171 :
172 0 : switchTypeCondition_ = condType;
173 0 : std::vector<std::shared_ptr<Type>> branchTypes;
174 0 : for (const auto &caseNode : node->cases()) {
175 0 : auto caseResult = caseNode->accept(*this);
176 0 : if (!caseResult)
177 0 : return createError(caseResult.error());
178 0 : auto caseType = caseResult.value();
179 0 : if (!typeTable_->areSameType(caseType, typeTable_->noPropagateType()) &&
180 0 : !typeTable_->areSameType(caseType, typeTable_->breakType())) {
181 0 : branchTypes.push_back(caseType);
182 0 : }
183 0 : }
184 0 : if (node->defaultCase()) {
185 0 : auto defaultResult = node->defaultCase()->accept(*this);
186 0 : if (!defaultResult)
187 0 : return createError(defaultResult.error());
188 0 : auto defaultType = defaultResult.value();
189 0 : if (!typeTable_->areSameType(defaultType, typeTable_->noPropagateType()) &&
190 0 : !typeTable_->areSameType(defaultType, typeTable_->breakType())) {
191 0 : branchTypes.push_back(defaultType);
192 0 : }
193 0 : }
194 0 : if (!branchTypes.empty()) {
195 0 : auto commonType = branchTypes.front();
196 0 : for (size_t i = 1; i < branchTypes.size(); ++i) {
197 0 : if (!typeTable_->areSameType(commonType, branchTypes[i])) {
198 0 : if (!typeTable_->haveCommonAncestor(commonType, branchTypes[i])) {
199 0 : return createError(ERROR_TYPE::TYPE,
200 0 : "inconsistent return types in switch branches");
201 0 : }
202 0 : }
203 0 : }
204 0 : node->setReturnedFromAnalysis(commonType);
205 0 : return commonType;
206 0 : }
207 0 : node->setReturnedFromAnalysis(typeTable_->noPropagateType());
208 0 : return typeTable_->noPropagateType();
209 0 : }
210 :
211 : /*
212 : - match solo bool, int char
213 : - igual que body
214 : */
215 : std::expected<std::shared_ptr<Type>, Error>
216 0 : TypeAnalysis::visit(const AST_CASE *node) const noexcept {
217 0 : if (!node) {
218 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_CASE");
219 0 : }
220 0 : auto matchResult = node->match()->accept(*this);
221 0 : if (!matchResult)
222 0 : return createError(matchResult.error());
223 0 : auto matchType = matchResult.value();
224 :
225 0 : if (auto constMatch = std::dynamic_pointer_cast<ConstType>(matchType))
226 0 : matchType = constMatch->baseType();
227 :
228 0 : bool isGeneric{false};
229 0 : if (insideDeclWithGenerics &&
230 0 : typeTable_->isGenericType(matchType, currentGenericList_)) {
231 0 : isGeneric = true;
232 : // return matchType;
233 0 : }
234 :
235 0 : if (!isGeneric) {
236 0 : if (!typeTable_->areSameType(matchType, switchTypeCondition_))
237 0 : return createError(
238 0 : ERROR_TYPE::TYPE,
239 0 : "case match type does not match switch condition type");
240 0 : }
241 :
242 0 : auto bodyResult = node->body()->accept(*this);
243 0 : if (!bodyResult)
244 0 : return createError(bodyResult.error());
245 0 : auto bodyType = bodyResult.value();
246 :
247 0 : if (!typeTable_->areSameType(bodyType, typeTable_->noPropagateType()) &&
248 0 : !typeTable_->areSameType(bodyType, typeTable_->breakType())) {
249 0 : node->setReturnedFromAnalysis(bodyType);
250 0 : return bodyType;
251 0 : }
252 0 : node->setReturnedFromAnalysis(typeTable_->noPropagateType());
253 0 : return typeTable_->noPropagateType();
254 0 : }
255 :
256 : /*
257 : - igual que body
258 : */
259 : std::expected<std::shared_ptr<Type>, Error>
260 0 : TypeAnalysis::visit(const AST_DEFAULT *node) const noexcept {
261 0 : if (!node) {
262 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_DEFAULT");
263 0 : }
264 0 : auto bodyResult = node->body()->accept(*this);
265 0 : if (!bodyResult)
266 0 : return createError(bodyResult.error());
267 0 : auto bodyType = bodyResult.value();
268 :
269 0 : if (!typeTable_->areSameType(bodyType, typeTable_->noPropagateType()) &&
270 0 : !typeTable_->areSameType(bodyType, typeTable_->breakType())) {
271 0 : node->setReturnedFromAnalysis(bodyType);
272 0 : return bodyType;
273 0 : }
274 0 : node->setReturnedFromAnalysis(typeTable_->noPropagateType());
275 0 : return typeTable_->noPropagateType();
276 0 : }
277 :
278 : /*
279 : - condtion debe ser bool
280 : - first y second no pueden ser breakType
281 : */
282 : std::expected<std::shared_ptr<Type>, Error>
283 0 : TypeAnalysis::visit(const AST_TERNARY *node) const noexcept {
284 0 : if (!node) {
285 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_TERNARY");
286 0 : }
287 0 : auto condition = node->condition()->accept(*this);
288 0 : if (!condition)
289 0 : return createError(condition.error());
290 0 : auto condType = condition.value();
291 :
292 0 : if (auto constCond = std::dynamic_pointer_cast<ConstType>(condType))
293 0 : condType = constCond->baseType();
294 :
295 0 : bool isGeneric{false};
296 0 : if (insideDeclWithGenerics &&
297 0 : typeTable_->isGenericType(condType, currentGenericList_)) {
298 0 : isGeneric = true;
299 : // return condType;
300 0 : }
301 :
302 0 : if (!isGeneric) {
303 0 : if (!typeTable_->areSameType(condType, typeTable_->boolType()))
304 0 : return createError(ERROR_TYPE::TYPE, "a condition must be boolean");
305 0 : }
306 :
307 0 : auto firstResult = node->first()->accept(*this);
308 0 : if (!firstResult)
309 0 : return createError(firstResult.error());
310 0 : auto firstType = firstResult.value();
311 : /*
312 : if (insideDeclWithGenerics &&
313 : typeTable_->isGenericType(firstType, currentGenericList_))
314 : firstType = std::make_shared<PlaceHolder>(firstType);
315 : */
316 0 : auto secondResult = node->second()->accept(*this);
317 0 : if (!secondResult)
318 0 : return createError(secondResult.error());
319 0 : auto secondType = secondResult.value();
320 : /*
321 : if (insideDeclWithGenerics &&
322 : typeTable_->isGenericType(secondType, currentGenericList_))
323 : secondType = std::make_shared<PlaceHolder>(secondType);
324 : */
325 0 : if (typeTable_->areSameType(firstType, secondType)) {
326 0 : node->setReturnedFromAnalysis(firstType);
327 0 : return firstType;
328 0 : } else if (!typeTable_->haveCommonAncestor(firstType, secondType))
329 0 : return createError(ERROR_TYPE::TYPE,
330 0 : "inconsistent types in ternary operator");
331 0 : else {
332 0 : node->setReturnedFromAnalysis(firstType);
333 0 : return firstType;
334 0 : }
335 0 : }
336 :
337 : /*
338 : - debe retornar bool
339 : */
340 : std::expected<std::shared_ptr<Type>, Error>
341 0 : TypeAnalysis::visit(const AST_CONDITION *node) const noexcept {
342 0 : if (!node) {
343 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_CONDITION");
344 0 : }
345 0 : auto condResult = node->condition()->accept(*this);
346 0 : if (!condResult)
347 0 : return createError(condResult.error());
348 0 : auto condType = condResult.value();
349 :
350 0 : if (auto constCond = std::dynamic_pointer_cast<ConstType>(condType))
351 0 : condType = constCond->baseType();
352 :
353 0 : if (insideDeclWithGenerics &&
354 0 : typeTable_->isGenericType(condType, currentGenericList_)) {
355 0 : return condType;
356 0 : }
357 :
358 0 : bool isEnum = (std::dynamic_pointer_cast<EnumType>(condType) != nullptr);
359 :
360 0 : if (!typeTable_->areSameType(condType, typeTable_->boolType()) &&
361 0 : !typeTable_->areSameType(condType, typeTable_->intType()) &&
362 0 : !typeTable_->areSameType(condType, typeTable_->charType()) && !isEnum) {
363 0 : return createError(ERROR_TYPE::TYPE,
364 0 : "condition must be bool, int, char, or enum(in a switch)");
365 0 : }
366 0 : node->setReturnedFromAnalysis(condType);
367 0 : return condType;
368 0 : }
369 :
370 : } // namespace nicole
|