diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-10-07 17:33:40 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-10-07 17:45:20 +0200 |
| commit | 12e304fd56f054ba7296ab538eecd4280a67832a (patch) | |
| tree | 218f37dc04fa14323d2ca7704e47a830dcd98b22 /boot/evaluator.cc | |
| parent | f547dae96d770cc7bc27d3790d0d87bb8e37963d (diff) | |
| download | elna-12e304fd56f054ba7296ab538eecd4280a67832a.tar.gz | |
Allow assigning contants to enumeration members
Diffstat (limited to 'boot/evaluator.cc')
| -rw-r--r-- | boot/evaluator.cc | 54 |
1 files changed, 35 insertions, 19 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc index 67fc42a..18633ba 100644 --- a/boot/evaluator.cc +++ b/boot/evaluator.cc @@ -48,6 +48,10 @@ namespace elna::boot return "Array dimensions for type '" + payload.array_type.to_string() + "' should be constant"; } + else if constexpr (std::is_same_v<T, enumeration_value>) + { + return "Enumeration member value must be an integer constant expression"; + } }, this->payload); } @@ -63,6 +67,21 @@ namespace elna::boot } } + /** + * Builds the constant for an enumeration value. + * + * Goes through the bit pattern because \c integer_literal::from imports + * the magnitude of a negative value, not its two's complement. + * + * \param value Member value. + * \param size Size of the enumeration type in bytes. + * \return Signed constant of the given size. + */ + static integer_literal enumeration_constant(const std::ptrdiff_t value, const std::size_t size) + { + return integer_literal::from(static_cast<std::size_t>(value)).cast_to(true, size); + } + std::optional<type_properties> get_type_properties(const type& subject, const target_info& target) { const type resolved = resolve_underlying_type(subject); @@ -330,10 +349,12 @@ namespace elna::boot { return std::nullopt; } - const std::size_t enumeration_position = static_cast<std::size_t>( - std::distance(enumeration->members.begin(), member_iterator)); + const std::ptrdiff_t enumeration_position = + std::distance(enumeration->members.begin(), member_iterator); - return constant_value{ integer_literal::from(enumeration_position + 1U) }; + return constant_value{ enumeration_constant( + enumeration->values.at(static_cast<std::size_t>(enumeration_position)), + this->target.word_properties.front().size) }; } } } @@ -897,21 +918,21 @@ namespace elna::boot } std::optional<constant_value> evaluator::cast_to_enumeration(const constant_value& source_expression, - const std::size_t member_count, const std::size_t target_size) + const enumeration_type& enumeration, const std::size_t target_size) { - std::optional<constant_value> position = cast_to_integer(source_expression, false, target_size); + std::optional<constant_value> value = cast_to_integer(source_expression, true, target_size); - if (!position.has_value()) + if (!value.has_value()) { return std::nullopt; } - const auto *converted = std::get_if<integer_literal>(&position.value()); + const auto *converted = std::get_if<integer_literal>(&value.value()); - if (converted == nullptr || *converted < std::size_t{ 1 } || *converted > member_count) + if (converted == nullptr || *converted < enumeration.minimum() || *converted > enumeration.maximum()) { return std::nullopt; } - return position; + return value; } std::optional<constant_value> evaluator::cast_to_pointer(const constant_value& source_expression) @@ -952,7 +973,7 @@ namespace elna::boot { return std::nullopt; } - return cast_to_enumeration(value.value(), enumeration->members.size(), properties->size); + return cast_to_enumeration(value.value(), *enumeration, properties->size); } if (is_integral_type(target_type)) { @@ -1055,10 +1076,8 @@ namespace elna::boot } if (const auto enumeration = resolved.get<enumeration_type>()) { - return constant_value{ - integer_literal::from<std::size_t>( - this->target.word_properties.front().size, 1U).value() - }; + return constant_value{ enumeration_constant(enumeration->minimum(), + this->target.word_properties.front().size) }; } } else if (subject.name.name() == "max") @@ -1104,11 +1123,8 @@ namespace elna::boot } if (const auto enumeration = resolved.get<enumeration_type>()) { - return constant_value{ - integer_literal::from<std::size_t>( - this->target.word_properties.front().size, - enumeration->members.size()).value() - }; + return constant_value{ enumeration_constant(enumeration->maximum(), + this->target.word_properties.front().size) }; } } else if (subject.name.name() == "offset") |
