MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
dbg.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <sstream>
5#include <stdexcept>
6
7#include <absl/container/flat_hash_map.h>
8#include <absl/container/flat_hash_set.h>
9#include <fe/loc.h>
10#include <fe/sym.h>
11#include <fe/term.h>
12
13namespace mim {
14
15/// Wraps `std::format` to throw `T` with a formatted message.
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)...));
19}
20
21using fe::Loc;
22using fe::Pos;
23using fe::Sym;
24
25class Error : public std::exception {
26public:
27 enum class Tag {
31 };
32
33 struct Msg {
34 Loc loc;
36 std::string str;
37
38 friend std::ostream& operator<<(std::ostream&, const Msg&);
39 };
40
41 /// @name Constructors
42 ///@{
43 Error() = default;
44 /// Creates a single Tag::Error message.
45 Error(Loc loc, const std::string& str)
46 : msgs_{
47 {loc, Tag::Error, str}
48 } {}
49 ///@}
50
51 /// @name Getters
52 ///@{
53 const auto& msgs() const { return msgs_; }
54 size_t num_msgs() const { return msgs_.size(); }
55 size_t num_errors() const { return std::ranges::count(msgs_, Tag::Error, &Msg::tag); }
56 size_t num_warnings() const { return std::ranges::count(msgs_, Tag::Warn, &Msg::tag); }
57 size_t num_notes() const { return std::ranges::count(msgs_, Tag::Note, &Msg::tag); }
58 ///@}
59
60 /// @name Add formatted message
61 ///@{
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)...));
65 return *this;
66 }
67
68 // clang-format off
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) {
72 assert(num_errors() > 0 || num_warnings() > 0);
73 return msg(loc, Tag::Note, s, std::forward<Args>(args)...);
74 }
75 // clang-format on
76 ///@}
77
78 /// @name Handle Errors/Warnings
79 ///@{
80 void clear();
81 /// If errors occurred, claim them and throw; if warnings occurred, claim them and report to @p os.
82 void ack(std::ostream& os = std::cerr);
83 ///@}
84
85 const char* what() const noexcept override {
86 if (what_.empty()) {
87 std::ostringstream oss;
88 oss << *this;
89 what_ = oss.str();
90 }
91 return what_.c_str();
92 }
93
94 friend std::ostream& operator<<(std::ostream& o, Tag tag) {
95 // clang-format off
96 switch (tag) {
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();
101 }
102 // clang-format on
103 }
104
105 friend std::ostream& operator<<(std::ostream& os, const Error& e) {
106 for (const auto& msg : e.msgs())
107 os << msg << std::endl;
108 return os;
109 }
110
111private:
112 std::vector<Msg> msgs_;
113 mutable std::string what_;
114};
115
116/// @name Formatted Output
117///@{
118/// Single Error that `throw`s immediately.
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)...));
122}
123///@}
124
125struct Dbg {
126public:
127 /// @name Constructors
128 ///@{
129 constexpr Dbg() noexcept = default;
130 constexpr Dbg(const Dbg&) noexcept = default;
131 constexpr Dbg(Loc loc, Sym sym) noexcept
132 : loc_(loc)
133 , sym_(sym) {}
134 constexpr Dbg(Loc loc) noexcept
135 : Dbg(loc, {}) {}
136 constexpr Dbg(Sym sym) noexcept
137 : Dbg({}, sym) {}
138 Dbg& operator=(const Dbg&) noexcept = default;
139 ///@}
140
141 /// @name Getters
142 ///@{
143 Sym sym() const { return sym_; }
144 Loc loc() const { return loc_; }
145 bool is_anon() const { return !sym() || sym() == '_'; }
146 explicit operator bool() const { return sym().operator bool(); }
147 ///@}
148
149 /// @name Setters
150 ///@{
151 Dbg& set(Sym sym) { return sym_ = sym, *this; }
152 Dbg& set(Loc loc) { return loc_ = loc, *this; }
153 ///@}
154
155private:
156 Loc loc_;
157 Sym sym_;
158
159 friend std::ostream& operator<<(std::ostream& os, const Dbg& dbg) { return os << dbg.sym(); }
160};
161
162} // namespace mim
163
164#ifndef DOXYGEN // clang-format off
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 {};
169#endif // clang-format on
170
171namespace mim {
172
173inline std::ostream& operator<<(std::ostream& os, const Error::Msg& msg) {
174 return os << std::format("{}{}: {}: {}{}", fe::term::FG::Yellow, msg.loc, msg.tag, fe::term::FG::Reset, msg.str);
175}
176
177} // namespace mim
size_t num_msgs() const
Definition dbg.h:54
Error & msg(Loc loc, Tag tag, std::format_string< Args... > s, Args &&... args)
Definition dbg.h:63
const char * what() const noexcept override
Definition dbg.h:85
size_t num_notes() const
Definition dbg.h:57
Error & error(Loc loc, std::format_string< Args... > s, Args &&... args)
Definition dbg.h:69
Error & warn(Loc loc, std::format_string< Args... > s, Args &&... args)
Definition dbg.h:70
const auto & msgs() const
Definition dbg.h:53
Error()=default
friend std::ostream & operator<<(std::ostream &o, Tag tag)
Definition dbg.h:94
friend std::ostream & operator<<(std::ostream &os, const Error &e)
Definition dbg.h:105
size_t num_errors() const
Definition dbg.h:55
Error(Loc loc, const std::string &str)
Creates a single Tag::Error message.
Definition dbg.h:45
Error & note(Loc loc, std::format_string< Args... > s, Args &&... args)
Definition dbg.h:71
size_t num_warnings() const
Definition dbg.h:56
Definition ast.h:14
std::ostream & operator<<(std::ostream &os, const Error::Msg &msg)
Definition dbg.h:173
void error(std::format_string< Args... > fmt, Args &&... args)
Wraps std::format to throw T with a formatted message.
Definition dbg.h:17
Dbg & operator=(const Dbg &) noexcept=default
Sym sym() const
Definition dbg.h:143
Dbg & set(Loc loc)
Definition dbg.h:152
Loc loc() const
Definition dbg.h:144
Dbg & set(Sym sym)
Definition dbg.h:151
bool is_anon() const
Definition dbg.h:145
friend std::ostream & operator<<(std::ostream &os, const Dbg &dbg)
Definition dbg.h:159
constexpr Dbg(Loc loc) noexcept
Definition dbg.h:134
constexpr Dbg() noexcept=default
constexpr Dbg(Sym sym) noexcept
Definition dbg.h:136
friend std::ostream & operator<<(std::ostream &, const Msg &)
Definition dbg.h:173
std::string str
Definition dbg.h:36