mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
AK+Everywhere: Replace DistinctNumeric bool parameters with named ones
This means that rather than this: ``` AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, FunctionAddress); ``` We now have this: ``` AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, FunctionAddress, Arithmetic, Comparison, Increment); ``` Which is a lot more readable. :^) Co-authored-by: Ali Mohammad Pur <mpfard@serenityos.org>
This commit is contained in:
parent
24c0a6e9a4
commit
c33eae24f9
Notes:
sideshowbarker
2024-07-17 23:02:37 +09:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/SerenityOS/serenity/commit/c33eae24f9 Pull-request: https://github.com/SerenityOS/serenity/pull/16006 Reviewed-by: https://github.com/alimpfard
7 changed files with 133 additions and 92 deletions
|
@ -113,13 +113,12 @@ struct ArbitrarySizedEnum : public T {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define AK_MAKE_ARBITRARY_SIZED_ENUM(EnumName, T, ...) \
|
#define AK_MAKE_ARBITRARY_SIZED_ENUM(EnumName, T, ...) \
|
||||||
namespace EnumName { \
|
namespace EnumName { \
|
||||||
using EnumName = ArbitrarySizedEnum<DistinctNumeric<T, struct __##EnumName##Tag, \
|
using EnumName = ArbitrarySizedEnum<DistinctNumeric<T, struct __##EnumName##Tag, AK::DistinctNumericFeature::Comparison>>; \
|
||||||
false, true, false, false, false, false>>; \
|
using Type = EnumName; \
|
||||||
using Type = EnumName; \
|
using UnderlyingType = T; \
|
||||||
using UnderlyingType = T; \
|
inline constexpr static EnumName __VA_ARGS__; \
|
||||||
inline constexpr static EnumName __VA_ARGS__; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Ben Wiederhake <BenWiederhake.GitHub@gmx.de>
|
* Copyright (c) 2020, Ben Wiederhake <BenWiederhake.GitHub@gmx.de>
|
||||||
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -19,20 +20,19 @@ namespace AK {
|
||||||
* want simply gets different values for `fn_length` and `line`. The macros
|
* want simply gets different values for `fn_length` and `line`. The macros
|
||||||
* `TYPEDEF_DISTINCT_NUMERIC_*()` at the bottom of `DistinctNumeric.h`.
|
* `TYPEDEF_DISTINCT_NUMERIC_*()` at the bottom of `DistinctNumeric.h`.
|
||||||
*
|
*
|
||||||
* `Incr`, `Cmp`, `Bool`, `Flags`, `Shift`, and `Arith` simply split up the
|
* The tags in `DistinctNumericFeature` simply split up the space of operators into 6 simple categories:
|
||||||
* space of operators into 6 simple categories:
|
|
||||||
* - No matter the values of these, `DistinctNumeric` always implements `==` and `!=`.
|
* - No matter the values of these, `DistinctNumeric` always implements `==` and `!=`.
|
||||||
* - If `Incr` is true, then `++a`, `a++`, `--a`, and `a--` are implemented.
|
* - If `Arithmetic` is present, then `a+b`, `a-b`, `+a`, `-a`, `a*b`, `a/b`, `a%b`, and the respective `a_=b` versions are implemented.
|
||||||
* - If `Cmp` is true, then `a>b`, `a<b`, `a>=b`, and `a<=b` are implemented.
|
* - If `CastToBool` is present, then `!a`, `a&&b`, and `a||b` are implemented (but not `operator bool()`, because of overzealous integer promotion rules).
|
||||||
* - If `Bool` is true, then `!a`, `a&&b`, and `a||b` are implemented (but not `operator bool()`, because of overzealous integer promotion rules).
|
* - If `Comparison` is present, then `a>b`, `a<b`, `a>=b`, and `a<=b` are implemented.
|
||||||
* - If `Flags` is true, then `~a`, `a&b`, `a|b`, `a^b`, `a&=b`, `a|=b`, and `a^=b` are implemented.
|
* - If `Flags` is present, then `~a`, `a&b`, `a|b`, `a^b`, `a&=b`, `a|=b`, and `a^=b` are implemented.
|
||||||
* - If `Shift` is true, then `a<<b`, `a>>b`, `a<<=b`, `a>>=b` are implemented.
|
* - If `Increment` is present, then `++a`, `a++`, `--a`, and `a--` are implemented.
|
||||||
* - If `Arith` is true, then `a+b`, `a-b`, `+a`, `-a`, `a*b`, `a/b`, `a%b`, and the respective `a_=b` versions are implemented.
|
* - If `Shift` is present, then `a<<b`, `a>>b`, `a<<=b`, `a>>=b` are implemented.
|
||||||
* The semantics are always those of the underlying basic type `T`.
|
* The semantics are always those of the underlying basic type `T`.
|
||||||
*
|
*
|
||||||
* These can be combined arbitrarily. Want a numeric type that supports `++a`
|
* These can be combined arbitrarily. Want a numeric type that supports `++a`
|
||||||
* and `a >> b` but not `a > b`? Sure thing, just set
|
* and `a >> b` but not `a > b`? Sure thing, just set
|
||||||
* `Incr=true, Cmp=false, Shift=true` and you're done!
|
* `Increment, Comparison, Shift` and you're done!
|
||||||
* Furthermore, some of these overloads make more sense with specific types, like `a&&b` which should be able to operate
|
* Furthermore, some of these overloads make more sense with specific types, like `a&&b` which should be able to operate
|
||||||
*
|
*
|
||||||
* I intentionally decided against overloading `&a` because these shall remain
|
* I intentionally decided against overloading `&a` because these shall remain
|
||||||
|
@ -47,9 +47,46 @@ namespace AK {
|
||||||
* There are many more operators that do not make sense for numerical types,
|
* There are many more operators that do not make sense for numerical types,
|
||||||
* or cannot be overloaded in the first place. Naturally, they are not implemented.
|
* or cannot be overloaded in the first place. Naturally, they are not implemented.
|
||||||
*/
|
*/
|
||||||
template<typename T, typename X, bool Incr, bool Cmp, bool Bool, bool Flags, bool Shift, bool Arith>
|
|
||||||
|
namespace DistinctNumericFeature {
|
||||||
|
enum Arithmetic {};
|
||||||
|
enum CastToBool {};
|
||||||
|
enum Comparison {};
|
||||||
|
enum Flags {};
|
||||||
|
enum Increment {};
|
||||||
|
enum Shift {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename X, typename... Opts>
|
||||||
class DistinctNumeric {
|
class DistinctNumeric {
|
||||||
using Self = DistinctNumeric<T, X, Incr, Cmp, Bool, Flags, Shift, Arith>;
|
using Self = DistinctNumeric<T, X, Opts...>;
|
||||||
|
|
||||||
|
struct Option {
|
||||||
|
template<typename K, typename... Os>
|
||||||
|
consteval Option(K option, Os... other_options)
|
||||||
|
: Option(other_options...)
|
||||||
|
{
|
||||||
|
set(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
consteval Option() { }
|
||||||
|
|
||||||
|
constexpr void set(DistinctNumericFeature::Arithmetic const&) { arithmetic = true; }
|
||||||
|
constexpr void set(DistinctNumericFeature::CastToBool const&) { cast_to_bool = true; }
|
||||||
|
constexpr void set(DistinctNumericFeature::Comparison const&) { comparisons = true; }
|
||||||
|
constexpr void set(DistinctNumericFeature::Flags const&) { flags = true; }
|
||||||
|
constexpr void set(DistinctNumericFeature::Increment const&) { increment = true; }
|
||||||
|
constexpr void set(DistinctNumericFeature::Shift const&) { shift = true; }
|
||||||
|
|
||||||
|
bool arithmetic { false };
|
||||||
|
bool cast_to_bool { false };
|
||||||
|
bool comparisons { false };
|
||||||
|
bool flags { false };
|
||||||
|
bool increment { false };
|
||||||
|
bool shift { false };
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr static Option options { Opts()... };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr DistinctNumeric() = default;
|
constexpr DistinctNumeric() = default;
|
||||||
|
@ -59,7 +96,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const T& value() const { return m_value; }
|
constexpr T const& value() const { return m_value; }
|
||||||
constexpr T& value() { return m_value; }
|
constexpr T& value() { return m_value; }
|
||||||
|
|
||||||
// Always implemented: identity.
|
// Always implemented: identity.
|
||||||
|
@ -68,61 +105,61 @@ public:
|
||||||
return this->m_value == other.m_value;
|
return this->m_value == other.m_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only implemented when `Incr` is true:
|
// Only implemented when `Increment` is true:
|
||||||
constexpr Self& operator++()
|
constexpr Self& operator++()
|
||||||
{
|
{
|
||||||
static_assert(Incr, "'++a' is only available for DistinctNumeric types with 'Incr'.");
|
static_assert(options.increment, "'++a' is only available for DistinctNumeric types with 'Increment'.");
|
||||||
this->m_value += 1;
|
this->m_value += 1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self operator++(int)
|
constexpr Self operator++(int)
|
||||||
{
|
{
|
||||||
static_assert(Incr, "'a++' is only available for DistinctNumeric types with 'Incr'.");
|
static_assert(options.increment, "'a++' is only available for DistinctNumeric types with 'Increment'.");
|
||||||
Self ret = this->m_value;
|
Self ret = this->m_value;
|
||||||
this->m_value += 1;
|
this->m_value += 1;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
constexpr Self& operator--()
|
constexpr Self& operator--()
|
||||||
{
|
{
|
||||||
static_assert(Incr, "'--a' is only available for DistinctNumeric types with 'Incr'.");
|
static_assert(options.increment, "'--a' is only available for DistinctNumeric types with 'Increment'.");
|
||||||
this->m_value -= 1;
|
this->m_value -= 1;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self operator--(int)
|
constexpr Self operator--(int)
|
||||||
{
|
{
|
||||||
static_assert(Incr, "'a--' is only available for DistinctNumeric types with 'Incr'.");
|
static_assert(options.increment, "'a--' is only available for DistinctNumeric types with 'Increment'.");
|
||||||
Self ret = this->m_value;
|
Self ret = this->m_value;
|
||||||
this->m_value -= 1;
|
this->m_value -= 1;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only implemented when `Cmp` is true:
|
// Only implemented when `Comparison` is true:
|
||||||
constexpr bool operator>(Self const& other) const
|
constexpr bool operator>(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Cmp, "'a>b' is only available for DistinctNumeric types with 'Cmp'.");
|
static_assert(options.comparisons, "'a>b' is only available for DistinctNumeric types with 'Comparison'.");
|
||||||
return this->m_value > other.m_value;
|
return this->m_value > other.m_value;
|
||||||
}
|
}
|
||||||
constexpr bool operator<(Self const& other) const
|
constexpr bool operator<(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Cmp, "'a<b' is only available for DistinctNumeric types with 'Cmp'.");
|
static_assert(options.comparisons, "'a<b' is only available for DistinctNumeric types with 'Comparison'.");
|
||||||
return this->m_value < other.m_value;
|
return this->m_value < other.m_value;
|
||||||
}
|
}
|
||||||
constexpr bool operator>=(Self const& other) const
|
constexpr bool operator>=(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Cmp, "'a>=b' is only available for DistinctNumeric types with 'Cmp'.");
|
static_assert(options.comparisons, "'a>=b' is only available for DistinctNumeric types with 'Comparison'.");
|
||||||
return this->m_value >= other.m_value;
|
return this->m_value >= other.m_value;
|
||||||
}
|
}
|
||||||
constexpr bool operator<=(Self const& other) const
|
constexpr bool operator<=(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Cmp, "'a<=b' is only available for DistinctNumeric types with 'Cmp'.");
|
static_assert(options.comparisons, "'a<=b' is only available for DistinctNumeric types with 'Comparison'.");
|
||||||
return this->m_value <= other.m_value;
|
return this->m_value <= other.m_value;
|
||||||
}
|
}
|
||||||
// 'operator<=>' cannot be implemented. See class comment.
|
// 'operator<=>' cannot be implemented. See class comment.
|
||||||
|
|
||||||
// Only implemented when `bool` is true:
|
// Only implemented when `CastToBool` is true:
|
||||||
constexpr bool operator!() const
|
constexpr bool operator!() const
|
||||||
{
|
{
|
||||||
static_assert(Bool, "'!a' is only available for DistinctNumeric types with 'Bool'.");
|
static_assert(options.cast_to_bool, "'!a' is only available for DistinctNumeric types with 'CastToBool'.");
|
||||||
return !this->m_value;
|
return !this->m_value;
|
||||||
}
|
}
|
||||||
// Intentionally don't define `operator bool() const` here. C++ is a bit
|
// Intentionally don't define `operator bool() const` here. C++ is a bit
|
||||||
|
@ -133,39 +170,39 @@ public:
|
||||||
// Only implemented when `Flags` is true:
|
// Only implemented when `Flags` is true:
|
||||||
constexpr Self operator~() const
|
constexpr Self operator~() const
|
||||||
{
|
{
|
||||||
static_assert(Flags, "'~a' is only available for DistinctNumeric types with 'Flags'.");
|
static_assert(options.flags, "'~a' is only available for DistinctNumeric types with 'Flags'.");
|
||||||
return ~this->m_value;
|
return ~this->m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator&(Self const& other) const
|
constexpr Self operator&(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Flags, "'a&b' is only available for DistinctNumeric types with 'Flags'.");
|
static_assert(options.flags, "'a&b' is only available for DistinctNumeric types with 'Flags'.");
|
||||||
return this->m_value & other.m_value;
|
return this->m_value & other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator|(Self const& other) const
|
constexpr Self operator|(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Flags, "'a|b' is only available for DistinctNumeric types with 'Flags'.");
|
static_assert(options.flags, "'a|b' is only available for DistinctNumeric types with 'Flags'.");
|
||||||
return this->m_value | other.m_value;
|
return this->m_value | other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator^(Self const& other) const
|
constexpr Self operator^(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Flags, "'a^b' is only available for DistinctNumeric types with 'Flags'.");
|
static_assert(options.flags, "'a^b' is only available for DistinctNumeric types with 'Flags'.");
|
||||||
return this->m_value ^ other.m_value;
|
return this->m_value ^ other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self& operator&=(Self const& other)
|
constexpr Self& operator&=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Flags, "'a&=b' is only available for DistinctNumeric types with 'Flags'.");
|
static_assert(options.flags, "'a&=b' is only available for DistinctNumeric types with 'Flags'.");
|
||||||
this->m_value &= other.m_value;
|
this->m_value &= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self& operator|=(Self const& other)
|
constexpr Self& operator|=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Flags, "'a|=b' is only available for DistinctNumeric types with 'Flags'.");
|
static_assert(options.flags, "'a|=b' is only available for DistinctNumeric types with 'Flags'.");
|
||||||
this->m_value |= other.m_value;
|
this->m_value |= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self& operator^=(Self const& other)
|
constexpr Self& operator^=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Flags, "'a^=b' is only available for DistinctNumeric types with 'Flags'.");
|
static_assert(options.flags, "'a^=b' is only available for DistinctNumeric types with 'Flags'.");
|
||||||
this->m_value ^= other.m_value;
|
this->m_value ^= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -174,90 +211,90 @@ public:
|
||||||
// TODO: Should this take `int` instead?
|
// TODO: Should this take `int` instead?
|
||||||
constexpr Self operator<<(Self const& other) const
|
constexpr Self operator<<(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Shift, "'a<<b' is only available for DistinctNumeric types with 'Shift'.");
|
static_assert(options.shift, "'a<<b' is only available for DistinctNumeric types with 'Shift'.");
|
||||||
return this->m_value << other.m_value;
|
return this->m_value << other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator>>(Self const& other) const
|
constexpr Self operator>>(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Shift, "'a>>b' is only available for DistinctNumeric types with 'Shift'.");
|
static_assert(options.shift, "'a>>b' is only available for DistinctNumeric types with 'Shift'.");
|
||||||
return this->m_value >> other.m_value;
|
return this->m_value >> other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self& operator<<=(Self const& other)
|
constexpr Self& operator<<=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Shift, "'a<<=b' is only available for DistinctNumeric types with 'Shift'.");
|
static_assert(options.shift, "'a<<=b' is only available for DistinctNumeric types with 'Shift'.");
|
||||||
this->m_value <<= other.m_value;
|
this->m_value <<= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self& operator>>=(Self const& other)
|
constexpr Self& operator>>=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Shift, "'a>>=b' is only available for DistinctNumeric types with 'Shift'.");
|
static_assert(options.shift, "'a>>=b' is only available for DistinctNumeric types with 'Shift'.");
|
||||||
this->m_value >>= other.m_value;
|
this->m_value >>= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only implemented when `Arith` is true:
|
// Only implemented when `Arithmetic` is true:
|
||||||
constexpr Self operator+(Self const& other) const
|
constexpr Self operator+(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a+b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a+b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
return this->m_value + other.m_value;
|
return this->m_value + other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator-(Self const& other) const
|
constexpr Self operator-(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a-b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a-b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
return this->m_value - other.m_value;
|
return this->m_value - other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator+() const
|
constexpr Self operator+() const
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'+a' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'+a' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
return +this->m_value;
|
return +this->m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator-() const
|
constexpr Self operator-() const
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'-a' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'-a' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
return -this->m_value;
|
return -this->m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator*(Self const& other) const
|
constexpr Self operator*(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a*b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a*b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
return this->m_value * other.m_value;
|
return this->m_value * other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator/(Self const& other) const
|
constexpr Self operator/(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a/b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a/b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
return this->m_value / other.m_value;
|
return this->m_value / other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self operator%(Self const& other) const
|
constexpr Self operator%(Self const& other) const
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a%b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a%b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
return this->m_value % other.m_value;
|
return this->m_value % other.m_value;
|
||||||
}
|
}
|
||||||
constexpr Self& operator+=(Self const& other)
|
constexpr Self& operator+=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a+=b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a+=b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
this->m_value += other.m_value;
|
this->m_value += other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self& operator-=(Self const& other)
|
constexpr Self& operator-=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a+=b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a+=b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
this->m_value += other.m_value;
|
this->m_value += other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self& operator*=(Self const& other)
|
constexpr Self& operator*=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a*=b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a*=b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
this->m_value *= other.m_value;
|
this->m_value *= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self& operator/=(Self const& other)
|
constexpr Self& operator/=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a/=b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a/=b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
this->m_value /= other.m_value;
|
this->m_value /= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
constexpr Self& operator%=(Self const& other)
|
constexpr Self& operator%=(Self const& other)
|
||||||
{
|
{
|
||||||
static_assert(Arith, "'a%=b' is only available for DistinctNumeric types with 'Arith'.");
|
static_assert(options.arithmetic, "'a%=b' is only available for DistinctNumeric types with 'Arithmetic'.");
|
||||||
this->m_value %= other.m_value;
|
this->m_value %= other.m_value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -266,29 +303,34 @@ private:
|
||||||
T m_value {};
|
T m_value {};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename X, bool Incr, bool Cmp, bool Bool, bool Flags, bool Shift, bool Arith>
|
template<typename T, typename X, typename... Opts>
|
||||||
struct Formatter<DistinctNumeric<T, X, Incr, Cmp, Bool, Flags, Shift, Arith>> : Formatter<T> {
|
struct Formatter<DistinctNumeric<T, X, Opts...>> : Formatter<T> {
|
||||||
ErrorOr<void> format(FormatBuilder& builder, DistinctNumeric<T, X, Incr, Cmp, Bool, Flags, Shift, Arith> value)
|
ErrorOr<void> format(FormatBuilder& builder, DistinctNumeric<T, X, Opts...> value)
|
||||||
{
|
{
|
||||||
return Formatter<T>::format(builder, value.value());
|
return Formatter<T>::format(builder, value.value());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: When 'consteval' sufficiently-well supported by host compilers, try to
|
|
||||||
// provide a more usable interface like this one:
|
|
||||||
// https://gist.github.com/alimpfard/a3b750e8c3a2f44fb3a2d32038968ddf
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, Incr, Cmp, Bool, Flags, Shift, Arith, NAME) \
|
#define AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, NAME, ...) \
|
||||||
using NAME = DistinctNumeric<T, struct __##NAME##_tag, Incr, Cmp, Bool, Flags, Shift, Arith>;
|
struct NAME##_decl { \
|
||||||
#define AK_TYPEDEF_DISTINCT_ORDERED_ID(T, NAME) AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, false, true, true, false, false, false, NAME)
|
using Arithmetic [[maybe_unused]] = AK::DistinctNumericFeature::Arithmetic; \
|
||||||
|
using CastToBool [[maybe_unused]] = AK::DistinctNumericFeature::CastToBool; \
|
||||||
|
using Comparison [[maybe_unused]] = AK::DistinctNumericFeature::Comparison; \
|
||||||
|
using Flags [[maybe_unused]] = AK::DistinctNumericFeature::Flags; \
|
||||||
|
using Increment [[maybe_unused]] = AK::DistinctNumericFeature::Increment; \
|
||||||
|
using Shift [[maybe_unused]] = AK::DistinctNumericFeature::Shift; \
|
||||||
|
using NAME [[maybe_unused]] = DistinctNumeric<T, struct __##NAME##_tag, ##__VA_ARGS__>; \
|
||||||
|
}; \
|
||||||
|
using NAME = typename NAME##_decl::NAME;
|
||||||
|
|
||||||
|
#define AK_TYPEDEF_DISTINCT_ORDERED_ID(T, NAME) AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, NAME, Comparison, CastToBool)
|
||||||
// TODO: Further type aliases?
|
// TODO: Further type aliases?
|
||||||
|
|
||||||
template<typename T, typename X, auto... Args>
|
template<typename T, typename X, typename... Opts>
|
||||||
struct Traits<AK::DistinctNumeric<T, X, Args...>> : public GenericTraits<AK::DistinctNumeric<T, X, Args...>> {
|
struct Traits<AK::DistinctNumeric<T, X, Opts...>> : public GenericTraits<AK::DistinctNumeric<T, X, Opts...>> {
|
||||||
static constexpr bool is_trivial() { return true; }
|
static constexpr bool is_trivial() { return true; }
|
||||||
static constexpr auto hash(DistinctNumeric<T, X, Args...> const& d) { return Traits<T>::hash(d.value()); }
|
static constexpr auto hash(DistinctNumeric<T, X, Opts...> const& d) { return Traits<T>::hash(d.value()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
using AK::DistinctNumeric;
|
using AK::DistinctNumeric;
|
||||||
|
|
|
@ -13,7 +13,7 @@ class ForType {
|
||||||
public:
|
public:
|
||||||
static void check_size()
|
static void check_size()
|
||||||
{
|
{
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, false, false, false, false, false, false, TheNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(T, TheNumeric);
|
||||||
EXPECT_EQ(sizeof(T), sizeof(TheNumeric));
|
EXPECT_EQ(sizeof(T), sizeof(TheNumeric));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -34,14 +34,14 @@ TEST_CASE(check_size)
|
||||||
ForType<double>::check_size();
|
ForType<double>::check_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, false, false, false, BareNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, BareNumeric);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, true, false, false, false, false, false, IncrNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, IncrNumeric, Increment);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, true, false, false, false, false, CmpNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, CmpNumeric, Comparison);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, true, false, false, false, BoolNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, BoolNumeric, CastToBool);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, true, false, false, FlagsNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, FlagsNumeric, Flags);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, false, true, false, ShiftNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, ShiftNumeric, Shift);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, false, false, false, false, false, true, ArithNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, ArithNumeric, Arithmetic);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, true, true, true, true, true, true, GeneralNumeric);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(int, GeneralNumeric, Arithmetic, CastToBool, Comparison, Flags, Increment, Shift);
|
||||||
|
|
||||||
TEST_CASE(address_identity)
|
TEST_CASE(address_identity)
|
||||||
{
|
{
|
||||||
|
@ -230,21 +230,21 @@ TEST_CASE(negative_incr)
|
||||||
{
|
{
|
||||||
BareNumeric a = 12;
|
BareNumeric a = 12;
|
||||||
a++;
|
a++;
|
||||||
// error: static assertion failed: 'a++' is only available for DistinctNumeric types with 'Incr'.
|
// error: static assertion failed: 'a++' is only available for DistinctNumeric types with 'Increment'.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(negative_cmp)
|
TEST_CASE(negative_cmp)
|
||||||
{
|
{
|
||||||
BareNumeric a = 12;
|
BareNumeric a = 12;
|
||||||
[[maybe_unused]] auto res = (a < a);
|
[[maybe_unused]] auto res = (a < a);
|
||||||
// error: static assertion failed: 'a<b' is only available for DistinctNumeric types with 'Cmp'.
|
// error: static assertion failed: 'a<b' is only available for DistinctNumeric types with 'Comparison'.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(negative_bool)
|
TEST_CASE(negative_bool)
|
||||||
{
|
{
|
||||||
BareNumeric a = 12;
|
BareNumeric a = 12;
|
||||||
[[maybe_unused]] auto res = !a;
|
[[maybe_unused]] auto res = !a;
|
||||||
// error: static assertion failed: '!a', 'a&&b', 'a||b' and similar operators are only available for DistinctNumeric types with 'Bool'.
|
// error: static assertion failed: '!a', 'a&&b', 'a||b' and similar operators are only available for DistinctNumeric types with 'CastToBool'.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(negative_flags)
|
TEST_CASE(negative_flags)
|
||||||
|
@ -265,7 +265,7 @@ TEST_CASE(negative_arith)
|
||||||
{
|
{
|
||||||
BareNumeric a = 12;
|
BareNumeric a = 12;
|
||||||
[[maybe_unused]] auto res = (a + a);
|
[[maybe_unused]] auto res = (a + a);
|
||||||
// error: static assertion failed: 'a+b' is only available for DistinctNumeric types with 'Arith'.
|
// error: static assertion failed: 'a+b' is only available for DistinctNumeric types with 'Arithmetic'.
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(negative_incompatible)
|
TEST_CASE(negative_incompatible)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace JS::Bytecode {
|
namespace JS::Bytecode {
|
||||||
|
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, false, true, false, false, false, false, IdentifierTableIndex);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, IdentifierTableIndex, Comparison);
|
||||||
|
|
||||||
class IdentifierTable {
|
class IdentifierTable {
|
||||||
AK_MAKE_NONMOVABLE(IdentifierTable);
|
AK_MAKE_NONMOVABLE(IdentifierTable);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
namespace JS::Bytecode {
|
namespace JS::Bytecode {
|
||||||
|
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, false, true, false, false, false, false, StringTableIndex);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(size_t, StringTableIndex, Comparison);
|
||||||
|
|
||||||
class StringTable {
|
class StringTable {
|
||||||
AK_MAKE_NONMOVABLE(StringTable);
|
AK_MAKE_NONMOVABLE(StringTable);
|
||||||
|
|
|
@ -29,13 +29,13 @@ struct LinkError {
|
||||||
Vector<OtherErrors> other_errors;
|
Vector<OtherErrors> other_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, FunctionAddress);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, FunctionAddress, Arithmetic, Comparison, Increment);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, ExternAddress);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, ExternAddress, Arithmetic, Comparison, Increment);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, TableAddress);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, TableAddress, Arithmetic, Comparison, Increment);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, GlobalAddress);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, GlobalAddress, Arithmetic, Comparison, Increment);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, ElementAddress);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, ElementAddress, Arithmetic, Comparison, Increment);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, DataAddress);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, DataAddress, Arithmetic, Comparison, Increment);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, false, false, true, MemoryAddress);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, MemoryAddress, Arithmetic, Comparison, Increment);
|
||||||
|
|
||||||
// FIXME: These should probably be made generic/virtual if/when we decide to do something more
|
// FIXME: These should probably be made generic/virtual if/when we decide to do something more
|
||||||
// fancy than just a dumb interpreter.
|
// fancy than just a dumb interpreter.
|
||||||
|
|
|
@ -57,7 +57,7 @@ AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LocalIndex);
|
||||||
AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, GlobalIndex);
|
AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, GlobalIndex);
|
||||||
AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LabelIndex);
|
AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, LabelIndex);
|
||||||
AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, DataIndex);
|
AK_TYPEDEF_DISTINCT_ORDERED_ID(size_t, DataIndex);
|
||||||
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, true, true, false, true, false, true, InstructionPointer);
|
AK_TYPEDEF_DISTINCT_NUMERIC_GENERAL(u64, InstructionPointer, Arithmetic, Comparison, Flags, Increment);
|
||||||
|
|
||||||
ParseError with_eof_check(InputStream const& stream, ParseError error_if_not_eof);
|
ParseError with_eof_check(InputStream const& stream, ParseError error_if_not_eof);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue