#ifndef PRESULT_H #define PRESULT_H #include "expected.h" #include "sourceerror.h" #include /// Returns from the CURRENT function, the one this macro is used in, /// if PResult contains an error #define RETURN_IF_ERR(presult) \ do { \ auto&& return_if_err_temp_ = (presult); \ if (!return_if_err_temp_) { \ return PError(return_if_err_temp_.error()); \ } \ } while (0) /// Works the same as RETURN_IF_ERR but can also assign the unwrapped result /// to a variable if successful #define ASSIGN_OR_RETURN_IF_ERR(var, presult) \ do { \ auto&& assign_or_return_if_err_temp_ = (presult); \ if (!assign_or_return_if_err_temp_) { \ return PError(assign_or_return_if_err_temp_.error()); \ } else { \ var = *assign_or_return_if_err_temp_; \ } \ } while (0) using PError = tl::unexpected; /// Holds either an AST node or an error /// The value MUST be checked before usage, e.g. using RETURN_IF_ERR template struct PResult : tl::expected { using tl::expected::expected; /// Implicit conversion from PResult to PResult /// if U is convertible to T template , T>::value>> PResult(PResult presult) : tl::expected(presult ? PResult(*presult) : PError(presult.error())) {} }; /// Alternative to PResult that is returned from parse* functions /// that only consume one token so they can fail without affecting /// the parser state template struct POptResult : public PResult { using PResult::PResult; std::optional optional() { if (*this) { return **this; } else { return std::nullopt; } } }; #endif // PRESULT_H