Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2025 ChilliBits. All rights reserved. | ||
2 | |||
3 | #include "SymbolTableBuilder.h" | ||
4 | |||
5 | #include <SourceFile.h> | ||
6 | #include <ast/ASTBuilder.h> | ||
7 | #include <ast/Attributes.h> | ||
8 | #include <exception/SemanticError.h> | ||
9 | #include <global/GlobalResourceManager.h> | ||
10 | |||
11 | namespace spice::compiler { | ||
12 | |||
13 | 1007 | SymbolTableBuilder::SymbolTableBuilder(GlobalResourceManager &resourceManager, SourceFile *sourceFile) | |
14 | 1007 | : CompilerPass(resourceManager, sourceFile), rootScope(sourceFile->globalScope.get()) {} | |
15 | |||
16 | 1007 | std::any SymbolTableBuilder::visitEntry(EntryNode *node) { | |
17 | // Initialize | ||
18 | 1007 | currentScope = rootScope; | |
19 | |||
20 | // Visit children | ||
21 |
2/2✓ Branch 0 (2→3) taken 991 times.
✓ Branch 1 (2→18) taken 16 times.
|
1007 | visitChildren(node); |
22 | |||
23 | // Check if the main function exists | ||
24 |
6/6✓ Branch 0 (4→5) taken 371 times.
✓ Branch 1 (4→15) taken 620 times.
✓ Branch 2 (5→6) taken 369 times.
✓ Branch 3 (5→15) taken 2 times.
✓ Branch 4 (6→7) taken 2 times.
✓ Branch 5 (6→15) taken 367 times.
|
991 | if (sourceFile->isMainFile && !cliOptions.noEntryFct && !hasMainFunction) |
25 |
2/4✓ Branch 0 (10→11) taken 2 times.
✗ Branch 1 (10→22) not taken.
✓ Branch 2 (11→12) taken 2 times.
✗ Branch 3 (11→19) not taken.
|
6 | throw SemanticError(node, MISSING_MAIN_FUNCTION, "No main function found", false); |
26 | |||
27 |
1/2✓ Branch 0 (15→16) taken 989 times.
✗ Branch 1 (15→28) not taken.
|
989 | return nullptr; |
28 | } | ||
29 | |||
30 | 372 | std::any SymbolTableBuilder::visitMainFctDef(MainFctDefNode *node) { | |
31 | // Visit attributes | ||
32 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→6) taken 371 times.
|
372 | if (node->attrs) |
33 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→51) taken 1 times.
|
1 | visit(node->attrs); |
34 | |||
35 | // Check if the function is already defined | ||
36 |
3/4✓ Branch 0 (8→9) taken 371 times.
✗ Branch 1 (8→54) not taken.
✓ Branch 2 (14→15) taken 1 times.
✓ Branch 3 (14→23) taken 370 times.
|
1484 | if (rootScope->lookupStrict(MAIN_FUNCTION_NAME)) |
37 |
2/4✓ Branch 0 (18→19) taken 1 times.
✗ Branch 1 (18→61) not taken.
✓ Branch 2 (19→20) taken 1 times.
✗ Branch 3 (19→58) not taken.
|
3 | throw SemanticError(node, FUNCTION_DECLARED_TWICE, "Main function is declared twice"); |
38 | |||
39 | // Insert symbol for main function | ||
40 |
1/2✓ Branch 0 (25→26) taken 370 times.
✗ Branch 1 (25→69) not taken.
|
1110 | SymbolTableEntry *mainFctEntry = currentScope->insert(MAIN_FUNCTION_NAME, node); |
41 | 370 | mainFctEntry->used = true; | |
42 | |||
43 | // Create scope for main function body | ||
44 |
1/2✓ Branch 0 (31→32) taken 370 times.
✗ Branch 1 (31→84) not taken.
|
370 | const std::string &scopeId = MainFctDefNode::getScopeId(); |
45 |
1/2✓ Branch 0 (32→33) taken 370 times.
✗ Branch 1 (32→82) not taken.
|
370 | node->bodyScope = currentScope = rootScope->createChildScope(scopeId, ScopeType::FUNC_PROC_BODY, &node->codeLoc); |
46 | 370 | currentScope->isGenericScope = false; | |
47 | |||
48 | // Declare variable for the return value in the function scope | ||
49 |
1/2✓ Branch 0 (35→36) taken 370 times.
✗ Branch 1 (35→75) not taken.
|
1110 | SymbolTableEntry *resultVarEntry = node->bodyScope->insert(RETURN_VARIABLE_NAME, node); |
50 | 370 | resultVarEntry->used = true; | |
51 | |||
52 | // Visit arguments in new scope | ||
53 |
2/2✓ Branch 0 (41→42) taken 4 times.
✓ Branch 1 (41→45) taken 366 times.
|
370 | if (node->takesArgs) |
54 |
1/2✓ Branch 0 (42→43) taken 4 times.
✗ Branch 1 (42→79) not taken.
|
4 | visit(node->paramLst); |
55 | |||
56 | // Visit function body in new scope | ||
57 |
2/2✓ Branch 0 (45→46) taken 369 times.
✓ Branch 1 (45→80) taken 1 times.
|
370 | visit(node->body); |
58 | |||
59 | // Return to root scope | ||
60 | 369 | currentScope = rootScope; | |
61 | |||
62 | 369 | hasMainFunction = true; | |
63 |
1/2✓ Branch 0 (47→48) taken 369 times.
✗ Branch 1 (47→81) not taken.
|
738 | return nullptr; |
64 | 370 | } | |
65 | |||
66 | 6007 | std::any SymbolTableBuilder::visitFctDef(FctDefNode *node) { | |
67 | // Visit attributes | ||
68 |
2/2✓ Branch 0 (2→3) taken 323 times.
✓ Branch 1 (2→6) taken 5684 times.
|
6007 | if (node->attrs) |
69 |
1/2✓ Branch 0 (3→4) taken 323 times.
✗ Branch 1 (3→86) not taken.
|
323 | visit(node->attrs); |
70 | |||
71 | // Build function qualifiers | ||
72 |
2/2✓ Branch 0 (6→7) taken 5843 times.
✓ Branch 1 (6→28) taken 164 times.
|
6007 | if (const QualifierLstNode *qualifierLst = node->qualifierLst; qualifierLst) { |
73 |
2/2✓ Branch 0 (26→9) taken 8099 times.
✓ Branch 1 (26→27) taken 5843 times.
|
13942 | for (const QualifierNode *qualifier : qualifierLst->qualifiers) { |
74 |
2/2✓ Branch 0 (10→11) taken 2263 times.
✓ Branch 1 (10→12) taken 5836 times.
|
8099 | if (qualifier->type == QualifierNode::QualifierType::TY_INLINE) |
75 | 2263 | node->qualifiers.isInline = true; | |
76 |
2/2✓ Branch 0 (12→13) taken 5821 times.
✓ Branch 1 (12→14) taken 15 times.
|
5836 | else if (qualifier->type == QualifierNode::QualifierType::TY_PUBLIC) |
77 | 5821 | node->qualifiers.isPublic = true; | |
78 |
1/2✓ Branch 0 (14→15) taken 15 times.
✗ Branch 1 (14→16) not taken.
|
15 | else if (qualifier->type == QualifierNode::QualifierType::TY_CONST) |
79 | 15 | node->qualifiers.isConst = true; | |
80 | else | ||
81 | ✗ | throw SemanticError(qualifier, QUALIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this qualifier on a function definition"); | |
82 | } | ||
83 | } | ||
84 | |||
85 | // Change to struct scope if this function is a method | ||
86 |
2/2✓ Branch 0 (28→29) taken 2673 times.
✓ Branch 1 (28→40) taken 3334 times.
|
6007 | if (node->isMethod) { |
87 |
2/4✓ Branch 0 (29→30) taken 2673 times.
✗ Branch 1 (29→99) not taken.
✓ Branch 2 (30→31) taken 2673 times.
✗ Branch 3 (30→97) not taken.
|
2673 | node->structScope = currentScope = currentScope->getChildScope(STRUCT_SCOPE_PREFIX + node->name->structName); |
88 |
1/2✗ Branch 0 (32→33) not taken.
✓ Branch 1 (32→40) taken 2673 times.
|
2673 | if (!currentScope) |
89 | ✗ | throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + node->name->structName + "' could not be found"); | |
90 | } | ||
91 | |||
92 | // Create scope for the function | ||
93 |
2/4✓ Branch 0 (40→41) taken 6007 times.
✗ Branch 1 (40→111) not taken.
✓ Branch 2 (41→42) taken 6007 times.
✗ Branch 3 (41→109) not taken.
|
6007 | node->scope = currentScope = currentScope->createChildScope(node->getScopeId(), ScopeType::FUNC_PROC_BODY, &node->codeLoc); |
94 |
6/6✓ Branch 0 (43→44) taken 5223 times.
✓ Branch 1 (43→46) taken 784 times.
✓ Branch 2 (44→45) taken 2570 times.
✓ Branch 3 (44→47) taken 2653 times.
✓ Branch 4 (45→46) taken 678 times.
✓ Branch 5 (45→47) taken 1892 times.
|
6007 | currentScope->isGenericScope = node->hasTemplateTypes || (node->structScope && node->structScope->isGenericScope); |
95 | |||
96 | // Create symbol for 'this' variable | ||
97 |
2/2✓ Branch 0 (48→49) taken 2673 times.
✓ Branch 1 (48→58) taken 3334 times.
|
6007 | if (node->isMethod) |
98 |
1/2✓ Branch 0 (51→52) taken 2673 times.
✗ Branch 1 (51→114) not taken.
|
10692 | currentScope->insert(THIS_VARIABLE_NAME, node); |
99 | |||
100 | // Create symbol for 'result' variable | ||
101 |
1/2✓ Branch 0 (60→61) taken 6007 times.
✗ Branch 1 (60→120) not taken.
|
18021 | currentScope->insert(RETURN_VARIABLE_NAME, node); |
102 | |||
103 | // Create symbols for the parameters | ||
104 |
2/2✓ Branch 0 (66→67) taken 4580 times.
✓ Branch 1 (66→70) taken 1427 times.
|
6007 | if (node->hasParams) |
105 |
1/2✓ Branch 0 (67→68) taken 4580 times.
✗ Branch 1 (67→124) not taken.
|
4580 | visit(node->paramLst); |
106 | |||
107 | // Visit the function body | ||
108 |
1/2✓ Branch 0 (70→71) taken 6007 times.
✗ Branch 1 (70→125) not taken.
|
6007 | visit(node->body); |
109 | |||
110 | // Leave function body scope | ||
111 | 6007 | currentScope = node->scope->parent; | |
112 | |||
113 | // Insert symbol for function into the symbol table | ||
114 |
1/2✓ Branch 0 (72→73) taken 6007 times.
✗ Branch 1 (72→128) not taken.
|
12014 | node->entry = currentScope->insert(node->getSymbolTableEntryName(), node); |
115 | |||
116 | // Add to external name registry | ||
117 | // if a function has overloads, they both refer to the same entry in the registry. So we only register the name once | ||
118 | 6007 | const NameRegistryEntry *existingRegistryEntry = sourceFile->getNameRegistryEntry(node->name->fqName); | |
119 |
3/4✓ Branch 0 (78→79) taken 1162 times.
✓ Branch 1 (78→80) taken 4845 times.
✓ Branch 2 (79→80) taken 1162 times.
✗ Branch 3 (79→81) not taken.
|
6007 | if (!existingRegistryEntry || existingRegistryEntry->targetEntry != node->entry) |
120 | 6007 | sourceFile->addNameRegistryEntry(node->name->fqName, TY_FUNCTION, node->entry, currentScope, true); | |
121 | |||
122 | // Leave the struct scope | ||
123 |
2/2✓ Branch 0 (81→82) taken 2673 times.
✓ Branch 1 (81→83) taken 3334 times.
|
6007 | if (node->isMethod) |
124 | 2673 | currentScope = node->structScope->parent; | |
125 | |||
126 |
1/2✓ Branch 0 (83→84) taken 6007 times.
✗ Branch 1 (83→129) not taken.
|
6007 | return nullptr; |
127 | } | ||
128 | |||
129 | 2954 | std::any SymbolTableBuilder::visitProcDef(ProcDefNode *node) { | |
130 | // Visit attributes | ||
131 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→6) taken 2953 times.
|
2954 | if (node->attrs) |
132 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→85) taken 1 times.
|
1 | visit(node->attrs); |
133 | |||
134 | // Build procedure qualifiers | ||
135 |
2/2✓ Branch 0 (6→7) taken 2646 times.
✓ Branch 1 (6→28) taken 307 times.
|
2953 | if (const QualifierLstNode *qualifierLst = node->qualifierLst) { |
136 |
2/2✓ Branch 0 (26→9) taken 3005 times.
✓ Branch 1 (26→27) taken 2646 times.
|
5651 | for (const QualifierNode *qualifier : qualifierLst->qualifiers) { |
137 |
2/2✓ Branch 0 (10→11) taken 360 times.
✓ Branch 1 (10→12) taken 2645 times.
|
3005 | if (qualifier->type == QualifierNode::QualifierType::TY_INLINE) |
138 | 360 | node->qualifiers.isInline = true; | |
139 |
1/2✓ Branch 0 (12→13) taken 2645 times.
✗ Branch 1 (12→14) not taken.
|
2645 | else if (qualifier->type == QualifierNode::QualifierType::TY_PUBLIC) |
140 | 2645 | node->qualifiers.isPublic = true; | |
141 | ✗ | else if (qualifier->type == QualifierNode::QualifierType::TY_CONST) | |
142 | ✗ | node->qualifiers.isConst = true; | |
143 | else | ||
144 | ✗ | throw SemanticError(qualifier, QUALIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this qualifier on a procedure definition"); | |
145 | } | ||
146 | } | ||
147 | |||
148 | // Change to struct scope if this procedure is a method | ||
149 |
2/2✓ Branch 0 (28→29) taken 2458 times.
✓ Branch 1 (28→40) taken 495 times.
|
2953 | if (node->isMethod) { |
150 |
2/4✓ Branch 0 (29→30) taken 2458 times.
✗ Branch 1 (29→98) not taken.
✓ Branch 2 (30→31) taken 2458 times.
✗ Branch 3 (30→96) not taken.
|
2458 | node->structScope = currentScope = currentScope->getChildScope(STRUCT_SCOPE_PREFIX + node->name->structName); |
151 |
2/2✓ Branch 0 (32→33) taken 1 times.
✓ Branch 1 (32→40) taken 2457 times.
|
2458 | if (!currentScope) |
152 |
3/6✓ Branch 0 (34→35) taken 1 times.
✗ Branch 1 (34→104) not taken.
✓ Branch 2 (35→36) taken 1 times.
✗ Branch 3 (35→102) not taken.
✓ Branch 4 (36→37) taken 1 times.
✗ Branch 5 (36→99) not taken.
|
1 | throw SemanticError(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + node->name->structName + "' could not be found"); |
153 | } | ||
154 | |||
155 | // Create scope for the procedure | ||
156 |
2/4✓ Branch 0 (40→41) taken 2952 times.
✗ Branch 1 (40→110) not taken.
✓ Branch 2 (41→42) taken 2952 times.
✗ Branch 3 (41→108) not taken.
|
2952 | node->scope = currentScope = currentScope->createChildScope(node->getScopeId(), ScopeType::FUNC_PROC_BODY, &node->codeLoc); |
157 |
6/6✓ Branch 0 (43→44) taken 2379 times.
✓ Branch 1 (43→46) taken 573 times.
✓ Branch 2 (44→45) taken 2244 times.
✓ Branch 3 (44→47) taken 135 times.
✓ Branch 4 (45→46) taken 593 times.
✓ Branch 5 (45→47) taken 1651 times.
|
2952 | currentScope->isGenericScope = node->hasTemplateTypes || (node->structScope && node->structScope->isGenericScope); |
158 |
4/4✓ Branch 0 (48→49) taken 2457 times.
✓ Branch 1 (48→52) taken 495 times.
✓ Branch 2 (50→51) taken 101 times.
✓ Branch 3 (50→52) taken 2356 times.
|
2952 | currentScope->isDtorScope = node->isMethod && node->name->name == DTOR_FUNCTION_NAME; |
159 | |||
160 | // Create symbol for 'this' variable | ||
161 |
2/2✓ Branch 0 (53→54) taken 2457 times.
✓ Branch 1 (53→63) taken 495 times.
|
2952 | if (node->isMethod) |
162 |
1/2✓ Branch 0 (56→57) taken 2457 times.
✗ Branch 1 (56→113) not taken.
|
9828 | currentScope->insert(THIS_VARIABLE_NAME, node); |
163 | |||
164 | // Create symbols for the parameters | ||
165 |
2/2✓ Branch 0 (63→64) taken 2094 times.
✓ Branch 1 (63→67) taken 858 times.
|
2952 | if (node->hasParams) |
166 |
1/2✓ Branch 0 (64→65) taken 2094 times.
✗ Branch 1 (64→117) not taken.
|
2094 | visit(node->paramLst); |
167 | |||
168 | // Visit the procedure body | ||
169 |
1/2✓ Branch 0 (67→68) taken 2952 times.
✗ Branch 1 (67→118) not taken.
|
2952 | visit(node->body); |
170 | |||
171 | // Leave procedure body scope | ||
172 | 2952 | currentScope = node->scope->parent; | |
173 | |||
174 | // Insert symbol for procedure into the symbol table | ||
175 |
1/2✓ Branch 0 (69→70) taken 2952 times.
✗ Branch 1 (69→121) not taken.
|
5904 | node->entry = currentScope->insert(node->getSymbolTableEntryName(), node); |
176 | |||
177 | // Add to external name registry | ||
178 | // if a procedure has overloads, they both refer to the same entry in the registry. So we only register the name once | ||
179 | 2952 | const NameRegistryEntry *existingRegistryEntry = sourceFile->getNameRegistryEntry(node->name->fqName); | |
180 |
3/4✓ Branch 0 (75→76) taken 782 times.
✓ Branch 1 (75→77) taken 2170 times.
✓ Branch 2 (76→77) taken 782 times.
✗ Branch 3 (76→78) not taken.
|
2952 | if (!existingRegistryEntry || existingRegistryEntry->targetEntry != node->entry) |
181 | 2952 | sourceFile->addNameRegistryEntry(node->name->fqName, TY_PROCEDURE, node->entry, currentScope, true); | |
182 | |||
183 | // Leave the struct scope | ||
184 |
2/2✓ Branch 0 (78→79) taken 2457 times.
✓ Branch 1 (78→80) taken 495 times.
|
2952 | if (node->isMethod) |
185 | 2457 | currentScope = node->structScope->parent; | |
186 | |||
187 | // Check if this is a constructor | ||
188 | 2952 | node->isCtor = node->name->nameFragments.back() == CTOR_FUNCTION_NAME; | |
189 | |||
190 |
1/2✓ Branch 0 (82→83) taken 2952 times.
✗ Branch 1 (82→122) not taken.
|
2952 | return nullptr; |
191 | } | ||
192 | |||
193 | 588 | std::any SymbolTableBuilder::visitStructDef(StructDefNode *node) { | |
194 | // Visit attributes | ||
195 |
2/2✓ Branch 0 (2→3) taken 53 times.
✓ Branch 1 (2→6) taken 535 times.
|
588 | if (node->attrs) |
196 |
1/2✓ Branch 0 (3→4) taken 53 times.
✗ Branch 1 (3→61) not taken.
|
53 | visit(node->attrs); |
197 | |||
198 | // Check if this name already exists | ||
199 |
2/2✓ Branch 0 (9→10) taken 1 times.
✓ Branch 1 (9→17) taken 587 times.
|
1176 | if (rootScope->lookupStrict(node->structName)) |
200 |
3/6✓ Branch 0 (11→12) taken 1 times.
✗ Branch 1 (11→67) not taken.
✓ Branch 2 (12→13) taken 1 times.
✗ Branch 3 (12→65) not taken.
✓ Branch 4 (13→14) taken 1 times.
✗ Branch 5 (13→62) not taken.
|
1 | throw SemanticError(node, DUPLICATE_SYMBOL, "Duplicate symbol '" + node->structName + "'"); |
201 | |||
202 | // Create scope for the struct | ||
203 | 587 | node->structScope = currentScope = | |
204 |
2/4✓ Branch 0 (17→18) taken 587 times.
✗ Branch 1 (17→73) not taken.
✓ Branch 2 (18→19) taken 587 times.
✗ Branch 3 (18→71) not taken.
|
587 | rootScope->createChildScope(STRUCT_SCOPE_PREFIX + node->structName, ScopeType::STRUCT, &node->codeLoc); |
205 | 587 | currentScope->isGenericScope = node->hasTemplateTypes; | |
206 | |||
207 | // Insert implicit field for each interface type | ||
208 |
2/2✓ Branch 0 (20→21) taken 93 times.
✓ Branch 1 (20→34) taken 494 times.
|
587 | if (node->hasInterfaces) { |
209 |
2/2✓ Branch 0 (32→23) taken 93 times.
✓ Branch 1 (32→33) taken 93 times.
|
186 | for (DataTypeNode *interfaceNode : node->interfaceTypeLst->dataTypes) { |
210 | 93 | const std::string &interfaceName = interfaceNode->baseDataType->customDataType->typeNameFragments.back(); | |
211 |
1/2✓ Branch 0 (25→26) taken 93 times.
✗ Branch 1 (25→76) not taken.
|
186 | SymbolTableEntry *interfaceFieldEntry = currentScope->insert("this." + interfaceName, interfaceNode); |
212 | 93 | interfaceFieldEntry->used = true; | |
213 | 93 | interfaceFieldEntry->isImplicitField = true; | |
214 | } | ||
215 | } | ||
216 | |||
217 | // Visit children | ||
218 |
2/2✓ Branch 0 (34→35) taken 586 times.
✓ Branch 1 (34→78) taken 1 times.
|
587 | visitChildren(node); |
219 | |||
220 | // Leave the struct scope | ||
221 | 586 | currentScope = node->structScope->parent; | |
222 | |||
223 | // Build struct qualifiers | ||
224 |
2/2✓ Branch 0 (36→37) taken 448 times.
✓ Branch 1 (36→54) taken 138 times.
|
586 | if (const QualifierLstNode *qualifierLst = node->qualifierLst) { |
225 |
2/2✓ Branch 0 (52→39) taken 448 times.
✓ Branch 1 (52→53) taken 448 times.
|
896 | for (const QualifierNode *qualifier : qualifierLst->qualifiers) { |
226 |
1/2✓ Branch 0 (40→41) taken 448 times.
✗ Branch 1 (40→42) not taken.
|
448 | if (qualifier->type == QualifierNode::QualifierType::TY_PUBLIC) |
227 | 448 | node->qualifiers.isPublic = true; | |
228 | else | ||
229 | ✗ | throw SemanticError(qualifier, QUALIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this qualifier on a struct definition"); | |
230 | } | ||
231 | } | ||
232 | |||
233 | // Add the struct to the symbol table | ||
234 | 586 | node->entry = rootScope->insert(node->structName, node); | |
235 | // Register the name in the exported name registry | ||
236 | 586 | sourceFile->addNameRegistryEntry(node->structName, node->typeId, node->entry, node->structScope, true); | |
237 | |||
238 |
1/2✓ Branch 0 (58→59) taken 586 times.
✗ Branch 1 (58→89) not taken.
|
586 | return nullptr; |
239 | } | ||
240 | |||
241 | 82 | std::any SymbolTableBuilder::visitInterfaceDef(InterfaceDefNode *node) { | |
242 | // Visit attributes | ||
243 |
2/2✓ Branch 0 (2→3) taken 57 times.
✓ Branch 1 (2→6) taken 25 times.
|
82 | if (node->attrs) |
244 |
1/2✓ Branch 0 (3→4) taken 57 times.
✗ Branch 1 (3→53) not taken.
|
57 | visit(node->attrs); |
245 | |||
246 | // Check if this name already exists | ||
247 |
2/2✓ Branch 0 (9→10) taken 1 times.
✓ Branch 1 (9→17) taken 81 times.
|
164 | if (rootScope->lookupStrict(node->interfaceName)) |
248 |
3/6✓ Branch 0 (11→12) taken 1 times.
✗ Branch 1 (11→59) not taken.
✓ Branch 2 (12→13) taken 1 times.
✗ Branch 3 (12→57) not taken.
✓ Branch 4 (13→14) taken 1 times.
✗ Branch 5 (13→54) not taken.
|
1 | throw SemanticError(node, DUPLICATE_SYMBOL, "Duplicate symbol '" + node->interfaceName + "'"); |
249 | |||
250 | // Create scope for the interface | ||
251 | 81 | node->interfaceScope = currentScope = | |
252 |
2/4✓ Branch 0 (17→18) taken 81 times.
✗ Branch 1 (17→65) not taken.
✓ Branch 2 (18→19) taken 81 times.
✗ Branch 3 (18→63) not taken.
|
81 | rootScope->createChildScope(INTERFACE_SCOPE_PREFIX + node->interfaceName, ScopeType::INTERFACE, &node->codeLoc); |
253 | |||
254 | // Visit signatures | ||
255 |
2/2✓ Branch 0 (27→22) taken 187 times.
✓ Branch 1 (27→28) taken 81 times.
|
268 | for (SignatureNode *signature : node->signatures) |
256 |
1/2✓ Branch 0 (23→24) taken 187 times.
✗ Branch 1 (23→66) not taken.
|
187 | visit(signature); |
257 | |||
258 | // Leave the interface scope | ||
259 | 81 | currentScope = node->interfaceScope->parent; | |
260 | |||
261 | // Build interface qualifiers | ||
262 |
2/2✓ Branch 0 (28→29) taken 66 times.
✓ Branch 1 (28→46) taken 15 times.
|
81 | if (const QualifierLstNode *qualifierLst = node->qualifierLst) { |
263 |
2/2✓ Branch 0 (44→31) taken 66 times.
✓ Branch 1 (44→45) taken 66 times.
|
132 | for (const QualifierNode *qualifier : qualifierLst->qualifiers) { |
264 |
1/2✓ Branch 0 (32→33) taken 66 times.
✗ Branch 1 (32→34) not taken.
|
66 | if (qualifier->type == QualifierNode::QualifierType::TY_PUBLIC) |
265 | 66 | node->qualifiers.isPublic = true; | |
266 | else | ||
267 | ✗ | throw SemanticError(qualifier, QUALIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this qualifier on an interface definition"); | |
268 | } | ||
269 | } | ||
270 | |||
271 | // Add the interface to the symbol table | ||
272 | 81 | node->entry = rootScope->insert(node->interfaceName, node); | |
273 | // Register the name in the exported name registry | ||
274 | 81 | sourceFile->addNameRegistryEntry(node->interfaceName, node->typeId, node->entry, node->interfaceScope, true); | |
275 | |||
276 |
1/2✓ Branch 0 (50→51) taken 81 times.
✗ Branch 1 (50→78) not taken.
|
81 | return nullptr; |
277 | } | ||
278 | |||
279 | 66 | std::any SymbolTableBuilder::visitEnumDef(EnumDefNode *node) { | |
280 | // Check if this name already exists | ||
281 |
2/2✓ Branch 0 (5→6) taken 1 times.
✓ Branch 1 (5→13) taken 65 times.
|
132 | if (rootScope->lookupStrict(node->enumName)) |
282 |
3/6✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→48) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→46) not taken.
✓ Branch 4 (9→10) taken 1 times.
✗ Branch 5 (9→43) not taken.
|
1 | throw SemanticError(node, DUPLICATE_SYMBOL, "Duplicate symbol '" + node->enumName + "'"); |
283 | |||
284 | // Create scope for the enum | ||
285 | 65 | node->enumScope = currentScope = | |
286 |
2/4✓ Branch 0 (13→14) taken 65 times.
✗ Branch 1 (13→54) not taken.
✓ Branch 2 (14→15) taken 65 times.
✗ Branch 3 (14→52) not taken.
|
65 | rootScope->createChildScope(ENUM_SCOPE_PREFIX + node->enumName, ScopeType::ENUM, &node->codeLoc); |
287 | |||
288 | // Visit items | ||
289 |
2/2✓ Branch 0 (16→17) taken 64 times.
✓ Branch 1 (16→55) taken 1 times.
|
65 | visit(node->itemLst); |
290 | |||
291 | // Leave the enum scope | ||
292 | 64 | currentScope = node->enumScope->parent; | |
293 | |||
294 | // Build enum qualifiers | ||
295 |
2/2✓ Branch 0 (18→19) taken 52 times.
✓ Branch 1 (18→36) taken 12 times.
|
64 | if (node->qualifierLst) { |
296 |
2/2✓ Branch 0 (34→21) taken 52 times.
✓ Branch 1 (34→35) taken 52 times.
|
104 | for (const QualifierNode *qualifier : node->qualifierLst->qualifiers) { |
297 |
1/2✓ Branch 0 (22→23) taken 52 times.
✗ Branch 1 (22→24) not taken.
|
52 | if (qualifier->type == QualifierNode::QualifierType::TY_PUBLIC) |
298 | 52 | node->qualifiers.isPublic = true; | |
299 | else | ||
300 | ✗ | throw SemanticError(qualifier, QUALIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this qualifier on an enum definition"); | |
301 | } | ||
302 | } | ||
303 | |||
304 | // Add the enum to the symbol table | ||
305 | 64 | node->entry = rootScope->insert(node->enumName, node); | |
306 | // Register the name in the exported name registry | ||
307 | 64 | sourceFile->addNameRegistryEntry(node->enumName, node->typeId, node->entry, node->enumScope, true); | |
308 | |||
309 |
1/2✓ Branch 0 (40→41) taken 64 times.
✗ Branch 1 (40→66) not taken.
|
64 | return nullptr; |
310 | } | ||
311 | |||
312 | 761 | std::any SymbolTableBuilder::visitGenericTypeDef(GenericTypeDefNode *node) { | |
313 | // Check if this name already exists | ||
314 |
2/2✓ Branch 0 (5→6) taken 1 times.
✓ Branch 1 (5→13) taken 760 times.
|
1522 | if (rootScope->lookupStrict(node->typeName)) |
315 |
3/6✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→24) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→22) not taken.
✓ Branch 4 (9→10) taken 1 times.
✗ Branch 5 (9→19) not taken.
|
1 | throw SemanticError(node, DUPLICATE_SYMBOL, "Duplicate symbol '" + node->typeName + "'"); |
316 | |||
317 | // Create the generic type to the symbol table | ||
318 | 760 | node->entry = rootScope->insert(node->typeName, node); | |
319 | 760 | node->entry->used = true; // Generic types are always used | |
320 | |||
321 |
1/2✓ Branch 0 (16→17) taken 760 times.
✗ Branch 1 (16→28) not taken.
|
760 | return nullptr; |
322 | } | ||
323 | |||
324 | 47 | std::any SymbolTableBuilder::visitAliasDef(AliasDefNode *node) { | |
325 | // Check if this name already exists | ||
326 |
3/4✓ Branch 0 (2→3) taken 47 times.
✗ Branch 1 (2→65) not taken.
✓ Branch 2 (5→6) taken 1 times.
✓ Branch 3 (5→13) taken 46 times.
|
94 | if (rootScope->lookupStrict(node->aliasName)) |
327 |
3/6✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→48) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→46) not taken.
✓ Branch 4 (9→10) taken 1 times.
✗ Branch 5 (9→43) not taken.
|
1 | throw SemanticError(node, DUPLICATE_SYMBOL, "Duplicate symbol '" + node->aliasName + "'"); |
328 | |||
329 | // Build alias qualifiers | ||
330 |
2/2✓ Branch 0 (13→14) taken 3 times.
✓ Branch 1 (13→31) taken 43 times.
|
46 | if (const QualifierLstNode *qualifierLst = node->qualifierLst) { |
331 |
2/2✓ Branch 0 (29→16) taken 3 times.
✓ Branch 1 (29→30) taken 3 times.
|
6 | for (const QualifierNode *qualifier : qualifierLst->qualifiers) { |
332 |
1/2✓ Branch 0 (17→18) taken 3 times.
✗ Branch 1 (17→19) not taken.
|
3 | if (qualifier->type == QualifierNode::QualifierType::TY_PUBLIC) |
333 | 3 | node->qualifiers.isPublic = true; | |
334 | else | ||
335 | ✗ | throw SemanticError(qualifier, QUALIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this qualifier on an alias definition"); | |
336 | } | ||
337 | } | ||
338 | |||
339 | // Add the alias to the symbol table | ||
340 |
1/2✓ Branch 0 (31→32) taken 46 times.
✗ Branch 1 (31→65) not taken.
|
46 | node->entry = rootScope->insert(node->aliasName, node); |
341 | // Register the name in the exported name registry | ||
342 |
1/2✓ Branch 0 (34→35) taken 46 times.
✗ Branch 1 (34→65) not taken.
|
46 | sourceFile->addNameRegistryEntry(node->aliasName, node->typeId, node->entry, rootScope, true); |
343 | |||
344 | // Add another symbol for the aliased type container | ||
345 |
1/2✓ Branch 0 (35→36) taken 46 times.
✗ Branch 1 (35→65) not taken.
|
46 | const std::string aliasedTypeContainerName = node->aliasName + ALIAS_CONTAINER_SUFFIX; |
346 |
1/2✓ Branch 0 (36→37) taken 46 times.
✗ Branch 1 (36→63) not taken.
|
46 | node->aliasedTypeContainerEntry = rootScope->insert(aliasedTypeContainerName, node); |
347 | |||
348 |
1/2✓ Branch 0 (39→40) taken 46 times.
✗ Branch 1 (39→62) not taken.
|
92 | return nullptr; |
349 | 46 | } | |
350 | |||
351 | 765 | std::any SymbolTableBuilder::visitGlobalVarDef(GlobalVarDefNode *node) { | |
352 | // Check if this name already exists | ||
353 |
2/2✓ Branch 0 (5→6) taken 1 times.
✓ Branch 1 (5→13) taken 764 times.
|
1530 | if (rootScope->lookupStrict(node->varName)) |
354 |
3/6✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→42) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→40) not taken.
✓ Branch 4 (9→10) taken 1 times.
✗ Branch 5 (9→37) not taken.
|
1 | throw SemanticError(node, DUPLICATE_SYMBOL, "Duplicate symbol '" + node->varName + "'"); |
355 | |||
356 | // Check if global already exists in an imported source file | ||
357 |
5/8✓ Branch 0 (13→14) taken 764 times.
✗ Branch 1 (13→55) not taken.
✓ Branch 2 (14→15) taken 764 times.
✗ Branch 3 (14→55) not taken.
✓ Branch 4 (15→16) taken 764 times.
✗ Branch 5 (15→55) not taken.
✓ Branch 6 (29→17) taken 317 times.
✓ Branch 7 (29→30) taken 763 times.
|
1080 | for (const auto &dependency : sourceFile->dependencies | std::views::values) |
358 |
3/4✓ Branch 0 (18→19) taken 317 times.
✗ Branch 1 (18→55) not taken.
✓ Branch 2 (19→20) taken 1 times.
✓ Branch 3 (19→27) taken 316 times.
|
317 | if (dependency->exportedNameRegistry.contains(node->varName)) |
359 |
3/6✓ Branch 0 (21→22) taken 1 times.
✗ Branch 1 (21→51) not taken.
✓ Branch 2 (22→23) taken 1 times.
✗ Branch 3 (22→49) not taken.
✓ Branch 4 (23→24) taken 1 times.
✗ Branch 5 (23→46) not taken.
|
1 | throw SemanticError(node, GLOBAL_DECLARED_TWICE, "Duplicate global variable '" + node->varName + "' in other module"); |
360 | |||
361 | // Add the global to the symbol table | ||
362 | 763 | node->entry = rootScope->insert(node->varName, node); | |
363 | // Register the name in the exported name registry | ||
364 | 763 | sourceFile->addNameRegistryEntry(node->varName, TY_INVALID, node->entry, currentScope, true); | |
365 | |||
366 |
1/2✓ Branch 0 (34→35) taken 763 times.
✗ Branch 1 (34→56) not taken.
|
763 | return nullptr; |
367 | } | ||
368 | |||
369 | 853 | std::any SymbolTableBuilder::visitExtDecl(ExtDeclNode *node) { | |
370 | // Visit attributes | ||
371 |
2/2✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→6) taken 852 times.
|
853 | if (node->attrs) |
372 |
1/2✓ Branch 0 (3→4) taken 1 times.
✗ Branch 1 (3→30) not taken.
|
1 | visit(node->attrs); |
373 | |||
374 | // Check if this name already exists | ||
375 |
2/2✓ Branch 0 (9→10) taken 1 times.
✓ Branch 1 (9→17) taken 852 times.
|
1706 | if (rootScope->lookupStrict(node->extFunctionName)) |
376 |
3/6✓ Branch 0 (11→12) taken 1 times.
✗ Branch 1 (11→36) not taken.
✓ Branch 2 (12→13) taken 1 times.
✗ Branch 3 (12→34) not taken.
✓ Branch 4 (13→14) taken 1 times.
✗ Branch 5 (13→31) not taken.
|
1 | throw SemanticError(node, DUPLICATE_SYMBOL, "Duplicate symbol '" + node->extFunctionName + "'"); |
377 | |||
378 | // Create scope for the external function (this is required in case of forceSubstantiation in FunctionManager::matchFunction) | ||
379 |
2/4✓ Branch 0 (17→18) taken 852 times.
✗ Branch 1 (17→42) not taken.
✓ Branch 2 (18→19) taken 852 times.
✗ Branch 3 (18→40) not taken.
|
852 | rootScope->createChildScope(node->getScopeId(), ScopeType::FUNC_PROC_BODY, &node->codeLoc); |
380 | |||
381 | // Add the external declaration to the symbol table | ||
382 | 852 | node->entry = rootScope->insert(node->extFunctionName, node); | |
383 | // Register the name in the exported name registry | ||
384 |
2/2✓ Branch 0 (23→24) taken 554 times.
✓ Branch 1 (23→25) taken 298 times.
|
852 | const uint64_t typeId = node->returnType ? TY_FUNCTION : TY_PROCEDURE; |
385 | 852 | sourceFile->addNameRegistryEntry(node->extFunctionName, typeId, node->entry, rootScope, /*keepNewOnCollision=*/true); | |
386 | |||
387 |
1/2✓ Branch 0 (27→28) taken 852 times.
✗ Branch 1 (27→43) not taken.
|
852 | return nullptr; |
388 | } | ||
389 | |||
390 | 2079 | std::any SymbolTableBuilder::visitUnsafeBlock(UnsafeBlockNode *node) { | |
391 | // Create scope for the unsafe block body | ||
392 | 2079 | node->bodyScope = currentScope = | |
393 |
2/4✓ Branch 0 (2→3) taken 2079 times.
✗ Branch 1 (2→12) not taken.
✓ Branch 2 (3→4) taken 2079 times.
✗ Branch 3 (3→10) not taken.
|
2079 | currentScope->createChildScope(node->getScopeId(), ScopeType::UNSAFE_BODY, &node->body->codeLoc); |
394 | |||
395 | // Visit body | ||
396 |
1/2✓ Branch 0 (5→6) taken 2079 times.
✗ Branch 1 (5→13) not taken.
|
2079 | visit(node->body); |
397 | |||
398 | // Leave thread body scope | ||
399 | 2079 | currentScope = node->bodyScope->parent; | |
400 | |||
401 |
1/2✓ Branch 0 (7→8) taken 2079 times.
✗ Branch 1 (7→14) not taken.
|
2079 | return nullptr; |
402 | } | ||
403 | |||
404 | 1036 | std::any SymbolTableBuilder::visitForLoop(ForLoopNode *node) { | |
405 | // Create scope for the loop body | ||
406 | 1036 | node->bodyScope = currentScope = | |
407 |
2/4✓ Branch 0 (2→3) taken 1036 times.
✗ Branch 1 (2→14) not taken.
✓ Branch 2 (3→4) taken 1036 times.
✗ Branch 3 (3→12) not taken.
|
1036 | currentScope->createChildScope(node->getScopeId(), ScopeType::FOR_BODY, &node->body->codeLoc); |
408 | |||
409 | // Visit loop variable declaration | ||
410 |
1/2✓ Branch 0 (5→6) taken 1036 times.
✗ Branch 1 (5→15) not taken.
|
1036 | visit(node->initDecl); |
411 | |||
412 | // Visit body | ||
413 |
1/2✓ Branch 0 (7→8) taken 1036 times.
✗ Branch 1 (7→16) not taken.
|
1036 | visit(node->body); |
414 | |||
415 | // Leave for body scope | ||
416 | 1036 | currentScope = node->bodyScope->parent; | |
417 | |||
418 |
1/2✓ Branch 0 (9→10) taken 1036 times.
✗ Branch 1 (9→17) not taken.
|
1036 | return nullptr; |
419 | } | ||
420 | |||
421 | 88 | std::any SymbolTableBuilder::visitForeachLoop(ForeachLoopNode *node) { | |
422 | // Create scope for the loop body | ||
423 | 88 | node->bodyScope = currentScope = | |
424 |
2/4✓ Branch 0 (2→3) taken 88 times.
✗ Branch 1 (2→18) not taken.
✓ Branch 2 (3→4) taken 88 times.
✗ Branch 3 (3→16) not taken.
|
88 | currentScope->createChildScope(node->getScopeId(), ScopeType::FOREACH_BODY, &node->body->codeLoc); |
425 | |||
426 | // Visit index variable declaration | ||
427 |
2/2✓ Branch 0 (5→6) taken 6 times.
✓ Branch 1 (5→9) taken 82 times.
|
88 | if (node->idxVarDecl) |
428 |
1/2✓ Branch 0 (6→7) taken 6 times.
✗ Branch 1 (6→19) not taken.
|
6 | visit(node->idxVarDecl); |
429 | |||
430 | // Visit item variable declaration | ||
431 |
1/2✓ Branch 0 (9→10) taken 88 times.
✗ Branch 1 (9→20) not taken.
|
88 | visit(node->itemVarDecl); |
432 | |||
433 | // Visit body | ||
434 |
1/2✓ Branch 0 (11→12) taken 88 times.
✗ Branch 1 (11→21) not taken.
|
88 | visit(node->body); |
435 | |||
436 | // Leave foreach body scope | ||
437 | 88 | currentScope = node->bodyScope->parent; | |
438 | |||
439 |
1/2✓ Branch 0 (13→14) taken 88 times.
✗ Branch 1 (13→22) not taken.
|
88 | return nullptr; |
440 | } | ||
441 | |||
442 | 576 | std::any SymbolTableBuilder::visitWhileLoop(WhileLoopNode *node) { | |
443 | // Create scope for the loop body | ||
444 | 576 | node->bodyScope = currentScope = | |
445 |
2/4✓ Branch 0 (2→3) taken 576 times.
✗ Branch 1 (2→14) not taken.
✓ Branch 2 (3→4) taken 576 times.
✗ Branch 3 (3→12) not taken.
|
576 | currentScope->createChildScope(node->getScopeId(), ScopeType::WHILE_BODY, &node->body->codeLoc); |
446 | |||
447 | // Visit condition | ||
448 |
1/2✓ Branch 0 (5→6) taken 576 times.
✗ Branch 1 (5→15) not taken.
|
576 | visit(node->condition); |
449 | |||
450 | // Visit body | ||
451 |
1/2✓ Branch 0 (7→8) taken 576 times.
✗ Branch 1 (7→16) not taken.
|
576 | visit(node->body); |
452 | |||
453 | // Leave while body scope | ||
454 | 576 | currentScope = node->bodyScope->parent; | |
455 | |||
456 |
1/2✓ Branch 0 (9→10) taken 576 times.
✗ Branch 1 (9→17) not taken.
|
576 | return nullptr; |
457 | } | ||
458 | |||
459 | 9 | std::any SymbolTableBuilder::visitDoWhileLoop(DoWhileLoopNode *node) { | |
460 | // Create scope for the loop body | ||
461 | 9 | node->bodyScope = currentScope = | |
462 |
2/4✓ Branch 0 (2→3) taken 9 times.
✗ Branch 1 (2→14) not taken.
✓ Branch 2 (3→4) taken 9 times.
✗ Branch 3 (3→12) not taken.
|
9 | currentScope->createChildScope(node->getScopeId(), ScopeType::WHILE_BODY, &node->body->codeLoc); |
463 | |||
464 | // Visit condition | ||
465 |
1/2✓ Branch 0 (5→6) taken 9 times.
✗ Branch 1 (5→15) not taken.
|
9 | visit(node->condition); |
466 | |||
467 | // Visit body | ||
468 |
1/2✓ Branch 0 (7→8) taken 9 times.
✗ Branch 1 (7→16) not taken.
|
9 | visit(node->body); |
469 | |||
470 | // Leave do-while body scope | ||
471 | 9 | currentScope = node->bodyScope->parent; | |
472 | |||
473 |
1/2✓ Branch 0 (9→10) taken 9 times.
✗ Branch 1 (9→17) not taken.
|
9 | return nullptr; |
474 | } | ||
475 | |||
476 | 3401 | std::any SymbolTableBuilder::visitIfStmt(IfStmtNode *node) { | |
477 | // Create scope for the then body | ||
478 | 3401 | node->thenBodyScope = currentScope = | |
479 |
2/4✓ Branch 0 (2→3) taken 3401 times.
✗ Branch 1 (2→18) not taken.
✓ Branch 2 (3→4) taken 3401 times.
✗ Branch 3 (3→16) not taken.
|
3401 | currentScope->createChildScope(node->getScopeId(), ScopeType::IF_ELSE_BODY, &node->thenBody->codeLoc); |
480 | |||
481 | // Visit condition | ||
482 |
1/2✓ Branch 0 (5→6) taken 3401 times.
✗ Branch 1 (5→19) not taken.
|
3401 | visit(node->condition); |
483 | |||
484 | // Visit then body | ||
485 |
1/2✓ Branch 0 (7→8) taken 3401 times.
✗ Branch 1 (7→20) not taken.
|
3401 | visit(node->thenBody); |
486 | |||
487 | // Leave then body scope | ||
488 | 3401 | currentScope = node->thenBodyScope->parent; | |
489 | |||
490 | // Visit else stmt | ||
491 |
2/2✓ Branch 0 (9→10) taken 171 times.
✓ Branch 1 (9→13) taken 3230 times.
|
3401 | if (node->elseStmt) |
492 |
1/2✓ Branch 0 (10→11) taken 171 times.
✗ Branch 1 (10→21) not taken.
|
171 | visit(node->elseStmt); |
493 | |||
494 |
1/2✓ Branch 0 (13→14) taken 3401 times.
✗ Branch 1 (13→22) not taken.
|
3401 | return nullptr; |
495 | } | ||
496 | |||
497 | 171 | std::any SymbolTableBuilder::visitElseStmt(ElseStmtNode *node) { | |
498 | // Visit if statement in the case of an else if branch | ||
499 |
2/2✓ Branch 0 (2→3) taken 52 times.
✓ Branch 1 (2→7) taken 119 times.
|
171 | if (node->isElseIf) { |
500 |
1/2✓ Branch 0 (3→4) taken 52 times.
✗ Branch 1 (3→15) not taken.
|
52 | visit(node->ifStmt); |
501 |
1/2✓ Branch 0 (5→6) taken 52 times.
✗ Branch 1 (5→16) not taken.
|
52 | return nullptr; |
502 | } | ||
503 | |||
504 | // Create scope for the else body | ||
505 | 119 | node->elseBodyScope = currentScope = | |
506 |
2/4✓ Branch 0 (7→8) taken 119 times.
✗ Branch 1 (7→19) not taken.
✓ Branch 2 (8→9) taken 119 times.
✗ Branch 3 (8→17) not taken.
|
119 | currentScope->createChildScope(node->getScopeId(), ScopeType::IF_ELSE_BODY, &node->body->codeLoc); |
507 | |||
508 | // Visit else body | ||
509 |
1/2✓ Branch 0 (10→11) taken 119 times.
✗ Branch 1 (10→20) not taken.
|
119 | visit(node->body); |
510 | |||
511 | // Leave else body scope | ||
512 | 119 | currentScope = node->elseBodyScope->parent; | |
513 | |||
514 |
1/2✓ Branch 0 (12→13) taken 119 times.
✗ Branch 1 (12→21) not taken.
|
119 | return nullptr; |
515 | } | ||
516 | |||
517 | 53 | std::any SymbolTableBuilder::visitCaseBranch(CaseBranchNode *node) { | |
518 | // Create scope for the case branch | ||
519 | 53 | node->bodyScope = currentScope = | |
520 |
2/4✓ Branch 0 (2→3) taken 53 times.
✗ Branch 1 (2→12) not taken.
✓ Branch 2 (3→4) taken 53 times.
✗ Branch 3 (3→10) not taken.
|
53 | currentScope->createChildScope(node->getScopeId(), ScopeType::CASE_BODY, &node->body->codeLoc); |
521 | |||
522 | // Visit case body | ||
523 |
1/2✓ Branch 0 (5→6) taken 53 times.
✗ Branch 1 (5→13) not taken.
|
53 | visit(node->body); |
524 | |||
525 | // Leave case body scope | ||
526 | 53 | currentScope = node->bodyScope->parent; | |
527 | |||
528 |
1/2✓ Branch 0 (7→8) taken 53 times.
✗ Branch 1 (7→14) not taken.
|
53 | return nullptr; |
529 | } | ||
530 | |||
531 | 6 | std::any SymbolTableBuilder::visitDefaultBranch(DefaultBranchNode *node) { | |
532 | // Create scope for the default branch | ||
533 | 6 | node->bodyScope = currentScope = | |
534 |
2/4✓ Branch 0 (2→3) taken 6 times.
✗ Branch 1 (2→12) not taken.
✓ Branch 2 (3→4) taken 6 times.
✗ Branch 3 (3→10) not taken.
|
6 | currentScope->createChildScope(node->getScopeId(), ScopeType::DEFAULT_BODY, &node->body->codeLoc); |
535 | |||
536 | // Visit default body | ||
537 |
1/2✓ Branch 0 (5→6) taken 6 times.
✗ Branch 1 (5→13) not taken.
|
6 | visit(node->body); |
538 | |||
539 | // Leave default body scope | ||
540 | 6 | currentScope = node->bodyScope->parent; | |
541 | |||
542 |
1/2✓ Branch 0 (7→8) taken 6 times.
✗ Branch 1 (7→14) not taken.
|
6 | return nullptr; |
543 | } | ||
544 | |||
545 | 27 | std::any SymbolTableBuilder::visitAnonymousBlockStmt(AnonymousBlockStmtNode *node) { | |
546 | // Create scope for the anonymous block body | ||
547 | 27 | node->bodyScope = currentScope = | |
548 |
2/4✓ Branch 0 (2→3) taken 27 times.
✗ Branch 1 (2→12) not taken.
✓ Branch 2 (3→4) taken 27 times.
✗ Branch 3 (3→10) not taken.
|
27 | currentScope->createChildScope(node->getScopeId(), ScopeType::ANONYMOUS_BLOCK_BODY, &node->body->codeLoc); |
549 | |||
550 | // Visit body | ||
551 |
1/2✓ Branch 0 (5→6) taken 27 times.
✗ Branch 1 (5→13) not taken.
|
27 | visit(node->body); |
552 | |||
553 | // Leave anonymous block body scope | ||
554 | 27 | currentScope = node->bodyScope->parent; | |
555 | |||
556 |
1/2✓ Branch 0 (7→8) taken 27 times.
✗ Branch 1 (7→14) not taken.
|
27 | return nullptr; |
557 | } | ||
558 | |||
559 | 738 | std::any SymbolTableBuilder::visitEnumItem(EnumItemNode *node) { | |
560 | // Check if enum item already exists in the same scope. | ||
561 |
3/4✓ Branch 0 (2→3) taken 738 times.
✗ Branch 1 (2→41) not taken.
✓ Branch 2 (5→6) taken 1 times.
✓ Branch 3 (5→13) taken 737 times.
|
1476 | if (currentScope->lookupStrict(node->itemName)) |
562 |
3/6✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→31) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→29) not taken.
✓ Branch 4 (9→10) taken 1 times.
✗ Branch 5 (9→26) not taken.
|
1 | throw SemanticError(node, VARIABLE_DECLARED_TWICE, "The enum item '" + node->itemName + "' was declared more than once"); |
563 | |||
564 | // Add enum item entry to symbol table | ||
565 |
1/2✓ Branch 0 (13→14) taken 737 times.
✗ Branch 1 (13→41) not taken.
|
737 | SymbolTableEntry *enumItemEntry = currentScope->insert(node->itemName, node); |
566 | |||
567 | // Add external registry entry | ||
568 |
1/2✗ Branch 0 (16→17) not taken.
✓ Branch 1 (16→18) taken 737 times.
|
737 | assert(node->enumDef != nullptr); |
569 |
2/4✓ Branch 0 (18→19) taken 737 times.
✗ Branch 1 (18→37) not taken.
✓ Branch 2 (19→20) taken 737 times.
✗ Branch 3 (19→35) not taken.
|
737 | const std::string name = node->enumDef->enumName + SCOPE_ACCESS_TOKEN + node->itemName; |
570 |
1/2✓ Branch 0 (21→22) taken 737 times.
✗ Branch 1 (21→39) not taken.
|
737 | sourceFile->addNameRegistryEntry(name, TY_INT, enumItemEntry, currentScope, true); |
571 | |||
572 |
1/2✓ Branch 0 (22→23) taken 737 times.
✗ Branch 1 (22→38) not taken.
|
1474 | return nullptr; |
573 | 737 | } | |
574 | |||
575 | 1267 | std::any SymbolTableBuilder::visitField(FieldNode *node) { | |
576 | // Check if field already exists in the same scope. | ||
577 |
2/2✓ Branch 0 (5→6) taken 1 times.
✓ Branch 1 (5→13) taken 1266 times.
|
2534 | if (currentScope->lookupStrict(node->fieldName)) |
578 |
3/6✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→24) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→22) not taken.
✓ Branch 4 (9→10) taken 1 times.
✗ Branch 5 (9→19) not taken.
|
1 | throw SemanticError(node, VARIABLE_DECLARED_TWICE, "The field '" + node->fieldName + "' was declared more than once"); |
579 | |||
580 | // Add field entry to symbol table | ||
581 | 1266 | currentScope->insert(node->fieldName, node); | |
582 | |||
583 |
1/2✓ Branch 0 (16→17) taken 1266 times.
✗ Branch 1 (16→28) not taken.
|
1266 | return nullptr; |
584 | } | ||
585 | |||
586 | 187 | std::any SymbolTableBuilder::visitSignature(SignatureNode *node) { | |
587 | // Build signature qualifiers | ||
588 |
2/2✓ Branch 0 (2→3) taken 11 times.
✓ Branch 1 (2→24) taken 176 times.
|
187 | if (const QualifierLstNode *qualifierLst = node->qualifierLst) { |
589 |
2/2✓ Branch 0 (22→5) taken 11 times.
✓ Branch 1 (22→23) taken 11 times.
|
22 | for (const QualifierNode *qualifier : qualifierLst->qualifiers) { |
590 |
1/2✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→8) taken 11 times.
|
11 | if (qualifier->type == QualifierNode::QualifierType::TY_INLINE) |
591 | ✗ | node->signatureQualifiers.isInline = true; | |
592 |
1/2✓ Branch 0 (8→9) taken 11 times.
✗ Branch 1 (8→10) not taken.
|
11 | else if (qualifier->type == QualifierNode::QualifierType::TY_PUBLIC) |
593 | 11 | node->signatureQualifiers.isPublic = true; | |
594 | ✗ | else if (qualifier->type == QualifierNode::QualifierType::TY_CONST) | |
595 | ✗ | node->signatureQualifiers.isConst = true; | |
596 | else | ||
597 | ✗ | throw SemanticError(qualifier, QUALIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this qualifier on a signature definition"); | |
598 | } | ||
599 | } | ||
600 | |||
601 | // Add signature entry to symbol table | ||
602 | 187 | node->entry = currentScope->insert(node->methodName, node); | |
603 | |||
604 |
1/2✓ Branch 0 (27→28) taken 187 times.
✗ Branch 1 (27→40) not taken.
|
187 | return nullptr; |
605 | } | ||
606 | |||
607 | 15880 | std::any SymbolTableBuilder::visitDeclStmt(DeclStmtNode *node) { | |
608 | // Check if variable already exists in the same scope. | ||
609 |
2/2✓ Branch 0 (5→6) taken 1 times.
✓ Branch 1 (5→13) taken 15879 times.
|
31760 | if (currentScope->lookupStrict(node->varName)) |
610 |
3/6✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→28) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→26) not taken.
✓ Branch 4 (9→10) taken 1 times.
✗ Branch 5 (9→23) not taken.
|
1 | throw SemanticError(node, VARIABLE_DECLARED_TWICE, "The variable '" + node->varName + "' was declared more than once"); |
611 | |||
612 | // Visit the right side | ||
613 |
2/2✓ Branch 0 (13→14) taken 5981 times.
✓ Branch 1 (13→17) taken 9898 times.
|
15879 | if (node->hasAssignment) |
614 |
1/2✓ Branch 0 (14→15) taken 5981 times.
✗ Branch 1 (14→32) not taken.
|
5981 | visit(node->assignExpr); |
615 | |||
616 | // Add variable entry to symbol table | ||
617 | 15879 | SymbolTableEntry *varEntry = currentScope->insert(node->varName, node); | |
618 | 15879 | varEntry->isParam = node->isFctParam; | |
619 | |||
620 |
1/2✓ Branch 0 (20→21) taken 15879 times.
✗ Branch 1 (20→33) not taken.
|
15879 | return nullptr; |
621 | } | ||
622 | |||
623 | 294 | std::any SymbolTableBuilder::visitModAttr(ModAttrNode *node) { | |
624 | // Visit attributes | ||
625 |
2/2✓ Branch 0 (2→3) taken 293 times.
✓ Branch 1 (2→87) taken 1 times.
|
294 | visitChildren(node); |
626 | |||
627 | // Retrieve attributes | ||
628 | 293 | const AttrLstNode *attrs = node->attrLst; | |
629 | |||
630 | // Collect linker flags | ||
631 | 293 | std::vector<const CompileTimeValue *> linkerFlagValues; | |
632 | // core.linker.flag | ||
633 |
2/4✓ Branch 0 (6→7) taken 293 times.
✗ Branch 1 (6→90) not taken.
✓ Branch 2 (7→8) taken 293 times.
✗ Branch 3 (7→88) not taken.
|
586 | std::vector<const CompileTimeValue *> values = attrs->getAttrValuesByName(ATTR_CORE_LINKER_FLAG); |
634 |
1/2✓ Branch 0 (14→15) taken 293 times.
✗ Branch 1 (14→94) not taken.
|
293 | linkerFlagValues.insert(linkerFlagValues.end(), values.begin(), values.end()); |
635 | // core.linux.linker.flag | ||
636 |
1/2✓ Branch 0 (18→19) taken 293 times.
✗ Branch 1 (18→33) not taken.
|
293 | if (sourceFile->targetMachine->getTargetTriple().isOSLinux()) { |
637 |
2/4✓ Branch 0 (21→22) taken 293 times.
✗ Branch 1 (21→98) not taken.
✓ Branch 2 (22→23) taken 293 times.
✗ Branch 3 (22→96) not taken.
|
586 | values = attrs->getAttrValuesByName(ATTR_CORE_LINUX_LINKER_FLAG); |
638 |
1/2✓ Branch 0 (31→32) taken 293 times.
✗ Branch 1 (31→103) not taken.
|
293 | linkerFlagValues.insert(linkerFlagValues.end(), values.begin(), values.end()); |
639 | } | ||
640 | // core.windows.linker.flag | ||
641 |
1/2✗ Branch 0 (36→37) not taken.
✓ Branch 1 (36→51) taken 293 times.
|
293 | if (sourceFile->targetMachine->getTargetTriple().isOSWindows()) { |
642 | ✗ | values = attrs->getAttrValuesByName(ATTR_CORE_WINDOWS_LINKER_FLAG); | |
643 | ✗ | linkerFlagValues.insert(linkerFlagValues.end(), values.begin(), values.end()); | |
644 | } | ||
645 |
2/2✓ Branch 0 (58→53) taken 427 times.
✓ Branch 1 (58→59) taken 293 times.
|
720 | for (const CompileTimeValue *value : linkerFlagValues) |
646 |
2/4✓ Branch 0 (54→55) taken 427 times.
✗ Branch 1 (54→114) not taken.
✓ Branch 2 (55→56) taken 427 times.
✗ Branch 3 (55→114) not taken.
|
427 | resourceManager.linker.addLinkerFlag(resourceManager.compileTimeStringValues.at(value->stringValueOffset)); |
647 | |||
648 | // core.linker.additionalSource | ||
649 |
4/6✓ Branch 0 (61→62) taken 293 times.
✗ Branch 1 (61→117) not taken.
✓ Branch 2 (62→63) taken 293 times.
✗ Branch 3 (62→115) not taken.
✓ Branch 4 (80→67) taken 2 times.
✓ Branch 5 (80→81) taken 293 times.
|
881 | for (const CompileTimeValue *value : attrs->getAttrValuesByName(ATTR_CORE_LINKER_ADDITIONAL_SOURCE)) { |
650 |
1/2✓ Branch 0 (68→69) taken 2 times.
✗ Branch 1 (68→132) not taken.
|
2 | const std::string &stringValue = resourceManager.compileTimeStringValues.at(value->stringValueOffset); |
651 |
3/6✓ Branch 0 (69→70) taken 2 times.
✗ Branch 1 (69→126) not taken.
✓ Branch 2 (70→71) taken 2 times.
✗ Branch 3 (70→123) not taken.
✓ Branch 4 (71→72) taken 2 times.
✗ Branch 5 (71→121) not taken.
|
2 | const std::filesystem::path path = sourceFile->filePath.parent_path() / stringValue; |
652 |
2/4✓ Branch 0 (74→75) taken 2 times.
✗ Branch 1 (74→129) not taken.
✓ Branch 2 (75→76) taken 2 times.
✗ Branch 3 (75→127) not taken.
|
2 | resourceManager.linker.addAdditionalSourcePath(canonical(path)); |
653 | 295 | } | |
654 | |||
655 |
1/2✓ Branch 0 (82→83) taken 293 times.
✗ Branch 1 (82→136) not taken.
|
586 | return nullptr; |
656 | 293 | } | |
657 | |||
658 | 1222 | std::any SymbolTableBuilder::visitAttr(AttrNode *node) { | |
659 | // Check if this attribute exists | ||
660 |
2/2✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→11) taken 1221 times.
|
1222 | if (!ATTR_CONFIGS.contains(node->key)) |
661 |
3/6✓ Branch 0 (5→6) taken 1 times.
✗ Branch 1 (5→37) not taken.
✓ Branch 2 (6→7) taken 1 times.
✗ Branch 3 (6→35) not taken.
✓ Branch 4 (7→8) taken 1 times.
✗ Branch 5 (7→32) not taken.
|
1 | throw SemanticError(node, UNKNOWN_ATTR, "Unknown attribute '" + node->key + "'"); |
662 | |||
663 | // Check if the target is correct | ||
664 | 1221 | const auto &[target, type] = ATTR_CONFIGS.at(node->key); | |
665 |
2/2✓ Branch 0 (12→13) taken 1 times.
✓ Branch 1 (12→20) taken 1220 times.
|
1221 | if ((node->target & target) == 0) |
666 |
3/6✓ Branch 0 (14→15) taken 1 times.
✗ Branch 1 (14→46) not taken.
✓ Branch 2 (15→16) taken 1 times.
✗ Branch 3 (15→44) not taken.
✓ Branch 4 (16→17) taken 1 times.
✗ Branch 5 (16→41) not taken.
|
1 | throw SemanticError(node, INVALID_ATTR_TARGET, "Attribute '" + node->key + "' cannot be used on this target"); |
667 | |||
668 | // Check if a value is present | ||
669 |
4/4✓ Branch 0 (20→21) taken 325 times.
✓ Branch 1 (20→29) taken 895 times.
✓ Branch 2 (21→22) taken 1 times.
✓ Branch 3 (21→29) taken 324 times.
|
1220 | if (!node->value && type != AttrNode::AttrType::TYPE_BOOL) |
670 |
3/6✓ Branch 0 (23→24) taken 1 times.
✗ Branch 1 (23→55) not taken.
✓ Branch 2 (24→25) taken 1 times.
✗ Branch 3 (24→53) not taken.
✓ Branch 4 (25→26) taken 1 times.
✗ Branch 5 (25→50) not taken.
|
1 | throw SemanticError(node, MISSING_ATTR_VALUE, "Attribute '" + node->key + "' requires a value"); |
671 | |||
672 |
1/2✓ Branch 0 (29→30) taken 1219 times.
✗ Branch 1 (29→59) not taken.
|
1219 | return nullptr; |
673 | } | ||
674 | |||
675 | 12 | std::any SymbolTableBuilder::visitLambdaFunc(LambdaFuncNode *node) { | |
676 | // Create scope for the lambda body | ||
677 | 12 | const CodeLoc &codeLoc = node->body->codeLoc; | |
678 |
2/4✓ Branch 0 (2→3) taken 12 times.
✗ Branch 1 (2→46) not taken.
✓ Branch 2 (3→4) taken 12 times.
✗ Branch 3 (3→44) not taken.
|
12 | node->bodyScope = currentScope = currentScope->createChildScope(node->getScopeId(), ScopeType::LAMBDA_BODY, &codeLoc); |
679 | // Requires capturing because the LLVM IR will end up in a separate function | ||
680 | 12 | currentScope->symbolTable.setCapturingRequired(); | |
681 | // Set to async scope if this is an async lambda | ||
682 |
4/18✗ Branch 0 (6→7) not taken.
✓ Branch 1 (6→13) taken 12 times.
✗ Branch 2 (9→10) not taken.
✗ Branch 3 (9→47) not taken.
✗ Branch 4 (10→11) not taken.
✗ Branch 5 (10→47) not taken.
✗ Branch 6 (11→12) not taken.
✗ Branch 7 (11→13) not taken.
✗ Branch 8 (14→15) not taken.
✓ Branch 9 (14→16) taken 12 times.
✗ Branch 10 (16→17) not taken.
✓ Branch 11 (16→19) taken 12 times.
✗ Branch 12 (19→20) not taken.
✓ Branch 13 (19→27) taken 12 times.
✗ Branch 14 (47→48) not taken.
✗ Branch 15 (47→49) not taken.
✗ Branch 16 (51→52) not taken.
✗ Branch 17 (51→54) not taken.
|
12 | if (node->lambdaAttr && node->lambdaAttr->attrLst->hasAttr(ATTR_ASYNC)) |
683 | ✗ | node->bodyScope->isAsyncScope = node->lambdaAttr->attrLst->getAttrValueByName(ATTR_ASYNC)->boolValue; | |
684 | |||
685 | // Create symbol for 'result' variable | ||
686 |
1/2✓ Branch 0 (29→30) taken 12 times.
✗ Branch 1 (29→64) not taken.
|
36 | currentScope->insert(RETURN_VARIABLE_NAME, node); |
687 | |||
688 | // Create symbols for the parameters | ||
689 |
2/2✓ Branch 0 (35→36) taken 8 times.
✓ Branch 1 (35→39) taken 4 times.
|
12 | if (node->hasParams) |
690 |
1/2✓ Branch 0 (36→37) taken 8 times.
✗ Branch 1 (36→68) not taken.
|
8 | visit(node->paramLst); |
691 | |||
692 | // Visit body | ||
693 |
1/2✓ Branch 0 (39→40) taken 12 times.
✗ Branch 1 (39→69) not taken.
|
12 | visit(node->body); |
694 | |||
695 | // Leave anonymous block body scope | ||
696 | 12 | currentScope = node->bodyScope->parent; | |
697 | |||
698 |
1/2✓ Branch 0 (41→42) taken 12 times.
✗ Branch 1 (41→70) not taken.
|
12 | return nullptr; |
699 | } | ||
700 | |||
701 | 27 | std::any SymbolTableBuilder::visitLambdaProc(LambdaProcNode *node) { | |
702 | // Create scope for the lambda body | ||
703 | 27 | const CodeLoc &codeLoc = node->body->codeLoc; | |
704 |
2/4✓ Branch 0 (2→3) taken 27 times.
✗ Branch 1 (2→38) not taken.
✓ Branch 2 (3→4) taken 27 times.
✗ Branch 3 (3→36) not taken.
|
27 | node->bodyScope = currentScope = currentScope->createChildScope(node->getScopeId(), ScopeType::LAMBDA_BODY, &codeLoc); |
705 | // Requires capturing because the LLVM IR will end up in a separate function | ||
706 | 27 | currentScope->symbolTable.setCapturingRequired(); | |
707 | // Set to async scope if this is an async lambda | ||
708 |
11/18✓ Branch 0 (6→7) taken 16 times.
✓ Branch 1 (6→13) taken 11 times.
✓ Branch 2 (9→10) taken 16 times.
✗ Branch 3 (9→39) not taken.
✓ Branch 4 (10→11) taken 16 times.
✗ Branch 5 (10→39) not taken.
✓ Branch 6 (11→12) taken 16 times.
✗ Branch 7 (11→13) not taken.
✓ Branch 8 (14→15) taken 16 times.
✓ Branch 9 (14→16) taken 11 times.
✓ Branch 10 (16→17) taken 16 times.
✓ Branch 11 (16→19) taken 11 times.
✓ Branch 12 (19→20) taken 16 times.
✓ Branch 13 (19→27) taken 11 times.
✗ Branch 14 (39→40) not taken.
✗ Branch 15 (39→41) not taken.
✗ Branch 16 (43→44) not taken.
✗ Branch 17 (43→46) not taken.
|
59 | if (node->lambdaAttr && node->lambdaAttr->attrLst->hasAttr(ATTR_ASYNC)) |
709 |
2/4✓ Branch 0 (22→23) taken 16 times.
✗ Branch 1 (22→50) not taken.
✓ Branch 2 (23→24) taken 16 times.
✗ Branch 3 (23→48) not taken.
|
48 | node->bodyScope->isAsyncScope = node->lambdaAttr->attrLst->getAttrValueByName(ATTR_ASYNC)->boolValue; |
710 | |||
711 | // Create symbols for the parameters | ||
712 |
2/2✓ Branch 0 (27→28) taken 7 times.
✓ Branch 1 (27→31) taken 20 times.
|
27 | if (node->hasParams) |
713 |
1/2✓ Branch 0 (28→29) taken 7 times.
✗ Branch 1 (28→54) not taken.
|
7 | visit(node->paramLst); |
714 | |||
715 | // Visit body | ||
716 |
1/2✓ Branch 0 (31→32) taken 27 times.
✗ Branch 1 (31→55) not taken.
|
27 | visit(node->body); |
717 | |||
718 | // Leave anonymous block body scope | ||
719 | 27 | currentScope = node->bodyScope->parent; | |
720 | |||
721 |
1/2✓ Branch 0 (33→34) taken 27 times.
✗ Branch 1 (33→56) not taken.
|
27 | return nullptr; |
722 | } | ||
723 | |||
724 | 1 | std::any SymbolTableBuilder::visitLambdaExpr(LambdaExprNode *node) { | |
725 | // Create scope for the anonymous block body | ||
726 | 1 | const CodeLoc &codeLoc = node->lambdaExpr->codeLoc; | |
727 |
2/4✓ Branch 0 (2→3) taken 1 times.
✗ Branch 1 (2→17) not taken.
✓ Branch 2 (3→4) taken 1 times.
✗ Branch 3 (3→15) not taken.
|
1 | node->bodyScope = currentScope = currentScope->createChildScope(node->getScopeId(), ScopeType::LAMBDA_BODY, &codeLoc); |
728 | // Requires capturing because the LLVM IR will end up in a separate function | ||
729 | 1 | currentScope->symbolTable.setCapturingRequired(); | |
730 | |||
731 | // Create symbols for the parameters | ||
732 |
1/2✓ Branch 0 (6→7) taken 1 times.
✗ Branch 1 (6→10) not taken.
|
1 | if (node->hasParams) |
733 |
1/2✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→18) not taken.
|
1 | visit(node->paramLst); |
734 | |||
735 | // Visit lambda expression | ||
736 |
1/2✓ Branch 0 (10→11) taken 1 times.
✗ Branch 1 (10→19) not taken.
|
1 | visit(node->lambdaExpr); |
737 | |||
738 | // Leave anonymous block body scope | ||
739 | 1 | currentScope = node->bodyScope->parent; | |
740 | |||
741 |
1/2✓ Branch 0 (12→13) taken 1 times.
✗ Branch 1 (12→20) not taken.
|
1 | return nullptr; |
742 | } | ||
743 | |||
744 | } // namespace spice::compiler | ||
745 |