diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/elna/boot/evaluator.h | 3 | ||||
| -rw-r--r-- | include/elna/boot/result.h | 77 |
2 files changed, 58 insertions, 22 deletions
diff --git a/include/elna/boot/evaluator.h b/include/elna/boot/evaluator.h index 0d1a7c8..02db6ab 100644 --- a/include/elna/boot/evaluator.h +++ b/include/elna/boot/evaluator.h @@ -86,6 +86,9 @@ namespace elna::boot std::optional<std::size_t> evaluate_traits_size(const type& subject); std::optional<std::size_t> evaluate_traits_alignment(const type& subject); + static std::optional<constant_value> cast_to_int(const constant_value& source_expression); + static std::optional<constant_value> cast_to_word(const constant_value& source_expression); + public: std::optional<std::size_t> evaluate_index(expression& subject); std::optional<constant_value> evaluate_traits(traits_expression& subject); diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h index 3d01eb2..49e078e 100644 --- a/include/elna/boot/result.h +++ b/include/elna/boot/result.h @@ -226,10 +226,10 @@ namespace elna::boot * * \tparam T The examined type. * - * \see is_unsigned + * \see is_unsigned_v */ template<typename T> - inline constexpr bool is_signed = std::is_same_v<T, std::int8_t> + inline constexpr bool is_signed_v = std::is_same_v<T, std::int8_t> || std::is_same_v<T, std::int16_t> || std::is_same_v<T, std::int32_t> || std::is_same_v<T, std::int64_t>; @@ -239,10 +239,10 @@ namespace elna::boot * * \tparam T The examined type. * - * \see is_signed + * \see is_signed_v */ template<typename T> - inline constexpr bool is_unsigned = std::is_same_v<T, std::uint8_t> + inline constexpr bool is_unsigned_v = std::is_same_v<T, std::uint8_t> || std::is_same_v<T, std::uint16_t> || std::is_same_v<T, std::uint32_t> || std::is_same_v<T, std::uint64_t>; @@ -255,7 +255,7 @@ namespace elna::boot * \tparam T The examined type. */ template<typename T> - inline constexpr bool is_integral = is_signed<T> || is_unsigned<T>; + inline constexpr bool is_integral = is_signed_v<T> || is_unsigned_v<T>; struct integer_literal { @@ -281,25 +281,25 @@ namespace elna::boot std::weak_ordering operator<=>(const integer_literal& that) const; template<typename U> bool operator==(U that) const - requires(is_unsigned<U> && sizeof(U) <= sizeof(unsigned long int)) + requires(is_unsigned_v<U> && sizeof(U) <= sizeof(unsigned long int)) { return mpz_cmp_ui(this->raw, that) == 0; } template<typename U> bool operator==(U that) const - requires(is_signed<U> && sizeof(U) <= sizeof(signed long int)) + requires(is_signed_v<U> && sizeof(U) <= sizeof(signed long int)) { return mpz_cmp_si(this->raw, that) == 0; } template<typename U> std::weak_ordering operator<=>(U that) const - requires(is_unsigned<U> && sizeof(U) <= sizeof(unsigned long int)) + requires(is_unsigned_v<U> && sizeof(U) <= sizeof(unsigned long int)) { return mpz_cmp_ui(this->raw, that) <=> 0; } template<typename U> std::weak_ordering operator<=>(U that) const - requires(is_signed<U> && sizeof(U) <= sizeof(signed long int)) + requires(is_signed_v<U> && sizeof(U) <= sizeof(signed long int)) { return mpz_cmp_si(this->raw, that) <=> 0; } @@ -312,23 +312,31 @@ namespace elna::boot std::string to_string(const std::uint8_t base = 10U) const; /** - * \return Whether the stored value is a negative integer. - */ - bool is_negative() const; - - /** - * Exports the stored value as a host \c std::ptrdiff_t. + * Exports the stored value as a host \p T. * - * \return The converted value, or \c std::nullopt if out of range. - */ - std::optional<std::ptrdiff_t> to_signed() const; - - /** - * Exports the stored value as a host \c std::size_t. + * This function tries to shrink or extend the value to fit into the + * target type if possible. * + * \tparam Target type. * \return The converted value, or \c std::nullopt if out of range. */ - std::optional<std::size_t> to_unsigned() const; + template<typename T> + std::optional<T> try_to() const + requires is_integral<T> + { + if constexpr (is_signed_v<T>) + { + return to_signed<T>(); + } + else if constexpr (is_unsigned_v<T>) + { + return to_unsigned<T>(); + } + else + { + static_assert("integer_literal::to expected only integral types"); + } + } /** * Attempts to narrow this literal's internally stored size to @@ -366,6 +374,7 @@ namespace elna::boot integer_literal(bool is_signed, std::size_t size); bool fits_in(const std::size_t bits) const; std::optional<integer_literal> check() &&; + bool is_negative() const; bool is_negative_minimum(const std::size_t bits) const; bool is_negative_minimum() const; std::size_t bits() const; @@ -381,6 +390,30 @@ namespace elna::boot return { written, rop[0] }; } + + template<typename T = std::ptrdiff_t> + std::optional<T> to_signed() const + { + if (is_negative_minimum(sizeof(T) * CHAR_BIT)) + { + return std::numeric_limits<T>::min(); + } + auto [written, rop] = export_to_words<T>(); + + if (written > 1 || rop < 0) + { + return std::nullopt; + } + return is_negative() ? -rop : rop; + } + + template<typename T = std::size_t> + std::optional<T> to_unsigned() const + { + auto [written, rop] = export_to_words<T>(); + + return written > 1 ? std::nullopt : std::make_optional(rop); + } }; /** |
