Line data Source code
1 : #include "../../../inc/visitors/typeAnalysis/typeAnalysis.h"
2 : #include "../../../inc/parsingAnalysis/ast/tree.h"
3 : #include <cstddef>
4 : #include <memory>
5 :
6 : /**
7 :
8 : FillSemanticInfo ---> insertar delcaraciones en las tablas / insertar tipos /
9 : comprobar que las variables pertenecen al scope (llamadas a variables) /
10 : comrpobar llamadas a enum
11 :
12 : TypeAnalysis ---> comprobar en una llamada a funcion que esta existe debido a
13 : sobrecarga de funciones requiere que se trate en el typeAnalysis / igual con
14 : metodos / llamadas a atributos / variables auto
15 :
16 : */
17 :
18 : namespace nicole {
19 :
20 : std::vector<GenericParameter> TypeAnalysis::mergeGenericLists(
21 : const std::vector<GenericParameter> &list,
22 0 : const std::vector<GenericParameter> &list1) const noexcept {
23 0 : std::vector<GenericParameter> result{};
24 0 : result.insert(result.end(), list.begin(), list.end());
25 0 : result.insert(result.end(), list1.begin(), list1.end());
26 0 : return result;
27 0 : }
28 :
29 : /*
30 : - retorna el tipo de la expresion
31 : */
32 : std::expected<std::shared_ptr<Type>, Error>
33 0 : TypeAnalysis::visit(const AST_STATEMENT *node) const noexcept {
34 0 : if (!node) {
35 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_STATEMENT");
36 0 : }
37 0 : const auto result{node->expression()->accept(*this)};
38 0 : if (!result) {
39 0 : return createError(result.error());
40 0 : }
41 0 : node->setReturnedFromAnalysis(*result);
42 0 : return result;
43 0 : }
44 :
45 : /*
46 : - si encuentra pass y stop devuelve void
47 : - si encuentra un return retorna su tipo, vijilar varios returns en diferentes
48 : body anidados
49 : - si no encuentra nada retorna NoPropagate
50 : */
51 : std::expected<std::shared_ptr<Type>, Error>
52 0 : TypeAnalysis::visit(const AST_BODY *node) const noexcept {
53 0 : if (!node) {
54 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_BODY");
55 0 : }
56 0 : currentScope_ = node->scope();
57 0 : std::vector<std::shared_ptr<Type>> returnTypes;
58 0 : bool foundBreak = false;
59 :
60 0 : for (const auto &expr : node->body()) {
61 0 : auto result = expr->accept(*this);
62 0 : if (!result)
63 0 : return createError(result.error());
64 :
65 0 : auto type = result.value();
66 0 : if (typeTable_->areSameType(type, typeTable_->noPropagateType()))
67 0 : continue;
68 :
69 0 : if (typeTable_->areSameType(type, typeTable_->breakType())) {
70 0 : foundBreak = true;
71 0 : continue;
72 0 : }
73 :
74 : /*
75 : if (!node->father()) {
76 :
77 : }
78 : */
79 0 : if (firstBody) {
80 0 : if (!foundReturn) {
81 0 : continue;
82 0 : }
83 0 : foundReturn = false;
84 0 : if (!typeTable_->areSameType(type, typeTable_->voidType()) and
85 0 : !typeTable_->areSameType(type, typeTable_->noPropagateType()) and
86 0 : !typeTable_->areSameType(type, typeTable_->intType())) {
87 0 : return createError(
88 0 : ERROR_TYPE::TYPE,
89 0 : " if a return affects the root body it must be void/int and cannot "
90 0 : "be affected by both at the same time");
91 0 : }
92 0 : returnTypes.push_back(type);
93 0 : }
94 :
95 0 : if (!firstBody) {
96 0 : returnTypes.push_back(type);
97 0 : }
98 0 : }
99 :
100 0 : if (!returnTypes.empty() && foundBreak)
101 0 : return createError(ERROR_TYPE::TYPE,
102 0 : "inconsistent return types: cannot mix return and "
103 0 : "break/continue in the same body");
104 :
105 0 : if (!returnTypes.empty()) {
106 0 : auto commonType = returnTypes.front();
107 0 : for (size_t i = 1; i < returnTypes.size(); ++i) {
108 0 : if (!typeTable_->areSameType(commonType, returnTypes[i])) {
109 0 : if (!typeTable_->haveCommonAncestor(commonType, returnTypes[i])) {
110 0 : return createError(ERROR_TYPE::TYPE,
111 0 : "inconsistent return types in body with id: " +
112 0 : std::to_string(node->nodeId()));
113 0 : }
114 0 : }
115 0 : }
116 0 : node->setReturnedFromAnalysis(commonType);
117 0 : return commonType;
118 0 : }
119 0 : if (foundBreak) {
120 0 : node->setReturnedFromAnalysis(typeTable_->breakType());
121 0 : return typeTable_->breakType();
122 0 : }
123 0 : node->setReturnedFromAnalysis(typeTable_->noPropagateType());
124 0 : return typeTable_->noPropagateType();
125 0 : }
126 :
127 : /*
128 : - comprueba que no hubo errores
129 : - retorna int / void
130 : */
131 : std::expected<std::shared_ptr<Type>, Error>
132 0 : TypeAnalysis::visit(const Tree *tree) const noexcept {
133 0 : if (!tree) {
134 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid Tree");
135 0 : }
136 0 : auto result = tree->root()->accept(*this);
137 0 : if (!result)
138 0 : return createError(result.error());
139 :
140 0 : auto bodyType = result.value();
141 0 : if (auto constBody = std::dynamic_pointer_cast<ConstType>(bodyType))
142 0 : bodyType = constBody->baseType();
143 :
144 0 : if (!(typeTable_->areSameType(bodyType, typeTable_->intType()) ||
145 0 : typeTable_->areSameType(bodyType, typeTable_->voidType()) ||
146 0 : typeTable_->areSameType(bodyType, typeTable_->noPropagateType())))
147 0 : return createError(ERROR_TYPE::TYPE,
148 0 : "body must return int, void, or noPropagate, got " +
149 0 : bodyType->toString());
150 :
151 0 : return result;
152 0 : }
153 :
154 : } // namespace nicole
|