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