kernel: add expanded result macros
This commit is contained in:
		| @@ -5,6 +5,7 @@ | |||||||
|  |  | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
|  | #include "common/common_funcs.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/expected.h" | #include "common/expected.h" | ||||||
|  |  | ||||||
| @@ -130,6 +131,10 @@ union Result { | |||||||
|     [[nodiscard]] constexpr bool IsError() const { |     [[nodiscard]] constexpr bool IsError() const { | ||||||
|         return !IsSuccess(); |         return !IsSuccess(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [[nodiscard]] constexpr bool IsFailure() const { | ||||||
|  |         return !IsSuccess(); | ||||||
|  |     } | ||||||
| }; | }; | ||||||
| static_assert(std::is_trivial_v<Result>); | static_assert(std::is_trivial_v<Result>); | ||||||
|  |  | ||||||
| @@ -349,10 +354,110 @@ private: | |||||||
|         }                                                                                          \ |         }                                                                                          \ | ||||||
|     } while (false) |     } while (false) | ||||||
|  |  | ||||||
| #define R_SUCCEEDED(res) (res.IsSuccess()) | #define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess()) | ||||||
|  | #define R_FAILED(res) (static_cast<Result>(res).IsFailure()) | ||||||
|  |  | ||||||
| /// Evaluates a boolean expression, and succeeds if that expression is true. | namespace ResultImpl { | ||||||
| #define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess) | template <auto EvaluateResult, class F> | ||||||
|  | class ScopedResultGuard { | ||||||
|  |     YUZU_NON_COPYABLE(ScopedResultGuard); | ||||||
|  |     YUZU_NON_MOVEABLE(ScopedResultGuard); | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     Result& m_ref; | ||||||
|  |     F m_f; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |     constexpr ScopedResultGuard(Result& ref, F f) : m_ref(ref), m_f(std::move(f)) {} | ||||||
|  |     constexpr ~ScopedResultGuard() { | ||||||
|  |         if (EvaluateResult(m_ref)) { | ||||||
|  |             m_f(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <auto EvaluateResult> | ||||||
|  | class ResultReferenceForScopedResultGuard { | ||||||
|  | private: | ||||||
|  |     Result& m_ref; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |     constexpr ResultReferenceForScopedResultGuard(Result& r) : m_ref(r) {} | ||||||
|  |     constexpr operator Result&() const { | ||||||
|  |         return m_ref; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | template <auto EvaluateResult, typename F> | ||||||
|  | constexpr ScopedResultGuard<EvaluateResult, F> operator+( | ||||||
|  |     ResultReferenceForScopedResultGuard<EvaluateResult> ref, F&& f) { | ||||||
|  |     return ScopedResultGuard<EvaluateResult, F>(static_cast<Result&>(ref), std::forward<F>(f)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | constexpr bool EvaluateResultSuccess(const Result& r) { | ||||||
|  |     return R_SUCCEEDED(r); | ||||||
|  | } | ||||||
|  | constexpr bool EvaluateResultFailure(const Result& r) { | ||||||
|  |     return R_FAILED(r); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename T> | ||||||
|  | constexpr void UpdateCurrentResultReference(T result_reference, Result result) { | ||||||
|  |     ASSERT(false); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | constexpr void UpdateCurrentResultReference<Result&>(Result& result_reference, Result result) { | ||||||
|  |     result_reference = result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <> | ||||||
|  | constexpr void UpdateCurrentResultReference<Result>(Result result_reference, Result result) {} | ||||||
|  | } // namespace ResultImpl | ||||||
|  |  | ||||||
|  | #define DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(COUNTER_VALUE)                                \ | ||||||
|  |     [[maybe_unused]] constexpr bool HasPrevRef_##COUNTER_VALUE =                                   \ | ||||||
|  |         std::same_as<decltype(__TmpCurrentResultReference), Result&>;                              \ | ||||||
|  |     [[maybe_unused]] auto& PrevRef_##COUNTER_VALUE = __TmpCurrentResultReference;                  \ | ||||||
|  |     [[maybe_unused]] Result __tmp_result_##COUNTER_VALUE = ResultSuccess;                          \ | ||||||
|  |     Result& __TmpCurrentResultReference =                                                          \ | ||||||
|  |         HasPrevRef_##COUNTER_VALUE ? PrevRef_##COUNTER_VALUE : __tmp_result_##COUNTER_VALUE | ||||||
|  |  | ||||||
|  | #define ON_RESULT_RETURN_IMPL(...)                                                                 \ | ||||||
|  |     static_assert(std::same_as<decltype(__TmpCurrentResultReference), Result&>);                   \ | ||||||
|  |     auto RESULT_GUARD_STATE_##__COUNTER__ =                                                        \ | ||||||
|  |         ResultImpl::ResultReferenceForScopedResultGuard<__VA_ARGS__>(                              \ | ||||||
|  |             __TmpCurrentResultReference) +                                                         \ | ||||||
|  |         [&]() | ||||||
|  |  | ||||||
|  | #define ON_RESULT_FAILURE_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultFailure) | ||||||
|  |  | ||||||
|  | #define ON_RESULT_FAILURE                                                                          \ | ||||||
|  |     DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__);                                     \ | ||||||
|  |     ON_RESULT_FAILURE_2 | ||||||
|  |  | ||||||
|  | #define ON_RESULT_SUCCESS_2 ON_RESULT_RETURN_IMPL(ResultImpl::EvaluateResultSuccess) | ||||||
|  |  | ||||||
|  | #define ON_RESULT_SUCCESS                                                                          \ | ||||||
|  |     DECLARE_CURRENT_RESULT_REFERENCE_AND_STORAGE(__COUNTER__);                                     \ | ||||||
|  |     ON_RESULT_SUCCESS_2 | ||||||
|  |  | ||||||
|  | constexpr inline Result __TmpCurrentResultReference = ResultSuccess; | ||||||
|  |  | ||||||
|  | /// Returns a result. | ||||||
|  | #define R_RETURN(res_expr)                                                                         \ | ||||||
|  |     {                                                                                              \ | ||||||
|  |         const Result _tmp_r_throw_rc = (res_expr);                                                 \ | ||||||
|  |         ResultImpl::UpdateCurrentResultReference<decltype(__TmpCurrentResultReference)>(           \ | ||||||
|  |             __TmpCurrentResultReference, _tmp_r_throw_rc);                                         \ | ||||||
|  |         return _tmp_r_throw_rc;                                                                    \ | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | /// Returns ResultSuccess() | ||||||
|  | #define R_SUCCEED() R_RETURN(ResultSuccess) | ||||||
|  |  | ||||||
|  | /// Throws a result. | ||||||
|  | #define R_THROW(res_expr) R_RETURN(res_expr) | ||||||
|  |  | ||||||
| /// Evaluates a boolean expression, and returns a result unless that expression is true. | /// Evaluates a boolean expression, and returns a result unless that expression is true. | ||||||
| #define R_UNLESS(expr, res)                                                                        \ | #define R_UNLESS(expr, res)                                                                        \ | ||||||
| @@ -361,7 +466,7 @@ private: | |||||||
|             if (res.IsError()) {                                                                   \ |             if (res.IsError()) {                                                                   \ | ||||||
|                 LOG_ERROR(Kernel, "Failed with result: {}", res.raw);                              \ |                 LOG_ERROR(Kernel, "Failed with result: {}", res.raw);                              \ | ||||||
|             }                                                                                      \ |             }                                                                                      \ | ||||||
|             return res;                                                                            \ |             R_THROW(res);                                                                          \ | ||||||
|         }                                                                                          \ |         }                                                                                          \ | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -369,7 +474,10 @@ private: | |||||||
| #define R_TRY(res_expr)                                                                            \ | #define R_TRY(res_expr)                                                                            \ | ||||||
|     {                                                                                              \ |     {                                                                                              \ | ||||||
|         const auto _tmp_r_try_rc = (res_expr);                                                     \ |         const auto _tmp_r_try_rc = (res_expr);                                                     \ | ||||||
|         if (_tmp_r_try_rc.IsError()) {                                                             \ |         if (R_FAILED(_tmp_r_try_rc)) {                                                             \ | ||||||
|             return _tmp_r_try_rc;                                                                  \ |             R_THROW(_tmp_r_try_rc);                                                                \ | ||||||
|         }                                                                                          \ |         }                                                                                          \ | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | /// Evaluates a boolean expression, and succeeds if that expression is true. | ||||||
|  | #define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user