73 int64_t source_start, source_end;
76 std::shared_ptr<SourceInfo> source_info;
79 Location() : source_start(0), source_end(0) {}
80 static Location NonPrintable() {
return Location(-1, -1); }
81 Location(int64_t source_start, int64_t source_end)
82 : source_start(source_start), source_end(source_end) {}
85 inline void advance() { source_end++; }
88 inline void devance() {
90 assert(source_end >= source_start);
94 inline void newLine() { advance(); }
97 Location operator|(
const Location &other)
const {
99 result.source_start = std::min(source_start, other.source_start);
100 result.source_end = std::max(source_end, other.source_end);
101 result.source_info = source_info ? source_info : other.source_info;
105 void operator|=(
const Location &other) {
106 source_start = std::min(source_start, other.source_start);
107 source_end = std::max(source_end, other.source_end);
109 source_info = other.source_info;
112 std::pair<int64_t, int64_t> as_pair()
const {
113 return std::make_pair(source_start, source_end);
117 friend std::ostream &operator<<(std::ostream &out,
const Location &loc) {
118 out << loc.source_start <<
":" << loc.source_end;
124 bool operator==(
const Location &other)
const {
125 return source_start == other.source_start &&
126 source_end == other.source_end &&
127 source_info.get() == other.source_info.get();
138 using Report = std::tuple<Location, std::vector<std::string>, ReportKind,
139 std::source_location>;
141 using iterator = std::vector<Report>::iterator;
142 using const_iterator = std::vector<Report>::const_iterator;
145 iterator begin() {
return reports.begin(); }
146 iterator end() {
return reports.end(); }
147 const_iterator begin()
const {
return reports.begin(); }
148 const_iterator end()
const {
return reports.end(); }
149 const_iterator cbegin()
const {
return reports.cbegin(); }
150 const_iterator cend()
const {
return reports.cend(); }
151 [[noreturn]]
virtual void abort(
const std::string &msg =
"<NO MESSAGE>") {
152 sammine_util::abort(msg);
154 template <explicitly_
bool_like T>
155 void abort_on(
const T &condition,
156 const std::string &message =
"<NO MESSAGE>") {
157 if (
static_cast<bool>(condition)) {
158 this->abort(message);
162 template <explicitly_
bool_like T>
163 void abort_if_not(
const T &condition,
164 const std::string &message =
"<NO MESSAGE>") {
165 if (!
static_cast<bool>(condition)) {
166 this->abort(message);
169 void add_error(
Location loc, std::string msg,
170 std::source_location src = std::source_location::current()) {
171 reports.push_back({loc, {std::move(msg)}, ReportKind::error, src});
174 void add_error(
Location loc, std::vector<std::string> msgs,
175 std::source_location src = std::source_location::current()) {
176 reports.push_back({loc, std::move(msgs), ReportKind::error, src});
179 void add_warn(
Location loc, std::string msg,
180 std::source_location src = std::source_location::current()) {
181 reports.push_back({loc, {std::move(msg)}, ReportKind::warn, src});
185 add_diagnostics(
Location loc, std::string msg,
186 std::source_location src = std::source_location::current()) {
187 reports.push_back({loc, {std::move(msg)}, ReportKind::diag, src});
191 [[nodiscard]]
virtual bool has_errors()
const {
return error_count > 0; }
192 [[nodiscard]]
bool has_warn()
const {
return warn_count > 0; }
193 [[nodiscard]]
bool has_message()
const {
return !reports.empty(); }
195 [[nodiscard]]
bool has_diagnostics()
const {
return diag_count > 0; }
197 [[nodiscard]] int64_t get_error_count()
const {
return error_count; }
199 [[nodiscard]] int64_t get_warn_count()
const {
return warn_count; }
200 [[nodiscard]] int64_t get_diagnostic_count()
const {
return diag_count; }
203 std::vector<Report> reports;
204 int64_t error_count = 0;
205 int64_t warn_count = 0;
206 int64_t diag_count = 0;
211 using ReportKind = Reportee::ReportKind;
212 using IndexPair = std::pair<int64_t, int64_t>;
213 using DiagnosticData = std::vector<std::pair<std::int64_t, std::string_view>>;
215 static DiagnosticData get_diagnostic_data(std::string_view str);
217 inline static fmt::terminal_color LINE_COLOR =
218 fmt::terminal_color::bright_magenta;
220 static fmt::terminal_color get_color_from(ReportKind report_kind);
222 template <
typename... T>
223 static void print_fmt(fmt::terminal_color ts,
224 fmt::format_string<T...> format_str, T &&...args) {
226 fmt::print(stderr, fg(ts), format_str, std::forward<T>(args)...);
228 fmt::print(stderr, format_str, std::forward<T>(args)...);
230 template <
typename... T>
231 static void print_fmt(fmt::color ts, fmt::format_string<T...> format_str,
234 fmt::print(stderr, fg(ts), format_str, std::forward<T>(args)...);
236 fmt::print(stderr, format_str, std::forward<T>(args)...);
238 template <
typename... T>
239 static void print_fmt(
const ReportKind report_kind,
240 fmt::format_string<T...> format_str, T &&...args) {
242 fmt::print(stderr, fg(get_color_from(report_kind)), format_str,
243 std::forward<T>(args)...);
245 fmt::print(stderr, format_str, std::forward<T>(args)...);
248 static void print_data_singular_line(std::string_view msg, int64_t col_start,
252 inline static fmt::terminal_color MSG_COLOR = fmt::terminal_color::blue;
253 std::string file_name;
255 std::vector<std::pair<std::int64_t, std::string_view>> diagnostic_data;
256 int64_t context_radius;
257 bool dev_mode =
false;
259 void report_single_msg(
const Location &loc,
260 const std::vector<std::string> &format_strs,
261 const ReportKind report_kind,
262 std::source_location src = std::source_location::current())
const;
264 void indicate_singular_line(ReportKind report_kind, int64_t col_start,
265 int64_t col_end)
const;
267 static void report_singular_line(ReportKind report_kind,
268 const std::vector<std::string> &msgs,
269 int64_t col_start, int64_t col_end);
272 void report(
const Reportee &reports)
const;
274 std::source_location src = std::source_location::current()) {
275 if (l.source_start <= 0 && l.source_end <= 0) {
276 print_fmt(LINE_COLOR,
" |");
277 print_fmt(fmt::terminal_color::blue,
"In {}\n", file_name);
278 report_singular_line(ReportKind::error, {str}, 0, 0);
281 report_single_msg(l, {str}, ReportKind::error, src);
285 std::source_location src = std::source_location::current()) {
286 if (l.source_start <= 0 && l.source_end <= 0) {
287 print_fmt(LINE_COLOR,
" |");
288 print_fmt(fmt::terminal_color::blue,
"In {}\n", file_name);
289 report_singular_line(ReportKind::diag, {str}, 0, 0);
291 report_single_msg(l, {str}, ReportKind::diag, src);
295 std::source_location src = std::source_location::current()) {
296 if (l.source_start <= 0 && l.source_end <= 0) {
297 print_fmt(LINE_COLOR,
" |");
298 print_fmt(fmt::terminal_color::blue,
"In {}\n", file_name);
299 report_singular_line(ReportKind::warn, {str}, 0, 0);
301 report_single_msg(l, {str}, ReportKind::warn, src);
305 Reporter(std::string file_name, std::string input, int64_t context_radius,
306 bool dev_mode =
false)
307 : file_name(file_name), input(input),
308 diagnostic_data(get_diagnostic_data(this->input)),
309 context_radius(context_radius), dev_mode(dev_mode) {}