From 8e655a0786aec5e0215e09f2a9629c6f32e34793 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 28 Aug 2026 02:39:42 +0200 Subject: Reject declarations shadowing imports --- boot/evaluator.cc | 75 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 50 insertions(+), 25 deletions(-) (limited to 'boot/evaluator.cc') diff --git a/boot/evaluator.cc b/boot/evaluator.cc index 1d10346..6a9fb3b 100644 --- a/boot/evaluator.cc +++ b/boot/evaluator.cc @@ -51,7 +51,7 @@ namespace elna::boot }, this->payload); } - std::optional> non_constant_expression_error::note() const + std::optional non_constant_expression_error::note() const { if (std::holds_alternative(this->payload)) { @@ -297,25 +297,37 @@ 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()) + // Accessing a member of an enumeration. The base is the type name, + // so the enumeration is looked up in the symbol table instead of + // reading the type decoration set by name analysis. + if (auto *base_designator = subject.base().is_designator()) { - type_to_check = subject.type_decoration; - } - auto resolved_base = resolve_underlying_type(type_to_check); - if (auto enumeration = resolved_base.get()) - { - auto enumeration_distance = std::distance(enumeration->members.begin(), - std::ranges::find(enumeration->members, subject.field().name())); - const std::size_t enumeration_position = static_cast(enumeration_distance); - - if (enumeration_position >= enumeration->members.size()) + if (auto *base_name = base_designator->is_named()) { - return std::nullopt; + auto symbol = this->bag.lookup(base_name->name); + + if (symbol != nullptr) + { + if (auto type_symbol = symbol->is_type()) + { + if (auto enumeration = resolve_underlying_type(type_symbol->symbol).get()) + { + auto member_iterator = std::ranges::find(enumeration->members, subject.field().name()); + + if (member_iterator == enumeration->members.end()) + { + return std::nullopt; + } + const std::size_t enumeration_position = static_cast( + std::distance(enumeration->members.begin(), member_iterator)); + + return constant_value{ integer_literal::from(enumeration_position + 1U) }; + } + } + } } - return constant_value{ integer_literal::from(enumeration_position + 1U) }; } - else if (auto base = evaluate(subject.base())) + if (auto base = evaluate(subject.base())) { if (auto *record = std::get_if>(&base.value())) { @@ -732,19 +744,32 @@ namespace elna::boot { auto value = evaluate(subject.value()); - if (!value.has_value() || subject.type_decoration.empty()) + if (!value.has_value()) { return std::nullopt; } - const type resolved = resolve_underlying_type(subject.type_decoration); - - if (is_primitive_type(resolved, "Int")) - { - return cast_to_int(value.value()); - } - else if (is_primitive_type(resolved, "Word")) + // The target type is looked up in the symbol table instead of reading + // the type decoration set by name analysis. + if (auto *target = subject.target().is_named()) { - return cast_to_word(value.value()); + auto symbol = this->bag.lookup(target->name); + + if (symbol != nullptr) + { + if (auto type_symbol = symbol->is_type()) + { + const type resolved = resolve_underlying_type(type_symbol->symbol); + + if (is_primitive_type(resolved, "Int")) + { + return cast_to_int(value.value()); + } + else if (is_primitive_type(resolved, "Word")) + { + return cast_to_word(value.value()); + } + } + } } return constant_value{ value.value() }; -- cgit v1.2.3