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

            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
        

Generated by: LCOV version 2.0-1