forked from lix-project/lix
Move PodIdx
to pos-idx.hh
and PosTable
to pos-table.hh
(cherry picked from commit c62c21e29af20f1c14a59ab37d7a25dd0b70f69e)
Change-Id: Id4ea2fc33b0874b2f1f2a32cabcbeb0afa26808f
This commit is contained in:
parent
7673312ccc
commit
d4c738fe4c
|
@ -9,6 +9,8 @@
|
||||||
#include "error.hh"
|
#include "error.hh"
|
||||||
#include "chunked-vector.hh"
|
#include "chunked-vector.hh"
|
||||||
#include "position.hh"
|
#include "position.hh"
|
||||||
|
#include "pos-idx.hh"
|
||||||
|
#include "pos-table.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -30,90 +32,6 @@ public:
|
||||||
using EvalError::EvalError;
|
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 Env;
|
||||||
struct Value;
|
struct Value;
|
||||||
class EvalState;
|
class EvalState;
|
||||||
|
|
48
src/libexpr/pos-idx.hh
Normal file
48
src/libexpr/pos-idx.hh
Normal file
|
@ -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 = {};
|
||||||
|
|
||||||
|
}
|
83
src/libexpr/pos-table.hh
Normal file
83
src/libexpr/pos-table.hh
Normal file
|
@ -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};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue