2012-07-18 18:59:03 +00:00
|
|
|
#pragma once
|
2010-04-13 12:25:42 +00:00
|
|
|
|
2021-12-20 10:29:14 +00:00
|
|
|
#include <list>
|
2010-04-13 12:25:42 +00:00
|
|
|
#include <map>
|
2021-12-20 10:29:14 +00:00
|
|
|
#include <unordered_map>
|
2010-04-13 12:25:42 +00:00
|
|
|
|
|
|
|
#include "types.hh"
|
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
/* Symbol table used by the parser and evaluator to represent and look
|
2013-10-24 14:41:04 +00:00
|
|
|
up identifiers and attributes efficiently. SymbolTable::create()
|
|
|
|
converts a string into a symbol. Symbols have the property that
|
|
|
|
they can be compared efficiently (using a pointer equality test),
|
|
|
|
because the symbol table stores only one copy of each string. */
|
2010-04-13 12:25:42 +00:00
|
|
|
|
|
|
|
class Symbol
|
|
|
|
{
|
|
|
|
private:
|
2022-02-21 15:37:25 +00:00
|
|
|
const std::string * s; // pointer into SymbolTable
|
|
|
|
Symbol(const std::string * s) : s(s) { };
|
2010-04-13 12:25:42 +00:00
|
|
|
friend class SymbolTable;
|
|
|
|
|
|
|
|
public:
|
2010-10-24 00:41:29 +00:00
|
|
|
Symbol() : s(0) { };
|
2013-05-16 17:08:02 +00:00
|
|
|
|
2010-04-13 12:25:42 +00:00
|
|
|
bool operator == (const Symbol & s2) const
|
|
|
|
{
|
|
|
|
return s == s2.s;
|
|
|
|
}
|
2013-05-16 17:08:02 +00:00
|
|
|
|
2020-04-16 23:02:29 +00:00
|
|
|
// FIXME: remove
|
|
|
|
bool operator == (std::string_view s2) const
|
|
|
|
{
|
|
|
|
return s->compare(s2) == 0;
|
|
|
|
}
|
|
|
|
|
2010-04-13 12:25:42 +00:00
|
|
|
bool operator != (const Symbol & s2) const
|
|
|
|
{
|
|
|
|
return s != s2.s;
|
|
|
|
}
|
2013-05-16 17:08:02 +00:00
|
|
|
|
2010-04-13 12:25:42 +00:00
|
|
|
bool operator < (const Symbol & s2) const
|
|
|
|
{
|
|
|
|
return s < s2.s;
|
|
|
|
}
|
|
|
|
|
2019-12-05 18:11:09 +00:00
|
|
|
operator const std::string & () const
|
|
|
|
{
|
|
|
|
return *s;
|
|
|
|
}
|
|
|
|
|
|
|
|
operator const std::string_view () const
|
2010-04-13 12:25:42 +00:00
|
|
|
{
|
|
|
|
return *s;
|
|
|
|
}
|
|
|
|
|
2013-05-16 17:08:02 +00:00
|
|
|
bool set() const
|
|
|
|
{
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2010-04-13 12:25:42 +00:00
|
|
|
friend std::ostream & operator << (std::ostream & str, const Symbol & sym);
|
|
|
|
};
|
|
|
|
|
|
|
|
class SymbolTable
|
|
|
|
{
|
|
|
|
private:
|
2021-12-20 10:29:14 +00:00
|
|
|
std::unordered_map<std::string_view, Symbol> symbols;
|
2022-02-21 15:37:25 +00:00
|
|
|
std::list<std::string> store;
|
2010-04-13 12:25:42 +00:00
|
|
|
|
|
|
|
public:
|
2020-04-16 23:02:29 +00:00
|
|
|
Symbol create(std::string_view s)
|
2010-04-13 12:25:42 +00:00
|
|
|
{
|
2021-12-20 10:29:14 +00:00
|
|
|
// Most symbols are looked up more than once, so we trade off insertion performance
|
|
|
|
// for lookup performance.
|
|
|
|
// TODO: could probably be done more efficiently with transparent Hash and Equals
|
|
|
|
// on the original implementation using unordered_set
|
|
|
|
auto it = symbols.find(s);
|
|
|
|
if (it != symbols.end()) return it->second;
|
|
|
|
|
2022-02-21 15:37:25 +00:00
|
|
|
auto & rawSym = store.emplace_back(s);
|
2021-12-20 10:29:14 +00:00
|
|
|
return symbols.emplace(rawSym, Symbol(&rawSym)).first->second;
|
2010-04-13 12:25:42 +00:00
|
|
|
}
|
2010-04-13 14:34:11 +00:00
|
|
|
|
2018-05-02 11:56:34 +00:00
|
|
|
size_t size() const
|
2010-04-13 14:34:11 +00:00
|
|
|
{
|
|
|
|
return symbols.size();
|
|
|
|
}
|
2013-10-08 13:34:57 +00:00
|
|
|
|
|
|
|
size_t totalSize() const;
|
2019-04-11 21:04:13 +00:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void dump(T callback)
|
|
|
|
{
|
2021-12-20 10:29:14 +00:00
|
|
|
for (auto & s : store)
|
2019-04-11 21:04:13 +00:00
|
|
|
callback(s);
|
|
|
|
}
|
2010-04-13 12:25:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|