summaryrefslogtreecommitdiff
path: root/willow/tools/willowc/lib/sourcemanager.cpp
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/tools/willowc/lib/sourcemanager.cpp
parentc2d4209f85f46cc91163bc47cc43db252c94acf6 (diff)
downloadcompiler-8f98dc579af1993ec85bd849656c4835b4039dd6.tar.gz
[willow]: frontend plumbing (#13)
...
Diffstat (limited to 'willow/tools/willowc/lib/sourcemanager.cpp')
-rw-r--r--willow/tools/willowc/lib/sourcemanager.cpp75
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