diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-05 01:03:55 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-05 21:27:36 +0200 |
| commit | b2dee14873402ee3d13d59ae5579593796ea862f (patch) | |
| tree | 1f245eac1a23a73f45124498fc8274874e35750e /boot/name_analysis.cc | |
| parent | 1c2fb173ea3b674207badc721556ad72962b266e (diff) | |
| download | elna-b2dee14873402ee3d13d59ae5579593796ea862f.tar.gz | |
Check that constants are initialized
Diffstat (limited to 'boot/name_analysis.cc')
| -rw-r--r-- | boot/name_analysis.cc | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/boot/name_analysis.cc b/boot/name_analysis.cc index 3667dff..56ea399 100644 --- a/boot/name_analysis.cc +++ b/boot/name_analysis.cc @@ -126,7 +126,8 @@ namespace elna::boot case field_on_type: return "Cannot access field '" + this->name + "' on type '" + this->composite.to_string() + "'"; - break; + default: + __builtin_unreachable(); } } else if constexpr (std::is_same_v<T, duplicate>) @@ -163,6 +164,23 @@ namespace elna::boot return std::nullopt; } + not_initialized_error::not_initialized_error(const source_position position, std::vector<identifier> identifiers) + : error(position), identifiers(std::move(identifiers)) + { + } + + std::string not_initialized_error::what() const + { + return "All constants should be initialized"; + } + + std::optional<std::pair<std::string, source_position>> not_initialized_error::note() const + { + auto position_span = source_position(this->identifiers.front().position().start(), + this->identifiers.back().position().end()); + return std::make_pair(join(this->identifiers), position_span); + } + // Members of a constant aggregate are constant themselves. static type qualify_member_type(const type& element, const type& aggregate) { @@ -177,8 +195,8 @@ namespace elna::boot } } - name_analysis_visitor::name_analysis_visitor(symbol_bag bag) - : bag(std::move(bag)) + name_analysis_visitor::name_analysis_visitor(symbol_bag bag, const target_info& target) + : bag(std::move(bag)), constant_evaluator(this->bag, target) { } @@ -294,14 +312,23 @@ namespace elna::boot void name_analysis_visitor::visit(array_type_expression *expression) { - walking_visitor::visit(expression); + expression->base().accept(this); + auto array_base = this->current_type; - if (this->current_type.get<constant_type>() != nullptr) + if (array_base.get<constant_type>() != nullptr) { add_error<const_qualifier_error>(expression->position(), const_qualifier_error::kind::array_position); } - this->current_type = type(std::make_shared<array_type>(this->current_type, expression->size)); + expression->dimensions().accept(this); + const auto size_constant = this->constant_evaluator.evaluate_index(expression->dimensions()); + + if (!size_constant.has_value()) + { + add_error<non_constant_expression_error>(expression->position(), + non_constant_expression_error::array_dimensions{ array_base }); + } + this->current_type = type(std::make_shared<array_type>(array_base, size_constant.value())); } void name_analysis_visitor::visit(slice_type_expression *expression) @@ -437,13 +464,12 @@ namespace elna::boot void name_analysis_visitor::visit(array_constructor_expression *expression) { - expression->m_element_type->accept(this); - auto element_type = this->current_type; + expression->array_type().accept(this); + expression->type_decoration = this->current_type; for (auto *element : expression->elements) { element->accept(this); } - expression->type_decoration = type(std::make_shared<array_type>(element_type, expression->size)); this->current_type = type(); } @@ -523,20 +549,36 @@ namespace elna::boot { declaration->variable_type().accept(this); auto variable_type = this->current_type; + std::optional<constant_value> computed; + if (declaration->initializer != nullptr) { declaration->initializer->accept(this); this->current_type = variable_type; + computed = this->constant_evaluator.evaluate(*declaration->initializer); + + if (this->bag.is_global() && !computed.has_value()) + { + add_error<non_constant_expression_error>(declaration->initializer->position(), + non_constant_expression_error::initializer{ extract_identifiers(declaration->identifiers) }); + } + } + else if (resolve_aliases(variable_type).get<constant_type>() != nullptr) + { + auto position_span = source_position(declaration->identifiers.front().id().position().start(), + declaration->identifiers.back().id().position().end()); + add_error<not_initialized_error>(position_span, + extract_identifiers(declaration->identifiers)); } for (const identifier_definition& variable_identifier : declaration->identifiers) { auto variable_symbol = register_variable(variable_identifier.name(), declaration->is_extern, declaration->position()); variable_symbol->exported = variable_identifier.exported(); + variable_symbol->value = computed; } } - void name_analysis_visitor::visit(procedure_declaration *declaration) { std::shared_ptr<procedure_info> info; |
