src/typechecker/PostTypeCheckingVerifier.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "PostTypeCheckingVerifier.h" | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cassert> | ||
| 7 | #include <ranges> | ||
| 8 | |||
| 9 | #include <ast/ASTNodes.h> | ||
| 10 | #include <typechecker/Builtins.h> | ||
| 11 | |||
| 12 | namespace spice::compiler { | ||
| 13 | |||
| 14 | 6019 | PostTypeCheckingVerifier::PostTypeCheckingVerifier(GlobalResourceManager &resourceManager, SourceFile *sourceFile) | |
| 15 | 6019 | : CompilerPass(resourceManager, sourceFile) {} | |
| 16 | |||
| 17 |
1/2✓ Branch 2 → 3 taken 6019 times.
✗ Branch 2 → 5 not taken.
|
6019 | void PostTypeCheckingVerifier::verify(ASTNode *ast) { visit(ast); } |
| 18 | |||
| 19 | 52433 | std::any PostTypeCheckingVerifier::visitFctDef(FctDefNode *node) { | |
| 20 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 52433 times.
|
52433 | assert(node->entry != nullptr); |
| 21 |
1/2✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 52433 times.
|
52433 | assert(!node->manifestations.empty()); |
| 22 | 52433 | return visitChildren(node); | |
| 23 | } | ||
| 24 | |||
| 25 | 30335 | std::any PostTypeCheckingVerifier::visitProcDef(ProcDefNode *node) { | |
| 26 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 30335 times.
|
30335 | assert(node->entry != nullptr); |
| 27 |
1/2✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 30335 times.
|
30335 | assert(!node->manifestations.empty()); |
| 28 | 30335 | return visitChildren(node); | |
| 29 | } | ||
| 30 | |||
| 31 | 8753 | std::any PostTypeCheckingVerifier::visitStructDef(StructDefNode *node) { | |
| 32 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 8753 times.
|
8753 | assert(node->entry != nullptr); |
| 33 | 8753 | return visitChildren(node); | |
| 34 | } | ||
| 35 | |||
| 36 | 1283 | std::any PostTypeCheckingVerifier::visitInterfaceDef(InterfaceDefNode *node) { | |
| 37 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1283 times.
|
1283 | assert(node->entry != nullptr); |
| 38 | 1283 | return visitChildren(node); | |
| 39 | } | ||
| 40 | |||
| 41 | 1105 | std::any PostTypeCheckingVerifier::visitEnumDef(EnumDefNode *node) { | |
| 42 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1105 times.
|
1105 | assert(node->entry != nullptr); |
| 43 | 1105 | return visitChildren(node); | |
| 44 | } | ||
| 45 | |||
| 46 | 14922 | std::any PostTypeCheckingVerifier::visitEnumItem(EnumItemNode *node) { | |
| 47 | // EnumItemNode::entry is intentionally not stored on the node; the entry lives in the enum scope. | ||
| 48 | 14922 | return visitChildren(node); | |
| 49 | } | ||
| 50 | |||
| 51 | 936 | std::any PostTypeCheckingVerifier::visitAliasDef(AliasDefNode *node) { | |
| 52 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 936 times.
|
936 | assert(node->entry != nullptr); |
| 53 | 936 | return visitChildren(node); | |
| 54 | } | ||
| 55 | |||
| 56 | 5905 | std::any PostTypeCheckingVerifier::visitGlobalVarDef(GlobalVarDefNode *node) { | |
| 57 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 5905 times.
|
5905 | assert(node->entry != nullptr); |
| 58 | 5905 | return visitChildren(node); | |
| 59 | } | ||
| 60 | |||
| 61 | 7838 | std::any PostTypeCheckingVerifier::visitSignature(SignatureNode *node) { | |
| 62 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 7838 times.
|
7838 | assert(node->entry != nullptr); |
| 63 | 7838 | return visitChildren(node); | |
| 64 | } | ||
| 65 | |||
| 66 | 129597 | std::any PostTypeCheckingVerifier::visitDeclStmt(DeclStmtNode *node) { | |
| 67 | // entries is resized to manifestationCount; unsubstantiated generic slots remain null. | ||
| 68 | // We can only assert the vector was populated at all. | ||
| 69 |
2/2✓ Branch 2 → 3 taken 128638 times.
✓ Branch 2 → 6 taken 959 times.
|
129597 | if (!node->isForEachItem) |
| 70 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 128638 times.
|
128638 | assert(!node->entries.empty()); |
| 71 | 129597 | return visitChildren(node); | |
| 72 | } | ||
| 73 | |||
| 74 | 125981 | std::any PostTypeCheckingVerifier::visitFctCall(FctCallNode *node) { | |
| 75 | // Builtin calls (printf, len, panic, etc.) return early in the TypeChecker before | ||
| 76 | // populating callee/calleeParentScope — skip them, matching the IRGenerator's behavior. | ||
| 77 |
2/2✓ Branch 8 → 3 taken 2015944 times.
✓ Branch 8 → 9 taken 113468 times.
|
2129412 | for (const auto &[builtinFctName, _] : BUILTIN_FUNCTIONS) |
| 78 |
2/2✓ Branch 5 → 6 taken 12513 times.
✓ Branch 5 → 7 taken 2003431 times.
|
2015944 | if (node->fqFunctionName == builtinFctName) |
| 79 | 12513 | return visitChildren(node); | |
| 80 | |||
| 81 |
1/2✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 113468 times.
|
113468 | assert(!node->data.empty()); |
| 82 | // calleeParentScope is set for every visited non-fct-ptr non-builtin slot; use it as the | ||
| 83 | // "was this slot actually resolved?" indicator. Unsubstantiated/uncompiled slots have it null. | ||
| 84 |
4/6✓ Branch 2 → 3 taken 140999 times.
✓ Branch 2 → 4 taken 30228 times.
✓ Branch 3 → 4 taken 140999 times.
✗ Branch 3 → 5 not taken.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 113468 times.
|
284695 | assert(std::ranges::all_of(node->data, [](const FctCallNode::FctCallData &d) { |
| 85 | return d.calleeParentScope == nullptr || d.callee != nullptr; | ||
| 86 | })); | ||
| 87 | 113468 | return visitChildren(node); | |
| 88 | } | ||
| 89 | |||
| 90 | 564994 | std::any PostTypeCheckingVerifier::visitAtomicExpr(AtomicExprNode *node) { | |
| 91 | // data is only populated for identifier accesses (not for constants / nested exprs). | ||
| 92 | // Within identifier accesses, only substantiated manifestation slots have accessScope set; | ||
| 93 | // unsubstantiated generic slots are left at the default-initialized nullptr. | ||
| 94 |
2/2✓ Branch 3 → 4 taken 331053 times.
✓ Branch 3 → 10 taken 233941 times.
|
564994 | if (!node->fqIdentifier.empty()) { |
| 95 |
1/2✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 331053 times.
|
331053 | assert(!node->data.empty()); |
| 96 |
4/6✓ Branch 2 → 3 taken 404875 times.
✓ Branch 2 → 4 taken 122950 times.
✓ Branch 3 → 4 taken 404875 times.
✗ Branch 3 → 5 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 331053 times.
|
858878 | assert(std::ranges::all_of(node->data, [](const AtomicExprNode::VarAccessData &d) { |
| 97 | return d.accessScope == nullptr || d.entry != nullptr; | ||
| 98 | })); | ||
| 99 | } | ||
| 100 | 564994 | return visitChildren(node); | |
| 101 | } | ||
| 102 | |||
| 103 | 2729 | std::any PostTypeCheckingVerifier::visitStructInstantiation(StructInstantiationNode *node) { | |
| 104 | // instantiatedStructs is resized to manifestationCount; unsubstantiated generic slots remain null. | ||
| 105 | // We can only safely assert the vector was populated — element-level null checks would false-positive | ||
| 106 | // on unsubstantiated generic manifestation slots. | ||
| 107 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2729 times.
|
2729 | assert(!node->instantiatedStructs.empty()); |
| 108 | 2729 | return visitChildren(node); | |
| 109 | } | ||
| 110 | |||
| 111 | 16 | std::any PostTypeCheckingVerifier::visitLambdaFunc(LambdaFuncNode *node) { | |
| 112 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 16 times.
|
16 | assert(!node->manifestations.empty()); |
| 113 | 16 | return visitChildren(node); | |
| 114 | } | ||
| 115 | |||
| 116 | 157 | std::any PostTypeCheckingVerifier::visitLambdaProc(LambdaProcNode *node) { | |
| 117 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 157 times.
|
157 | assert(!node->manifestations.empty()); |
| 118 | 157 | return visitChildren(node); | |
| 119 | } | ||
| 120 | |||
| 121 | 1 | std::any PostTypeCheckingVerifier::visitLambdaExpr(LambdaExprNode *node) { | |
| 122 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
|
1 | assert(!node->manifestations.empty()); |
| 123 | 1 | return visitChildren(node); | |
| 124 | } | ||
| 125 | |||
| 126 | } // namespace spice::compiler | ||
| 127 |