LCOV - code coverage report
Current view: top level - src/visitors/typeAnalysis - typeAnalysisFunctions.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 119 0
Test Date: 2025-04-18 15:53:49 Functions: 0.0 % 3 0

            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
        

Generated by: LCOV version 2.0-1