refactor(3p/nix/libexpr): Use absl::node_hash_set in SymbolTable

This replaces the previous use of std::unordered_set with
absl::node_hash_set.

This type was chosen because the current implementation requires
pointer stability.

This does not yet touch the 'Attr' struct.

As a bonus, the implementation of the SymbolTable struct is now
consolidated into a single header/implementation file pair.
This commit is contained in:
Vincent Ambo 2020-05-21 04:53:09 +01:00
parent 00017ace04
commit 97e85f94e5
3 changed files with 39 additions and 32 deletions

View file

@ -413,14 +413,4 @@ string ExprLambda::showNamePos() const {
.str(); .str();
} }
/* Symbol table. */
size_t SymbolTable::totalSize() const {
size_t n = 0;
for (auto& i : symbols) {
n += i.size();
}
return n;
}
} // namespace nix } // namespace nix

View file

@ -0,0 +1,24 @@
#include "symbol-table.hh"
#include <absl/container/node_hash_set.h>
#include <absl/strings/string_view.h>
namespace nix {
Symbol SymbolTable::Create(absl::string_view sym) {
auto it = symbols_.emplace(sym);
const string* ptr = &(*it.first);
return Symbol(ptr);
}
size_t SymbolTable::Size() const { return symbols_.size(); }
size_t SymbolTable::TotalSize() const {
size_t n = 0;
for (auto& i : symbols_) {
n += i.size();
}
return n;
}
} // namespace nix

View file

@ -1,11 +1,11 @@
#pragma once #pragma once
#include <map> #include <absl/container/node_hash_set.h>
#include <unordered_set> #include <absl/strings/string_view.h>
#include "types.hh" #include "types.hh"
namespace nix { namespace nix { // TODO(tazjin): ::expr
/* Symbol table used by the parser and evaluator to represent and look /* Symbol table used by the parser and evaluator to represent and look
up identifiers and attributes efficiently. SymbolTable::create() up identifiers and attributes efficiently. SymbolTable::create()
@ -15,8 +15,8 @@ namespace nix {
class Symbol { class Symbol {
private: private:
const string* s; // pointer into SymbolTable const std::string* s; // pointer into SymbolTable
Symbol(const string* s) : s(s){}; Symbol(const std::string* s) : s(s){};
friend class SymbolTable; friend class SymbolTable;
public: public:
@ -28,7 +28,7 @@ class Symbol {
bool operator<(const Symbol& s2) const { return s < s2.s; } bool operator<(const Symbol& s2) const { return s < s2.s; }
operator const string&() const { return *s; } operator const std::string&() const { return *s; }
bool set() const { return s; } bool set() const { return s; }
@ -38,26 +38,19 @@ class Symbol {
}; };
class SymbolTable { class SymbolTable {
private:
typedef std::unordered_set<string> Symbols;
Symbols symbols;
public: public:
Symbol create(const string& s) { Symbol Create(absl::string_view sym);
std::pair<Symbols::iterator, bool> res = symbols.insert(s);
return Symbol(&*res.first);
}
size_t size() const { return symbols.size(); } // TODO(tazjin): two of these?
size_t Size() const;
size_t totalSize() const; // Return the total size (in bytes)
size_t TotalSize() const;
template <typename T> private:
void dump(T callback) { // flat_hash_set does not retain pointer stability on rehashing,
for (auto& s : symbols) { // hence "interned" strings/symbols are stored on the heap.
callback(s); absl::node_hash_set<std::string> symbols_;
}
}
}; };
} // namespace nix } // namespace nix