54 int64_t source_start, source_end;
57 Location() : source_start(0), source_end(0) {}
58 static Location NonPrintable() {
return Location(-1, -1); }
59 Location(int64_t source_start, int64_t source_end)
60 : source_start(source_start), source_end(source_end) {}
63 inline void advance() { source_end++; }
66 inline void devance() {
68 assert(source_end >= source_start);
72 inline void newLine() { advance(); }
75 Location operator|(
const Location &other)
const {
77 result.source_start = std::min(source_start, other.source_start);
78 result.source_end = std::max(source_end, other.source_end);
82 void operator|=(
const Location &other) {
83 source_start = std::min(source_start, other.source_start);
84 source_end = std::max(source_end, other.source_end);
86 operator std::pair<int64_t, int64_t>()
const {
87 return std::make_pair(source_start, source_end);
91 friend std::ostream &operator<<(std::ostream &out,
const Location &loc) {
92 out << loc.source_start <<
":" << loc.source_end;
98 bool operator==(
const Location &other)
const {
99 return source_start == other.source_start && source_end == other.source_end;
109 using Report = std::tuple<Location, std::string, ReportKind>;
111 using iterator = std::vector<Report>::iterator;
112 using const_iterator = std::vector<Report>::const_iterator;
115 iterator begin() {
return reports.begin(); }
116 iterator end() {
return reports.end(); }
117 const_iterator begin()
const {
return reports.begin(); }
118 const_iterator end()
const {
return reports.end(); }
119 const_iterator cbegin()
const {
return reports.cbegin(); }
120 const_iterator cend()
const {
return reports.cend(); }
121 [[noreturn]]
virtual void abort(
const std::string &msg =
"<NO MESSAGE>") {
122 sammine_util::abort(msg);
124 template <explicitly_
bool_like T>
125 void abort_on(
const T &condition,
126 const std::string &message =
"<NO MESSAGE>") {
127 if (
static_cast<bool>(condition)) {
128 this->abort(message);
132 template <explicitly_
bool_like T>
133 void abort_if_not(
const T &condition,
134 const std::string &message =
"<NO MESSAGE>") {
135 if (!
static_cast<bool>(condition)) {
136 this->abort(message);
139 void add_error(
Location loc, std::string msg) {
140 reports.push_back({loc, msg, ReportKind::error});
143 void add_warn(
Location loc, std::string msg) {
144 reports.push_back({loc, msg, ReportKind::warn});
147 void add_diagnostics(
Location loc, std::string msg) {
148 reports.push_back({loc, msg, ReportKind::diag});
152 [[nodiscard]]
virtual bool has_errors()
const {
return error_count > 0; }
153 [[nodiscard]]
bool has_warn()
const {
return warn_count > 0; }
154 [[nodiscard]]
bool has_message()
const {
return !reports.empty(); }
156 [[nodiscard]]
bool has_diagnostics()
const {
return diag_count > 0; }
158 [[nodiscard]] int64_t get_error_count()
const {
return error_count; }
160 [[nodiscard]] int64_t get_warn_count()
const {
return warn_count; }
161 [[nodiscard]] int64_t get_diagnostic_count()
const {
return diag_count; }
164 std::vector<Report> reports;
165 int64_t error_count = 0;
166 int64_t warn_count = 0;
167 int64_t diag_count = 0;
172 using ReportKind = Reportee::ReportKind;
173 using IndexPair = std::pair<int64_t, int64_t>;
174 using DiagnosticData = std::vector<std::pair<std::int64_t, std::string_view>>;
177 static DiagnosticData get_diagnostic_data(std::string_view str);
178 inline static fmt::terminal_color LINE_COLOR =
179 fmt::terminal_color::bright_magenta;
181 inline static fmt::terminal_color MSG_COLOR =
182 fmt::terminal_color::bright_blue;
183 std::string file_name;
185 std::vector<std::pair<std::int64_t, std::string_view>> diagnostic_data;
186 int64_t context_radius;
187 static fmt::terminal_color get_color_from(ReportKind report_kind);
189 void report_single_msg(std::pair<int64_t, int64_t> index_pair,
190 const std::string &format_str,
191 const ReportKind report_kind)
const;
193 template <
typename... T>
194 static void print_fmt(fmt::terminal_color ts,
195 fmt::format_string<T...> format_str, T &&...args) {
196 fmt::print(stderr, fg(ts), format_str, std::forward<T>(args)...);
198 template <
typename... T>
199 static void print_fmt(fmt::color ts, fmt::format_string<T...> format_str,
201 fmt::print(stderr, fg(ts), format_str, std::forward<T>(args)...);
203 template <
typename... T>
204 static void print_fmt(
const ReportKind report_kind,
205 fmt::format_string<T...> format_str, T &&...args) {
206 fmt::print(stderr, fg(get_color_from(report_kind)), format_str,
207 std::forward<T>(args)...);
210 void indicate_singular_line(ReportKind report_kind, int64_t col_start,
211 int64_t col_end)
const;
213 static void report_singular_line(ReportKind report_kind,
214 const std::string &msg, int64_t col_start,
217 void print_data_singular_line(std::string_view msg, int64_t col_start,
218 int64_t col_end)
const;
221 void report(
const Reportee &reports)
const;
222 void immediate_error(
const std::string &str,
Location l =
Location(-1, -1)) {
223 if (l.source_start <= 0 && l.source_end <= 0) {
224 print_fmt(LINE_COLOR,
" |");
225 print_fmt(fmt::terminal_color::bright_blue,
"In {}\n", file_name);
226 report_singular_line(ReportKind::error, str, 0, 0);
229 report_single_msg(l, str, ReportKind::error);
232 void immediate_diag(
const std::string &str,
Location l =
Location(-1, -1)) {
233 if (l.source_start <= 0 && l.source_end <= 0) {
234 print_fmt(LINE_COLOR,
" |");
235 print_fmt(fmt::terminal_color::bright_blue,
"In {}\n", file_name);
236 report_singular_line(ReportKind::diag, str, 0, 0);
238 report_single_msg(l, str, ReportKind::diag);
242 Reporter(std::string file_name, std::string input, int64_t context_radius)
243 : file_name(file_name), input(input),
244 diagnostic_data(get_diagnostic_data(this->input)),
245 context_radius(context_radius) {}