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/tools/willowc/lib/sourcemanager.cpp | |
| parent | c2d4209f85f46cc91163bc47cc43db252c94acf6 (diff) | |
| download | compiler-8f98dc579af1993ec85bd849656c4835b4039dd6.tar.gz | |
[willow]: frontend plumbing (#13)
...
Diffstat (limited to 'willow/tools/willowc/lib/sourcemanager.cpp')
| -rw-r--r-- | willow/tools/willowc/lib/sourcemanager.cpp | 75 |
1 files changed, 71 insertions, 4 deletions
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 <cassert> #include <filesystem> - #include <fstream> +#include <iostream> +#include <string_view> + #include <sourcemanager.hpp> namespace willowc { @@ -11,9 +14,14 @@ std::optional<FileID> 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<FileID> 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<FileID> SourceManager::getFileID(const std::string &path) { + auto it = ids.find(path); + + if (it != ids.end()) + return it->second; + + return std::nullopt; +} + +std::optional<FileID> SourceManager::addStdIn() { + std::string content{std::istreambuf_iterator<char>(std::cin), + std::istreambuf_iterator<char>()}; + + if (std::cin.bad()) + return std::nullopt; + + std::size_t size = content.size(); + auto buf = std::make_unique<char[]>(size); + const FileID id = file_table.size(); + file_table.emplace_back("<stdin>", "<stdin>", 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<uint32_t>(offset - line_start + 1), offset}; +} + } // namespace willowc |