Line data Source code
1 : #include "../../../inc/tables/typeTable/typeManager.h"
2 : #include <memory>
3 :
4 : namespace nicole {
5 :
6 : bool TypeManager::canAssign(const std::shared_ptr<Type> &dest,
7 0 : const std::shared_ptr<Type> &src) const noexcept {
8 : // Caso 0: Si ambos punteros son iguales o alguno es nulo.
9 0 : if (dest == src) {
10 0 : return true;
11 0 : }
12 0 : if (!dest || !src) {
13 0 : return false;
14 0 : }
15 :
16 : // Caso 1: Manejo de tipos const (se "desenvuelven" para comparar el tipo
17 : // base).
18 0 : if (auto destConst = std::dynamic_pointer_cast<ConstType>(dest)) {
19 0 : return canAssign(destConst->baseType(), src);
20 0 : }
21 0 : if (auto srcConst = std::dynamic_pointer_cast<ConstType>(src)) {
22 0 : return canAssign(dest, srcConst->baseType());
23 0 : }
24 :
25 : // Caso 2: Tipos básicos.
26 0 : if (auto destBasic = std::dynamic_pointer_cast<BasicType>(dest)) {
27 0 : if (auto srcBasic = std::dynamic_pointer_cast<BasicType>(src)) {
28 0 : if (destBasic->baseKind() == srcBasic->baseKind()) {
29 0 : return true;
30 0 : }
31 : // Ejemplo de promoción: char -> int.
32 0 : if (srcBasic->baseKind() == BasicKind::Char &&
33 0 : destBasic->baseKind() == BasicKind::Int) {
34 0 : return true;
35 0 : }
36 : // Se pueden agregar otras reglas de conversión.
37 0 : return false;
38 0 : }
39 0 : return false;
40 0 : }
41 :
42 : // Caso 3: Tipo void.
43 0 : if (std::dynamic_pointer_cast<VoidType>(dest)) {
44 0 : return std::dynamic_pointer_cast<VoidType>(src) != nullptr;
45 0 : }
46 :
47 : // Caso 4: Tipo nulo.
48 0 : if (std::dynamic_pointer_cast<NullType>(src)) {
49 : // Se permite asignar nullptr a punteros o si ambos son nullptr.
50 0 : return std::dynamic_pointer_cast<PointerType>(dest) ||
51 0 : std::dynamic_pointer_cast<NullType>(dest);
52 0 : }
53 :
54 : // Caso 5: Tipos puntero.
55 0 : if (auto destPtr = std::dynamic_pointer_cast<PointerType>(dest)) {
56 0 : if (auto srcPtr = std::dynamic_pointer_cast<PointerType>(src)) {
57 0 : return canAssign(destPtr->baseType(), srcPtr->baseType());
58 0 : }
59 0 : return false;
60 0 : }
61 :
62 : // Caso 6: Tipos vector.
63 0 : if (auto destVec = std::dynamic_pointer_cast<VectorType>(dest)) {
64 0 : if (auto srcVec = std::dynamic_pointer_cast<VectorType>(src)) {
65 0 : return canAssign(destVec->elementType(), srcVec->elementType());
66 0 : }
67 0 : return false;
68 0 : }
69 :
70 : // Caso 7: Tipos de usuario y sus instancias genéricas.
71 0 : if (auto destUser = std::dynamic_pointer_cast<UserType>(dest)) {
72 0 : if (auto srcUser = std::dynamic_pointer_cast<UserType>(src)) {
73 : // Si se trata de instancias genéricas, se deben comparar los argumentos.
74 0 : if (auto destGen = std::dynamic_pointer_cast<GenericInstanceType>(dest)) {
75 0 : if (auto srcGen = std::dynamic_pointer_cast<GenericInstanceType>(src)) {
76 0 : if (destGen->name() != srcGen->name()) {
77 0 : return false;
78 0 : }
79 0 : const auto &destArgs = destGen->typeArgs();
80 0 : const auto &srcArgs = srcGen->typeArgs();
81 0 : if (destArgs.size() != srcArgs.size()) {
82 0 : return false;
83 0 : }
84 0 : for (size_t i = 0; i < destArgs.size(); ++i) {
85 0 : if (!canAssign(destArgs[i], srcArgs[i])) {
86 0 : return false;
87 0 : }
88 0 : }
89 0 : return true;
90 0 : }
91 0 : return false;
92 0 : }
93 : // Para tipos de usuario no genéricos, se permite si son iguales o si
94 : // 'dest' es un antecesor en la jerarquía de 'src'.
95 0 : if (destUser->name() == srcUser->name() ||
96 0 : destUser->isAboveInHearchy(srcUser)) {
97 0 : return true;
98 0 : }
99 0 : return false;
100 0 : }
101 0 : return false;
102 0 : }
103 :
104 : // Caso 8: Fallback a comparación de representaciones.
105 0 : return dest->toString() == src->toString();
106 0 : }
107 :
108 : } // namespace nicole
|