kernel: add expanded result macros
This commit is contained in:
		| @@ -5,6 +5,7 @@ | ||||
|  | ||||
| #include "common/assert.h" | ||||
| #include "common/bit_field.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/expected.h" | ||||
|  | ||||
| @@ -130,6 +131,10 @@ union Result { | ||||
|     [[nodiscard]] constexpr bool IsError() const { | ||||
|         return !IsSuccess(); | ||||
|     } | ||||
|  | ||||
|     [[nodiscard]] constexpr bool IsFailure() const { | ||||
|         return !IsSuccess(); | ||||
|     } | ||||
| }; | ||||
| static_assert(std::is_trivial_v<Result>); | ||||
|  | ||||
| @@ -349,10 +354,110 @@ private: | ||||
|         }                                                                                          \ | ||||
|     } 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. | ||||
| #define R_SUCCEED_IF(expr) R_UNLESS(!(expr), ResultSuccess) | ||||
| namespace ResultImpl { | ||||
| 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. | ||||
| #define R_UNLESS(expr, res)                                                                        \ | ||||
| @@ -361,7 +466,7 @@ private: | ||||
|             if (res.IsError()) {                                                                   \ | ||||
|                 LOG_ERROR(Kernel, "Failed with result: {}", res.raw);                              \ | ||||
|             }                                                                                      \ | ||||
|             return res;                                                                            \ | ||||
|             R_THROW(res);                                                                          \ | ||||
|         }                                                                                          \ | ||||
|     } | ||||
|  | ||||
| @@ -369,7 +474,10 @@ private: | ||||
| #define R_TRY(res_expr)                                                                            \ | ||||
|     {                                                                                              \ | ||||
|         const auto _tmp_r_try_rc = (res_expr);                                                     \ | ||||
|         if (_tmp_r_try_rc.IsError()) {                                                             \ | ||||
|             return _tmp_r_try_rc;                                                                  \ | ||||
|         if (R_FAILED(_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