summaryrefslogtreecommitdiff
path: root/willow/include
diff options
context:
space:
mode:
authorStefan Weigl-Bosker <stefan@s00.xyz>2026-02-23 22:18:22 -0500
committerGitHub <noreply@github.com>2026-02-23 22:18:22 -0500
commit8f98dc579af1993ec85bd849656c4835b4039dd6 (patch)
tree3ee45620d83b209c1c11248afc9ab83ffcf39691 /willow/include
parentc2d4209f85f46cc91163bc47cc43db252c94acf6 (diff)
downloadcompiler-8f98dc579af1993ec85bd849656c4835b4039dd6.tar.gz
[willow]: frontend plumbing (#13)
...
Diffstat (limited to 'willow/include')
-rw-r--r--willow/include/willow/IR/Diagnostic.h34
-rw-r--r--willow/include/willow/IR/Location.h5
-rw-r--r--willow/include/willow/Util/Color.h219
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