diff options
| author | Stefan Weigl-Bosker <stefan@s00.xyz> | 2026-02-23 22:18:22 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-02-23 22:18:22 -0500 |
| commit | 8f98dc579af1993ec85bd849656c4835b4039dd6 (patch) | |
| tree | 3ee45620d83b209c1c11248afc9ab83ffcf39691 /willow/include | |
| parent | c2d4209f85f46cc91163bc47cc43db252c94acf6 (diff) | |
| download | compiler-8f98dc579af1993ec85bd849656c4835b4039dd6.tar.gz | |
[willow]: frontend plumbing (#13)
...
Diffstat (limited to 'willow/include')
| -rw-r--r-- | willow/include/willow/IR/Diagnostic.h | 34 | ||||
| -rw-r--r-- | willow/include/willow/IR/Location.h | 5 | ||||
| -rw-r--r-- | willow/include/willow/Util/Color.h | 219 |
3 files changed, 256 insertions, 2 deletions
diff --git a/willow/include/willow/IR/Diagnostic.h b/willow/include/willow/IR/Diagnostic.h index 68483d9..137c537 100644 --- a/willow/include/willow/IR/Diagnostic.h +++ b/willow/include/willow/IR/Diagnostic.h @@ -2,10 +2,12 @@ #define WILLOW_INCLUDE_IR_DIAGNOSTIC_H #include <willow/IR/Location.h> +#include <willow/Util/Color.h> #include <string> #include <vector> #include <ostream> +#include <utility> namespace willow { @@ -18,6 +20,38 @@ struct Diagnostic { std::vector<Diagnostic> notes; }; +constexpr termcolor::TextStyle getSeverityColor(Severity sev) { + using namespace termcolor; + switch (sev) { + case Severity::Debug: + return TextStyle{AnsiColor::Green, Emphasis::Bold}; + case Severity::Remark: + return TextStyle{AnsiColor::Cyan, Emphasis::Bold}; + case Severity::Warning: + return TextStyle{AnsiColor::Magenta, Emphasis::Bold}; + case Severity::Error: + return TextStyle{AnsiColor::Red, Emphasis::Bold}; + default: + std::unreachable(); + } +} + +constexpr std::string_view getSeverityName(Severity sev) { + using namespace std::string_view_literals; + switch (sev) { + case Severity::Debug: + return "debug"sv; + case Severity::Remark: + return "info"sv; + case Severity::Warning: + return "warning"sv; + case Severity::Error: + return "error"sv; + default: + std::unreachable(); + } +} + } // namespace willow std::ostream &operator<<(std::ostream &os, const willow::Diagnostic &diagnostic); diff --git a/willow/include/willow/IR/Location.h b/willow/include/willow/IR/Location.h index c3c241d..0db7c58 100644 --- a/willow/include/willow/IR/Location.h +++ b/willow/include/willow/IR/Location.h @@ -9,8 +9,9 @@ namespace willow { /// A source location struct Location { std::string_view filename; - int line; - int col; + uint32_t line; + uint32_t col; + size_t offset; }; } // namespace willow diff --git a/willow/include/willow/Util/Color.h b/willow/include/willow/Util/Color.h new file mode 100644 index 0000000..d7c7840 --- /dev/null +++ b/willow/include/willow/Util/Color.h @@ -0,0 +1,219 @@ +#ifndef WILLOW_INCLUDE_UTIL_COLOR_H +#define WILLOW_INCLUDE_UTIL_COLOR_H + +#include <cassert> +#include <cstddef> +#include <format> +#include <stdint.h> +#include <string_view> + +/// \file Utilities for printing pretty terminal output +/// +/// This is heavily inspired by fmtlib include/fmt/color.h + +namespace willow { + +namespace termcolor { + +enum class AnsiColor : uint8_t { + None = 0, + Black = 30, + Red, + Green, + Yellow, + Blue, + Magenta, + Cyan, + White, + Default = 39, + BrightBlack = 90, + BrightRed, + BrightGreen, + BrightYellow, + BrightBlue, + BrightMagenta, + BrightCyan, + BrightWhite +}; + +enum class Emphasis : uint8_t { + None = 0, + Bold = 1, + Faint = 1 << 1, + Italic = 1 << 2, + Underline = 1 << 3, + Blink = 1 << 4, + Reverse = 1 << 5, + Conceal = 1 << 6, + Strikethrough = 1 << 7, +}; + +constexpr Emphasis operator|(Emphasis a, Emphasis b) noexcept { + return static_cast<Emphasis>(static_cast<uint8_t>(a) | + static_cast<uint8_t>(b)); +} +constexpr Emphasis &operator|=(Emphasis &a, Emphasis b) noexcept { + return a = (a | b); +} +constexpr bool has(Emphasis a, Emphasis b) { + return (static_cast<uint8_t>(a) & static_cast<uint8_t>(b)) != 0; +} + +struct TextStyle { + AnsiColor fg = AnsiColor::None; + AnsiColor bg = AnsiColor::None; + Emphasis emph = Emphasis::None; + + explicit constexpr TextStyle() = default; + constexpr TextStyle(AnsiColor fg, AnsiColor bg = AnsiColor::None, + Emphasis emph = Emphasis::None) noexcept + : fg(fg), bg(bg) {} + constexpr TextStyle(AnsiColor fg, Emphasis emph = Emphasis::None) noexcept + : fg(fg), emph(emph) {} + + constexpr bool has_foreground() const noexcept { + return fg != AnsiColor::None; + } + + constexpr bool has_background() const noexcept { + return bg != AnsiColor::None; + } + + constexpr bool has_emphasis() const noexcept { + return emph != Emphasis::None; + } + + // special sentinel value for a full reset + constexpr bool is_reset() const noexcept { + return fg == AnsiColor::None && bg == AnsiColor::None && + emph == Emphasis::None; + } +}; + +template <typename CharT> +struct AnsiColorEscape { + constexpr AnsiColorEscape(AnsiColor text_color, bool is_bg = false) noexcept { + if (is_bg) + text_color = + static_cast<AnsiColor>(static_cast<uint8_t>(text_color) + 10); + + buffer[size++] = static_cast<CharT>('\x1b'); + buffer[size++] = static_cast<CharT>('['); + + uint8_t value = static_cast<uint8_t>(text_color); + + // some bg colors need 3 digits + if (value >= 100u) { + buffer[size++] = static_cast<CharT>('1'); + value %= 100u; + } + buffer[size++] = static_cast<CharT>('0' + value / 10u); + buffer[size++] = static_cast<CharT>('0' + value % 10u); + + buffer[size++] = static_cast<CharT>('m'); + } + + constexpr AnsiColorEscape(Emphasis em) noexcept { + uint8_t em_codes[NUM_EMPHASES] = {}; + if (has_emphasis(em, Emphasis::Bold)) + em_codes[0] = 1; + if (has_emphasis(em, Emphasis::Faint)) + em_codes[1] = 2; + if (has_emphasis(em, Emphasis::Italic)) + em_codes[2] = 3; + if (has_emphasis(em, Emphasis::Underline)) + em_codes[3] = 4; + if (has_emphasis(em, Emphasis::Blink)) + em_codes[4] = 5; + if (has_emphasis(em, Emphasis::Reverse)) + em_codes[5] = 7; + if (has_emphasis(em, Emphasis::Conceal)) + em_codes[6] = 8; + if (has_emphasis(em, Emphasis::Strikethrough)) + em_codes[7] = 9; + + buffer[size++] = static_cast<CharT>('\x1b'); + buffer[size++] = static_cast<CharT>('['); + + for (unsigned char em_code : em_codes) { + if (!em_code) + continue; + buffer[size++] = static_cast<CharT>('0' + em_code); + buffer[size++] = static_cast<CharT>(';'); + } + + buffer[size - 1] = static_cast<CharT>('m'); + } + + constexpr operator const char *() const noexcept { return buffer; } + constexpr operator std::string_view() const noexcept { + return std::string_view(buffer, size); + } + + constexpr const CharT *begin() const noexcept { return buffer; } + constexpr const CharT *end() const noexcept { return buffer + size; } + +private: + static constexpr size_t NUM_EMPHASES = 8; + CharT buffer[7u + 4u * NUM_EMPHASES]; + size_t size = 0; + + static constexpr bool has_emphasis(Emphasis em, Emphasis mask) noexcept { + return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask); + } +}; + +template <typename CharT> +AnsiColorEscape<CharT> make_foreground_color(AnsiColor c) { + return AnsiColorEscape<CharT>(c); +} + +template <typename CharT> +AnsiColorEscape<CharT> make_background_color(AnsiColor c) { + return AnsiColorEscape<CharT>(c, true); +} + +template <typename CharT> +AnsiColorEscape<CharT> make_emphasis(Emphasis c) { + return AnsiColorEscape<CharT>(c); +} + +}; // namespace termcolor + +}; // namespace willow + +template <typename CharT> +struct std::formatter<willow::termcolor::TextStyle, CharT> { + constexpr auto parse(const std::format_parse_context &ctx) { + auto it = ctx.begin(); + assert(it == ctx.end() || *it == '}'); + return it; + } + template <class FormatContext> + auto format(const willow::termcolor::TextStyle &style, + FormatContext &ctx) const { + auto out = ctx.out(); + if (style.is_reset()) + return std::format_to(out, "{}", "\x1b[0m"); + + if (style.has_emphasis()) { + auto emphasis = willow::termcolor::make_emphasis<CharT>(style.emph); + out = std::format_to( + out, "{}", static_cast<std::basic_string_view<CharT>>(emphasis)); + } + if (style.has_foreground()) { + auto fg = willow::termcolor::make_foreground_color<CharT>(style.fg); + out = std::format_to(out, "{}", + static_cast<std::basic_string_view<CharT>>(fg)); + } + if (style.has_background()) { + auto bg = willow::termcolor::make_background_color<CharT>(style.bg); + out = std::format_to(out, "{}", + static_cast<std::basic_string_view<CharT>>(bg)); + } + + return out; + } +}; + +#endif // WILLOW_INCLUDE_UTIL_COLOR_H |