Skip to content

Commit

Permalink
✨ Equivalence between matchers
Browse files Browse the repository at this point in the history
A building block for intel#456. Two matchers are three-way comparable, yielding a
partial ordering.

X => Y means that X > Y (intuition: "greater than" means "more strongly
constrained match").

X => Y and Y => X means that X and Y are equivalent.
  • Loading branch information
elbeno committed Jan 5, 2024
1 parent 62b3708 commit a6a630f
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
16 changes: 16 additions & 0 deletions include/match/ops.hpp
Expand Up @@ -8,6 +8,9 @@
#include <match/or.hpp>
#include <match/simplify.hpp>

#include <compare>
#include <utility>

template <match::matcher L, match::matcher R>
[[nodiscard]] constexpr auto operator and(L const &lhs, R const &rhs)
-> decltype(match::simplify(std::declval<match::and_t<L, R>>())) {
Expand All @@ -25,3 +28,16 @@ template <match::matcher M>
-> decltype(match::simplify(match::negate(std::declval<M>()))) {
return match::simplify(match::negate(m));
}

template <match::matcher L, match::matcher R>
[[nodiscard]] constexpr auto operator<=>(L const &lhs, R const &rhs)
-> std::partial_ordering {
auto const l = match::simplify(lhs);
auto const r = match::simplify(rhs);
auto const x = match::implies(l, r);
auto const y = match::implies(r, l);
if (not x and not y) {
return std::partial_ordering::unordered;
}
return x <=> y;
}
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Expand Up @@ -38,6 +38,7 @@ add_tests(
lookup/strategies
match/and
match/constant
match/equivalence
match/implies
match/not
match/or
Expand Down
37 changes: 37 additions & 0 deletions test/match/equivalence.cpp
@@ -0,0 +1,37 @@
#include "test_matcher.hpp"

#include <match/ops.hpp>

#include <catch2/catch_test_macros.hpp>

#include <compare>
#include <type_traits>

TEST_CASE("less than", "[match equivalence]") {
using T = test_m<0>;
using U = match::and_t<T, test_m<1>>;
constexpr auto result = T{} <=> U{};
static_assert(result == std::partial_ordering::less);
static_assert(T{} < U{});
}

TEST_CASE("greater than", "[match equivalence]") {
using T = test_m<0>;
using U = match::or_t<T, test_m<1>>;
constexpr auto result = T{} <=> U{};
static_assert(result == std::partial_ordering::greater);
static_assert(T{} > U{});
}

TEST_CASE("equivalent", "[match equivalence]") {
using T = test_m<0>;
constexpr auto result = T{} <=> T{};
static_assert(result == std::partial_ordering::equivalent);
}

TEST_CASE("unorderable", "[match equivalence]") {
using T = test_m<0>;
using U = test_m<1>;
constexpr auto result = T{} <=> U{};
static_assert(result == std::partial_ordering::unordered);
}

0 comments on commit a6a630f

Please sign in to comment.