GCC Code Coverage Report


Directory: src/
File: src/frontend/type-resolver.cpp
Date: 2025-10-15 09:43:47
Exec Total Coverage
Lines: 188 291 64.6%
Functions: 18 21 85.7%
Branches: 57 82 69.5%

Line Branch Exec Source
1 #include <gyoji-frontend/type-resolver.hpp>
2 #include <variant>
3 #include <stdio.h>
4 #include <gyoji-misc/jstring.hpp>
5
6 using namespace Gyoji::mir;
7 using namespace Gyoji::context;
8 using namespace Gyoji::frontend::tree;
9 using namespace Gyoji::frontend::lowering;
10
11 32 TypeResolver::TypeResolver(
12 Gyoji::context::CompilerContext & _compiler_context,
13 const Gyoji::frontend::tree::TranslationUnit & _translation_unit,
14 32 Gyoji::mir::MIR & _mir)
15 32 : mir(_mir)
16 32 , compiler_context(_compiler_context)
17 32 , translation_unit(_translation_unit)
18 32 {}
19 32 TypeResolver::~TypeResolver()
20 32 {}
21
22 32 void TypeResolver::resolve()
23 {
24 // To resolve the types, we need only iterate the
25 // input parse tree and pull out any type declarations,
26 // resolving them down to their primitive types.
27 32 extract_types(translation_unit.get_statements());
28 32 }
29
30 void
31 8 TypeResolver::extract_from_class_declaration(const ClassDeclaration & declaration)
32 {
33 8 Gyoji::owned<Type> type = std::make_unique<Type>(declaration.get_name(), Type::TYPE_COMPOSITE, false, declaration.get_name_source_ref());
34 8 mir.get_types().define_type(std::move(type));
35 8 }
36
37 Type *
38 320 TypeResolver::get_or_create(std::string pointer_name, Type::TypeType type_type, bool complete, const SourceReference & source_ref)
39 {
40 320 Type *pointer_type = mir.get_types().get_type(pointer_name);
41
2/2
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 118 times.
320 if (pointer_type != nullptr) {
42 202 return pointer_type;
43 }
44 else {
45 118 Gyoji::owned<Type> pointer_type_created = std::make_unique<Type>(pointer_name, type_type, complete, source_ref);
46 118 pointer_type = pointer_type_created.get();
47 118 mir.get_types().define_type(std::move(pointer_type_created));
48 118 return pointer_type;
49 118 }
50 }
51
52 const Type*
53 2030 TypeResolver::extract_from_type_specifier_simple(const TypeSpecifierSimple & type_specifier)
54 {
55 2030 const auto & type_name = type_specifier.get_type_name();
56
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2030 times.
2030 if (type_name.is_expression()) {
57 auto error = std::make_unique<Gyoji::context::Error>("Could not resolve type");
58 error->add_message(type_name.get_name_source_ref(), "Specifying types from expressions is not yet supported.");
59 compiler_context.get_errors().add_error(std::move(error));
60 return nullptr;
61 }
62 2030 std::string name = type_name.get_name();
63 2030 const Type *type = mir.get_types().get_type(name);
64
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2030 times.
2030 if (type == nullptr) {
65 compiler_context
66 .get_errors()
67 .add_simple_error(type_name.get_name_source_ref(),
68 "Could not find type",
69 std::string("Could not resolve type ") + name
70 );
71 return nullptr;
72 }
73 2030 return type;
74 2030 }
75
76 const Type*
77 TypeResolver::extract_from_type_specifier_template(const TypeSpecifierTemplate & type_specifier)
78 {
79 compiler_context
80 .get_errors()
81 .add_simple_error(type_specifier.get_source_ref(),
82 "Could not find type",
83 "Template types are not supported yet."
84 );
85 return nullptr;
86 }
87
88 const Type*
89 TypeResolver::extract_from_type_specifier_function_pointer(const TypeSpecifierFunctionPointer & type_specifier)
90 {
91 compiler_context
92 .get_errors()
93 .add_simple_error(type_specifier.get_source_ref(),
94 "Could not find type",
95 "Function pointer types are not supported yet."
96 );
97 return nullptr;
98 }
99
100 const Type*
101 140 TypeResolver::extract_from_type_specifier_pointer_to(const TypeSpecifierPointerTo & type_specifier)
102 {
103 140 const Type *pointer_target = extract_from_type_specifier(type_specifier.get_type_specifier());
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (pointer_target == nullptr) {
105 compiler_context
106 .get_errors()
107 .add_simple_error(type_specifier.get_source_ref(),
108 "Could not find type",
109 "Could not resolve target of pointer"
110 );
111 return nullptr;
112 }
113 140 const Type *pointer_type = mir.get_types().get_pointer_to(pointer_target, type_specifier.get_source_ref());
114 140 return pointer_type;
115 }
116
117 const Type*
118 8 TypeResolver::extract_from_type_specifier_reference_to(const TypeSpecifierReferenceTo & type_specifier)
119 {
120 8 const Type *pointer_target = extract_from_type_specifier(type_specifier.get_type_specifier());
121
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (pointer_target == nullptr) {
122 compiler_context
123 .get_errors()
124 .add_simple_error(type_specifier.get_source_ref(),
125 "Could not find type",
126 "Could not resolve target of reference"
127 );
128 return nullptr;
129 }
130 8 const Type *pointer_type = mir.get_types().get_reference_to(pointer_target, type_specifier.get_source_ref());
131 8 return pointer_type;
132 }
133
134 const Type*
135 2 TypeResolver::extract_from_type_specifier_array(const TypeSpecifierArray & type_specifier)
136 {
137 2 const Type *pointer_target = extract_from_type_specifier(type_specifier.get_type_specifier());
138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pointer_target == nullptr) {
139 compiler_context
140 .get_errors()
141 .add_simple_error(type_specifier.get_literal_int_token().get_source_ref(),
142 "Could not parse type of array elements.",
143 "Array element type could not be parsed."
144 );
145 return nullptr;
146 }
147
148 Gyoji::frontend::integers::ParseLiteralIntResult parse_result;
149 2 bool parsed = parse_literal_int(compiler_context, mir.get_types(), type_specifier.get_literal_int_token(), parse_result);
150
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (!parsed || parse_result.parsed_type == nullptr) {
151 compiler_context
152 .get_errors()
153 .add_simple_error(type_specifier.get_literal_int_token().get_source_ref(),
154 "Array size invalid",
155 "Could not parse array size."
156 );
157 return nullptr;
158 }
159
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (parse_result.parsed_type->get_type() != Type::TYPE_PRIMITIVE_u32) {
160 compiler_context
161 .get_errors()
162 .add_simple_error(type_specifier.get_literal_int_token().get_source_ref(),
163 "Array size invalid",
164 "Array size must be an unsigned 32-bit integer (u32) constant. Sizes may not be computed at runtime."
165 );
166 }
167
168 2 const Type *array_type = mir.get_types().get_array_of(pointer_target, parse_result.u32_value, type_specifier.get_source_ref());
169 2 return array_type;
170 }
171
172 const Type *
173 2180 TypeResolver::extract_from_type_specifier(const TypeSpecifier & type_specifier)
174 {
175 2180 const auto & type_specifier_type = type_specifier.get_type();
176
2/2
✓ Branch 1 taken 2030 times.
✓ Branch 2 taken 150 times.
2180 if (std::holds_alternative<Gyoji::owned<TypeSpecifierSimple>>(type_specifier_type)) {
177 2030 const auto & type_specifier = std::get<Gyoji::owned<TypeSpecifierSimple>>(type_specifier_type);
178 2030 return extract_from_type_specifier_simple(*type_specifier);
179 }
180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
150 else if (std::holds_alternative<Gyoji::owned<TypeSpecifierTemplate>>(type_specifier_type)) {
181 const auto & type_specifier = std::get<Gyoji::owned<TypeSpecifierTemplate>>(type_specifier_type);
182 return extract_from_type_specifier_template(*type_specifier);
183 }
184
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
150 else if (std::holds_alternative<Gyoji::owned<TypeSpecifierFunctionPointer>>(type_specifier_type)) {
185 const auto & type_specifier = std::get<Gyoji::owned<TypeSpecifierFunctionPointer>>(type_specifier_type);
186 return extract_from_type_specifier_function_pointer(*type_specifier);
187 }
188
2/2
✓ Branch 1 taken 140 times.
✓ Branch 2 taken 10 times.
150 else if (std::holds_alternative<Gyoji::owned<TypeSpecifierPointerTo>>(type_specifier_type)) {
189 140 const auto & type_specifier = std::get<Gyoji::owned<TypeSpecifierPointerTo>>(type_specifier_type);
190 140 return extract_from_type_specifier_pointer_to(*type_specifier);
191 }
192
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
10 else if (std::holds_alternative<Gyoji::owned<TypeSpecifierReferenceTo>>(type_specifier_type)) {
193 8 const auto & type_specifier = std::get<Gyoji::owned<TypeSpecifierReferenceTo>>(type_specifier_type);
194 8 return extract_from_type_specifier_reference_to(*type_specifier);
195
196 }
197
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 else if (std::holds_alternative<Gyoji::owned<TypeSpecifierArray>>(type_specifier_type)) {
198 2 const auto & type_specifier = std::get<Gyoji::owned<TypeSpecifierArray>>(type_specifier_type);
199 2 return extract_from_type_specifier_array(*type_specifier);
200
201 }
202
203 compiler_context
204 .get_errors()
205 .add_simple_error(type_specifier.get_source_ref(),
206 "Compiler bug! Please report this message(2)",
207 "Unknown TypeSpecifier type in variant (compiler bug)"
208 );
209
210 return nullptr;
211 }
212
213 void
214 16 TypeResolver::extract_from_class_members(Type & type, const ClassDefinition & class_definition)
215 {
216 16 std::vector<TypeMember> members;
217 16 std::map<std::string, const TypeMember*> members_by_name;
218 16 std::map<std::string, TypeMethod> methods;
219
220 16 const auto & class_members = class_definition.get_members();
221 16 size_t member_id = 0;
222
2/2
✓ Branch 5 taken 44 times.
✓ Branch 6 taken 16 times.
60 for (const auto & class_member : class_members) {
223 44 const auto & class_member_type = class_member->get_member();
224
2/2
✓ Branch 1 taken 42 times.
✓ Branch 2 taken 2 times.
44 if (std::holds_alternative<Gyoji::owned<ClassMemberDeclarationVariable>>(class_member_type)) {
225 42 const auto & member_variable = std::get<Gyoji::owned<ClassMemberDeclarationVariable>>(class_member_type);
226
227 42 const Type *member_type = extract_from_type_specifier(member_variable->get_type_specifier());
228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (member_type == nullptr) {
229 compiler_context
230 .get_errors()
231 .add_simple_error(member_variable->get_type_specifier().get_source_ref(),
232 "Could not find type",
233 "Could not extract type of member variable " + member_variable->get_name()
234 );
235 }
236 else {
237 42 const auto existing_member_it = members_by_name.find(member_variable->get_name());
238
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
42 if (existing_member_it != members_by_name.end()) {
239 std::unique_ptr<Gyoji::context::Error> error = std::make_unique<Gyoji::context::Error>("Duplicate member variable in class.");
240 error->add_message(member_variable->get_name_source_ref(),
241 std::string("Member variable ") +
242 member_variable->get_name() +
243 std::string(" in class ") +
244 class_definition.get_name() +
245 std::string(" was already defined"));
246 error->add_message(existing_member_it->second->get_source_ref(),
247 "Originally defined here.");
248 compiler_context
249 .get_errors()
250 .add_error(std::move(error));
251 }
252 else {
253 42 TypeMember add_member(member_variable->get_name(), member_id, member_type, member_variable->get_name_source_ref());
254 42 members.push_back(add_member);
255 42 members_by_name.insert(std::pair(member_variable->get_name(), &members.back()));
256 42 member_id++;
257 42 }
258 }
259 }
260
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 else if (std::holds_alternative<Gyoji::owned<ClassMemberDeclarationMethod>>(class_member_type)) {
261 2 const auto & member_method = std::get<Gyoji::owned<ClassMemberDeclarationMethod>>(class_member_type);
262
263 2 std::vector<std::string> arg_list;
264 2 std::vector<Argument> fptr_arguments;
265 // First, pass the 'this' pointer
266 // to the function.
267 2 const Type * this_type = mir.get_types().get_pointer_to(&type, type.get_defined_source_ref());
268 2 Argument arg_this(this_type, member_method->get_source_ref());
269 2 fptr_arguments.push_back(arg_this);
270 2 arg_list.push_back(this_type->get_name());
271
272 2 const Type * ret_type = extract_from_type_specifier(member_method->get_type_specifier());
273
274 2 const FunctionDefinitionArgList & function_definition_arg_list = member_method->get_arguments();
275 const std::vector<Gyoji::owned<FunctionDefinitionArg>> & function_definition_args =
276 2 function_definition_arg_list.get_arguments();
277
2/2
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
4 for (const auto & function_definition_arg : function_definition_args) {
278 2 const Type *argument_type = extract_from_type_specifier(function_definition_arg->get_type_specifier());
279 2 Argument arg(argument_type, function_definition_arg->get_source_ref());
280 2 fptr_arguments.push_back(arg);
281 2 arg_list.push_back(argument_type->get_name());
282 2 }
283
284 TypeMethod method(
285 4 member_method->get_identifier().get_name(),
286 2 member_method->get_source_ref(),
287 &type,
288 ret_type,
289 fptr_arguments
290 8 );
291 2 methods.insert(std::pair(member_method->get_identifier().get_name(), method));
292
293 4 std::string arg_string = Gyoji::misc::join(arg_list, ",");
294 10 std::string pointer_name = ret_type->get_name() + std::string("(*)") + std::string("(") + arg_string + std::string(")");
295 2 Type *fptr_type = get_or_create(pointer_name, Type::TYPE_FUNCTION_POINTER, false, member_method->get_source_ref());
296
297
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!fptr_type->is_complete()) {
298 2 fptr_type->complete_function_pointer_definition(
299 ret_type,
300 fptr_arguments,
301 2 member_method->get_source_ref()
302 );
303 }
304
305 4 mir.get_symbols().define_symbol(
306 4 member_method->get_identifier().get_fully_qualified_name(),
307 fptr_type
308 );
309 2 }
310 }
311
312 16 type.complete_composite_definition(
313 members,
314 methods,
315 class_definition.get_name_source_ref());
316 16 }
317
318 void
319 16 TypeResolver::extract_from_class_definition(const ClassDefinition & definition)
320 {
321 16 const auto it = mir.get_types().get_types().find(definition.get_name());
322
323
2/2
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 6 times.
16 if (it == mir.get_types().get_types().end()) {
324 // Case 1: No forward declaration exists, fill in the definition
325 // from the class.
326 10 Gyoji::owned<Type> type = std::make_unique<Type>(definition.get_name(), Type::TYPE_COMPOSITE, true, definition.get_name_source_ref());
327 10 extract_from_class_members(*type, definition);
328 10 mir.get_types().define_type(std::move(type));
329 10 }
330 else {
331 6 auto & type = *it->second;
332 // Case 2: Class is forward declared, but is incomplete, so fill in the declaration.
333
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 if (!type.is_complete()) {
334 6 extract_from_class_members(type, definition);
335 }
336 else {
337 // Case 3: Class is declared and complete, but does not match our current definition,
338 // so this is a duplicate. Raise an error to avoid ambiguity.
339 std::unique_ptr<Gyoji::context::Error> error = std::make_unique<Gyoji::context::Error>(std::string("Duplicate class definition: ") + definition.get_name());
340 error->add_message(type.get_defined_source_ref(),
341 "Originally defined here"
342 );
343 error->add_message(definition.get_name_source_ref(),
344 "Re-declared here"
345 );
346 compiler_context
347 .get_errors()
348 .add_error(std::move(error));
349 }
350
351 }
352 16 }
353
354 void
355 TypeResolver::extract_from_enum_definition(const EnumDefinition & enum_definition)
356 {
357 const auto it = mir.get_types().get_types().find(enum_definition.get_name());
358 if (it == mir.get_types().get_types().end()) {
359 // No definition exists, create it.
360 Gyoji::owned<Type> type = std::make_unique<Type>(enum_definition.get_name(), Type::TYPE_ENUM, true, enum_definition.get_name_source_ref());
361 mir.get_types().define_type(std::move(type));
362
363 for (const auto & ev : enum_definition.get_value_list().get_values()) {
364 fprintf(stderr, "Value is %s\n", ev->get_name().c_str());
365 }
366
367
368 // mir.get_symbols().define_symbol(
369 // fully_qualified_function_name,
370 // pointer_type
371 // );
372 }
373 else {
374 // This is a duplicate, reference the original definition.
375 // Case 3: Class is declared and complete, but does not match our current definition,
376 // so this is a duplicate. Raise an error to avoid ambiguity.
377 auto & type = *it->second;
378 std::unique_ptr<Gyoji::context::Error> error = std::make_unique<Gyoji::context::Error>(std::string("Duplicate enum definition: ") + enum_definition.get_name());
379 error->add_message(type.get_defined_source_ref(),
380 "Originally defined here"
381 );
382 error->add_message(enum_definition.get_name_source_ref(),
383 "Re-declared here"
384 );
385 compiler_context
386 .get_errors()
387 .add_error(std::move(error));
388 }
389 }
390
391 void
392 6 TypeResolver::extract_from_type_definition(const TypeDefinition & type_definition)
393 {
394 6 const auto it = mir.get_types().get_types().find(type_definition.get_name());
395
1/2
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 if (it == mir.get_types().get_types().end()) {
396 // No definition exists, create it.
397 6 const Type *defined_type = extract_from_type_specifier(type_definition.get_type_specifier());
398
399 // We effectively make a new type as a copy of the old one.
400 // This may seem redundant, but it's done
401 // so that we can later modify the type by "instantiating"
402 // it as a generic with specific type parameters
403 // when we get to that point.
404 Gyoji::owned<Type> type = std::make_unique<Type>(
405 6 type_definition.get_name(),
406 6 type_definition.get_type_specifier().get_source_ref(),
407 *defined_type
408 12 );
409 6 mir.get_types().define_type(std::move(type));
410 6 }
411 else {
412 // This is a duplicate, reference the original definition.
413 // Case 3: Class is declared and complete, but does not match our current definition,
414 // so this is a duplicate. Raise an error to avoid ambiguity.
415 auto & type = *it->second;
416 std::unique_ptr<Gyoji::context::Error> error = std::make_unique<Gyoji::context::Error>(std::string("Duplicate enum definition: ") + type_definition.get_name());
417 error->add_message(type.get_defined_source_ref(),
418 "Originally defined here"
419 );
420 error->add_message(type_definition.get_name_source_ref(),
421 "Re-declared here"
422 );
423 compiler_context
424 .get_errors()
425 .add_error(std::move(error));
426 }
427 6 }
428
429
430 void
431 318 TypeResolver::extract_from_function_specifications(
432 const Terminal & name,
433 const TypeSpecifier & type_specifier,
434 const FunctionDefinitionArgList & function_argument_list
435 )
436 {
437
438 std::string fully_qualified_function_name =
439 318 name.get_fully_qualified_name();
440
441 318 const Type *type = extract_from_type_specifier(type_specifier);
442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 318 times.
318 if (type == nullptr) {
443 compiler_context
444 .get_errors()
445 .add_simple_error(type_specifier.get_source_ref(),
446 "Compiler bug! Please report this message(3)",
447 "Function pointer type declared with invalid type"
448 );
449 return;
450 }
451 //////
452 // Define the type of a function pointer.
453 //////
454 318 std::vector<std::string> arg_list;
455 318 std::vector<Argument> fptr_arguments;
456 318 const auto & function_definition_args = function_argument_list.get_arguments();
457
2/2
✓ Branch 5 taken 558 times.
✓ Branch 6 taken 318 times.
876 for (const auto & function_definition_arg : function_definition_args) {
458 558 std::string name = function_definition_arg->get_identifier().get_fully_qualified_name();
459 558 const Type * t = extract_from_type_specifier(function_definition_arg->get_type_specifier());
460 558 arg_list.push_back(t->get_name());
461 558 fptr_arguments.push_back(
462 1116 Argument(t, function_definition_arg->get_type_specifier().get_source_ref())
463 );
464 558 }
465 636 std::string arg_string = Gyoji::misc::join(arg_list, ",");
466 1590 std::string pointer_name = type->get_name() + std::string("(*)") + std::string("(") + arg_string + std::string(")");
467 318 Type *pointer_type = get_or_create(pointer_name, Type::TYPE_FUNCTION_POINTER, false, name.get_source_ref());
468
469
2/2
✓ Branch 1 taken 116 times.
✓ Branch 2 taken 202 times.
318 if (!pointer_type->is_complete()) {
470 116 pointer_type->complete_function_pointer_definition(
471 type,
472 fptr_arguments,
473 name.get_source_ref()
474 );
475 }
476 //////
477 // Now that the type has been defined, we can
478 // define the symbol for this specific function.
479 //////
480 318 mir.get_symbols().define_symbol(
481 fully_qualified_function_name,
482 pointer_type
483 );
484
485
1/2
✓ Branch 5 taken 318 times.
✗ Branch 6 not taken.
318 }
486
487 void
488 266 TypeResolver::extract_from_function_definition(const FileStatementFunctionDefinition & function_definition)
489 {
490 266 extract_from_function_specifications(
491 function_definition.get_name(),
492 function_definition.get_return_type(),
493 function_definition.get_arguments()
494 );
495 266 }
496
497 void
498 52 TypeResolver::extract_from_function_declaration(const FileStatementFunctionDeclaration & function_declaration)
499 {
500 52 extract_from_function_specifications(
501 function_declaration.get_name(),
502 function_declaration.get_return_type(),
503 function_declaration.get_arguments()
504 );
505 52 }
506
507 void
508 12 TypeResolver::extract_from_namespace(const FileStatementNamespace & namespace_declaration)
509 {
510 12 const auto & statements = namespace_declaration.get_statement_list().get_statements();
511 12 extract_types(statements);
512 12 }
513
514 void
515 44 TypeResolver::extract_types(const std::vector<Gyoji::owned<FileStatement>> & statements)
516 {
517
2/2
✓ Branch 5 taken 366 times.
✓ Branch 6 taken 44 times.
410 for (const auto & statement : statements) {
518 366 const auto & file_statement = statement->get_statement();
519
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 314 times.
366 if (std::holds_alternative<Gyoji::owned<FileStatementFunctionDeclaration>>(file_statement)) {
520 52 extract_from_function_declaration(*std::get<Gyoji::owned<FileStatementFunctionDeclaration>>(file_statement));
521 }
522
2/2
✓ Branch 1 taken 266 times.
✓ Branch 2 taken 48 times.
314 else if (std::holds_alternative<Gyoji::owned<FileStatementFunctionDefinition>>(file_statement)) {
523 266 extract_from_function_definition(*std::get<Gyoji::owned<FileStatementFunctionDefinition>>(file_statement));
524 }
525
2/2
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 2 times.
48 else if (std::holds_alternative<Gyoji::owned<FileStatementGlobalDefinition>>(file_statement)) {
526 // Nothing, no statements can be declared inside here.
527 }
528
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 38 times.
46 else if (std::holds_alternative<Gyoji::owned<ClassDeclaration>>(file_statement)) {
529 8 extract_from_class_declaration(*std::get<Gyoji::owned<ClassDeclaration>>(file_statement));
530 }
531
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 22 times.
38 else if (std::holds_alternative<Gyoji::owned<ClassDefinition>>(file_statement)) {
532 16 extract_from_class_definition(*std::get<Gyoji::owned<ClassDefinition>>(file_statement));
533 }
534
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 else if (std::holds_alternative<Gyoji::owned<EnumDefinition>>(file_statement)) {
535 extract_from_enum_definition(*std::get<Gyoji::owned<EnumDefinition>>(file_statement));
536 }
537
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 16 times.
22 else if (std::holds_alternative<Gyoji::owned<TypeDefinition>>(file_statement)) {
538 6 extract_from_type_definition(*std::get<Gyoji::owned<TypeDefinition>>(file_statement));
539 }
540
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 4 times.
16 else if (std::holds_alternative<Gyoji::owned<FileStatementNamespace>>(file_statement)) {
541 12 extract_from_namespace(*std::get<Gyoji::owned<FileStatementNamespace>>(file_statement));
542 }
543
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 else if (std::holds_alternative<Gyoji::owned<FileStatementUsing>>(file_statement)) {
544 // Nothing, no statements can be declared inside here.
545 }
546 else {
547 compiler_context
548 .get_errors()
549 .add_simple_error(statement->get_source_ref(),
550 "Compiler bug! Please report this message(1)",
551 "Unknown statement type in variant, extracting statements from file (compiler bug)"
552 );
553 }
554 }
555 44 }
556
557