diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-08-28 02:39:42 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-08-28 02:39:42 +0200 |
| commit | 8e655a0786aec5e0215e09f2a9629c6f32e34793 (patch) | |
| tree | 0788634cf66fed9c1a1d264b5b8c30da49380559 /boot/evaluator.cc | |
| parent | 4d4537866690a1ef3d882f5e9a6e01d8220a3650 (diff) | |
| download | elna-8e655a0786aec5e0215e09f2a9629c6f32e34793.tar.gz | |
Reject declarations shadowing imports
Diffstat (limited to 'boot/evaluator.cc')
| -rw-r--r-- | boot/evaluator.cc | 75 |
1 files changed, 50 insertions, 25 deletions
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<std::pair<std::string, source_position>> non_constant_expression_error::note() const + std::optional<diagnostic_note> non_constant_expression_error::note() const { if (std::holds_alternative<initializer>(this->payload)) { @@ -297,25 +297,37 @@ namespace elna::boot std::optional<constant_value> 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<enumeration_type>()) - { - auto enumeration_distance = std::distance(enumeration->members.begin(), - std::ranges::find(enumeration->members, subject.field().name())); - const std::size_t enumeration_position = static_cast<std::size_t>(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<enumeration_type>()) + { + 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::size_t>( + 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<constant_aggregate<ordered_map>>(&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() }; |
