diff --git a/TODO b/TODO new file mode 100644 index 0000000..436882e --- /dev/null +++ b/TODO @@ -0,0 +1,9 @@ +TODO: Remove all this bullshit like rng.h, keep pointer, current boxed, and util; keep the error stuff and get a consistent framework for it but then work on the ruleset, rule definitions, making it ergonomic and `constinit`, etc. The actual real reason this project exists... +Then add things like `iterator` to use for parsing, and `argument_{input/output}_stream` for transformations, etc. See notes on phone for custom handlers as well. Use as much aggregate (POD) init as possible, e.g: + +``` +// with rule ctor for `(char8_t, const char &(desc)[DN], kind, attribute = {})` +// ... + { 'v', "Increase verbosity" , kind::Switch, { .allow_multuple = 3 }}, +// ... +``` diff --git a/include/error.hh b/include/error.hh index c6113e8..75663cf 100644 --- a/include/error.hh +++ b/include/error.hh @@ -11,13 +11,24 @@ #include "util.hh" +#define _EO_DEFEXCEPT_BASIC_(NAME, BASE, ...) class NAME : public ::exopt:: BASE { \ + constexpr static inline auto MESSSAGE = (__VA_ARGS__); \ + public: \ + _EO_CLASS_DEFINE(NAME, constexpr, noexcept, virtual, =default); \ + constexpr virtual std::string_view message() const noexcept override { return { MESSAGE }; } \ + } +#define _EO_DEFEXCEPT_BASIC(NAME, MSG) _EO_DEFEXCEPT_BASIC_(NAME, Error, MSG) +#define _EO_DEFEXCEPT_TRACE_BASIC(NAME, MSG) _EO_DEFEXCEPT_BASIC_(NAME, TracedError, MSG) + namespace exopt { + // Report generated from an error. (virtual base, not abstract.) class Report { public: virtual ~Report(); }; - // This is propagated returned (base, abstract) + + // This is base thrown (base, abstract) class Error { public: constexpr Error(Error const&) = default; @@ -25,6 +36,9 @@ namespace exopt { constexpr Error& operator=(Error &&) = default; constexpr Error& operator=(Error const&) = default; + virtual types::Box into_traced(std::stacktrace&& trace) &&noexcept;// = std::stacktrace::current()) && noexcept; + inline typed::Box into_traced(std::stacktrace trace = std::stacktrace::current()) && noexcept + { return std::move(*this).into_traced(std::move(trace)); } constexpr virtual std::source_location const& location() const noexcept { return m_location; } @@ -32,8 +46,9 @@ namespace exopt { constexpr virtual std::string_view message() const noexcept =0; - constexpr virtual types::Option inner() noexcept { return { std::nullopt }; } - constexpr virtual types::MaybeOwned into_report() noexcept { /* TODO */ } //TODO: Maybe just use `std::optional>`? Or Box? + //constexpr virtual types::Option inner() noexcept { return { std::nullopt }; } + constexpr virtual types::Option inner() const noexcept { return { std::nullopt }; } + constexpr virtual types::MaybeOwned into_report() & noexcept { /* TODO */ } //TODO: Maybe just use `std::optional>`? Or Box? constexpr virtual types::MaybeOwned into_report() && noexcept { /* TODO: auto{*this}.into_report() */ } constexpr virtual ~Error() = default; @@ -47,7 +62,7 @@ namespace exopt { }; // This is propagated returned, along with a stack trace. (base, abstract) - class TracedError : Error { + class TracedError : public Error { public: TracedError(TracedError const &) = default; TracedError(TracedError &&) = default; @@ -62,13 +77,27 @@ namespace exopt { std::source_location loc = std::source_location::current() , std::stacktrace trace = std::stacktrace::current()) noexcept : Error(std::move(loc)), m_trace(std::move(trace)) {} + /*inline TracedError( + std::stacktrace&& trace, + , std::source_location loc = std::source_location::current()) noexcept + : Error(std::move(loc)), m_trace(std::move(trace)) {}*/ + inline TracedError( + std::stacktrace&& trace, + , std::source_location&& loc) noexcept + : Error(std::move(loc)), m_trace(std::move(trace)) {} + private: + inline types::Box into_traced(std::stacktrace trace&&) &&noexcept override final// = std::stacktrace::current()) && noexcept; + { return typed::Box { std::move(*this) }; } //TODO: use `boxed::is_boxed_value()` to check if *this is boxed... Uhh, actually... XXX: No that doesn't work, since `Box` doesn't make `T` visible to `boxed::ObjectBase`.... Eh... + inline typed::Box into_traced(std::stacktrace trace = std::stacktrace::current()) && noexcept override final + { return typed::Box { std::move(*this) }; } std::stacktrace m_trace; //TODO: Maybe box this? idk how big it is... }; - +#if 0 // This is thrown. (virtual base, abstract) class Panic : /*virtual?? I think it should be XXX*/ Error { //TODO: How to make a `constexpr` deduced panic that has stack-trace at runtime only? Is it needed? Hnm... }; //TODO: Fatal(string) : public virtual Panic +#endif } diff --git a/src/error.cpp b/src/error.cpp new file mode 100644 index 0000000..59cc41d --- /dev/null +++ b/src/error.cpp @@ -0,0 +1,30 @@ +#include + +#include + +using namespace exopt::types; + +namespace exopt { + Box Error::into_traced(std::stacktrace&& trace) &&noexcept { + struct DynamicTracedError final : TracedError { + _EO_CTORS_BASIC_DEFAULT(DynamicTracedError, _EO_NOTHING, noexcept); + virtual ~DynamicTracedError() noexcept = default; + + DynamicTracedError(Error&& self, std::stacktrace&& trace) noexcept + : TracedError(std::move(trace), std::move(self.m_location)) + , m_error(std::move(self)) {} + + std::string_view message() const noexcept override { return m_error->message(); } + Option inner() const noexcept override { return Option(*m_error); }//{ return Option::from_pointer(std::as_const(m_error.get())); } + MaybeOwned into_report() && noexcept override { return std::move(*m_error).into_report(); } + MaybeOwned into_report() & noexcept override { return m_error->into_report(); } + + + private: + Box m_error; + }; +#define ERR DynamicTracedError{std::move(*this), std::move(trace)} + return Box::template new_dynamic(ERR); +#undef ERR + } +}