+ constexpr bool has_match_member_v = has_match_member::value;
+
+ // Detects if `p.bind(s)` is a valid expression.
+ template
+ struct has_bind_member : std::false_type {};
+
+ template
+ struct has_bind_member<
+ P,
+ S,
+ typename void_type().bind(
+ std::declval()))>::type> : std::true_type {};
+
+ template
+ constexpr bool has_bind_member_v = has_bind_member::value;
+ } // namespace detail
+ // ---------------------------------
+
+ /** Case Matching */
+
+ /// @brief Checks if a case's pattern matches a subject.
+ template
+ struct case_matcher {
+ using case_type = Case;
+ using subject_type = Subject;
+ using pattern_type = case_pattern_t;
+
+ /// @brief Returns true if the pattern matches the subject.
+ static constexpr bool
+ matches(const case_type &c, const subject_type &subject) {
+ // Supports both class-based patterns with a .match() method and
+ // functional patterns (via std::invoke).
+#if PTN_USE_CONCEPTS
+ if constexpr (requires(const pattern_type &p, const subject_type &s) {
+ { p.match(s) } -> std::convertible_to;
+ }) {
+ return c.pattern.match(subject);
+ }
+ else {
+ return static_cast(std::invoke(c.pattern, subject));
+ }
+#else
+ // Use a robust SFINAE check instead of the faulty member function
+ // pointer check.
+ if constexpr (detail::has_match_member_v) {
+ return c.pattern.match(subject);
+ }
+ else {
+ return static_cast(std::invoke(c.pattern, subject));
+ }
+#endif
+ }
+ };
+
+ /** Handler Invocation Logic */
+
+ /// @brief Invokes a handler with the subject and values bound by its pattern.
+ template
+ constexpr decltype(auto) invoke_handler(const Case &c, Subject &&subject) {
+ using pattern_type = case_pattern_t;
+
+// The check is different for C++17 and C++20.
+#if PTN_USE_CONCEPTS
+ static_assert(
+ requires(const pattern_type &p, Subject &&s) {
+ { p.bind(std::forward(s)) };
+ },
+ "Pattern must have a 'bind(subject)' method that returns a tuple of "
+ "bound values.");
+#else
+ // Use the robust SFINAE check instead of the faulty sizeof trick.
+ static_assert(
+ detail::has_bind_member_v,
+ "Pattern must have a 'bind(subject)' method that returns a tuple of "
+ "bound values.");
+#endif
+
+ // Let the pattern perform the binding.
+ auto bound_values = c.pattern.bind(std::forward(subject));
+
+ // Combine the subject and bound values into a single tuple.
+ auto full_args = std::tuple_cat(
+ std::forward_as_tuple(std::forward(subject)),
+ std::move(bound_values));
+
+ // Apply the handler to the full set of arguments.
+ return std::apply(c.handler, std::move(full_args));
+ }
+
+ /** Case Sequence Evaluation */
+ namespace detail {
+ /// @brief Recursive implementation for evaluating a tuple of cases.
+ template <
+ std::size_t I,
+ typename Subject,
+ typename CasesTuple,
+ typename Otherwise,
+ std::size_t N = std::tuple_size_v>>
+ constexpr decltype(auto) eval_cases_impl(
+ Subject &subject, CasesTuple &cases, Otherwise &&otherwise_handler) {
+ if constexpr (I >= N) {
+ // Base case: no case matched, invoke the `otherwise` handler.
+ if constexpr (std::is_invocable_v) {
+ return std::forward(otherwise_handler)(subject);
+ }
+ else {
+ return std::forward(otherwise_handler)();
+ }
+ }
+ else {
+ auto ¤t_case = std::get(cases);
+ using case_t = std::remove_reference_t;
+
+ if (case_matcher::matches(current_case, subject)) {
+ // Found a match, invoke its handler.
+ return invoke_handler(current_case, std::forward(subject));
+ }
+ else {
+ // Try the next case.
+ return eval_cases_impl(
+ subject, cases, std::forward(otherwise_handler));
+ }
+ }
+ }
+ } // namespace detail
+
+ /// @brief Public entry point to evaluate a sequence of cases.
+ template
+ constexpr decltype(auto) eval_cases(
+ Subject &subject, CasesTuple &cases, Otherwise &&otherwise_handler) {
+ using tuple_t = std::remove_reference_t;
+ constexpr std::size_t N = std::tuple_size_v;
+
+ return detail::eval_cases_impl<0>(
+ subject, cases, std::forward(otherwise_handler));
+ }
+
+} // namespace ptn::core::common
diff --git a/include/ptn/core/common/optimize.hpp b/include/ptn/core/common/optimize.hpp
new file mode 100644
index 00000000..6a512d31
--- /dev/null
+++ b/include/ptn/core/common/optimize.hpp
@@ -0,0 +1,16 @@
+#pragma once
+
+namespace ptn::core::common {
+
+ namespace detail {
+ template
+ struct optimize_case_sequence {
+ using type = CasesTuple;
+ };
+ } // namespace detail
+
+ template
+ using optimize_case_sequence_t =
+ typename detail::optimize_case_sequence::type;
+
+} // namespace ptn::core::common
diff --git a/include/ptn/core/detail/match_builder_detail.hpp b/include/ptn/core/detail/match_builder_detail.hpp
deleted file mode 100644
index a3cc038d..00000000
--- a/include/ptn/core/detail/match_builder_detail.hpp
+++ /dev/null
@@ -1,260 +0,0 @@
-#pragma once
-
-#include "ptn/config.hpp"
-#include
-#include
-#include
-#include
-#include
-
-#if PTN_USE_CONCEPTS
-#include
-#endif
-
-/**
- * @file match_builder_impl.hpp (detail)
- * @brief Internal implementation of the core matching engine.
- *
- * This is an internal header containing the implementation of:
- * - `match_builder`: Core engine storing subject and case list.
- * - `run_handler()`: Handler invocation logic.
- *
- * Users should use the public `match()` function and `.when()/.otherwise()` API
- * from `ptn/core/match_builder.hpp` instead of directly instantiating
- * match_builder.
- *
- * Part of the Core Layer (namespace ptn::core::detail)
- *
- * @internal This is an internal implementation detail.
- */
-
-namespace ptn::dsl::detail {
- template
- struct case_expr;
-}
-
-namespace ptn::core::detail {
-
-#if PTN_USE_CONCEPTS
-
- template
- concept Invocable1 = std::is_invocable_v;
-
- template
- concept Invocable0 = std::is_invocable_v;
-
- /**
- * @brief Invoke handler `h(x)` if available.
- *
- * @internal This is an internal implementation detail.
- */
- template
- requires Invocable1
- constexpr decltype(auto) run_handler(H &h, X &x) {
- return std::invoke(h, x);
- }
-
- /**
- * @brief Invoke handler `h()` if `(x)` overload is not available.
- *
- * @internal This is an internal implementation detail.
- */
- template
- requires(!Invocable1 && Invocable0)
- constexpr decltype(auto) run_handler(H &h, X &) {
- return std::invoke(h);
- }
-
- /**
- * @brief Fallback: return handler as value.
- *
- * @internal This is an internal implementation detail.
- */
- template
- requires(!Invocable1 && !Invocable0)
- constexpr decltype(auto) run_handler(H &h, X &) {
- return (h);
- }
-
-#else // C++17 fallback
-
- template <
- typename H,
- typename X,
- typename = std::enable_if_t>>
- constexpr decltype(auto) run_handler(H &h, X &x) {
- return std::invoke(h, x);
- }
-
- template <
- typename H,
- typename X,
- typename = void,
- typename = std::enable_if_t<
- !std::is_invocable_v && std::is_invocable_v>>
- constexpr decltype(auto) run_handler(H &h, X &) {
- return std::invoke(h);
- }
-
- template <
- typename H,
- typename X,
- typename = void,
- typename = void,
- typename = std::enable_if_t<
- !std::is_invocable_v && !std::is_invocable_v>>
- constexpr decltype(auto) run_handler(H &h, X &) {
- return (h);
- }
-
-#endif
-
- /**
- * @brief Tag used to disambiguate private constructors.
- *
- * @internal This is an internal implementation detail.
- */
- struct ctor_tag {};
-
- /**
- * @brief Core engine storing subject and case list, evaluated via
- * `.otherwise()`.
- *
- * @tparam TV Type of stored subject value.
- * @tparam Cases Variadic pack of `(Pattern, Handler)` pairs.
- *
- * This class is immutable: each `.when()` returns a new type with the added
- * case.
- *
- * @internal This is an internal implementation detail. Use `match()`
- * function.
- */
- template
- class match_builder {
- TV value_; ///< Subject value
- std::tuple cases_; ///< Stored (Pattern, Handler) pairs
- using ctor_tag_t = ptn::core::detail::ctor_tag;
-
- template
- friend struct ptn::dsl::detail::case_expr;
-
- template
- friend class match_builder;
-
- /**
- * @brief Private constructor used by `create()`.
- */
- template
-#if PTN_USE_CONCEPTS
- requires std::constructible_from &&
- std::constructible_from, Tuple>
-#endif
- explicit constexpr match_builder(TV2 &&v, Tuple &&cs, ctor_tag_t)
- : value_(std::forward(v)), cases_(std::forward(cs)) {
- }
-
- // Append a case (lvalue)
- template
- constexpr auto with(Pattern p, Handler h) & {
- using pair_t = std::pair;
- auto new_cases = std::tuple_cat(
- cases_, std::make_tuple(pair_t{std::move(p), std::move(h)}));
-
- return match_builder(
- value_, std::move(new_cases), ctor_tag_t{});
- }
-
- // Append a case (rvalue)
- template
- constexpr auto with(Pattern p, Handler h) && {
- using pair_t = std::pair;
- auto new_cases = std::tuple_cat(
- std::move(cases_),
- std::make_tuple(pair_t{std::move(p), std::move(h)}));
-
- return match_builder(
- std::move(value_), std::move(new_cases), ctor_tag_t{});
- }
-
- // Recursive case matching
- /**
- * @brief Try each case in order.
- *
- * Stops when a pattern matches or all cases exhausted.
- *
- * @tparam I Current tuple index.
- * @tparam OutT Output type inferred from handlers.
- */
- template
- constexpr void try_cases(OutT &out, bool &done) {
- if constexpr (I < sizeof...(Cases)) {
- auto &c = std::get(cases_);
- auto &[p, handler] = c;
-
- // Unified Pattern Layer API: Pattern must implement match(value)
- if (!done && p.match(value_)) {
- out = static_cast(run_handler(handler, value_));
- done = true;
- }
- else {
- try_cases(out, done);
- }
- }
- }
-
- public:
- // Builder creation (called from ptn::match())
- template
-#if PTN_USE_CONCEPTS
- requires std::constructible_from, Tuple>
-#endif
- static constexpr auto create(VArg &&v, Tuple &&cs)
- -> match_builder, Cases...> {
- using result_t = match_builder, Cases...>;
- return result_t(
- std::forward(v), std::forward(cs), ctor_tag{});
- }
-
- // otherwise()
- /**
- * @brief Finalize matching.
- *
- * Computes a common return type from all handlers, applies the first
- * matching handler, or the fallback if none match.
- */
- template
- constexpr auto otherwise(H &&fallback) && {
- using R = std::common_type_t<
- decltype(run_handler(
- std::declval(),
- std::declval()))...,
- decltype(run_handler(
- std::declval &>(), std::declval()))>;
-
- R out{};
- bool done = false;
-
- try_cases(out, done);
-
- if (!done)
- out = static_cast(run_handler(fallback, value_));
-
- return out;
- }
-
- // when()
- /**
- * @brief Add a pattern-handler case from a `case_expr`.
- */
- template
- constexpr auto when(ptn::dsl::detail::case_expr &&e) & {
- return this->with(std::move(e.pattern), std::move(e.handler));
- }
-
- template
- constexpr auto when(ptn::dsl::detail::case_expr &&e) && {
- return std::move(*this).with(std::move(e.pattern), std::move(e.handler));
- }
- };
-
-} // namespace ptn::core::detail
diff --git a/include/ptn/core/dsl/case_expr.hpp b/include/ptn/core/dsl/case_expr.hpp
index 74247632..e7c48225 100644
--- a/include/ptn/core/dsl/case_expr.hpp
+++ b/include/ptn/core/dsl/case_expr.hpp
@@ -3,47 +3,21 @@
/**
* @file case_expr.hpp
* @brief Public type alias for case expressions.
- *
- * This module provides the public `case_expr` type (via alias to detail
- * implementation). Case expressions are created implicitly when using the `>>`
- * operator:
- *
- * ```cpp
- * auto case = pattern >> handler; // Creates a case_expr
- * ```
- *
- * Users should NOT instantiate `case_expr` directly. Use the `>>` operator
- * instead.
- *
- * Part of the Core Layer (namespace ptn::dsl)
*/
-#include "ptn/core/dsl/detail/case_expr_detail.hpp"
-
-namespace ptn::dsl::detail {
+namespace ptn::core::dsl::detail {
template
struct case_expr;
}
-namespace ptn::dsl {
+namespace ptn::core::dsl {
/**
* @brief Public type alias for case expressions.
*
* Represents a pattern-handler pair in the match DSL.
- * Created via the `>>` operator: `pattern >> handler`.
- *
- * @tparam Pattern The pattern type.
- * @tparam Handler The handler type.
- *
- * @example
- * ```cpp
- * using namespace ptn::pattern::value;
- * auto case1 = lit(10) >> "ten";
- * auto case2 = lt(5) >> "small";
- * ```
*/
template
using case_expr = detail::case_expr;
-} // namespace ptn::dsl
\ No newline at end of file
+} // namespace ptn::core::dsl
\ No newline at end of file
diff --git a/include/ptn/core/dsl/detail/case_expr_detail.hpp b/include/ptn/core/dsl/detail/case_expr_impl.hpp
similarity index 64%
rename from include/ptn/core/dsl/detail/case_expr_detail.hpp
rename to include/ptn/core/dsl/detail/case_expr_impl.hpp
index 04f5a835..8a060877 100644
--- a/include/ptn/core/dsl/detail/case_expr_detail.hpp
+++ b/include/ptn/core/dsl/detail/case_expr_impl.hpp
@@ -4,18 +4,10 @@
* @file case_expr_impl.hpp (detail)
* @brief Internal implementation of case expressions.
*
- * This is an internal header containing the implementation of:
- * - `case_expr`: Represents a single case in match() DSL.
- *
- * Users should create case expressions using the `>>` operator defined in
- * `ptn/core/dsl/operators.hpp` instead of directly instantiating this type.
- *
- * Part of the Core Layer (namespace ptn::dsl::detail)
- *
* @internal This is an internal implementation detail.
*/
-namespace ptn::dsl::detail {
+namespace ptn::core::dsl::detail {
/**
* @brief Internal representation of a pattern-handler pair (case).
@@ -36,4 +28,4 @@ namespace ptn::dsl::detail {
Handler handler; ///< The handler to execute if pattern matches
};
-} // namespace ptn::dsl::detail
+} // namespace ptn::core::dsl::detail
diff --git a/include/ptn/core/dsl/operators.hpp b/include/ptn/core/dsl/operators.hpp
deleted file mode 100644
index c7cefbe6..00000000
--- a/include/ptn/core/dsl/operators.hpp
+++ /dev/null
@@ -1,108 +0,0 @@
-#pragma once
-
-#include
-#include
-
-namespace ptn::dsl::detail {
- template
- struct case_expr;
-}
-
-namespace ptn::pattern::value {
-
- template
- struct predicate_pattern;
-
-} // namespace ptn::pattern::value
-
-namespace ptn::pattern::value::detail {
-
- template
- struct and_pattern;
-
- template
- struct or_pattern;
-
- template
- struct not_pattern;
-
-} // namespace ptn::pattern::value::detail
-
-namespace ptn::pattern::detail {
- template
- struct is_pattern;
-
- template
- extern const bool is_pattern_v;
-} // namespace ptn::pattern::detail
-
-namespace ptn::dsl::ops {
-
- // ========== operator>> (pattern >> handler) ==========
- template
- constexpr auto operator>>(P &&p, H &&h) {
- return ptn::dsl::detail::case_expr, std::decay_t>{
- std::forward(p), std::forward(h)};
- }
-
- // =====================================================
- // Logical DSL operators: && || !
- // =====================================================
-
-#if defined(PTN_USE_CONCEPTS) && PTN_USE_CONCEPTS
-
- template
- constexpr auto operator&&(L &&l, R &&r) {
- return ptn::value::and_pattern, std::decay_t>(
- std::forward(l), std::forward(r));
- }
-
- template
- constexpr auto operator||(L &&l, R &&r) {
- return ptn::value::or_pattern, std::decay_t>(
- std::forward(l), std::forward(r));
- }
-
- template
- constexpr auto operator!(P &&p) {
- return ptn::value::not_pattern>(std::forward(p));
- }
-
-#else // C++17 fallback (SFINAE)
-
- template <
- typename L,
- typename R,
- typename = std::enable_if_t<
- pattern::detail::is_pattern_v> &&
- pattern::detail::is_pattern_v>>>
- constexpr auto operator&&(L &&l, R &&r) {
- return ptn::pattern::value::detail::
- and_pattern, std::decay_t>(
- std::forward(l), std::forward(r));
- }
-
- template <
- typename L,
- typename R,
- typename = std::enable_if_t<
- pattern::detail::is_pattern_v> &&
- pattern::detail::is_pattern_v>>>
- constexpr auto operator||(L &&l, R &&r) {
- return ptn::pattern::value::detail::
- or_pattern, std::decay_t>(
- std::forward(l), std::forward(r));
- }
-
- template <
- typename P,
- typename =
- std::enable_if_t