From 8f98dc579af1993ec85bd849656c4835b4039dd6 Mon Sep 17 00:00:00 2001 From: Stefan Weigl-Bosker Date: Mon, 23 Feb 2026 22:18:22 -0500 Subject: [willow]: frontend plumbing (#13) ... --- willow/tools/willowc/lib/sourcemanager.cpp | 75 ++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 4 deletions(-) (limited to 'willow/tools/willowc/lib/sourcemanager.cpp') diff --git a/willow/tools/willowc/lib/sourcemanager.cpp b/willow/tools/willowc/lib/sourcemanager.cpp index e2a8e72..a30c76e 100644 --- a/willow/tools/willowc/lib/sourcemanager.cpp +++ b/willow/tools/willowc/lib/sourcemanager.cpp @@ -1,6 +1,9 @@ +#include #include - #include +#include +#include + #include namespace willowc { @@ -11,9 +14,14 @@ std::optional SourceManager::addFile(std::string_view _path) { std::filesystem::path uncanonical_path{_path}; auto path = std::filesystem::weakly_canonical(uncanonical_path, ec); if (ec) { - return false; + return std::nullopt; } - std::string display_path = path.make_preferred(); + + std::filesystem::path display_path = path; + display_path.make_preferred(); + std::string display = display_path.string(); + + assert(!getFileID(display)); if (!std::filesystem::exists(path, ec) || ec) return std::nullopt; @@ -33,9 +41,68 @@ std::optional SourceManager::addFile(std::string_view _path) { f.read(buf.get(), filesize); const FileID id = file_table.size(); - file_table.push_back(File{std::move(display_path), std::move(buf)}); + file_table.emplace_back(std::move(display), std::string(_path), std::move(buf), filesize); + ids[file_table.back().path] = id; return id; } +std::optional SourceManager::getFileID(const std::string &path) { + auto it = ids.find(path); + + if (it != ids.end()) + return it->second; + + return std::nullopt; +} + +std::optional SourceManager::addStdIn() { + std::string content{std::istreambuf_iterator(std::cin), + std::istreambuf_iterator()}; + + if (std::cin.bad()) + return std::nullopt; + + std::size_t size = content.size(); + auto buf = std::make_unique(size); + const FileID id = file_table.size(); + file_table.emplace_back("", "", std::move(buf), size); + ids[file_table.back().path] = id; + return id; +} + +willow::Location SourceManager::File::getLoc(std::size_t offset) { + size_t line_start = offset; + while (line_start != 0) { + if (this->buf[--line_start] != '\n') + continue; + + line_start++; + break; + } + + uint32_t col = offset - line_start + 1; + auto it = linecache_.find(line_start); + + if (it != linecache_.end()) + return willow::Location{display_path, it->second, col, offset}; + + auto back = linecache_.rbegin(); + auto i = back->first; + auto line = back->second; + assert(i < line_start); + for (; i < line_start; i++) { + if (buf[i] == '\n') { + line = line + 1; + size_t next_start = i + 1; + + if (next_start <= size) + linecache_.insert({next_start, ++line}); + } + } + linecache_.insert({line_start, line}); + return willow::Location{ + display_path, line, static_cast(offset - line_start + 1), offset}; +} + } // namespace willowc -- cgit v1.2.3