7#include <absl/container/flat_hash_map.h>
8#include <absl/container/flat_hash_set.h>
16template<
class T = std::logic_error,
class... Args>
17[[noreturn]]
void error(std::format_string<Args...> fmt, Args&&... args) {
18 throw T(
"error: " + std::format(fmt, std::forward<Args>(args)...));
25class Error :
public std::exception {
45 Error(Loc loc,
const std::string& str)
53 const auto&
msgs()
const {
return msgs_; }
54 size_t num_msgs()
const {
return msgs_.size(); }
62 template<
class... Args>
63 Error&
msg(Loc loc,
Tag tag, std::format_string<Args...> s, Args&&... args) {
64 msgs_.emplace_back(loc, tag, std::format(s, std::forward<Args>(args)...));
69 template<
class... Args>
Error&
error(Loc loc, std::format_string<Args...> s, Args&&... args) {
return msg(loc,
Tag::Error, s, std::forward<Args>(args)...); }
70 template<
class... Args>
Error&
warn (Loc loc, std::format_string<Args...> s, Args&&... args) {
return msg(loc,
Tag::Warn, s, std::forward<Args>(args)...); }
71 template<
class... Args>
Error&
note (Loc loc, std::format_string<Args...> s, Args&&... args) {
73 return msg(loc,
Tag::Note, s, std::forward<Args>(args)...);
82 void ack(std::ostream& os = std::cerr);
85 const char*
what() const noexcept
override {
87 std::ostringstream oss;
97 case Tag::Error:
return o << fe::term::FG::Red <<
"error";
98 case Tag::Warn:
return o << fe::term::FG::Magenta <<
"warning";
99 case Tag::Note:
return o << fe::term::FG::Green <<
"note";
100 default: fe::unreachable();
106 for (
const auto&
msg : e.msgs())
107 os <<
msg << std::endl;
112 std::vector<Msg> msgs_;
113 mutable std::string what_;
119template<
class... Args>
120[[noreturn]]
void error(Loc loc, std::format_string<Args...> f, Args&&... args) {
121 throw Error(loc, std::format(f, std::forward<Args>(args)...));
129 constexpr Dbg() noexcept = default;
130 constexpr
Dbg(const
Dbg&) noexcept = default;
143 Sym
sym()
const {
return sym_; }
144 Loc
loc()
const {
return loc_; }
146 explicit operator bool()
const {
return sym().operator bool(); }
159 friend std::ostream&
operator<<(std::ostream& os,
const Dbg& dbg) {
return os << dbg.sym(); }
165template<>
struct std::formatter<
mim::Dbg > : fe::ostream_formatter {};
166template<>
struct std::formatter<
mim::Error > : fe::ostream_formatter {};
167template<>
struct std::formatter<
mim::Error::Tag> : fe::ostream_formatter {};
168template<>
struct std::formatter<
mim::Error::Msg> : fe::ostream_formatter {};
174 return os << std::format(
"{}{}: {}: {}{}", fe::term::FG::Yellow,
msg.loc,
msg.tag, fe::term::FG::Reset,
msg.str);
Error & msg(Loc loc, Tag tag, std::format_string< Args... > s, Args &&... args)
const char * what() const noexcept override
Error & error(Loc loc, std::format_string< Args... > s, Args &&... args)
Error & warn(Loc loc, std::format_string< Args... > s, Args &&... args)
const auto & msgs() const
friend std::ostream & operator<<(std::ostream &o, Tag tag)
friend std::ostream & operator<<(std::ostream &os, const Error &e)
size_t num_errors() const
Error(Loc loc, const std::string &str)
Creates a single Tag::Error message.
Error & note(Loc loc, std::format_string< Args... > s, Args &&... args)
size_t num_warnings() const
std::ostream & operator<<(std::ostream &os, const Error::Msg &msg)
void error(std::format_string< Args... > fmt, Args &&... args)
Wraps std::format to throw T with a formatted message.
Dbg & operator=(const Dbg &) noexcept=default
friend std::ostream & operator<<(std::ostream &os, const Dbg &dbg)
constexpr Dbg(Loc loc) noexcept
constexpr Dbg() noexcept=default
constexpr Dbg(Sym sym) noexcept
friend std::ostream & operator<<(std::ostream &, const Msg &)