Skip to content

Commit 844e3aa

Browse files
committed
compiles
1 parent adbba69 commit 844e3aa

File tree

11 files changed

+90
-136
lines changed

11 files changed

+90
-136
lines changed

src/ast/module_declaration_node.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "utility/semantic_version.hpp"
88
#include "utility/enum_variant.hpp"
99
#include <string>
10+
#include <filesystem>
1011

1112
namespace hk::ast {
1213

@@ -25,7 +26,7 @@ class module_declaration_node : public node {
2526
*
2627
* This is the path to the file that contains the module declaration.
2728
*/
28-
path_id path = {};
29+
std::filesystem::path path = {};
2930

3031
/** The type of module declaration.
3132
*

src/prologue/prologue_scan.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11

22
#include "prologue_scan.hpp"
33
#include "utility/vector_set.hpp"
4+
#include "utility/file_cursor.hpp"
5+
#include "error/error_list.hpp"
6+
#include "parser/parsers.hpp"
47

58
namespace hk {
69

@@ -39,11 +42,12 @@ namespace hk {
3942
continue;
4043
}
4144

45+
auto errors = error_list{};
4246
auto cursor = file_cursor(entry.path());
4347
if (auto node = parse_module(cursor, errors, true)) {
4448

45-
r.push_back(std::move(node()).value());
46-
} else if (node.is_error()) {
49+
r.push_back(std::move(node).value());
50+
} else if (node.error()) {
4751

4852

4953
} else {

src/tokenizer/tokenizer_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ TEST_SUITE(tokenizer_suite)
1717

1818
static std::vector<hk::token> parse_tokens(std::string_view text)
1919
{
20-
auto path_id = hk::make_file_buffer(text);
21-
auto cursor = hk::file_cursor{path_id, path_id};
20+
auto path = hk::make_file_buffer(text);
21+
auto cursor = hk::file_cursor{path};
2222
auto delegate = delegate_type{};
2323

2424
hk::tokenize(cursor, delegate);

src/utility/file.cpp

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,18 @@
88

99
namespace hk {
1010

11-
file::file(hk::path_id path_id)
12-
: _path_id(path_id)
13-
{
14-
}
15-
1611

17-
inline static std::mutex file_mutex;
18-
inline static std::map<path_id, std::unique_ptr<file>> file_by_path_id;
19-
20-
[[nodiscard]] file& get_file(hk::path_id path_id)
12+
[[nodiscard]] std::unique_ptr<file> make_file(std::filesystem::path path)
2113
{
22-
auto const _ = std::scoped_lock(file_mutex);
23-
24-
auto it = file_by_path_id.lower_bound(path_id);
25-
if (it != file_by_path_id.end() and it->first == path_id) {
26-
return *(it->second);
27-
}
28-
29-
auto file_ptr = std::unique_ptr<file>{};
30-
31-
auto rel_path = path_id->relative_path();
14+
assert(not path.empty());
15+
auto rel_path = path.relative_path();
3216
auto rel_path_str = rel_path.generic_string();
3317

3418
if (rel_path_str.starts_with("tmp/hic-buffer-") and rel_path_str.ends_with(".bin")) {
35-
file_ptr = std::make_unique<file_buffer>(path_id);
19+
return std::make_unique<file_buffer>(std::move(path));
3620
} else {
37-
file_ptr = std::make_unique<file_ifstream>(path_id);
21+
return std::make_unique<file_ifstream>(std::move(path));
3822
}
39-
assert(file_ptr != nullptr);
40-
41-
it = file_by_path_id.emplace_hint(it, path_id, std::move(file_ptr));
42-
return *(it->second);
4323
}
4424

4525
} // namespace hk

src/utility/file.hpp

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,12 @@ namespace hk {
1313
* This class provides methods to read the content of a file, open and close it,
1414
* and manage its path identifier.
1515
*
16-
* This class is thread-safe, meaning that multiple threads can access it
17-
* concurrently.
1816
*/
1917
class file {
2018
public:
2119
virtual ~file() = default;
2220

23-
/** Create a file object with the given path.
24-
*
25-
* @param path The absolute normalized path to the file.
26-
*/
27-
explicit file(hk::path_id path_id);
21+
file() = default;
2822

2923
/** Read the file content into a buffer.
3024
*
@@ -61,31 +55,12 @@ class file {
6155
* If the file is not open, this will do nothing.
6256
*/
6357
virtual void close() noexcept {};
64-
65-
protected:
66-
/** This class is thread-safe, so we need a mutex to protect access to the file stream.
67-
*/
68-
std::mutex _mutex;
69-
70-
/** The absolute normalized path to the file.
71-
*/
72-
path_id _path_id = {};
7358
};
7459

75-
/** Get a file object pointing the the given path identifier.
76-
*
77-
* @param path_id The path identifier to get the file for.
78-
* @return A file object pointing to the file, or an error code if the file could not be opened.
79-
*/
80-
[[nodiscard]] file &get_file(hk::path_id path_id);
81-
82-
/** Remove the file object from memory.
83-
*
84-
* This will close the file and remove it from the internal cache.
85-
* This is used when the file no longer exists during incremental compilation.
60+
/** Make a file object from a path.
8661
*
87-
* @param path_id The path identifier of the file object to remove.
62+
* @param path The path to open.
8863
*/
89-
void free_file(hk::path_id path_id) noexcept;
64+
[[nodiscard]] std::unique_ptr<file> make_file(std::filesystem::path path);
9065

9166
} // namespace hk

src/utility/file_buffer.cpp

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
#include "file.hpp"
44
#include <cassert>
55
#include <format>
6+
#include <mutex>
7+
#include <map>
68

79
namespace hk {
810

9-
file_buffer::file_buffer(hk::path_id path_id)
10-
: file(path_id)
11+
std::mutex file_buffer::_mutex;
12+
std::map<std::filesystem::path, std::vector<char>> file_buffer::_content_by_path;
13+
14+
file_buffer::file_buffer(std::filesystem::path path)
15+
: file(), _path(std::move(path))
1116
{
1217
}
1318

@@ -18,13 +23,18 @@ file_buffer::file_buffer(hk::path_id path_id)
1823
}
1924

2025
auto const _ = std::scoped_lock(_mutex);
26+
auto it = _content_by_path.lower_bound(_path);
27+
if (it == _content_by_path.end() or it->first != _path) {
28+
it = _content_by_path.emplace_hint(it, _path, std::vector<char>{});
29+
}
30+
auto const &content = it->second;
2131

22-
if (position >= _content.size()) {
32+
if (position >= content.size()) {
2333
return 0; // Position is beyond the end of the content
2434
}
2535

26-
auto bytes_read = std::min(buffer.size(), _content.size() - position);
27-
std::copy_n(_content.data() + position, bytes_read, buffer.data());
36+
auto bytes_read = std::min(buffer.size(), content.size() - position);
37+
std::copy_n(content.data() + position, bytes_read, buffer.data());
2838

2939
if (bytes_read < buffer.size()) {
3040
// If we read less than the buffer size, fill the rest with null characters.
@@ -36,10 +46,17 @@ file_buffer::file_buffer(hk::path_id path_id)
3646

3747
std::size_t file_buffer::write(std::size_t position, std::span<char const> buffer)
3848
{
39-
if (position >= _content.size()) {
40-
_content.resize(position + buffer.size(), '\0');
49+
auto const _ = std::scoped_lock(_mutex);
50+
auto it = _content_by_path.lower_bound(_path);
51+
if (it == _content_by_path.end() or it->first != _path) {
52+
it = _content_by_path.emplace_hint(it, _path, std::vector<char>{});
53+
}
54+
auto &content = it->second;
55+
56+
if (position >= content.size()) {
57+
content.resize(position + buffer.size(), '\0');
4158
}
42-
std::copy(buffer.begin(), buffer.end(), _content.begin() + position);
59+
std::copy(buffer.begin(), buffer.end(), content.begin() + position);
4360
return buffer.size();
4461
}
4562

@@ -49,20 +66,19 @@ std::size_t file_buffer::write(std::size_t position, std::span<char const> buffe
4966

5067
// Generate a unique path for the file buffer.
5168
// This could be a temporary file or a specific directory for file buffers.
52-
return std::format("/tmp/hic-buffer-{}.bin", ++counter);
69+
return std::filesystem::path{std::format("/tmp/hic-buffer-{}.bin", ++counter)};
5370
}
5471

55-
[[nodiscard]] path_id make_file_buffer(std::span<char const> content)
72+
[[nodiscard]] std::filesystem::path make_file_buffer(std::span<char const> content)
5673
{
57-
auto path = path_id{make_file_buffer_path()};
58-
auto& file = get_file(path);
59-
assert(dynamic_cast<file_buffer*>(&file) != nullptr);
74+
auto path = make_file_buffer_path();
75+
auto file = file_buffer{path};
6076

6177
file.write(0, content);
6278
return path;
6379
}
6480

65-
[[nodiscard]] path_id make_file_buffer(std::string_view content)
81+
[[nodiscard]] std::filesystem::path make_file_buffer(std::string_view content)
6682
{
6783
return make_file_buffer(std::span<char const>{content.data(), content.size()});
6884
}

src/utility/file_buffer.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "file.hpp"
55
#include <vector>
6+
#include <map>
67

78
namespace hk {
89

@@ -14,7 +15,7 @@ class file_buffer : public file {
1415
*
1516
* @param path The absolute normalized path to the file.
1617
*/
17-
explicit file_buffer(hk::path_id path_id);
18+
explicit file_buffer(std::filesystem::path path);
1819

1920
/** Read the file content into a buffer.
2021
*
@@ -27,26 +28,30 @@ class file_buffer : public file {
2728
std::size_t write(std::size_t position, std::span<char const> buffer) override;
2829

2930
private:
31+
static std::mutex _mutex;
32+
3033
/** The file content stored in a vector.
3134
*
3235
* This is used to read the file content from memory instead of from disk.
3336
* It is initialized when the file is opened.
3437
*/
35-
std::vector<char> _content = {};
38+
static std::map<std::filesystem::path, std::vector<char>> _content_by_path;
39+
40+
std::filesystem::path _path;
3641
};
3742

3843
/** Create a file buffer with the given content.
3944
*
4045
* @param content The content to write to the file buffer.
4146
* @return A unique identifier for the file buffer.
4247
*/
43-
[[nodiscard]] path_id make_file_buffer(std::span<char const> content);
48+
[[nodiscard]] std::filesystem::path make_file_buffer(std::span<char const> content);
4449

4550
/** Create a file buffer with the given content.
4651
*
4752
* @param content The content to write to the file buffer.
4853
* @return A unique identifier for the file buffer.
4954
*/
50-
[[nodiscard]] path_id make_file_buffer(std::string_view content);
55+
[[nodiscard]] std::filesystem::path make_file_buffer(std::string_view content);
5156

5257
}

src/utility/file_cursor.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
namespace hk {
88

9-
file_cursor::file_cursor(hk::path_id base_path_id, hk::path_id path_id) noexcept : _location(base_path_id, path_id)
9+
file_cursor::file_cursor(std::filesystem::path path) : _file(make_file(path))
1010
{
11+
_upstream_paths.push_back(std::move(path));
1112
_buffer.resize(max_buffer_size);
1213
fill_lookahead();
1314
}
@@ -54,10 +55,8 @@ void file_cursor::advance()
5455

5556
void file_cursor::fill_buffer()
5657
{
57-
auto &file = hk::get_file(_location.path_id);
58-
5958
assert(_buffer.size() == max_buffer_size);
60-
_buffer_size = file.read(_offset, std::span<char>(_buffer));
59+
_buffer_size = _file->read(_offset, std::span<char>(_buffer));
6160
if (_buffer_size < max_buffer_size) {
6261
// Fill the rest of the buffer with zeros, so that the lookahead
6362
// can safely read beyond the end of the file.

src/utility/file_cursor.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "path.hpp"
55
#include "file_location.hpp"
6+
#include "file.hpp"
67
#include <cstddef>
78
#include <bit>
89
#include <vector>
@@ -25,16 +26,11 @@ namespace hk {
2526
*/
2627
class file_cursor {
2728
public:
28-
/** Create a file_cursor that is not associated with any file.
29-
*/
30-
constexpr file_cursor() noexcept = default;
31-
3229
/** Create a file_cursor that points to the given file.
3330
*
34-
* @param base_path_id The path where compilation started.
35-
* @param path_id The file being compiled.
31+
* @param path The path of the file being read.
3632
*/
37-
file_cursor(hk::path_id base_path_id, hk::path_id path_id) noexcept;
33+
file_cursor(std::filesystem::path path);
3834

3935
/** Get the file location where this file_cursor is currently pointint to.
4036
*
@@ -165,6 +161,10 @@ class file_cursor {
165161

166162
constexpr static std::size_t buffer_mask = max_buffer_size - 1;
167163

164+
/** The file object to read from.
165+
*/
166+
std::unique_ptr<file> _file;
167+
168168
/** The buffer used to read the file.
169169
*
170170
* This buffer is used to read the file in chunks, so that we can efficiently

0 commit comments

Comments
 (0)