GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 98.4% 122 / 0 / 124
Functions: 100.0% 15 / 0 / 15
Branches: 64.9% 144 / 0 / 222

src/symboltablebuilder/SymbolTable.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "SymbolTable.h"
4
5 #include <SourceFile.h>
6 #include <ast/ASTNodes.h>
7 #include <symboltablebuilder/Scope.h>
8 #include <symboltablebuilder/SymbolTableBuilder.h>
9 #include <util/CodeLoc.h>
10 #include <util/CompilerWarning.h>
11
12 namespace spice::compiler {
13
14 /**
15 * Insert a new symbol into the current symbol table. If it is a parameter, append its name to the paramNames vector
16 *
17 * @param name Name of the symbol
18 * @param declNode AST node where the symbol is declared
19 * @param isAnonymousSymbol If this symbol should be anonymous
20 * @return Inserted entry
21 */
22 575824 SymbolTableEntry *SymbolTable::insert(const std::string &name, ASTNode *declNode, bool isAnonymousSymbol) {
23 575824 const bool isGlobal = parent == nullptr;
24 575824 size_t orderIndex = SIZE_MAX;
25
2/2
✓ Branch 2 → 3 taken 539082 times.
✓ Branch 2 → 5 taken 36742 times.
575824 if (!isAnonymousSymbol)
26 5096016 orderIndex = std::ranges::count_if(symbols, [](const auto &entry) { return !entry.second.anonymous; });
27 // Insert into symbols map. The type is 'dyn', because concrete types are determined by the type checker later on
28
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 575824 times.
575824 assert(!symbols.contains(name));
29
3/6
✓ Branch 8 → 9 taken 575824 times.
✗ Branch 8 → 41 not taken.
✓ Branch 9 → 10 taken 575824 times.
✗ Branch 9 → 40 not taken.
✓ Branch 11 → 12 taken 575824 times.
✗ Branch 11 → 36 not taken.
575824 symbols.emplace(name, SymbolTableEntry(name, QualType(TY_INVALID), scope, declNode, orderIndex, isGlobal));
30 // Set entry to declared
31 575824 SymbolTableEntry *entry = &symbols.at(name);
32
1/2
✓ Branch 15 → 16 taken 575824 times.
✗ Branch 15 → 43 not taken.
575824 entry->updateState(DECLARED, declNode);
33
34 // Check if shadowed
35
10/10
✓ Branch 16 → 17 taken 488205 times.
✓ Branch 16 → 24 taken 87619 times.
✓ Branch 18 → 19 taken 6112 times.
✓ Branch 18 → 24 taken 482093 times.
✓ Branch 20 → 21 taken 107 times.
✓ Branch 20 → 24 taken 6005 times.
✓ Branch 22 → 23 taken 10 times.
✓ Branch 22 → 24 taken 97 times.
✓ Branch 25 → 26 taken 10 times.
✓ Branch 25 → 34 taken 575814 times.
575824 if (parent != nullptr && parent->lookup(name) != nullptr && !declNode->isParam() && name != RETURN_VARIABLE_NAME) {
36
2/4
✓ Branch 26 → 27 taken 10 times.
✗ Branch 26 → 46 not taken.
✓ Branch 27 → 28 taken 10 times.
✗ Branch 27 → 44 not taken.
10 const std::string warningMsg = "Variable '" + name + "' shadows a variable in a parent scope";
37
1/2
✓ Branch 29 → 30 taken 10 times.
✗ Branch 29 → 49 not taken.
10 const CompilerWarning warning(declNode->codeLoc, SHADOWED_VARIABLE, warningMsg);
38
1/2
✓ Branch 30 → 31 taken 10 times.
✗ Branch 30 → 47 not taken.
10 scope->sourceFile->compilerOutput.warnings.push_back(warning);
39 10 }
40
41 575824 return entry;
42 }
43
44 /**
45 * Insert a new anonymous symbol into the current symbol table.
46 * The anonymous symbol will be identified via the definition code location
47 *
48 * @param qualType Type of the symbol
49 * @param declNode AST node where the anonymous symbol is declared
50 * @param numericSuffix Custom numeric suffix
51 * @return Inserted entry
52 */
53 36890 SymbolTableEntry *SymbolTable::insertAnonymous(const QualType &qualType, ASTNode *declNode, size_t numericSuffix) {
54 // Check if the anonymous entry already exists
55
3/4
✓ Branch 2 → 3 taken 36890 times.
✗ Branch 2 → 34 not taken.
✓ Branch 3 → 4 taken 148 times.
✓ Branch 3 → 5 taken 36742 times.
36890 if (SymbolTableEntry *anonSymbol = lookupAnonymous(declNode, numericSuffix))
56 148 return anonSymbol;
57 // Otherwise, create an anonymous entry
58
1/2
✓ Branch 5 → 6 taken 36742 times.
✗ Branch 5 → 34 not taken.
36742 std::stringstream name;
59
5/10
✓ Branch 6 → 7 taken 36742 times.
✗ Branch 6 → 32 not taken.
✓ Branch 7 → 8 taken 36742 times.
✗ Branch 7 → 26 not taken.
✓ Branch 8 → 9 taken 36742 times.
✗ Branch 8 → 24 not taken.
✓ Branch 9 → 10 taken 36742 times.
✗ Branch 9 → 24 not taken.
✓ Branch 10 → 11 taken 36742 times.
✗ Branch 10 → 24 not taken.
36742 name << "anon." << declNode->codeLoc.toString() << "." << reinterpret_cast<size_t>(declNode);
60
2/2
✓ Branch 12 → 13 taken 1018 times.
✓ Branch 12 → 15 taken 35724 times.
36742 if (numericSuffix > 0)
61
2/4
✓ Branch 13 → 14 taken 1018 times.
✗ Branch 13 → 32 not taken.
✓ Branch 14 → 15 taken 1018 times.
✗ Branch 14 → 32 not taken.
1018 name << "." << numericSuffix;
62
2/4
✓ Branch 15 → 16 taken 36742 times.
✗ Branch 15 → 29 not taken.
✓ Branch 16 → 17 taken 36742 times.
✗ Branch 16 → 27 not taken.
36742 SymbolTableEntry *anonSymbol = insert(name.str(), declNode, true);
63
1/2
✓ Branch 18 → 19 taken 36742 times.
✗ Branch 18 → 32 not taken.
36742 anonSymbol->updateType(qualType, false);
64
1/2
✓ Branch 19 → 20 taken 36742 times.
✗ Branch 19 → 30 not taken.
36742 anonSymbol->updateState(DECLARED, declNode);
65
1/2
✓ Branch 20 → 21 taken 36742 times.
✗ Branch 20 → 31 not taken.
36742 anonSymbol->updateState(INITIALIZED, declNode);
66 36742 anonSymbol->anonymous = true;
67 36742 anonSymbol->used = true;
68 36742 return anonSymbol;
69 36742 }
70
71 /**
72 * Copy a symbol by its name
73 *
74 * @param originalName Original symbol name
75 * @param newName New symbol name
76 * @return Copied entry
77 */
78 54027 SymbolTableEntry *SymbolTable::copySymbol(const std::string &originalName, const std::string &newName) {
79
1/2
✓ Branch 2 → 3 taken 54027 times.
✗ Branch 2 → 13 not taken.
54027 SymbolTableEntry *entryToCopy = lookupStrict(originalName);
80
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 54027 times.
54027 assert(entryToCopy != nullptr);
81
1/2
✓ Branch 5 → 6 taken 54027 times.
✗ Branch 5 → 13 not taken.
54027 auto [it, success] = symbols.emplace(newName, *entryToCopy);
82
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 54027 times.
54027 assert(success);
83 54027 return &it->second;
84 }
85
86 /**
87 * Check if a symbol exists in the current or any parent scope and return it if possible
88 *
89 * @param name Name of the desired symbol
90 * @return Desired symbol / nullptr if the symbol was not found
91 */
92 3394772 SymbolTableEntry *SymbolTable::lookup(const std::string &name) { // NOLINT(misc-no-recursion)
93 // Check if the symbol exists in the current scope. If yes, take it
94
2/2
✓ Branch 3 → 4 taken 975576 times.
✓ Branch 3 → 5 taken 2419196 times.
3394772 if (SymbolTableEntry *entry = lookupStrict(name))
95 975576 return entry;
96
97 // Symbol was not found in the current scope
98 // We reached the root scope, the symbol does not exist at all
99
2/2
✓ Branch 5 → 6 taken 864656 times.
✓ Branch 5 → 7 taken 1554540 times.
2419196 if (!parent)
100 864656 return nullptr;
101 // If we search for the result variable, we want to stop the search when exiting a lambda body
102
6/6
✓ Branch 8 → 9 taken 133601 times.
✓ Branch 8 → 11 taken 1420939 times.
✓ Branch 9 → 10 taken 22 times.
✓ Branch 9 → 11 taken 133579 times.
✓ Branch 12 → 13 taken 22 times.
✓ Branch 12 → 14 taken 1554518 times.
1554540 if (name == RETURN_VARIABLE_NAME && scope->type == ScopeType::LAMBDA_BODY)
103 22 return nullptr;
104 // If there is a parent scope, continue the search there
105 1554518 SymbolTableEntry *entry = parent->lookup(name);
106 // Symbol was also not found in all the parent scopes, return nullptr
107
2/2
✓ Branch 15 → 16 taken 763198 times.
✓ Branch 15 → 17 taken 791320 times.
1554518 if (!entry)
108 763198 return nullptr;
109 // Check if this scope requires capturing and capture the variable if appropriate
110
9/14
✓ Branch 17 → 18 taken 338 times.
✓ Branch 17 → 24 taken 790982 times.
✓ Branch 18 → 19 taken 338 times.
✗ Branch 18 → 37 not taken.
✓ Branch 19 → 20 taken 338 times.
✗ Branch 19 → 24 not taken.
✓ Branch 20 → 21 taken 338 times.
✗ Branch 20 → 37 not taken.
✓ Branch 21 → 22 taken 338 times.
✗ Branch 21 → 37 not taken.
✓ Branch 22 → 23 taken 338 times.
✗ Branch 22 → 24 not taken.
✓ Branch 25 → 26 taken 338 times.
✓ Branch 25 → 35 taken 790982 times.
791320 if (capturingRequired && !captures.contains(name) && !entry->getQualType().isOneOf({TY_IMPORT, TY_FUNCTION, TY_PROCEDURE})) {
111 // We need to make the symbol volatile if we are in an async scope and try to access a symbol that is not in an async scope
112
3/4
✓ Branch 27 → 28 taken 22 times.
✓ Branch 27 → 31 taken 316 times.
✓ Branch 29 → 30 taken 22 times.
✗ Branch 29 → 31 not taken.
338 entry->isVolatile = scope->isInAsyncScope() && !entry->scope->isInAsyncScope();
113 // Add the capture to the current scope
114
2/4
✓ Branch 32 → 33 taken 338 times.
✗ Branch 32 → 38 not taken.
✓ Branch 33 → 34 taken 338 times.
✗ Branch 33 → 38 not taken.
338 captures.emplace(name, Capture(entry));
115 }
116 791320 return entry;
117 }
118
119 /**
120 * Check if a symbol exists in the current or any parent scope and return it if possible.
121 * If the target symbol is an alias symbol, resolve the alias container entry.
122 *
123 * @param name Name of the desired symbol
124 * @return Desired symbol / nullptr if the symbol was not found + alias or not
125 */
126 198261 std::pair<SymbolTableEntry *, bool> SymbolTable::lookupWithAliasResolution(const std::string &name) {
127
1/2
✓ Branch 2 → 3 taken 198261 times.
✗ Branch 2 → 28 not taken.
198261 SymbolTableEntry *entry = lookup(name);
128
8/10
✓ Branch 3 → 4 taken 42077 times.
✓ Branch 3 → 7 taken 156184 times.
✓ Branch 4 → 5 taken 42077 times.
✗ Branch 4 → 28 not taken.
✓ Branch 5 → 6 taken 42077 times.
✗ Branch 5 → 28 not taken.
✓ Branch 6 → 7 taken 41953 times.
✓ Branch 6 → 8 taken 124 times.
✓ Branch 9 → 10 taken 198137 times.
✓ Branch 9 → 12 taken 124 times.
198261 if (!entry || !entry->getQualType().is(TY_ALIAS))
129 198137 return {entry, false};
130
131 // We have an alias type here, resolve it
132
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 124 times.
248 assert(entry->scope->isRootScope());
133 124 entry->used = true;
134
1/2
✓ Branch 16 → 17 taken 124 times.
✗ Branch 16 → 28 not taken.
124 const std::string aliasedContainerEntryName = entry->name + ALIAS_CONTAINER_SUFFIX;
135
1/2
✓ Branch 17 → 18 taken 124 times.
✗ Branch 17 → 26 not taken.
124 SymbolTableEntry *aliasedTypeContainerEntry = entry->scope->lookupStrict(aliasedContainerEntryName);
136
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 124 times.
124 assert(aliasedTypeContainerEntry != nullptr);
137 124 return {aliasedTypeContainerEntry, true};
138 124 }
139
140 /**
141 * Check if a symbol exists in the current scope and return it if possible
142 *
143 * @param symbolName Name of the desired symbol
144 * @return Desired symbol / nullptr if the symbol was not found
145 */
146 5458440 SymbolTableEntry *SymbolTable::lookupStrict(const std::string &symbolName) {
147
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 5458440 times.
5458440 if (symbolName.empty())
148 ✗ return nullptr;
149 // Check if a symbol with this name exists in this scope
150
3/4
✓ Branch 5 → 6 taken 5458440 times.
✗ Branch 5 → 19 not taken.
✓ Branch 8 → 9 taken 2746935 times.
✓ Branch 8 → 11 taken 2711505 times.
5458440 if (const auto it = symbols.find(symbolName); it != symbols.end())
151 2746935 return &it->second;
152 // Check if a capture with this name exists in this scope
153
3/4
✓ Branch 11 → 12 taken 2711505 times.
✗ Branch 11 → 20 not taken.
✓ Branch 14 → 15 taken 232 times.
✓ Branch 14 → 17 taken 2711273 times.
2711505 if (const auto it = captures.find(symbolName); it != captures.end())
154 232 return it->second.capturedSymbol;
155 // Otherwise, return a nullptr
156 2711273 return nullptr;
157 }
158
159 /**
160 * Check if a symbol exists in one of the composed field scopes of the current scope and return it if possible.
161 * This only works if the current scope is a struct scope.
162 *
163 * @param name Name of the desired symbol
164 * @param indexPath How to index the found symbol using order indices (e.g. for GEP)
165 * @return Desired symbol / nullptr if the symbol was not found
166 */
167 486900 SymbolTableEntry *SymbolTable::lookupInComposedFields(const std::string &name, // NOLINT(misc-no-recursion)
168 std::vector<size_t> &indexPath) {
169
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 486900 times.
486900 assert(scope->type == ScopeType::STRUCT);
170
171 // Check if we have a symbol with this name in the current scope
172
2/2
✓ Branch 5 → 6 taken 470300 times.
✓ Branch 5 → 8 taken 16600 times.
486900 if (SymbolTableEntry *result = lookupStrict(name)) {
173 470300 indexPath.push_back(result->orderIndex);
174 470300 return result;
175 }
176
177 // If it was not found in the current scope, loop through all composed fields in this scope
178
2/2
✓ Branch 25 → 9 taken 25988 times.
✓ Branch 25 → 26 taken 28 times.
26016 for (size_t i = 0; i < scope->getFieldCount(); i++) {
179 25988 const SymbolTableEntry *fieldEntry = lookupStrictByIndex(i);
180
181 // Skip all fields that are not composition fields
182
2/2
✓ Branch 12 → 13 taken 9394 times.
✓ Branch 12 → 14 taken 16594 times.
25988 if (!fieldEntry->getQualType().isComposition())
183 9394 continue;
184
185 // Add the current field's order index to the index path
186 16594 indexPath.push_back(fieldEntry->orderIndex);
187
188 // Search in the composed field's body scope
189 16594 Scope *searchScope = fieldEntry->getQualType().getBodyScope();
190
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 16594 times.
16594 assert(searchScope != nullptr);
191
2/2
✓ Branch 20 → 21 taken 16572 times.
✓ Branch 20 → 22 taken 22 times.
16594 if (SymbolTableEntry *result = searchScope->symbolTable.lookupInComposedFields(name, indexPath))
192 16572 return result;
193
194 // Remove the current field's order index from the index path
195 22 indexPath.pop_back();
196 }
197
198 // Symbol was not found in current scope, return nullptr
199 28 return nullptr;
200 }
201
202 /**
203 * Check if an order index exists in the current or any parent scope and returns it if possible.
204 * Warning: Unlike the `lookup` method, this one doesn't consider the parent scopes
205 *
206 * @param orderIndex Order index of the desired symbol
207 * @return Desired symbol / nullptr if the symbol was not found
208 */
209 966467 SymbolTableEntry *SymbolTable::lookupStrictByIndex(unsigned int orderIndex) {
210
4/8
✓ Branch 2 → 3 taken 966467 times.
✗ Branch 2 → 14 not taken.
✓ Branch 3 → 4 taken 966467 times.
✗ Branch 3 → 14 not taken.
✓ Branch 4 → 5 taken 966467 times.
✗ Branch 4 → 14 not taken.
✓ Branch 11 → 6 taken 10364216 times.
✗ Branch 11 → 12 not taken.
10364216 for (auto &val : symbols | std::views::values) {
211
2/2
✓ Branch 7 → 8 taken 966467 times.
✓ Branch 7 → 9 taken 9397749 times.
10364216 if (val.orderIndex == orderIndex)
212 966467 return &val;
213 }
214 ✗ return nullptr;
215 }
216
217 /**
218 * Check if an anonymous symbol exists in the current scope and return it if possible
219 *
220 * @param declNode AST node where the anonymous symbol is declared
221 * @param numericSuffix Numeric suffix of the anonymous symbol
222 * @return Anonymous symbol
223 */
224 101216 SymbolTableEntry *SymbolTable::lookupAnonymous(const ASTNode *declNode, size_t numericSuffix) {
225
1/2
✓ Branch 2 → 3 taken 101216 times.
✗ Branch 2 → 27 not taken.
101216 std::stringstream name;
226
5/10
✓ Branch 3 → 4 taken 101216 times.
✗ Branch 3 → 25 not taken.
✓ Branch 4 → 5 taken 101216 times.
✗ Branch 4 → 21 not taken.
✓ Branch 5 → 6 taken 101216 times.
✗ Branch 5 → 19 not taken.
✓ Branch 6 → 7 taken 101216 times.
✗ Branch 6 → 19 not taken.
✓ Branch 7 → 8 taken 101216 times.
✗ Branch 7 → 19 not taken.
101216 name << "anon." << declNode->codeLoc.toString() << "." << reinterpret_cast<size_t>(declNode);
227
2/2
✓ Branch 9 → 10 taken 2036 times.
✓ Branch 9 → 12 taken 99180 times.
101216 if (numericSuffix > 0)
228
2/4
✓ Branch 10 → 11 taken 2036 times.
✗ Branch 10 → 25 not taken.
✓ Branch 11 → 12 taken 2036 times.
✗ Branch 11 → 25 not taken.
2036 name << "." << numericSuffix;
229
2/4
✓ Branch 12 → 13 taken 101216 times.
✗ Branch 12 → 24 not taken.
✓ Branch 13 → 14 taken 101216 times.
✗ Branch 13 → 22 not taken.
202432 return lookup(name.str());
230 101216 }
231
232 /**
233 * Check if a capture exists in the current or any parent scope and return it if possible
234 *
235 * @param name Name of the desired captured symbol
236 * @return Capture / nullptr if the capture was not found
237 */
238 2473612 Capture *SymbolTable::lookupCapture(const std::string &name) { // NOLINT(misc-no-recursion)
239 // Check if the capture exists in the current scope. If yes, take it
240
2/2
✓ Branch 3 → 4 taken 528 times.
✓ Branch 3 → 5 taken 2473084 times.
2473612 if (Capture *capture = lookupCaptureStrict(name))
241 528 return capture;
242
243 // We reached the root scope, the symbol does not exist at all
244
2/2
✓ Branch 5 → 6 taken 665563 times.
✓ Branch 5 → 7 taken 1807521 times.
2473084 if (parent == nullptr)
245 665563 return nullptr;
246
247 1807521 return parent->lookupCapture(name);
248 }
249
250 /**
251 * Check if a capture exists in the current scope and return it if possible
252 *
253 * @param name Name of the desired captured symbol
254 * @return Capture / nullptr if the capture was not found
255 */
256 2473612 Capture *SymbolTable::lookupCaptureStrict(const std::string &name) {
257 // If available in the current scope, return it
258
1/2
✓ Branch 2 → 3 taken 2473612 times.
✗ Branch 2 → 11 not taken.
2473612 const auto it = captures.find(name);
259
2/2
✓ Branch 5 → 6 taken 528 times.
✓ Branch 5 → 8 taken 2473084 times.
2473612 if (it != captures.end())
260 528 return &it->second;
261 // Otherwise, return nullptr
262 2473084 return nullptr;
263 }
264
265 /**
266 * Set capturing for this scope required.
267 */
268 401 void SymbolTable::setCapturingRequired() { capturingRequired = true; }
269
270 /**
271 * Deletes an existing anonymous symbol
272 *
273 * @param name Anonymous symbol name
274 */
275 45984 void SymbolTable::deleteAnonymous(const std::string &name) { symbols.erase(name); }
276
277 /**
278 * Stringify a symbol table to a human-readable form. This is used to realize dumps of symbol tables
279 *
280 * Example:
281 * {
282 * "name": "<SymbolTableName>"
283 * "symbols": [
284 * ... (SymbolTableEntry)
285 * ],
286 * "children": [
287 * ... (SymbolTable)
288 * ]
289 * }
290 *
291 * @return Symbol table if form of a string
292 */
293 3011101 nlohmann::json SymbolTable::toJSON() const {
294 // Collect all symbols
295 3011101 std::vector<nlohmann::json> jsonSymbols;
296
1/2
✓ Branch 3 → 4 taken 3011101 times.
✗ Branch 3 → 59 not taken.
3011101 jsonSymbols.reserve(symbols.size());
297
5/8
✓ Branch 4 → 5 taken 3011101 times.
✗ Branch 4 → 44 not taken.
✓ Branch 5 → 6 taken 3011101 times.
✗ Branch 5 → 44 not taken.
✓ Branch 6 → 7 taken 3011101 times.
✗ Branch 6 → 44 not taken.
✓ Branch 14 → 8 taken 4648147 times.
✓ Branch 14 → 15 taken 3011101 times.
7659248 for (const SymbolTableEntry &symbol : symbols | std::views::values)
298
2/4
✓ Branch 9 → 10 taken 4648147 times.
✗ Branch 9 → 43 not taken.
✓ Branch 10 → 11 taken 4648147 times.
✗ Branch 10 → 41 not taken.
4648147 jsonSymbols.emplace_back(symbol.toJSON());
299
300 // Collect all captures
301 3011101 std::vector<nlohmann::json> jsonCaptures;
302
1/2
✓ Branch 16 → 17 taken 3011101 times.
✗ Branch 16 → 57 not taken.
3011101 jsonCaptures.reserve(captures.size());
303
5/8
✓ Branch 17 → 18 taken 3011101 times.
✗ Branch 17 → 48 not taken.
✓ Branch 18 → 19 taken 3011101 times.
✗ Branch 18 → 48 not taken.
✓ Branch 19 → 20 taken 3011101 times.
✗ Branch 19 → 48 not taken.
✓ Branch 27 → 21 taken 754 times.
✓ Branch 27 → 28 taken 3011101 times.
3011855 for (const Capture &capture : captures | std::views::values)
304
2/4
✓ Branch 22 → 23 taken 754 times.
✗ Branch 22 → 47 not taken.
✓ Branch 23 → 24 taken 754 times.
✗ Branch 23 → 45 not taken.
754 jsonCaptures.emplace_back(capture.toJSON());
305
306 // Generate json
307 3011101 nlohmann::json result;
308
2/4
✓ Branch 29 → 30 taken 3011101 times.
✗ Branch 29 → 51 not taken.
✓ Branch 30 → 31 taken 3011101 times.
✗ Branch 30 → 49 not taken.
3011101 result["symbols"] = jsonSymbols;
309
2/4
✓ Branch 33 → 34 taken 3011101 times.
✗ Branch 33 → 54 not taken.
✓ Branch 34 → 35 taken 3011101 times.
✗ Branch 34 → 52 not taken.
3011101 result["captures"] = jsonCaptures;
310 3011101 return result;
311 3011101 }
312
313 } // namespace spice::compiler
314