Line data Source code
1 : #include "../../../inc/parsingAnalysis/ast/functions/ast_funcCall.h"
2 : #include "../../../inc/parsingAnalysis/ast/functions/ast_funcDecl.h"
3 : #include "../../../inc/parsingAnalysis/ast/functions/ast_return.h"
4 : #include "../../../inc/visitors/typeAnalysis/typeAnalysis.h"
5 : #include <cstddef>
6 : #include <memory>
7 :
8 : namespace nicole {
9 :
10 : /*
11 : - numero correcto de generics en caso de tener
12 : - parametros son del tipo correcto (no pueden ser void ni punteros a este)
13 : - body debe retornar un tipo compatible al tipo de la funcion
14 : - si no tiene generics debe existir una función con esos argumentos
15 : - retorna tipo de función
16 : */
17 : std::expected<std::shared_ptr<Type>, Error>
18 0 : TypeAnalysis::visit(const AST_FUNC_CALL *node) const noexcept {
19 0 : if (!node) {
20 0 : return createError(ERROR_TYPE::NULL_NODE, "Invalid AST_FUNC_CALL");
21 0 : }
22 :
23 0 : std::vector<std::shared_ptr<Type>> argTypes;
24 0 : for (const auto &expr : node->parameters()) {
25 0 : auto res = expr->accept(*this);
26 0 : if (!res)
27 0 : return createError(res.error());
28 0 : argTypes.push_back(res.value());
29 0 : }
30 :
31 0 : auto candidates = functionTable_->getFunctions(node->id());
32 0 : if (candidates.empty())
33 0 : return createError(ERROR_TYPE::FUNCTION,
34 0 : "no function with id: " + node->id() + " exists");
35 :
36 0 : std::vector<Function> viableFunctions;
37 0 : const auto &explicitGenerics = node->replaceOfGenerics();
38 :
39 0 : for (const auto &func : candidates) {
40 0 : if (func.params().size() != argTypes.size())
41 0 : continue;
42 0 : if (!explicitGenerics.empty() &&
43 0 : func.generics().size() != explicitGenerics.size())
44 0 : continue;
45 :
46 0 : bool candidateMatches = true;
47 0 : const auto &funcParams = func.params().params();
48 0 : for (size_t i = 0; i < funcParams.size(); ++i) {
49 0 : auto paramType = funcParams[i].second;
50 0 : auto argType = argTypes[i];
51 :
52 0 : if (insideDeclWithGenerics &&
53 0 : (typeTable_->isGenericType(paramType, currentGenericList_) ||
54 0 : typeTable_->isGenericType(argType, currentGenericList_))) {
55 0 : continue;
56 0 : }
57 0 : if (!typeTable_->canAssign(paramType, argType)) {
58 0 : candidateMatches = false;
59 0 : break;
60 0 : }
61 0 : }
62 0 : if (candidateMatches)
63 0 : viableFunctions.push_back(func);
64 0 : }
65 :
66 0 : if (viableFunctions.empty())
67 0 : return createError(ERROR_TYPE::FUNCTION,
68 0 : "no matching function found for call: " + node->id());
69 0 : if (viableFunctions.size() > 1)
70 0 : return createError(ERROR_TYPE::FUNCTION,
71 0 : "ambiguous function call for: " + node->id());
72 0 : currentType_ = viableFunctions.front().returnType();
73 0 : const auto returnType{viableFunctions.front().returnType()};
74 0 : node->setReturnedFromAnalysis(returnType);
75 0 : return returnType;
76 0 : }
77 :
78 : /*
79 : - parametros no pueden ser void ni punteros a este
80 : - comprobar si algo es generic
81 : - body debe retornar un tipo compatible al tipo de la funcion
82 : - retorna el tipo NoPropagate
83 : */
84 : std::expected<std::shared_ptr<Type>, Error>
85 0 : TypeAnalysis::visit(const AST_FUNC_DECL *node) const noexcept {
86 0 : if (!node)
87 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_FUNC_DECL");
88 :
89 0 : firstBody = false;
90 :
91 0 : if (!node->generics().empty()) {
92 0 : insideDeclWithGenerics = true;
93 0 : currentGenericList_ = node->generics();
94 0 : }
95 :
96 0 : auto bodyRes = node->body()->accept(*this);
97 0 : if (!bodyRes)
98 0 : return createError(bodyRes.error());
99 0 : auto bodyType = bodyRes.value();
100 0 : auto voidType = typeTable_->voidType();
101 0 : auto declaredReturnType = node->returnType();
102 :
103 0 : if (typeTable_->areSameType(bodyType, typeTable_->noPropagateType()) ||
104 0 : typeTable_->areSameType(bodyType, voidType)) {
105 0 : if (!typeTable_->areSameType(declaredReturnType, voidType)) {
106 0 : return createError(ERROR_TYPE::TYPE,
107 0 : "function body returns void/noPropagate, but function "
108 0 : "return type is: " +
109 0 : declaredReturnType->toString());
110 0 : }
111 0 : } else {
112 0 : if (!typeTable_->canAssign(declaredReturnType, bodyType)) {
113 0 : return createError(
114 0 : ERROR_TYPE::TYPE,
115 0 : "function body return type does not match declared return type -> " +
116 0 : declaredReturnType->toString() + " | " + bodyType->toString());
117 0 : }
118 0 : }
119 :
120 0 : insideDeclWithGenerics = false;
121 0 : firstBody = true;
122 0 : currentGenericList_.clear();
123 0 : node->setReturnedFromAnalysis(typeTable_->noPropagateType());
124 0 : return typeTable_->noPropagateType();
125 0 : }
126 :
127 : /*
128 : - si esta vacio retorna void
129 : - si no el tipo de la expresion
130 : */
131 : std::expected<std::shared_ptr<Type>, Error>
132 0 : TypeAnalysis::visit(const AST_RETURN *node) const noexcept {
133 0 : if (!node) {
134 0 : return createError(ERROR_TYPE::NULL_NODE, "invalid AST_RETURN");
135 0 : }
136 :
137 0 : if (firstBody)
138 0 : foundReturn = true;
139 0 : else {
140 0 : foundReturn = false;
141 0 : }
142 0 : const auto voidType{typeTable_->voidType()};
143 0 : if (!node->expression()) {
144 0 : node->setReturnedFromAnalysis(voidType);
145 0 : return voidType;
146 0 : }
147 0 : auto result = node->expression()->accept(*this);
148 0 : if (!result)
149 0 : return createError(result.error());
150 0 : auto retType = result.value();
151 :
152 0 : if (insideDeclWithGenerics &&
153 0 : typeTable_->isGenericType(retType, currentGenericList_)) {
154 0 : node->setReturnedFromAnalysis(retType);
155 0 : return retType;
156 0 : }
157 :
158 0 : if (typeTable_->areSameType(retType, voidType)) {
159 0 : return createError(ERROR_TYPE::TYPE,
160 0 : "a return statement can return void when it does not "
161 0 : "have expression, but if it has it must not be void");
162 0 : }
163 :
164 0 : node->setReturnedFromAnalysis(retType);
165 0 : return retType;
166 0 : }
167 :
168 : } // namespace nicole
|