aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-31 10:20:56 +0200
committerEugen Wissner <belka@caraus.de>2026-07-31 10:20:56 +0200
commit661c29a7835cf1755deaf21f91832f00e958a318 (patch)
treedc048d1672e17beec2d8a81e2c748280277a191c /include
parentf8daedce5c73e02dfb2fc59d75777190185584df (diff)
downloadelna-661c29a7835cf1755deaf21f91832f00e958a318.tar.gz
Review spaceship usage
Diffstat (limited to 'include')
-rw-r--r--include/elna/boot/ast.h6
-rw-r--r--include/elna/boot/name_analysis.h2
-rw-r--r--include/elna/boot/result.h183
-rw-r--r--include/elna/gcc/elna-generic.h2
4 files changed, 153 insertions, 40 deletions
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<std::int32_t> *) = 0;
- virtual void visit(literal<std::uint32_t> *) = 0;
+ virtual void visit(literal<integer_literal> *) = 0;
virtual void visit(literal<double> *) = 0;
virtual void visit(literal<bool> *) = 0;
virtual void visit(literal<unsigned char> *) = 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<std::int32_t> *) override;
- [[noreturn]] void visit(literal<std::uint32_t> *) override;
+ [[noreturn]] void visit(literal<integer_literal> *) override;
[[noreturn]] void visit(literal<double> *) override;
[[noreturn]] void visit(literal<bool> *) override;
[[noreturn]] void visit(literal<unsigned char> *) override;
@@ -237,7 +237,7 @@ namespace elna::boot
void visit(field_access_expression *expression) override;
void visit(dereference_expression *expression) override;
void visit(literal<std::int32_t> *) override;
- void visit(literal<std::uint32_t> *) override;
+ void visit(literal<integer_literal> *) override;
void visit(literal<double> *) override;
void visit(literal<bool> *) override;
void visit(literal<unsigned char> *) 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<std::int32_t> *literal) override;
- void visit(literal<std::uint32_t> *literal) override;
+ void visit(literal<integer_literal> *literal) override;
void visit(literal<double> *literal) override;
void visit(literal<bool> *literal) override;
void visit(literal<unsigned char> *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 <vector>
#include <unordered_map>
+#include <gmp.h>
+
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;
@@ -180,6 +181,138 @@ namespace elna::boot
};
/**
+ * Checks whether \p T is a signed, std::int*_t type.
+ *
+ * \tparam T The examined type.
+ *
+ * \see is_unsigned
+ */
+ template<typename T>
+ inline constexpr bool is_signed = 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>;
+
+ /**
+ * Checks whether \p T is a signed, std::uint*_t type.
+ *
+ * \tparam T The examined type.
+ *
+ * \see is_signed
+ */
+ template<typename T>
+ inline constexpr bool is_unsigned = 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>;
+
+ /**
+ * 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<typename T>
+ inline constexpr bool is_integral = is_signed<T> || is_unsigned<T>;
+
+ /**
+ * Checks whether \p T is an integral or floating point type.
+ *
+ * \tparam T The examined type.
+ *
+ * \see is_integral
+ */
+ template<typename T>
+ inline constexpr bool is_arithmetic = is_integral<T> || std::is_floating_point_v<T>;
+
+ struct integer_literal
+ {
+ integer_literal(integer_literal&& that) noexcept;
+ integer_literal(const integer_literal& that);
+ ~integer_literal();
+
+ std::optional<integer_literal> add(const integer_literal& that) const;
+ std::optional<integer_literal> sub(const integer_literal& that) const;
+ std::optional<integer_literal> mul(const integer_literal& that) const;
+ std::optional<integer_literal> div(const integer_literal& that) const;
+ std::optional<integer_literal> mod(const integer_literal& that) const;
+ std::optional<integer_literal> neg() const;
+ std::optional<integer_literal> shl(const integer_literal& that) const;
+ std::optional<integer_literal> 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<typename U>
+ bool operator==(U that) const
+ requires(is_unsigned<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))
+ {
+ 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))
+ {
+ 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))
+ {
+ 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<typename T>
+ T to() const
+ requires is_integral<T>
+ {
+ T result;
+
+ mpz_export(&result, nullptr, 1, sizeof(T), 0, 0, this->raw);
+
+ return result;
+ }
+
+ template<typename T>
+ static integer_literal from(T initial)
+ requires is_integral<T>
+ {
+ integer_literal result{ std::is_signed_v<T>, 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<integer_literal> 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<value_type>::iterator;
using const_iterator = std::vector<value_type>::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<template<typename, typename> typename C, template<typename> 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<std::vector>& that) const
- requires std::is_same_v<Container, std::vector<constant_value, Alloc<constant_value>>>
- {
- 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<ordered_map>& that) const
- requires std::is_same_v<Container, ordered_map<constant_value, Alloc<constant_value>>>
- {
- 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<C, Alloc>& that) const
{
- return !(*this == that);
+ return *this->container == *that.container;
}
};
@@ -540,3 +647,9 @@ struct std::hash<elna::boot::constant_aggregate<elna::boot::ordered_map>>
{
std::size_t operator()(const elna::boot::constant_aggregate<elna::boot::ordered_map>& key) const noexcept;
};
+
+template<>
+struct std::hash<elna::boot::integer_literal>
+{
+ 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<std::int32_t> *literal) override;
- void visit(boot::literal<std::uint32_t> *literal) override;
+ void visit(boot::literal<boot::integer_literal> *literal) override;
void visit(boot::literal<double> *literal) override;
void visit(boot::literal<bool> *boolean) override;
void visit(boot::literal<unsigned char> *character) override;