aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/nixexpr.hh86
-rw-r--r--src/libexpr/pos-idx.hh48
-rw-r--r--src/libexpr/pos-table.hh83
3 files changed, 133 insertions, 84 deletions
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 4b41fe1fc..84f66ba4c 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -9,6 +9,8 @@
#include "error.hh"
#include "chunked-vector.hh"
#include "position.hh"
+#include "pos-idx.hh"
+#include "pos-table.hh"
namespace nix {
@@ -30,90 +32,6 @@ public:
using EvalError::EvalError;
};
-class PosIdx {
- friend class PosTable;
-
-private:
- uint32_t id;
-
- explicit PosIdx(uint32_t id): id(id) {}
-
-public:
- PosIdx() : id(0) {}
-
- explicit operator bool() const { return id > 0; }
-
- bool operator <(const PosIdx other) const { return id < other.id; }
-
- bool operator ==(const PosIdx other) const { return id == other.id; }
-
- bool operator !=(const PosIdx other) const { return id != other.id; }
-};
-
-class PosTable
-{
-public:
- class Origin {
- friend PosTable;
- private:
- // must always be invalid by default, add() replaces this with the actual value.
- // subsequent add() calls use this index as a token to quickly check whether the
- // current origins.back() can be reused or not.
- mutable uint32_t idx = std::numeric_limits<uint32_t>::max();
-
- // Used for searching in PosTable::[].
- explicit Origin(uint32_t idx): idx(idx), origin{std::monostate()} {}
-
- public:
- const Pos::Origin origin;
-
- Origin(Pos::Origin origin): origin(origin) {}
- };
-
- struct Offset {
- uint32_t line, column;
- };
-
-private:
- std::vector<Origin> origins;
- ChunkedVector<Offset, 8192> offsets;
-
-public:
- PosTable(): offsets(1024)
- {
- origins.reserve(1024);
- }
-
- PosIdx add(const Origin & origin, uint32_t line, uint32_t column)
- {
- const auto idx = offsets.add({line, column}).second;
- if (origins.empty() || origins.back().idx != origin.idx) {
- origin.idx = idx;
- origins.push_back(origin);
- }
- return PosIdx(idx + 1);
- }
-
- Pos operator[](PosIdx p) const
- {
- if (p.id == 0 || p.id > offsets.size())
- return {};
- const auto idx = p.id - 1;
- /* we want the last key <= idx, so we'll take prev(first key > idx).
- this is guaranteed to never rewind origin.begin because the first
- key is always 0. */
- const auto pastOrigin = std::upper_bound(
- origins.begin(), origins.end(), Origin(idx),
- [] (const auto & a, const auto & b) { return a.idx < b.idx; });
- const auto origin = *std::prev(pastOrigin);
- const auto offset = offsets[idx];
- return {offset.line, offset.column, origin.origin};
- }
-};
-
-inline PosIdx noPos = {};
-
-
struct Env;
struct Value;
class EvalState;
diff --git a/src/libexpr/pos-idx.hh b/src/libexpr/pos-idx.hh
new file mode 100644
index 000000000..9949f1dc5
--- /dev/null
+++ b/src/libexpr/pos-idx.hh
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <cinttypes>
+
+namespace nix {
+
+class PosIdx
+{
+ friend class PosTable;
+
+private:
+ uint32_t id;
+
+ explicit PosIdx(uint32_t id)
+ : id(id)
+ {
+ }
+
+public:
+ PosIdx()
+ : id(0)
+ {
+ }
+
+ explicit operator bool() const
+ {
+ return id > 0;
+ }
+
+ bool operator<(const PosIdx other) const
+ {
+ return id < other.id;
+ }
+
+ bool operator==(const PosIdx other) const
+ {
+ return id == other.id;
+ }
+
+ bool operator!=(const PosIdx other) const
+ {
+ return id != other.id;
+ }
+};
+
+inline PosIdx noPos = {};
+
+}
diff --git a/src/libexpr/pos-table.hh b/src/libexpr/pos-table.hh
new file mode 100644
index 000000000..1decf3c85
--- /dev/null
+++ b/src/libexpr/pos-table.hh
@@ -0,0 +1,83 @@
+#pragma once
+
+#include <cinttypes>
+#include <numeric>
+#include <vector>
+
+#include "chunked-vector.hh"
+#include "pos-idx.hh"
+#include "position.hh"
+
+namespace nix {
+
+class PosTable
+{
+public:
+ class Origin
+ {
+ friend PosTable;
+ private:
+ // must always be invalid by default, add() replaces this with the actual value.
+ // subsequent add() calls use this index as a token to quickly check whether the
+ // current origins.back() can be reused or not.
+ mutable uint32_t idx = std::numeric_limits<uint32_t>::max();
+
+ // Used for searching in PosTable::[].
+ explicit Origin(uint32_t idx)
+ : idx(idx)
+ , origin{std::monostate()}
+ {
+ }
+
+ public:
+ const Pos::Origin origin;
+
+ Origin(Pos::Origin origin)
+ : origin(origin)
+ {
+ }
+ };
+
+ struct Offset
+ {
+ uint32_t line, column;
+ };
+
+private:
+ std::vector<Origin> origins;
+ ChunkedVector<Offset, 8192> offsets;
+
+public:
+ PosTable()
+ : offsets(1024)
+ {
+ origins.reserve(1024);
+ }
+
+ PosIdx add(const Origin & origin, uint32_t line, uint32_t column)
+ {
+ const auto idx = offsets.add({line, column}).second;
+ if (origins.empty() || origins.back().idx != origin.idx) {
+ origin.idx = idx;
+ origins.push_back(origin);
+ }
+ return PosIdx(idx + 1);
+ }
+
+ Pos operator[](PosIdx p) const
+ {
+ if (p.id == 0 || p.id > offsets.size())
+ return {};
+ const auto idx = p.id - 1;
+ /* we want the last key <= idx, so we'll take prev(first key > idx).
+ this is guaranteed to never rewind origin.begin because the first
+ key is always 0. */
+ const auto pastOrigin = std::upper_bound(
+ origins.begin(), origins.end(), Origin(idx), [](const auto & a, const auto & b) { return a.idx < b.idx; });
+ const auto origin = *std::prev(pastOrigin);
+ const auto offset = offsets[idx];
+ return {offset.line, offset.column, origin.origin};
+ }
+};
+
+}