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 |