From 661c29a7835cf1755deaf21f91832f00e958a318 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 31 Jul 2026 10:20:56 +0200 Subject: Review spaceship usage --- include/elna/boot/ast.h | 6 +- include/elna/boot/name_analysis.h | 2 +- include/elna/boot/result.h | 183 ++++++++++++++++++++++++++++++-------- include/elna/gcc/elna-generic.h | 2 +- 4 files changed, 153 insertions(+), 40 deletions(-) (limited to 'include') diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index cc5878b..0eda1a3 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -139,7 +139,7 @@ namespace elna::boot virtual void visit(field_access_expression *) = 0; virtual void visit(dereference_expression *) = 0; virtual void visit(literal *) = 0; - virtual void visit(literal *) = 0; + virtual void visit(literal *) = 0; virtual void visit(literal *) = 0; virtual void visit(literal *) = 0; virtual void visit(literal *) = 0; @@ -189,7 +189,7 @@ namespace elna::boot [[noreturn]] void visit(field_access_expression *) override; [[noreturn]] void visit(dereference_expression *) override; [[noreturn]] void visit(literal *) override; - [[noreturn]] void visit(literal *) override; + [[noreturn]] void visit(literal *) override; [[noreturn]] void visit(literal *) override; [[noreturn]] void visit(literal *) override; [[noreturn]] void visit(literal *) override; @@ -237,7 +237,7 @@ namespace elna::boot void visit(field_access_expression *expression) override; void visit(dereference_expression *expression) override; void visit(literal *) override; - void visit(literal *) override; + void visit(literal *) override; void visit(literal *) override; void visit(literal *) override; void visit(literal *) override; diff --git a/include/elna/boot/name_analysis.h b/include/elna/boot/name_analysis.h index 626e9f2..5d43f67 100644 --- a/include/elna/boot/name_analysis.h +++ b/include/elna/boot/name_analysis.h @@ -158,7 +158,7 @@ namespace elna::boot void visit(for_statement *statement) override; void visit(literal *literal) override; - void visit(literal *literal) override; + void visit(literal *literal) override; void visit(literal *literal) override; void visit(literal *literal) override; void visit(literal *literal) override; diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h index 42c96f2..3e8dfdf 100644 --- a/include/elna/boot/result.h +++ b/include/elna/boot/result.h @@ -29,6 +29,8 @@ along with GCC; see the file COPYING3. If not see #include #include +#include + namespace elna::boot { /** @@ -143,7 +145,7 @@ namespace elna::boot { } - auto operator<=>(const return_declaration&) const = default; + bool operator==(const return_declaration&) const = default; T proper_type{}; bool no_return{ false }; @@ -156,9 +158,8 @@ namespace elna::boot const std::string& name() const; const source_position& position() const; - std::strong_ordering operator<=>(const identifier& that) const; + bool operator==(const identifier& that) const; bool operator==(std::string_view that) const; - bool operator!=(std::string_view that) const; private: std::string m_name; @@ -179,6 +180,138 @@ namespace elna::boot bool m_exported{ false }; }; + /** + * Checks whether \p T is a signed, std::int*_t type. + * + * \tparam T The examined type. + * + * \see is_unsigned + */ + template + inline constexpr bool is_signed = std::is_same_v + || std::is_same_v + || std::is_same_v + || std::is_same_v; + + /** + * Checks whether \p T is a signed, std::uint*_t type. + * + * \tparam T The examined type. + * + * \see is_signed + */ + template + inline constexpr bool is_unsigned = std::is_same_v + || std::is_same_v + || std::is_same_v + || std::is_same_v; + + /** + * Checks whether \p T is any of std::int*_t or std::uint*_t types. + * + * Contrary to \c std::is_integral characters and booleans do not count. + * + * \tparam T The examined type. + */ + template + inline constexpr bool is_integral = is_signed || is_unsigned; + + /** + * Checks whether \p T is an integral or floating point type. + * + * \tparam T The examined type. + * + * \see is_integral + */ + template + inline constexpr bool is_arithmetic = is_integral || std::is_floating_point_v; + + struct integer_literal + { + integer_literal(integer_literal&& that) noexcept; + integer_literal(const integer_literal& that); + ~integer_literal(); + + std::optional add(const integer_literal& that) const; + std::optional sub(const integer_literal& that) const; + std::optional mul(const integer_literal& that) const; + std::optional div(const integer_literal& that) const; + std::optional mod(const integer_literal& that) const; + std::optional neg() const; + std::optional shl(const integer_literal& that) const; + std::optional shr(const integer_literal& that) const; + + integer_literal operator|(const integer_literal& that) const; + integer_literal operator&(const integer_literal& that) const; + integer_literal operator^(const integer_literal& that) const; + integer_literal operator~() const; + + bool operator==(const integer_literal& that) const; + std::weak_ordering operator<=>(const integer_literal& that) const; + template + bool operator==(U that) const + requires(is_unsigned && sizeof(U) <= sizeof(unsigned long int)) + { + return mpz_cmp_ui(this->raw, that) == 0; + } + template + bool operator==(U that) const + requires(is_signed && sizeof(U) <= sizeof(signed long int)) + { + return mpz_cmp_si(this->raw, that) == 0; + } + template + std::weak_ordering operator<=>(U that) const + requires(is_unsigned && sizeof(U) <= sizeof(unsigned long int)) + { + return mpz_cmp_ui(this->raw, that) <=> 0; + } + template + std::weak_ordering operator<=>(U that) const + requires(is_signed && sizeof(U) <= sizeof(signed long int)) + { + return mpz_cmp_si(this->raw, that) <=> 0; + } + + integer_literal& operator=(integer_literal&& that) noexcept; + integer_literal& operator=(const integer_literal& that); + + bool is_signed() const; + std::size_t size() const; + + template + T to() const + requires is_integral + { + T result; + + mpz_export(&result, nullptr, 1, sizeof(T), 0, 0, this->raw); + + return result; + } + + template + static integer_literal from(T initial) + requires is_integral + { + integer_literal result{ std::is_signed_v, sizeof(T) }; + + mpz_import(result.raw, 1, 1, sizeof(T), 0, 0, &initial); + + return result; + } + + private: + bool m_signed; + std::size_t m_size; + mpz_t raw; + + integer_literal(bool is_signed, std::size_t size); + std::optional check() &&; + bool is_negative_minimum() const; + std::size_t bits() const; + }; + /** * An associative container that contains key-value pairs with unique keys. * Keys preserve the insertion order. @@ -202,9 +335,9 @@ namespace elna::boot using iterator = std::vector::iterator; using const_iterator = std::vector::const_iterator; - auto operator<=>(const ordered_map& that) const + bool operator==(const ordered_map& that) const { - return this->payload <=> that.payload; + return this->payload == that.payload; } /** @@ -357,7 +490,7 @@ namespace elna::boot { std::string name; - auto operator<=>(const global_address&) const = default; + bool operator==(const global_address&) const = default; }; template typename C, template typename Alloc = std::allocator> @@ -371,7 +504,7 @@ namespace elna::boot */ using constant_value = std::variant< std::int32_t, - std::uint32_t, + integer_literal, double, bool, unsigned char, @@ -387,7 +520,6 @@ namespace elna::boot struct constant_value_hash { std::size_t operator()(const constant_value& value) const noexcept; - bool operator()(const constant_value& lhs, const constant_value& rhs) const noexcept; }; /** @@ -433,34 +565,9 @@ namespace elna::boot return this->container.get(); } - bool operator==(const constant_aggregate& that) const - requires std::is_same_v>> - { - if (this->container->size() != that.container->size()) - { - return false; - } - return std::ranges::equal(*this->container, *that.container, constant_value_hash{}); - } - - bool operator==(const constant_aggregate& that) const - requires std::is_same_v>> - { - if (this->container->size() != that.container->size()) - { - return false; - } - const constant_value_hash comparator{}; - - return std::ranges::equal(*this->container, *that.container, - [comparator](const auto& lhs, const auto& rhs) { - return lhs.first == rhs.first && comparator(lhs.second, rhs.second); - }); - } - - bool operator!=(const constant_aggregate& that) const + bool operator==(const constant_aggregate& that) const { - return !(*this == that); + return *this->container == *that.container; } }; @@ -540,3 +647,9 @@ struct std::hash> { std::size_t operator()(const elna::boot::constant_aggregate& key) const noexcept; }; + +template<> +struct std::hash +{ + std::size_t operator()(const elna::boot::integer_literal& key) const noexcept; +}; diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index b5ba5e0..944c4d0 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -74,7 +74,7 @@ namespace elna::gcc void visit(boot::procedure_call *call) override; void visit(boot::cast_expression *expression) override; void visit(boot::literal *literal) override; - void visit(boot::literal *literal) override; + void visit(boot::literal *literal) override; void visit(boot::literal *literal) override; void visit(boot::literal *boolean) override; void visit(boot::literal *character) override; -- cgit v1.2.3