aboutsummaryrefslogtreecommitdiff
path: root/boot/name_analysis.cc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-08-05 01:03:55 +0200
committerEugen Wissner <belka@caraus.de>2026-08-05 21:27:36 +0200
commitb2dee14873402ee3d13d59ae5579593796ea862f (patch)
tree1f245eac1a23a73f45124498fc8274874e35750e /boot/name_analysis.cc
parent1c2fb173ea3b674207badc721556ad72962b266e (diff)
downloadelna-b2dee14873402ee3d13d59ae5579593796ea862f.tar.gz
Check that constants are initialized
Diffstat (limited to 'boot/name_analysis.cc')
-rw-r--r--boot/name_analysis.cc62
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;