59 int64_t source_start, source_end;
62 Location() : source_start(0), source_end(0) {}
63 static Location NonPrintable() {
return Location(-1, -1); }
64 Location(int64_t source_start, int64_t source_end)
65 : source_start(source_start), source_end(source_end) {}
68 inline void advance() { source_end++; }
71 inline void devance() {
73 assert(source_end >= source_start);
77 inline void newLine() { advance(); }
80 Location operator|(
const Location &other)
const {
82 result.source_start = std::min(source_start, other.source_start);
83 result.source_end = std::max(source_end, other.source_end);
87 void operator|=(
const Location &other) {
88 source_start = std::min(source_start, other.source_start);
89 source_end = std::max(source_end, other.source_end);
91 operator std::pair<int64_t, int64_t>()
const {
92 return std::make_pair(source_start, source_end);
96 friend std::ostream &operator<<(std::ostream &out,
const Location &loc) {
97 out << loc.source_start <<
":" << loc.source_end;
103 bool operator==(
const Location &other)
const {
104 return source_start == other.source_start && source_end == other.source_end;
114 using Report = std::tuple<Location, std::string, ReportKind>;
116 using iterator = std::vector<Report>::iterator;
117 using const_iterator = std::vector<Report>::const_iterator;
120 iterator begin() {
return reports.begin(); }
121 iterator end() {
return reports.end(); }
122 const_iterator begin()
const {
return reports.begin(); }
123 const_iterator end()
const {
return reports.end(); }
124 const_iterator cbegin()
const {
return reports.cbegin(); }
125 const_iterator cend()
const {
return reports.cend(); }
126 [[noreturn]]
virtual void abort(
const std::string &msg =
"<NO MESSAGE>") {
127 sammine_util::abort(msg);
129 template <explicitly_
bool_like T>
130 void abort_on(
const T &condition,
131 const std::string &message =
"<NO MESSAGE>") {
132 if (
static_cast<bool>(condition)) {
133 this->abort(message);
137 template <explicitly_
bool_like T>
138 void abort_if_not(
const T &condition,
139 const std::string &message =
"<NO MESSAGE>") {
140 if (!
static_cast<bool>(condition)) {
141 this->abort(message);
144 void add_error(
Location loc, std::string msg) {
145 reports.push_back({loc, msg, ReportKind::error});
148 void add_warn(
Location loc, std::string msg) {
149 reports.push_back({loc, msg, ReportKind::warn});
152 void add_diagnostics(
Location loc, std::string msg) {
153 reports.push_back({loc, msg, ReportKind::diag});
157 [[nodiscard]]
virtual bool has_errors()
const {
return error_count > 0; }
158 [[nodiscard]]
bool has_warn()
const {
return warn_count > 0; }
159 [[nodiscard]]
bool has_message()
const {
return !reports.empty(); }
161 [[nodiscard]]
bool has_diagnostics()
const {
return diag_count > 0; }
163 [[nodiscard]] int64_t get_error_count()
const {
return error_count; }
165 [[nodiscard]] int64_t get_warn_count()
const {
return warn_count; }
166 [[nodiscard]] int64_t get_diagnostic_count()
const {
return diag_count; }
169 std::vector<Report> reports;
170 int64_t error_count = 0;
171 int64_t warn_count = 0;
172 int64_t diag_count = 0;
177 using ReportKind = Reportee::ReportKind;
178 using IndexPair = std::pair<int64_t, int64_t>;
179 using DiagnosticData = std::vector<std::pair<std::int64_t, std::string_view>>;
182 static DiagnosticData get_diagnostic_data(std::string_view str);
183 inline static fmt::terminal_color LINE_COLOR =
184 fmt::terminal_color::bright_magenta;
186 inline static fmt::terminal_color MSG_COLOR =
187 fmt::terminal_color::bright_blue;
188 std::string file_name;
190 std::vector<std::pair<std::int64_t, std::string_view>> diagnostic_data;
191 int64_t context_radius;
192 static fmt::terminal_color get_color_from(ReportKind report_kind);
194 void report_single_msg(std::pair<int64_t, int64_t> index_pair,
195 const std::string &format_str,
196 const ReportKind report_kind)
const;
198 template <
typename... T>
199 static void print_fmt(fmt::terminal_color ts,
200 fmt::format_string<T...> format_str, T &&...args) {
201 fmt::print(stderr, fg(ts), format_str, std::forward<T>(args)...);
203 template <
typename... T>
204 static void print_fmt(fmt::color ts, fmt::format_string<T...> format_str,
206 fmt::print(stderr, fg(ts), format_str, std::forward<T>(args)...);
208 template <
typename... T>
209 static void print_fmt(
const ReportKind report_kind,
210 fmt::format_string<T...> format_str, T &&...args) {
211 fmt::print(stderr, fg(get_color_from(report_kind)), format_str,
212 std::forward<T>(args)...);
215 void indicate_singular_line(ReportKind report_kind, int64_t col_start,
216 int64_t col_end)
const;
218 static void report_singular_line(ReportKind report_kind,
219 const std::string &msg, int64_t col_start,
222 void print_data_singular_line(std::string_view msg, int64_t col_start,
223 int64_t col_end)
const;
226 void report(
const Reportee &reports)
const;
227 void immediate_error(
const std::string &str,
Location l =
Location(-1, -1)) {
228 if (l.source_start <= 0 && l.source_end <= 0) {
229 print_fmt(LINE_COLOR,
" |");
230 print_fmt(fmt::terminal_color::bright_blue,
"In {}\n", file_name);
231 report_singular_line(ReportKind::error, str, 0, 0);
234 report_single_msg(l, str, ReportKind::error);
237 void immediate_diag(
const std::string &str,
Location l =
Location(-1, -1)) {
238 if (l.source_start <= 0 && l.source_end <= 0) {
239 print_fmt(LINE_COLOR,
" |");
240 print_fmt(fmt::terminal_color::bright_blue,
"In {}\n", file_name);
241 report_singular_line(ReportKind::diag, str, 0, 0);
243 report_single_msg(l, str, ReportKind::diag);
247 Reporter(std::string file_name, std::string input, int64_t context_radius)
248 : file_name(file_name), input(input),
249 diagnostic_data(get_diagnostic_data(this->input)),
250 context_radius(context_radius) {}