From 36a274c9a8bca944234589220def025d3920b3ef Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 28 Jul 2026 19:19:32 +0200 Subject: Enforce case label uniqueness and constness --- boot/evaluator.cc | 224 +++++------------------------------------------------- 1 file changed, 19 insertions(+), 205 deletions(-) (limited to 'boot/evaluator.cc') diff --git a/boot/evaluator.cc b/boot/evaluator.cc index 6d3153e..b49a9ec 100644 --- a/boot/evaluator.cc +++ b/boot/evaluator.cc @@ -16,25 +16,17 @@ along with GCC; see the file COPYING3. If not see . */ #include "elna/boot/evaluator.h" + #include "elna/boot/ast.h" #include #include +#include #include #include 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"; - } - std::optional get_type_properties(const type& subject, const target_info& target) { auto resolved = resolve_underlying_type(subject); @@ -304,6 +296,23 @@ namespace elna::boot std::optional evaluator::evaluate_field_access(field_access_expression& subject) { + auto type_to_check = subject.base().type_decoration; + if (type_to_check.empty()) + { + type_to_check = subject.type_decoration; + } + auto resolved_base = resolve_underlying_type(type_to_check); + if (auto enumeration = resolved_base.get()) + { + auto member_iterator = std::ranges::find(enumeration->members, subject.field().name()); + if (member_iterator != enumeration->members.end()) + { + return constant_value{ + static_cast(std::distance(enumeration->members.begin(), member_iterator) + 1) + }; + } + return std::nullopt; + } auto base = evaluate(subject.base()); if (!base.has_value()) { @@ -770,199 +779,4 @@ namespace elna::boot return std::nullopt; } - /** - * Converts a constant_value to an AST literal expression. - * - * \param value Evaluated constant to convert. - * \param position Source position for the new literal node. - * \param decoration Type decoration to apply to the literal. - * \return A new literal expression, or \c nullptr if \p value - * is an aggregate (handled separately by the caller). - */ - static expression *value_to_expression(const constant_value& value, - const source_position& position, const type& decoration) - { - return std::visit([&position, &decoration](auto&& value) -> expression* - { - using T = std::decay_t; - - if constexpr (std::is_same_v) - { - auto *lit = new literal(position, value); - lit->type_decoration = decoration; - return lit; - } - else if constexpr (std::is_same_v) - { - auto *lit = new literal(position, value); - lit->type_decoration = decoration; - return lit; - } - else if constexpr (std::is_same_v) - { - auto *lit = new literal(position, value); - lit->type_decoration = decoration; - return lit; - } - else if constexpr (std::is_same_v) - { - auto *lit = new literal(position, value); - lit->type_decoration = decoration; - return lit; - } - else if constexpr (std::is_same_v) - { - auto *lit = new literal(position, value); - lit->type_decoration = decoration; - return lit; - } - else if constexpr (std::is_same_v - || std::is_same_v) - { - auto *lit = new literal(position, nullptr); - lit->type_decoration = decoration; - return lit; - } - else - { - return nullptr; - } - }, value); - } - - expression *evaluator::fold(expression& original) - { - auto value = evaluate(original); - if (!value.has_value()) - { - return &original; - } - if (expression *literal = value_to_expression(value.value(), original.position(), original.type_decoration)) - { - delete &original; - return literal; - } - if (auto *record = original.is_record_constructor()) - { - for (auto& field_init : record->field_initializers) - { - fold_aggregate_field(field_init); - } - } - else if (auto *array = original.is_array_constructor()) - { - for (auto& element : array->elements) - { - element = fold(*element); - } - } - return &original; - } - - void evaluator::fold_aggregate_field(field_initializer& field_init) - { - auto value = evaluate(field_init.value()); - if (!value.has_value()) - { - return; - } - expression *literal = value_to_expression(value.value(), - field_init.value().position(), field_init.value().type_decoration); - if (literal != nullptr) - { - field_init.value(*literal); - return; - } - expression *folded = fold(field_init.value()); - if (folded != &field_init.value()) - { - field_init.value(*folded); - } - } - - constant_folder::constant_folder(symbol_bag& bag, const target_info& target) - : bag(bag), target(target), constant_evaluator(this->bag, this->target) - { - } - - void constant_folder::visit(variable_declaration* declaration) - { - if (declaration->initializer == nullptr || has_errors()) - { - return; - } - auto computed = this->constant_evaluator.evaluate(*declaration->initializer); - if (!computed) - { - add_error(declaration->initializer->position()); - return; - } - declaration->initializer = this->constant_evaluator.fold(*declaration->initializer); - - for (const auto& identifier : declaration->identifiers) - { - auto symbol = this->bag.lookup(identifier.name()); - if (symbol == nullptr) - { - continue; - } - if (auto var = symbol->is_variable(); - resolve_aliases(var->symbol).get() != nullptr) - { - var->value = computed; - } - } - } - - void constant_folder::visit(cast_expression *expr) - { - expr->target().accept(this); - expr->value().accept(this); - expr->value(fold_trait(expr->value())); - } - - void constant_folder::visit(binary_expression *expr) - { - expr->lhs().accept(this); - expr->lhs(fold_trait(expr->lhs())); - expr->rhs().accept(this); - expr->rhs(fold_trait(expr->rhs())); - } - - void constant_folder::visit(unary_expression *expr) - { - expr->operand().accept(this); - expr->operand(fold_trait(expr->operand())); - } - - void constant_folder::visit(procedure_call *call) - { - call->callable().accept(this); - for (auto& argument : call->arguments) - { - argument->accept(this); - expression& folded = fold_trait(*argument); - if (&folded != argument) - { - delete argument; - argument = &folded; - } - } - } - - expression& constant_folder::fold_trait(expression& expr) - { - if (auto *trait = expr.is_traits()) - { - if (auto value = this->constant_evaluator.evaluate_traits(*trait)) - { - if (auto *literal = value_to_expression(value.value(), trait->position(), trait->type_decoration)) - { - return *literal; - } - } - } - return expr; - } - } -- cgit v1.2.3