aboutsummaryrefslogtreecommitdiff
path: root/boot/type_check.cc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-19 02:08:06 +0200
committerEugen Wissner <belka@caraus.de>2026-07-19 02:08:06 +0200
commit2e1e95dc716167853be4a4b6acaaee1688142744 (patch)
tree343a27402a2aa0f1f83bc0ca05ad8803310e4959 /boot/type_check.cc
parent349e84c693c1444606e877f4d8cdc1a39aa91634 (diff)
downloadelna-2e1e95dc716167853be4a4b6acaaee1688142744.tar.gz
Implement initializer evaluator
Diffstat (limited to 'boot/type_check.cc')
-rw-r--r--boot/type_check.cc32
1 files changed, 29 insertions, 3 deletions
diff --git a/boot/type_check.cc b/boot/type_check.cc
index b42792b..b310e34 100644
--- a/boot/type_check.cc
+++ b/boot/type_check.cc
@@ -21,6 +21,16 @@ along with GCC; see the file COPYING3. If not see
namespace elna::boot
{
+ non_constant_initializer_error::non_constant_initializer_error(const source_position position)
+ : error(position)
+ {
+ }
+
+ std::string non_constant_initializer_error::what() const
+ {
+ return "Variable initializers must be constant expressions";
+ }
+
type_mismatch_error::type_mismatch_error(const source_position position,
type expected, type actual)
: error(position), expected(expected), actual(actual)
@@ -354,8 +364,8 @@ namespace elna::boot
}.run();
}
- type_analysis_visitor::type_analysis_visitor(symbol_bag bag)
- : error_container(), bag(bag)
+ type_analysis_visitor::type_analysis_visitor(symbol_bag bag, const target_info& target)
+ : error_container(), bag(bag), target(target)
{
}
@@ -424,10 +434,26 @@ namespace elna::boot
{
walking_visitor::visit(declaration);
- if (declaration->initializer == nullptr)
+ if (declaration->initializer == nullptr || has_errors())
{
return;
}
+ evaluator constant_evaluator(this->bag, this->target, this->evaluated_initializers);
+ if (!constant_evaluator.evaluate(*declaration->initializer))
+ {
+ add_error<non_constant_initializer_error>(declaration->initializer->position());
+ return;
+ }
+ // Record const variable initializers so later declarations
+ // can chain through them.
+ for (const auto& id : declaration->identifiers)
+ {
+ if (auto var = this->bag.lookup(id.name())->is_variable();
+ resolve_aliases(var->symbol).get<constant_type>() != nullptr)
+ {
+ this->evaluated_initializers[id.name()] = declaration->initializer;
+ }
+ }
for (const identifier_definition& variable_identifier : declaration->identifiers)
{
auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable();