src/typechecker/TypeCheckerTopLevelDefinitions.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "TypeChecker.h" | ||
| 4 | |||
| 5 | #include <ast/ASTNodes.h> | ||
| 6 | #include <global/TypeRegistry.h> | ||
| 7 | |||
| 8 | namespace spice::compiler { | ||
| 9 | |||
| 10 | 1086 | std::any TypeChecker::visitMainFctDef(MainFctDefNode *node) { | |
| 11 |
2/2✓ Branch 2 → 3 taken 510 times.
✓ Branch 2 → 4 taken 576 times.
|
1086 | if (typeCheckerMode == TC_MODE_PRE) |
| 12 | 510 | return visitMainFctDefPrepare(node); | |
| 13 | else | ||
| 14 | 576 | return visitMainFctDefCheck(node); | |
| 15 | } | ||
| 16 | |||
| 17 | 62627 | std::any TypeChecker::visitFctDef(FctDefNode *node) { | |
| 18 |
2/2✓ Branch 2 → 3 taken 20207 times.
✓ Branch 2 → 4 taken 42420 times.
|
62627 | if (typeCheckerMode == TC_MODE_PRE) |
| 19 | 20207 | return visitFctDefPrepare(node); | |
| 20 | else | ||
| 21 | 42420 | return visitFctDefCheck(node); | |
| 22 | } | ||
| 23 | |||
| 24 | 33914 | std::any TypeChecker::visitProcDef(ProcDefNode *node) { | |
| 25 |
2/2✓ Branch 2 → 3 taken 10796 times.
✓ Branch 2 → 4 taken 23118 times.
|
33914 | if (typeCheckerMode == TC_MODE_PRE) |
| 26 | 10796 | return visitProcDefPrepare(node); | |
| 27 | else | ||
| 28 | 23118 | return visitProcDefCheck(node); | |
| 29 | } | ||
| 30 | |||
| 31 | 8651 | std::any TypeChecker::visitStructDef(StructDefNode *node) { | |
| 32 |
2/2✓ Branch 2 → 3 taken 2989 times.
✓ Branch 2 → 4 taken 5662 times.
|
8651 | if (typeCheckerMode == TC_MODE_PRE) |
| 33 | 2989 | return visitStructDefPrepare(node); | |
| 34 | else | ||
| 35 | 5662 | return visitStructDefCheck(node); | |
| 36 | } | ||
| 37 | |||
| 38 | 807 | std::any TypeChecker::visitInterfaceDef(InterfaceDefNode *node) { | |
| 39 |
2/2✓ Branch 2 → 3 taken 364 times.
✓ Branch 2 → 4 taken 443 times.
|
807 | if (typeCheckerMode == TC_MODE_PRE) |
| 40 | 364 | return visitInterfaceDefPrepare(node); | |
| 41 |
1/2✓ Branch 4 → 5 taken 443 times.
✗ Branch 4 → 8 not taken.
|
886 | return nullptr; |
| 42 | } | ||
| 43 | |||
| 44 | /** | ||
| 45 | * Assign the opaque type to a struct, interface, enum or alias that is referenced before it has been prepared. This | ||
| 46 | * effectively acts as an implicit forward declaration and is what makes circular imports work: two types in mutually | ||
| 47 | * importing files can reference each other, so neither can be prepared strictly before the other. The full prepare pass | ||
| 48 | * (visitStructDefPrepare / visitInterfaceDefPrepare / visitEnumDefPrepare / visitAliasDefPrepare) assigns the identical | ||
| 49 | * interned type later and additionally fills in the body scope and manifestations. | ||
| 50 | * | ||
| 51 | * Only non-generic structs/interfaces can be pre-declared this way, since the opaque type carries no template types. | ||
| 52 | * | ||
| 53 | * @param entry Symbol table entry of the referenced struct, interface, enum or alias (its type must still be invalid) | ||
| 54 | */ | ||
| 55 | 1023 | void TypeChecker::assignDeferredOpaqueType(SymbolTableEntry *entry) { | |
| 56 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1023 times.
|
1023 | assert(entry->getQualType().is(TY_INVALID)); |
| 57 | 1023 | ASTNode *declNode = entry->declNode; | |
| 58 |
3/4✓ Branch 6 → 7 taken 1023 times.
✗ Branch 6 → 8 not taken.
✓ Branch 9 → 10 taken 1006 times.
✓ Branch 9 → 18 taken 17 times.
|
1023 | if (const auto *structDef = dynamic_cast<StructDefNode *>(declNode)) { |
| 59 |
1/2✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 1006 times.
|
1006 | if (structDef->hasTemplateTypes) |
| 60 | ✗ | return; | |
| 61 | 1006 | const TypeChainElementData data = {.bodyScope = structDef->structScope}; | |
| 62 |
1/2✓ Branch 13 → 14 taken 1006 times.
✗ Branch 13 → 48 not taken.
|
1006 | const Type *type = TypeRegistry::getOrInsert(TY_STRUCT, structDef->structName, structDef->typeId, data, {}); |
| 63 |
2/4✓ Branch 15 → 16 taken 1006 times.
✗ Branch 15 → 51 not taken.
✓ Branch 16 → 17 taken 1006 times.
✗ Branch 16 → 51 not taken.
|
1006 | entry->updateType(QualType(type, structDef->qualifiers), false); |
| 64 |
3/4✓ Branch 18 → 19 taken 17 times.
✗ Branch 18 → 20 not taken.
✓ Branch 21 → 22 taken 15 times.
✓ Branch 21 → 30 taken 2 times.
|
17 | } else if (const auto *interfaceDef = dynamic_cast<InterfaceDefNode *>(declNode)) { |
| 65 |
1/2✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 15 times.
|
15 | if (interfaceDef->hasTemplateTypes) |
| 66 | ✗ | return; | |
| 67 | 15 | const TypeChainElementData data = {.bodyScope = interfaceDef->interfaceScope}; | |
| 68 |
1/2✓ Branch 25 → 26 taken 15 times.
✗ Branch 25 → 53 not taken.
|
15 | const Type *type = TypeRegistry::getOrInsert(TY_INTERFACE, interfaceDef->interfaceName, interfaceDef->typeId, data, {}); |
| 69 |
2/4✓ Branch 27 → 28 taken 15 times.
✗ Branch 27 → 56 not taken.
✓ Branch 28 → 29 taken 15 times.
✗ Branch 28 → 56 not taken.
|
15 | entry->updateType(QualType(type, interfaceDef->qualifiers), false); |
| 70 |
3/4✓ Branch 30 → 31 taken 2 times.
✗ Branch 30 → 32 not taken.
✓ Branch 33 → 34 taken 1 time.
✓ Branch 33 → 40 taken 1 time.
|
2 | } else if (const auto *enumDef = dynamic_cast<EnumDefNode *>(declNode)) { |
| 71 | 1 | const TypeChainElementData data = {.bodyScope = enumDef->enumScope}; | |
| 72 |
1/2✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 58 not taken.
|
1 | const Type *type = TypeRegistry::getOrInsert(TY_ENUM, enumDef->enumName, enumDef->typeId, data, {}); |
| 73 |
2/4✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 61 not taken.
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 61 not taken.
|
1 | entry->updateType(QualType(type, enumDef->qualifiers), false); |
| 74 |
2/4✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 42 not taken.
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 47 not taken.
|
1 | } else if (auto *aliasDef = dynamic_cast<AliasDefNode *>(declNode)) { |
| 75 | // An alias additionally needs its aliased type resolved, so prepare it fully on demand. visitAliasDefPrepare is | ||
| 76 | // idempotent: the real prepare pass for the alias's own file skips it once the type is no longer invalid. | ||
| 77 |
1/2✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 63 not taken.
|
1 | visitAliasDefPrepare(aliasDef); |
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | 1061 | std::any TypeChecker::visitEnumDef(EnumDefNode *node) { | |
| 82 |
2/2✓ Branch 2 → 3 taken 369 times.
✓ Branch 2 → 4 taken 692 times.
|
1061 | if (typeCheckerMode == TC_MODE_PRE) |
| 83 | 369 | return visitEnumDefPrepare(node); | |
| 84 |
1/2✓ Branch 4 → 5 taken 692 times.
✗ Branch 4 → 8 not taken.
|
1384 | return nullptr; |
| 85 | } | ||
| 86 | |||
| 87 | 6103 | std::any TypeChecker::visitGenericTypeDef(GenericTypeDefNode *node) { | |
| 88 |
2/2✓ Branch 2 → 3 taken 1941 times.
✓ Branch 2 → 4 taken 4162 times.
|
6103 | if (typeCheckerMode == TC_MODE_PRE) |
| 89 | 1941 | return visitGenericTypeDefPrepare(node); | |
| 90 |
1/2✓ Branch 4 → 5 taken 4162 times.
✗ Branch 4 → 8 not taken.
|
8324 | return nullptr; |
| 91 | } | ||
| 92 | |||
| 93 | 958 | std::any TypeChecker::visitAliasDef(AliasDefNode *node) { | |
| 94 |
2/2✓ Branch 2 → 3 taken 341 times.
✓ Branch 2 → 4 taken 617 times.
|
958 | if (typeCheckerMode == TC_MODE_PRE) |
| 95 | 341 | return visitAliasDefPrepare(node); | |
| 96 |
1/2✓ Branch 4 → 5 taken 617 times.
✗ Branch 4 → 8 not taken.
|
1234 | return nullptr; |
| 97 | } | ||
| 98 | |||
| 99 | 6014 | std::any TypeChecker::visitGlobalVarDef(GlobalVarDefNode *node) { | |
| 100 |
2/2✓ Branch 2 → 3 taken 2373 times.
✓ Branch 2 → 4 taken 3641 times.
|
6014 | if (typeCheckerMode == TC_MODE_PRE) |
| 101 | 2373 | return visitGlobalVarDefPrepare(node); | |
| 102 |
1/2✓ Branch 4 → 5 taken 3641 times.
✗ Branch 4 → 8 not taken.
|
7282 | return nullptr; |
| 103 | } | ||
| 104 | |||
| 105 | 8715 | std::any TypeChecker::visitExtDecl(ExtDeclNode *node) { | |
| 106 |
2/2✓ Branch 2 → 3 taken 2978 times.
✓ Branch 2 → 4 taken 5737 times.
|
8715 | if (typeCheckerMode == TC_MODE_PRE) |
| 107 | 2978 | return visitExtDeclPrepare(node); | |
| 108 |
1/2✓ Branch 4 → 5 taken 5737 times.
✗ Branch 4 → 8 not taken.
|
11474 | return nullptr; |
| 109 | } | ||
| 110 | |||
| 111 | 7206 | std::any TypeChecker::visitImportDef(ImportDefNode *node) { | |
| 112 |
2/2✓ Branch 2 → 3 taken 2488 times.
✓ Branch 2 → 4 taken 4718 times.
|
7206 | if (typeCheckerMode == TC_MODE_PRE) |
| 113 | 2488 | return visitImportDefPrepare(node); | |
| 114 |
1/2✓ Branch 4 → 5 taken 4718 times.
✗ Branch 4 → 8 not taken.
|
9436 | return nullptr; |
| 115 | } | ||
| 116 | |||
| 117 | } // namespace spice::compiler | ||
| 118 |