aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcmd/installables.cc4
-rw-r--r--src/libexpr/attr-path.cc4
-rw-r--r--src/libexpr/attr-set.cc4
-rw-r--r--src/libexpr/attr-set.hh19
-rw-r--r--src/libexpr/eval-cache.cc28
-rw-r--r--src/libexpr/eval-cache.hh8
-rw-r--r--src/libexpr/eval.cc84
-rw-r--r--src/libexpr/eval.hh15
-rw-r--r--src/libexpr/flake/flake.cc44
-rw-r--r--src/libexpr/get-drvs.cc12
-rw-r--r--src/libexpr/nixexpr.cc283
-rw-r--r--src/libexpr/nixexpr.hh68
-rw-r--r--src/libexpr/parser.y56
-rw-r--r--src/libexpr/primops.cc39
-rw-r--r--src/libexpr/primops/context.cc23
-rw-r--r--src/libexpr/primops/fetchClosure.cc10
-rw-r--r--src/libexpr/primops/fetchMercurial.cc4
-rw-r--r--src/libexpr/primops/fetchTree.cc14
-rw-r--r--src/libexpr/symbol-table.hh77
-rw-r--r--src/libexpr/value-to-json.cc2
-rw-r--r--src/libexpr/value-to-xml.cc16
-rw-r--r--src/libexpr/value.hh16
-rw-r--r--src/libutil/types.hh8
-rw-r--r--src/nix-env/nix-env.cc2
-rw-r--r--src/nix-env/user-env.cc2
-rw-r--r--src/nix-instantiate/nix-instantiate.cc6
-rw-r--r--src/nix/app.cc6
-rw-r--r--src/nix/eval.cc14
-rw-r--r--src/nix/flake.cc80
-rw-r--r--src/nix/main.cc2
-rw-r--r--src/nix/repl.cc21
-rw-r--r--src/nix/search.cc2
32 files changed, 525 insertions, 448 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index 6197f4be4..c81f76a22 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -235,7 +235,7 @@ void SourceExprCommand::completeInstallable(std::string_view prefix)
if (v2.type() == nAttrs) {
for (auto & i : *v2.attrs) {
- std::string name = i.name;
+ std::string name = state->symbols[i.name];
if (name.find(searchWord) == 0) {
if (prefix_ == "")
completions->add(name);
@@ -600,7 +600,7 @@ std::tuple<std::string, FlakeRef, InstallableValue::DerivationInfo> InstallableF
auto drvInfo = DerivationInfo {
std::move(drvPath),
- attr->getAttr(state->sOutputName)->getString()
+ attr->getAttr("outputName")->getString()
};
return {attrPath, getLockedFlake()->flake.lockedRef, std::move(drvInfo)};
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index 1c12dfbe2..f63caeb10 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -36,7 +36,7 @@ std::vector<Symbol> parseAttrPath(EvalState & state, std::string_view s)
{
std::vector<Symbol> res;
for (auto & a : parseAttrPath(s))
- res.push_back(state.symbols.create(a));
+ res.emplace_back(a);
return res;
}
@@ -77,7 +77,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
if (a == v->attrs->end()) {
std::set<std::string> attrNames;
for (auto & attr : *v->attrs)
- attrNames.insert(attr.name);
+ attrNames.insert(state.symbols[attr.name]);
auto suggestions = Suggestions::bestMatches(attrNames, attr);
throw AttrPathNotFound(suggestions, "attribute '%1%' in selection path '%2%' not found", attr, attrPath);
diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc
index 61996eae4..1d17ef7e4 100644
--- a/src/libexpr/attr-set.cc
+++ b/src/libexpr/attr-set.cc
@@ -26,7 +26,7 @@ Bindings * EvalState::allocBindings(size_t capacity)
/* Create a new attribute named 'name' on an existing attribute set stored
in 'vAttrs' and return the newly allocated Value which is associated with
this attribute. */
-Value * EvalState::allocAttr(Value & vAttrs, const Symbol & name)
+Value * EvalState::allocAttr(Value & vAttrs, const SymbolIdx & name)
{
Value * v = allocValue();
vAttrs.attrs->push_back(Attr(name, v));
@@ -40,7 +40,7 @@ Value * EvalState::allocAttr(Value & vAttrs, std::string_view name)
}
-Value & BindingsBuilder::alloc(const Symbol & name, PosIdx pos)
+Value & BindingsBuilder::alloc(const SymbolIdx & name, PosIdx pos)
{
auto value = state.allocValue();
bindings->push_back(Attr(name, value, pos));
diff --git a/src/libexpr/attr-set.hh b/src/libexpr/attr-set.hh
index 23d68dda2..c42aba0f6 100644
--- a/src/libexpr/attr-set.hh
+++ b/src/libexpr/attr-set.hh
@@ -15,10 +15,10 @@ struct Value;
/* Map one attribute name to its value. */
struct Attr
{
- Symbol name;
+ SymbolIdx name;
Value * value;
PosIdx pos;
- Attr(Symbol name, Value * value, PosIdx pos = noPos)
+ Attr(SymbolIdx name, Value * value, PosIdx pos = noPos)
: name(name), value(value), pos(pos) { };
Attr() { };
bool operator < (const Attr & a) const
@@ -57,7 +57,7 @@ public:
attrs[size_++] = attr;
}
- iterator find(const Symbol & name)
+ iterator find(const SymbolIdx & name)
{
Attr key(name, 0);
iterator i = std::lower_bound(begin(), end(), key);
@@ -65,7 +65,7 @@ public:
return end();
}
- Attr * get(const Symbol & name)
+ Attr * get(const SymbolIdx & name)
{
Attr key(name, 0);
iterator i = std::lower_bound(begin(), end(), key);
@@ -86,14 +86,15 @@ public:
size_t capacity() { return capacity_; }
/* Returns the attributes in lexicographically sorted order. */
- std::vector<const Attr *> lexicographicOrder() const
+ std::vector<const Attr *> lexicographicOrder(const SymbolTable & symbols) const
{
std::vector<const Attr *> res;
res.reserve(size_);
for (size_t n = 0; n < size_; n++)
res.emplace_back(&attrs[n]);
- std::sort(res.begin(), res.end(), [](const Attr * a, const Attr * b) {
- return (const std::string &) a->name < (const std::string &) b->name;
+ std::sort(res.begin(), res.end(), [&](const Attr * a, const Attr * b) {
+ std::string_view sa = symbols[a->name], sb = symbols[b->name];
+ return sa < sb;
});
return res;
}
@@ -118,7 +119,7 @@ public:
: bindings(bindings), state(state)
{ }
- void insert(Symbol name, Value * value, PosIdx pos = noPos)
+ void insert(SymbolIdx name, Value * value, PosIdx pos = noPos)
{
insert(Attr(name, value, pos));
}
@@ -133,7 +134,7 @@ public:
bindings->push_back(attr);
}
- Value & alloc(const Symbol & name, PosIdx pos = noPos);
+ Value & alloc(const SymbolIdx & name, PosIdx pos = noPos);
Value & alloc(std::string_view name, PosIdx pos = noPos);
diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc
index 7d3fd01a4..0d2160efd 100644
--- a/src/libexpr/eval-cache.cc
+++ b/src/libexpr/eval-cache.cc
@@ -253,7 +253,7 @@ struct AttrDb
std::vector<Symbol> attrs;
auto queryAttributes(state->queryAttributes.use()(rowId));
while (queryAttributes.next())
- attrs.push_back(symbols.create(queryAttributes.getStr(0)));
+ attrs.emplace_back(queryAttributes.getStr(0));
return {{rowId, attrs}};
}
case AttrType::String: {
@@ -325,7 +325,7 @@ AttrCursor::AttrCursor(
AttrKey AttrCursor::getKey()
{
if (!parent)
- return {0, root->state.sEpsilon};
+ return {0, {""}};
if (!parent->first->cachedValue) {
parent->first->cachedValue = root->db->getAttr(
parent->first->getKey(), root->state.symbols);
@@ -340,7 +340,7 @@ Value & AttrCursor::getValue()
if (parent) {
auto & vParent = parent->first->getValue();
root->state.forceAttrs(vParent, noPos);
- auto attr = vParent.attrs->get(parent->second);
+ auto attr = vParent.attrs->get(root->state.symbols.create(parent->second));
if (!attr)
throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr());
_value = allocRootValue(attr->value);
@@ -419,7 +419,7 @@ Suggestions AttrCursor::getSuggestionsForAttr(Symbol name)
return Suggestions::bestMatches(strAttrNames, name);
}
-std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors)
+std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name, bool forceErrors)
{
if (root->db) {
if (!cachedValue)
@@ -461,10 +461,10 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
for (auto & attr : *v.attrs) {
if (root->db)
- root->db->setPlaceholder({cachedValue->first, attr.name});
+ root->db->setPlaceholder({cachedValue->first, root->state.symbols[attr.name]});
}
- auto attr = v.attrs->get(name);
+ auto attr = v.attrs->get(root->state.symbols.create(name));
if (!attr) {
if (root->db) {
@@ -486,12 +486,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
root, std::make_pair(shared_from_this(), name), attr->value, std::move(cachedValue2));
}
-std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
-{
- return maybeGetAttr(root->state.symbols.create(name));
-}
-
-ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
+ref<AttrCursor> AttrCursor::getAttr(std::string_view name, bool forceErrors)
{
auto p = maybeGetAttr(name, forceErrors);
if (!p)
@@ -499,11 +494,6 @@ ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors)
return ref(p);
}
-ref<AttrCursor> AttrCursor::getAttr(std::string_view name)
-{
- return getAttr(root->state.symbols.create(name));
-}
-
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force)
{
auto res = shared_from_this();
@@ -616,7 +606,7 @@ std::vector<Symbol> AttrCursor::getAttrs()
std::vector<Symbol> attrs;
for (auto & attr : *getValue().attrs)
- attrs.push_back(attr.name);
+ attrs.push_back(root->state.symbols[attr.name]);
std::sort(attrs.begin(), attrs.end(), [](const Symbol & a, const Symbol & b) {
return (const std::string &) a < (const std::string &) b;
});
@@ -635,7 +625,7 @@ bool AttrCursor::isDerivation()
StorePath AttrCursor::forceDerivation()
{
- auto aDrvPath = getAttr(root->state.sDrvPath, true);
+ auto aDrvPath = getAttr("drvPath", true);
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
/* The eval cache contains 'drvPath', but the actual path has
diff --git a/src/libexpr/eval-cache.hh b/src/libexpr/eval-cache.hh
index b0709ebc2..f4481c72a 100644
--- a/src/libexpr/eval-cache.hh
+++ b/src/libexpr/eval-cache.hh
@@ -96,13 +96,9 @@ public:
Suggestions getSuggestionsForAttr(Symbol name);
- std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
+ std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name, bool forceErrors = false);
- std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
-
- ref<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
-
- ref<AttrCursor> getAttr(std::string_view name);
+ ref<AttrCursor> getAttr(std::string_view name, bool forceErrors = false);
/* Get an attribute along a chain of attrsets. Note that this does
not auto-call functors or functions. */
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 39f1a625f..8fc144a84 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -96,7 +96,8 @@ RootValue allocRootValue(Value * v)
}
-void Value::print(std::ostream & str, std::set<const void *> * seen) const
+void Value::print(const SymbolTable & symbols, std::ostream & str,
+ std::set<const void *> * seen) const
{
checkInterrupt();
@@ -129,9 +130,9 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
str << "«repeated»";
else {
str << "{ ";
- for (auto & i : attrs->lexicographicOrder()) {
- str << i->name << " = ";
- i->value->print(str, seen);
+ for (auto & i : attrs->lexicographicOrder(symbols)) {
+ str << symbols[i->name] << " = ";
+ i->value->print(symbols, str, seen);
str << "; ";
}
str << "}";
@@ -146,7 +147,7 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
else {
str << "[ ";
for (auto v2 : listItems()) {
- v2->print(str, seen);
+ v2->print(symbols, str, seen);
str << " ";
}
str << "]";
@@ -177,17 +178,18 @@ void Value::print(std::ostream & str, std::set<const void *> * seen) const
}
-void Value::print(std::ostream & str, bool showRepeated) const
+void Value::print(const SymbolTable & symbols, std::ostream & str, bool showRepeated) const
{
std::set<const void *> seen;
- print(str, showRepeated ? nullptr : &seen);
+ print(symbols, str, showRepeated ? nullptr : &seen);
}
-std::ostream & operator << (std::ostream & str, const Value & v)
+std::string printValue(const EvalState & state, const Value & v)
{
- v.print(str, false);
- return str;
+ std::ostringstream out;
+ v.print(state.symbols, out);
+ return out.str();
}
@@ -306,9 +308,9 @@ static BoehmGCStackAllocator boehmGCStackAllocator;
#endif
-static Symbol getName(const AttrName & name, EvalState & state, Env & env)
+static SymbolIdx getName(const AttrName & name, EvalState & state, Env & env)
{
- if (name.symbol.set()) {
+ if (name.symbol) {
return name.symbol;
} else {
Value nameValue;
@@ -639,7 +641,7 @@ Value * EvalState::addPrimOp(const std::string & name,
size_t arity, PrimOpFun primOp)
{
auto name2 = name.substr(0, 2) == "__" ? name.substr(2) : name;
- Symbol sym = symbols.create(name2);
+ auto sym = symbols.create(name2);
/* Hack to make constants lazy: turn them into a application of
the primop to a dummy value. */
@@ -673,7 +675,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
return addConstant(primOp.name, v);
}
- Symbol envName = symbols.create(primOp.name);
+ auto envName = symbols.create(primOp.name);
if (hasPrefix(primOp.name, "__"))
primOp.name = primOp.name.substr(2);
@@ -767,11 +769,11 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
});
}
-void EvalState::throwEvalError(const PosIdx p1, const char * s, const Symbol & sym, const PosIdx p2) const
+void EvalState::throwEvalError(const PosIdx p1, const char * s, const SymbolIdx sym, const PosIdx p2) const
{
// p1 is where the error occurred; p2 is a position mentioned in the message.
throw EvalError({
- .msg = hintfmt(s, sym, positions[p2]),
+ .msg = hintfmt(s, symbols[sym], positions[p2]),
.errPos = positions[p1]
});
}
@@ -785,19 +787,19 @@ void EvalState::throwTypeError(const PosIdx pos, const char * s) const
}
void EvalState::throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun,
- const Symbol & s2) const
+ const SymbolIdx s2) const
{
throw TypeError({
- .msg = hintfmt(s, fun.showNamePos(positions), s2),
+ .msg = hintfmt(s, fun.showNamePos(*this), symbols[s2]),
.errPos = positions[pos]
});
}
void EvalState::throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
- const ExprLambda & fun, const Symbol & s2) const
+ const ExprLambda & fun, const SymbolIdx s2) const
{
throw TypeError(ErrorInfo {
- .msg = hintfmt(s, fun.showNamePos(positions), s2),
+ .msg = hintfmt(s, fun.showNamePos(*this), symbols[s2]),
.errPos = positions[pos],
.suggestions = suggestions,
});
@@ -901,7 +903,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
return j->value;
}
if (!env->prevWith)
- throwUndefinedVarError(var.pos, "undefined variable '%1%'", var.name);
+ throwUndefinedVarError(var.pos, "undefined variable '%1%'", symbols[var.name]);
for (size_t l = env->prevWith; l; --l, env = env->up) ;
}
}
@@ -1187,7 +1189,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
if (nameVal.type() == nNull)
continue;
state.forceStringNoCtx(nameVal);
- Symbol nameSym = state.symbols.create(nameVal.string.s);
+ auto nameSym = state.symbols.create(nameVal.string.s);
Bindings::iterator j = v.attrs->find(nameSym);
if (j != v.attrs->end())
state.throwEvalError(i.pos, "dynamic attribute '%1%' already defined at %2%", nameSym, j->pos);
@@ -1243,10 +1245,12 @@ static std::string showAttrPath(EvalState & state, Env & env, const AttrPath & a
for (auto & i : attrPath) {
if (!first) out << '.'; else first = false;
try {
- out << getName(i, state, env);
+ out << state.symbols[getName(i, state, env)];
} catch (Error & e) {
- assert(!i.symbol.set());
- out << "\"${" << *i.expr << "}\"";
+ assert(!i.symbol);
+ out << "\"${";
+ i.expr->show(state.symbols, out);
+ out << "}\"";
}
}
return out.str();
@@ -1266,7 +1270,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
for (auto & i : attrPath) {
state.nrLookups++;
Bindings::iterator j;
- Symbol name = getName(i, state, env);
+ auto name = getName(i, state, env);
if (def) {
state.forceValue(*vAttrs, pos);
if (vAttrs->type() != nAttrs ||
@@ -1280,11 +1284,11 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) {
std::set<std::string> allAttrNames;
for (auto & attr : *vAttrs->attrs)
- allAttrNames.insert(attr.name);
+ allAttrNames.insert(state.symbols[attr.name]);
state.throwEvalError(
pos,
- Suggestions::bestMatches(allAttrNames, name),
- "attribute '%1%' missing", name);
+ Suggestions::bestMatches(allAttrNames, state.symbols[name]),
+ "attribute '%1%' missing", state.symbols[name]);
}
}
vAttrs = j->value;
@@ -1316,7 +1320,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
for (auto & i : attrPath) {
state.forceValue(*vAttrs, noPos);
Bindings::iterator j;
- Symbol name = getName(i, state, env);
+ auto name = getName(i, state, env);
if (vAttrs->type() != nAttrs ||
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
{
@@ -1366,7 +1370,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
ExprLambda & lambda(*vCur.lambda.fun);
auto size =
- (!lambda.arg.set() ? 0 : 1) +
+ (!lambda.arg ? 0 : 1) +
(lambda.hasFormals() ? lambda.formals->formals.size() : 0);
Env & env2(allocEnv(size));
env2.up = vCur.lambda.env;
@@ -1379,7 +1383,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
else {
forceAttrs(*args[0], pos);
- if (lambda.arg.set())
+ if (lambda.arg)
env2.values[displ++] = args[0];
/* For each formal argument, get the actual argument. If
@@ -1407,10 +1411,10 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
if (!lambda.formals->has(i.name)) {
std::set<std::string> formalNames;
for (auto & formal : lambda.formals->formals)
- formalNames.insert(formal.name);
+ formalNames.insert(symbols[formal.name]);
throwTypeError(
pos,
- Suggestions::bestMatches(formalNames, i.name),
+ Suggestions::bestMatches(formalNames, symbols[i.name]),
"%1% called with unexpected argument '%2%'",
lambda,
i.name);
@@ -1428,8 +1432,8 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
} catch (Error & e) {
if (loggerSettings.showTrace.get()) {
addErrorTrace(e, lambda.pos, "while evaluating %s",
- (lambda.name.set()
- ? "'" + (const std::string &) lambda.name + "'"
+ (lambda.name
+ ? concatStrings("'", symbols[lambda.name], "'")
: "anonymous lambda"));
addErrorTrace(e, pos, "from call site%s", "");
}
@@ -1578,7 +1582,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
Nix attempted to evaluate a function as a top level expression; in
this case it must have its arguments supplied either by default
values, or passed explicitly with '--arg' or '--argstr'. See
-https://nixos.org/manual/nix/stable/#ss-functions.)", i.name);
+https://nixos.org/manual/nix/stable/#ss-functions.)", symbols[i.name]);
}
}
@@ -1610,7 +1614,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v)
{
if (!state.evalBool(env, cond, pos)) {
std::ostringstream out;
- cond->show(out);
+ cond->show(state.symbols, out);
state.throwAssertionError(pos, "assertion '%1%' failed", out.str());
}
body->eval(state, env, v);
@@ -1844,7 +1848,7 @@ void EvalState::forceValueDeep(Value & v)
try {
recurse(*i.value);
} catch (Error & e) {
- addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", i.name);
+ addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", symbols[i.name]);
throw;
}
}
@@ -2267,7 +2271,7 @@ void EvalState::printStats()
auto list = topObj.list("functions");
for (auto & i : functionCalls) {
auto obj = list.object();
- if (i.first->name.set())
+ if (i.first->name)
obj.attr("name", (const std::string &) i.first->name);
else
obj.attr("name", nullptr);
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 71d6e7e7f..59c9c4873 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -53,7 +53,8 @@ void copyContext(const Value & v, PathSet & context);
typedef std::map<Path, StorePath> SrcToStore;
-std::ostream & operator << (std::ostream & str, const Value & v);
+std::ostream & printValue(const EvalState & state, std::ostream & str, const Value & v);
+std::string printValue(const EvalState & state, const Value & v);
typedef std::pair<std::string, std::string> SearchPathElem;
@@ -77,7 +78,7 @@ public:
static inline std::string derivationNixPath = "//builtin/derivation.nix";
- const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
+ const SymbolIdx sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
sFile, sLine, sColumn, sFunctor, sToString,
sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
@@ -86,7 +87,7 @@ public:
sRecurseForDerivations,
sDescription, sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath,
sPrefix;
- Symbol sDerivationNix;
+ SymbolIdx sDerivationNix;
/* If set, force copying files to the Nix store even if they
already exist there. */
@@ -268,14 +269,14 @@ public:
[[gnu::noinline, gnu::noreturn]]
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3) const;
[[gnu::noinline, gnu::noreturn]]
- void throwEvalError(const PosIdx p1, const char * s, const Symbol & sym, const PosIdx p2) const;
+ void throwEvalError(const PosIdx p1, const char * s, const SymbolIdx sym, const PosIdx p2) const;
[[gnu::noinline, gnu::noreturn]]
void throwTypeError(const PosIdx pos, const char * s) const;
[[gnu::noinline, gnu::noreturn]]
- void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const Symbol & s2) const;
+ void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const SymbolIdx s2) const;
[[gnu::noinline, gnu::noreturn]]
void throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
- const ExprLambda & fun, const Symbol & s2) const;
+ const ExprLambda & fun, const SymbolIdx s2) const;
[[gnu::noinline, gnu::noreturn]]
void throwTypeError(const char * s, const Value & v) const;
[[gnu::noinline, gnu::noreturn]]
@@ -391,7 +392,7 @@ public:
inline Value * allocValue();
inline Env & allocEnv(size_t size);
- Value * allocAttr(Value & vAttrs, const Symbol & name);
+ Value * allocAttr(Value & vAttrs, const SymbolIdx & name);
Value * allocAttr(Value & vAttrs, std::string_view name);
Bindings * allocBindings(size_t capacity);
diff --git a/src/libexpr/flake/flake.cc b/src/libexpr/flake/flake.cc
index 44fb8317a..cbf4f0a6f 100644
--- a/src/libexpr/flake/flake.cc
+++ b/src/libexpr/flake/flake.cc
@@ -127,21 +127,23 @@ static FlakeInput parseFlakeInput(EvalState & state,
} else {
switch (attr.value->type()) {
case nString:
- attrs.emplace(attr.name, attr.value->string.s);
+ attrs.emplace(state.symbols[attr.name], attr.value->string.s);
break;
case nBool:
- attrs.emplace(attr.name, Explicit<bool> { attr.value->boolean });
+ attrs.emplace(state.symbols[attr.name], Explicit<bool> { attr.value->boolean });
break;
case nInt:
- attrs.emplace(attr.name, (long unsigned int)attr.value->integer);
+ attrs.emplace(state.symbols[attr.name], (long unsigned int)attr.value->integer);
break;
default:
throw TypeError("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
- attr.name, showType(*attr.value));
+ state.symbols[attr.name], showType(*attr.value));
}
}
} catch (Error & e) {
- e.addTrace(state.positions[attr.pos], hintfmt("in flake attribute '%s'", attr.name));
+ e.addTrace(
+ state.positions[attr.pos],
+ hintfmt("in flake attribute '%s'", state.symbols[attr.name]));
throw;
}
}
@@ -176,9 +178,9 @@ static std::map<FlakeId, FlakeInput> parseFlakeInputs(
expectType(state, nAttrs, *value, pos);
for (nix::Attr & inputAttr : *(*value).attrs) {
- inputs.emplace(inputAttr.name,
+ inputs.emplace(state.symbols[inputAttr.name],
parseFlakeInput(state,
- inputAttr.name,
+ state.symbols[inputAttr.name],
inputAttr.value,
inputAttr.pos,
baseDir,
@@ -218,7 +220,7 @@ static Flake getFlake(
Value vInfo;
state.evalFile(flakeFile, vInfo, true); // FIXME: symlink attack
- expectType(state, nAttrs, vInfo, state.positions.add({state.symbols.create(flakeFile), foFile}, 0, 0));
+ expectType(state, nAttrs, vInfo, state.positions.add({flakeFile, foFile}, 0, 0));
if (auto description = vInfo.attrs->get(state.sDescription)) {
expectType(state, nString, *description->value, description->pos);
@@ -238,8 +240,8 @@ static Flake getFlake(
if (outputs->value->isLambda() && outputs->value->lambda.fun->hasFormals()) {
for (auto & formal : outputs->value->lambda.fun->formals->formals) {
if (formal.name != state.sSelf)
- flake.inputs.emplace(formal.name, FlakeInput {
- .ref = parseFlakeRef(formal.name)
+ flake.inputs.emplace(state.symbols[formal.name], FlakeInput {
+ .ref = parseFlakeRef(state.symbols[formal.name])
});
}
}
@@ -255,30 +257,36 @@ static Flake getFlake(
for (auto & setting : *nixConfig->value->attrs) {
forceTrivialValue(state, *setting.value, setting.pos);
if (setting.value->type() == nString)
- flake.config.settings.insert({setting.name, std::string(state.forceStringNoCtx(*setting.value, setting.pos))});
+ flake.config.settings.emplace(
+ state.symbols[setting.name],
+ std::string(state.forceStringNoCtx(*setting.value, setting.pos)));
else if (setting.value->type() == nPath) {
PathSet emptyContext = {};
flake.config.settings.emplace(
- setting.name,
+ state.symbols[setting.name],
state.coerceToString(setting.pos, *setting.value, emptyContext, false, true, true) .toOwned());
}
else if (setting.value->type() == nInt)
- flake.config.settings.insert({setting.name, state.forceInt(*setting.value, setting.pos)});
+ flake.config.settings.emplace(
+ state.symbols[setting.name],
+ state.forceInt(*setting.value, setting.pos));
else if (setting.value->type() == nBool)
- flake.config.settings.insert({setting.name, Explicit<bool> { state.forceBool(*setting.value, setting.pos) }});
+ flake.config.settings.emplace(
+ state.symbols[setting.name],
+ Explicit<bool> { state.forceBool(*setting.value, setting.pos) });
else if (setting.value->type() == nList) {
std::vector<std::string> ss;
for (auto elem : setting.value->listItems()) {
if (elem->type() != nString)
throw TypeError("list element in flake configuration setting '%s' is %s while a string is expected",
- setting.name, showType(*setting.value));
+ state.symbols[setting.name], showType(*setting.value));
ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos));
}
- flake.config.settings.insert({setting.name, ss});
+ flake.config.settings.emplace(state.symbols[setting.name], ss);
}
else
throw TypeError("flake configuration setting '%s' is %s",
- setting.name, showType(*setting.value));
+ state.symbols[setting.name], showType(*setting.value));
}
}
@@ -288,7 +296,7 @@ static Flake getFlake(
attr.name != sOutputs &&
attr.name != sNixConfig)
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
- lockedRef, attr.name, state.positions[attr.pos]);
+ lockedRef, state.symbols[attr.name], state.positions[attr.pos]);
}
return flake;
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index afb35586d..11f2b279d 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -179,7 +179,7 @@ StringSet DrvInfo::queryMetaNames()
StringSet res;
if (!getMeta()) return res;
for (auto & i : *meta)
- res.insert(i.name);
+ res.emplace(state->symbols[i.name]);
return res;
}
@@ -269,7 +269,7 @@ void DrvInfo::setMeta(const std::string & name, Value * v)
{
getMeta();
auto attrs = state->buildBindings(1 + (meta ? meta->size() : 0));
- Symbol sym = state->symbols.create(name);
+ auto sym = state->symbols.create(name);
if (meta)
for (auto i : *meta)
if (i.name != sym)
@@ -356,11 +356,11 @@ static void getDerivations(EvalState & state, Value & vIn,
there are names clashes between derivations, the derivation
bound to the attribute with the "lower" name should take
precedence). */
- for (auto & i : v.attrs->lexicographicOrder()) {
- debug("evaluating attribute '%1%'", i->name);
- if (!std::regex_match(std::string(i->name), attrRegex))
+ for (auto & i : v.attrs->lexicographicOrder(state.symbols)) {
+ debug("evaluating attribute '%1%'", state.symbols[i->name]);
+ if (!std::regex_match(std::string(state.symbols[i->name]), attrRegex))
continue;
- std::string pathPrefix2 = addToPath(pathPrefix, i->name);
+ std::string pathPrefix2 = addToPath(pathPrefix, state.symbols[i->name]);
if (combineChannels)
getDerivations(state, *i->value, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
else if (getDerivation(state, *i->value, pathPrefix2, drvs, done, ignoreAssertionFailures)) {
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 4138977ea..9fee3cb58 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -1,5 +1,7 @@
#include "nixexpr.hh"
#include "derivations.hh"
+#include "eval.hh"
+#include "symbol-table.hh"
#include "util.hh"
#include <cstdlib>
@@ -10,12 +12,6 @@ namespace nix {
/* Displaying abstract syntax trees. */
-std::ostream & operator << (std::ostream & str, const Expr & e)
-{
- e.show(str);
- return str;
-}
-
static void showString(std::ostream & str, std::string_view s)
{
str << '"';
@@ -54,81 +50,101 @@ static void showId(std::ostream & str, std::string_view s)
std::ostream & operator << (std::ostream & str, const Symbol & sym)
{
- showId(str, *sym.s);
+ showId(str, sym.s);
return str;
}
-void Expr::show(std::ostream & str) const
+void Expr::show(const SymbolTable & symbols, std::ostream & str) const
{
abort();
}
-void ExprInt::show(std::ostream & str) const
+void ExprInt::show(const SymbolTable & symbols, std::ostream & str) const
{
str << n;
}
-void ExprFloat::show(std::ostream & str) const
+void ExprFloat::show(const SymbolTable & symbols, std::ostream & str) const
{
str << nf;
}
-void ExprString::show(std::ostream & str) const
+void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
{
showString(str, s);
}
-void ExprPath::show(std::ostream & str) const
+void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const
{
str << s;
}
-void ExprVar::show(std::ostream & str) const
+void ExprVar::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << name;
+ str << symbols[name];
}
-void ExprSelect::show(std::ostream & str) const
+void ExprSelect::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << "(" << *e << ")." << showAttrPath(attrPath);
- if (def) str << " or (" << *def << ")";
+ str << "(";
+ e->show(symbols, str);
+ str << ")." << showAttrPath(symbols, attrPath);
+ if (def) {
+ str << " or (";
+ def->show(symbols, str);
+ str << ")";
+ }
}
-void ExprOpHasAttr::show(std::ostream & str) const
+void ExprOpHasAttr::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << "((" << *e << ") ? " << showAttrPath(attrPath) << ")";
+ str << "((";
+ e->show(symbols, str);
+ str << ") ? " << showAttrPath(symbols, attrPath) << ")";
}
-void ExprAttrs::show(std::ostream & str) const
+void ExprAttrs::show(const SymbolTable & symbols, std::ostream & str) const
{
if (recursive) str << "rec ";
str << "{ ";
typedef const decltype(attrs)::value_type * Attr;
std::vector<Attr> sorted;
for (auto & i : attrs) sorted.push_back(&i);
- std::sort(sorted.begin(), sorted.end(), [](Attr a, Attr b) {
- return (const std::string &) a->first < (const std::string &) b->first;
- });
+ std::sort(sorted.begin(), sorted.end(), [&](Attr a, Attr b) {
+ std::string_view sa = symbols[a->first], sb = symbols[b->first];
+ return sa < sb;
+ });
for (auto & i : sorted) {
if (i->second.inherited)
- str << "inherit " << i->first << " " << "; ";
- else
- str << i->first << " = " << *i->second.e << "; ";
+ str << "inherit " << symbols[i->first] << " " << "; ";
+ else {
+ str << symbols[i->first] << " = ";
+ i->second.e->show(symbols, str);
+ str << "; ";
+ }
+ }
+ for (auto & i : dynamicAttrs) {
+ str << "\"${";
+ i.nameExpr->show(symbols, str);
+ str << "}\" = ";
+ i.valueExpr->show(symbols, str);
+ str << "; ";
}
- for (auto & i : dynamicAttrs)
- str << "\"${" << *i.nameExpr << "}\" = " << *i.valueExpr << "; ";
str << "}";
}
-void ExprList::show(std::ostream & str) const
+void ExprList::show(const SymbolTable & symbols, std::ostream & str) const
{
str << "[ ";
- for (auto & i : elems)
- str << "(" << *i << ") ";
+ for (auto & i : elems) {
+ str << "(";
+ i->show(symbols, str);
+ str << ") ";
+ }
str << "]";
}
-void ExprLambda::show(std::ostream & str) const
+void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const
{
str << "(";
if (hasFormals()) {
@@ -136,74 +152,100 @@ void ExprLambda::show(std::ostream & str) const
bool first = true;
for (auto & i : formals->formals) {
if (first) first = false; else str << ", ";
- str << i.name;
- if (i.def) str << " ? " << *i.def;
+ str << symbols[i.name];
+ if (i.def) {
+ str << " ? ";
+ i.def->show(symbols, str);
+ }
}
if (formals->ellipsis) {
if (!first) str << ", ";
str << "...";
}
str << " }";
- if (arg.set()) str << " @ ";
+ if (arg) str << " @ ";
}
- if (arg.set()) str << arg;
- str << ": " << *body << ")";
+ if (arg) str << symbols[arg];
+ str << ": ";
+ body->show(symbols, str);
+ str << ")";
}
-void ExprCall::show(std::ostream & str) const
+void ExprCall::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << '(' << *fun;
+ str << '(';
+ fun->show(symbols, str);
for (auto e : args) {
str << ' ';
- str << *e;
+ e->show(symbols, str);
}
str << ')';
}
-void ExprLet::show(std::ostream & str) const
+void ExprLet::show(const SymbolTable & symbols, std::ostream & str) const
{
str << "(let ";
for (auto & i : attrs->attrs)
if (i.second.inherited) {
- str << "inherit " << i.first << "; ";
+ str << "inherit " << symbols[i.first] << "; ";
+ }
+ else {
+ str << symbols[i.first] << " = ";
+ i.second.e->show(symbols, str);
+ str << "; ";
}
- else
- str << i.first << " = " << *i.second.e << "; ";
- str << "in " << *body << ")";
+ str << "in ";
+ body->show(symbols, str);
+ str << ")";
}
-void ExprWith::show(std::ostream & str) const
+void ExprWith::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << "(with " << *attrs << "; " << *body << ")";
+ str << "(with ";
+ attrs->show(symbols, str);
+ str << "; ";
+ body->show(symbols, str);
+ str << ")";
}
-void ExprIf::show(std::ostream & str) const
+void ExprIf::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << "(if " << *cond << " then " << *then << " else " << *else_ << ")";
+ str << "(if ";
+ cond->show(symbols, str);
+ str << " then ";
+ then->show(symbols, str);
+ str << " else ";
+ else_->show(symbols, str);
+ str << ")";
}
-void ExprAssert::show(std::ostream & str) const
+void ExprAssert::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << "assert " << *cond << "; " << *body;
+ str << "assert ";
+ cond->show(symbols, str);
+ str << "; ";
+ body->show(symbols, str);
}
-void ExprOpNot::show(std::ostream & str) const
+void ExprOpNot::show(const SymbolTable & symbols, std::ostream & str) const
{
- str << "(! " << *e << ")";
+ str << "(! ";
+ e->show(symbols, str);
+ str << ")";
}
-void ExprConcatStrings::show(std::ostream & str) const
+void ExprConcatStrings::show(const SymbolTable & symbols, std::ostream & str) const
{
bool first = true;
str << "(";
for (auto & i : *es) {
if (first) first = false; else str << " + ";
- str << *i.second;
+ i.second->show(symbols, str);
}
str << ")";
}
-void ExprPos::show(std::ostream & str) const
+void ExprPos::show(const SymbolTable & symbols, std::ostream & str) const
{
str << "__curPos";
}
@@ -234,16 +276,19 @@ std::ostream & operator << (std::ostream & str, const Pos & pos)
}
-std::string showAttrPath(const AttrPath & attrPath)
+std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath)
{
std::ostringstream out;
bool first = true;
for (auto & i : attrPath) {
if (!first) out << '.'; else first = false;
- if (i.symbol.set())
- out << i.symbol;
- else
- out << "\"${" << *i.expr << "}\"";
+ if (i.symbol)
+ out << symbols[i.symbol];
+ else {
+ out << "\"${";
+ i.expr->show(symbols, out);
+ out << "}\"";
+ }
}
return out.str();
}
@@ -252,28 +297,28 @@ std::string showAttrPath(const AttrPath & attrPath)
/* Computing levels/displacements for variables. */
-void Expr::bindVars(const PosTable & pt, const StaticEnv & env)
+void Expr::bindVars(const EvalState & es, const StaticEnv & env)
{
abort();
}
-void ExprInt::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprInt::bindVars(const EvalState & es, const StaticEnv & env)
{
}
-void ExprFloat::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprFloat::bindVars(const EvalState & es, const StaticEnv & env)
{
}
-void ExprString::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprString::bindVars(const EvalState & es, const StaticEnv & env)
{
}
-void ExprPath::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprPath::bindVars(const EvalState & es, const StaticEnv & env)
{
}
-void ExprVar::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprVar::bindVars(const EvalState & es, const StaticEnv & env)
{
/* Check whether the variable appears in the environment. If so,
set its level and displacement. */
@@ -299,31 +344,31 @@ void ExprVar::bindVars(const PosTable & pt, const StaticEnv & env)
"undefined variable" error now. */
if (withLevel == -1)
throw UndefinedVarError({
- .msg = hintfmt("undefined variable '%1%'", name),
- .errPos = pt[pos]
+ .msg = hintfmt("undefined variable '%1%'", es.symbols[name]),
+ .errPos = es.positions[pos]
});
fromWith = true;
this->level = withLevel;
}
-void ExprSelect::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprSelect::bindVars(const EvalState & es, const StaticEnv & env)
{
- e->bindVars(pt, env);
- if (def) def->bindVars(pt, env);
+ e->bindVars(es, env);
+ if (def) def->bindVars(es, env);
for (auto & i : attrPath)
- if (!i.symbol.set())
- i.expr->bindVars(pt, env);
+ if (!i.symbol)
+ i.expr->bindVars(es, env);
}
-void ExprOpHasAttr::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprOpHasAttr::bindVars(const EvalState & es, const StaticEnv & env)
{
- e->bindVars(pt, env);
+ e->bindVars(es, env);
for (auto & i : attrPath)
- if (!i.symbol.set())
- i.expr->bindVars(pt, env);
+ if (!i.symbol)
+ i.expr->bindVars(es, env);
}
-void ExprAttrs::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprAttrs::bindVars(const EvalState & es, const StaticEnv & env)
{
const StaticEnv * dynamicEnv = &env;
StaticEnv newEnv(false, &env, recursive ? attrs.size() : 0);
@@ -338,35 +383,35 @@ void ExprAttrs::bindVars(const PosTable & pt, const StaticEnv & env)
// No need to sort newEnv since attrs is in sorted order.
for (auto & i : attrs)
- i.second.e->bindVars(pt, i.second.inherited ? env : newEnv);
+ i.second.e->bindVars(es, i.second.inherited ? env : newEnv);
}
else
for (auto & i : attrs)
- i.second.e->bindVars(pt, env);
+ i.second.e->bindVars(es, env);
for (auto & i : dynamicAttrs) {
- i.nameExpr->bindVars(pt, *dynamicEnv);
- i.valueExpr->bindVars(pt, *dynamicEnv);
+ i.nameExpr->bindVars(es, *dynamicEnv);
+ i.valueExpr->bindVars(es, *dynamicEnv);
}
}
-void ExprList::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprList::bindVars(const EvalState & es, const StaticEnv & env)
{
for (auto & i : elems)
- i->bindVars(pt, env);
+ i->bindVars(es, env);
}
-void ExprLambda::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprLambda::bindVars(const EvalState & es, const StaticEnv & env)
{
StaticEnv newEnv(
false, &env,
(hasFormals() ? formals->formals.size() : 0) +
- (!arg.set() ? 0 : 1));
+ (!arg ? 0 : 1));
Displacement displ = 0;
- if (arg.set()) newEnv.vars.emplace_back(arg, displ++);
+ if (arg) newEnv.vars.emplace_back(arg, displ++);
if (hasFormals()) {
for (auto & i : formals->formals)
@@ -375,20 +420,20 @@ void ExprLambda::bindVars(const PosTable & pt, const StaticEnv & env)
newEnv.sort();
for (auto & i : formals->formals)
- if (i.def) i.def->bindVars(pt, newEnv);
+ if (i.def) i.def->bindVars(es, newEnv);
}
- body->bindVars(pt, newEnv);
+ body->bindVars(es, newEnv);
}
-void ExprCall::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprCall::bindVars(const EvalState & es, const StaticEnv & env)
{
- fun->bindVars(pt, env);
+ fun->bindVars(es, env);
for (auto e : args)
- e->bindVars(pt, env);
+ e->bindVars(es, env);
}
-void ExprLet::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprLet::bindVars(const EvalState & es, const StaticEnv & env)
{
StaticEnv newEnv(false, &env, attrs->attrs.size());
@@ -399,12 +444,12 @@ void ExprLet::bindVars(const PosTable & pt, const StaticEnv & env)
// No need to sort newEnv since attrs->attrs is in sorted order.
for (auto & i : attrs->attrs)
- i.second.e->bindVars(pt, i.second.inherited ? env : newEnv);
+ i.second.e->bindVars(es, i.second.inherited ? env : newEnv);
- body->bindVars(pt, newEnv);
+ body->bindVars(es, newEnv);
}
-void ExprWith::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprWith::bindVars(const EvalState & es, const StaticEnv & env)
{
/* Does this `with' have an enclosing `with'? If so, record its
level so that `lookupVar' can look up variables in the previous
@@ -418,57 +463,60 @@ void ExprWith::bindVars(const PosTable & pt, const StaticEnv & env)
break;
}
- attrs->bindVars(pt, env);
+ attrs->bindVars(es, env);
StaticEnv newEnv(true, &env);
- body->bindVars(pt, newEnv);
+ body->bindVars(es, newEnv);
}
-void ExprIf::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprIf::bindVars(const EvalState & es, const StaticEnv & env)
{
- cond->bindVars(pt, env);
- then->bindVars(pt, env);
- else_->bindVars(pt, env);
+ cond->bindVars(es, env);
+ then->bindVars(es, env);
+ else_->bindVars(es, env);
}
-void ExprAssert::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprAssert::bindVars(const EvalState & es, const StaticEnv & env)
{
- cond->bindVars(pt, env);
- body->bindVars(pt, env);
+ cond->bindVars(es, env);
+ body->bindVars(es, env);
}
-void ExprOpNot::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprOpNot::bindVars(const EvalState & es, const StaticEnv & env)
{
- e->bindVars(pt, env);
+ e->bindVars(es, env);
}
-void ExprConcatStrings::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprConcatStrings::bindVars(const EvalState & es, const StaticEnv & env)
{
- for (auto & i : *es)
- i.second->bindVars(pt, env);
+ for (auto & i : *this->es)
+ i.second->bindVars(es, env);
}
-void ExprPos::bindVars(const PosTable & pt, const StaticEnv & env)
+void ExprPos::bindVars(const EvalState & es, const StaticEnv & env)
{
}
/* Storing function names. */
-void Expr::setName(Symbol & name)
+void Expr::setName(SymbolIdx name)
{
}
-void ExprLambda::setName(Symbol & name)
+void ExprLambda::setName(SymbolIdx name)
{
this->name = name;
body->setName(name);
}
-std::string ExprLambda::showNamePos(const PosTable & pt) const
+std::string ExprLambda::showNamePos(const EvalState & state) const
{
- return fmt("%1% at %2%", name.set() ? "'" + (std::string) name + "'" : "anonymous function", pt[pos]);
+ std::string id(name
+ ? concatStrings("'", state.symbols[name], "'")
+ : "anonymous function");
+ return fmt("%1% at %2%", id, state.positions[pos]);
}
@@ -478,8 +526,7 @@ std::string ExprLambda::showNamePos(const PosTable & pt) const
size_t SymbolTable::totalSize() const
{
size_t n = 0;
- for (auto & i : store)
- n += i.size();
+ dump([&] (const Symbol & s) { n += std::string_view(s).size(); });
return n;
}
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 2e12f0b4f..1a387d4fd 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -125,15 +125,15 @@ struct StaticEnv;
/* An attribute path is a sequence of attribute names. */
struct AttrName
{
- Symbol symbol;
+ SymbolIdx symbol;
Expr * expr;
- AttrName(const Symbol & s) : symbol(s) {};
+ AttrName(const SymbolIdx & s) : symbol(s) {};
AttrName(Expr * e) : expr(e) {};
};
typedef std::vector<AttrName> AttrPath;
-std::string showAttrPath(const AttrPath & attrPath);
+std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath);
/* Abstract syntax of Nix expressions. */
@@ -141,19 +141,17 @@ std::string showAttrPath(const AttrPath & attrPath);
struct Expr
{
virtual ~Expr() { };
- virtual void show(std::ostream & str) const;
- virtual void bindVars(const PosTable & pt, const StaticEnv & env);
+ virtual void show(const SymbolTable & symbols, std::ostream & str) const;
+ virtual void bindVars(const EvalState & es, const StaticEnv & env);
virtual void eval(EvalState & state, Env & env, Value & v);
virtual Value * maybeThunk(EvalState & state, Env & env);
- virtual void setName(Symbol & name);
+ virtual void setName(SymbolIdx name);
};
-std::ostream & operator << (std::ostream & str, const Expr & e);
-
#define COMMON_METHODS \
- void show(std::ostream & str) const; \
+ void show(const SymbolTable & symbols, std::ostream & str) const; \
void eval(EvalState & state, Env & env, Value & v); \
- void bindVars(const PosTable & pt, const StaticEnv & env);
+ void bindVars(const EvalState & es, const StaticEnv & env);
struct ExprInt : Expr
{
@@ -197,7 +195,7 @@ typedef uint32_t Displacement;
struct ExprVar : Expr
{
PosIdx pos;
- Symbol name;
+ SymbolIdx name;
/* Whether the variable comes from an environment (e.g. a rec, let
or function argument) or from a "with". */
@@ -212,8 +210,8 @@ struct ExprVar : Expr
Level level;
Displacement displ;
- ExprVar(const Symbol & name) : name(name) { };
- ExprVar(const PosIdx & pos, const Symbol & name) : pos(pos), name(name) { };
+ ExprVar(const SymbolIdx & name) : name(name) { };
+ ExprVar(const PosIdx & pos, const SymbolIdx & name) : pos(pos), name(name) { };
COMMON_METHODS
Value * maybeThunk(EvalState & state, Env & env);
};
@@ -224,7 +222,7 @@ struct ExprSelect : Expr
Expr * e, * def;
AttrPath attrPath;
ExprSelect(const PosIdx & pos, Expr * e, const AttrPath & attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(attrPath) { };
- ExprSelect(const PosIdx & pos, Expr * e, const Symbol & name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); };
+ ExprSelect(const PosIdx & pos, Expr * e, const SymbolIdx & name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); };
COMMON_METHODS
};
@@ -249,7 +247,7 @@ struct ExprAttrs : Expr
: inherited(inherited), e(e), pos(pos) { };
AttrDef() { };
};
- typedef std::map<Symbol, AttrDef> AttrDefs;
+ typedef std::map<SymbolIdx, AttrDef> AttrDefs;
AttrDefs attrs;
struct DynamicAttrDef {
Expr * nameExpr, * valueExpr;
@@ -274,9 +272,8 @@ struct ExprList : Expr
struct Formal
{
PosIdx pos;
- Symbol name;
+ SymbolIdx name;
Expr * def;
- Formal(const PosIdx & pos, const Symbol & name, Expr * def) : pos(pos), name(name), def(def) { };
};
struct Formals
@@ -285,18 +282,19 @@ struct Formals
Formals_ formals;
bool ellipsis;
- bool has(Symbol arg) const {
+ bool has(SymbolIdx arg) const {
auto it = std::lower_bound(formals.begin(), formals.end(), arg,
- [] (const Formal & f, const Symbol & sym) { return f.name < sym; });
+ [] (const Formal & f, const SymbolIdx & sym) { return f.name < sym; });
return it != formals.end() && it->name == arg;
}
- std::vector<Formal> lexicographicOrder() const
+ std::vector<Formal> lexicographicOrder(const SymbolTable & symbols) const
{
std::vector<Formal> result(formals.begin(), formals.end());
std::sort(result.begin(), result.end(),
- [] (const Formal & a, const Formal & b) {
- return std::string_view(a.name) < std::string_view(b.name);
+ [&] (const Formal & a, const Formal & b) {
+ std::string_view sa = symbols[a.name], sb = symbols[b.name];
+ return sa < sb;
});
return result;
}
@@ -305,16 +303,20 @@ struct Formals
struct ExprLambda : Expr
{
PosIdx pos;
- Symbol name;
- Symbol arg;
+ SymbolIdx name;
+ SymbolIdx arg;
Formals * formals;
Expr * body;
- ExprLambda(const PosIdx & pos, const Symbol & arg, Formals * formals, Expr * body)
+ ExprLambda(PosIdx pos, SymbolIdx arg, Formals * formals, Expr * body)
: pos(pos), arg(arg), formals(formals), body(body)
{
};
- void setName(Symbol & name);
- std::string showNamePos(const PosTable & pt) const;
+ ExprLambda(PosIdx pos, Formals * formals, Expr * body)
+ : pos(pos), formals(formals), body(body)
+ {
+ }
+ void setName(SymbolIdx name);
+ std::string showNamePos(const EvalState & state) const;
inline bool hasFormals() const { return formals != nullptr; }
COMMON_METHODS
};
@@ -377,13 +379,13 @@ struct ExprOpNot : Expr
Expr * e1, * e2; \
name(Expr * e1, Expr * e2) : e1(e1), e2(e2) { }; \
name(const PosIdx & pos, Expr * e1, Expr * e2) : pos(pos), e1(e1), e2(e2) { }; \
- void show(std::ostream & str) const \
+ void show(const SymbolTable & symbols, std::ostream & str) const \
{ \
- str << "(" << *e1 << " " s " " << *e2 << ")"; \
+ str << "("; e1->show(symbols, str); str << " " s " "; e2->show(symbols, str); str << ")"; \
} \
- void bindVars(const PosTable & pt, const StaticEnv & env) \
+ void bindVars(const EvalState & es, const StaticEnv & env) \
{ \
- e1->bindVars(pt, env); e2->bindVars(pt, env); \
+ e1->bindVars(es, env); e2->bindVars(es, env); \
} \
void eval(EvalState & state, Env & env, Value & v); \
};
@@ -423,7 +425,7 @@ struct StaticEnv
const StaticEnv * up;
// Note: these must be in sorted order.
- typedef std::vector<std::pair<Symbol, Displacement>> Vars;
+ typedef std::vector<std::pair<SymbolIdx, Displacement>> Vars;
Vars vars;
StaticEnv(bool isWith, const StaticEnv * up, size_t expectedSize = 0) : isWith(isWith), up(up) {
@@ -447,7 +449,7 @@ struct StaticEnv
vars.erase(it, end);
}
- Vars::const_iterator find(const Symbol & name) const
+ Vars::const_iterator find(const SymbolIdx & name) const
{
Vars::value_type key(name, 0);
auto i = std::lower_bound(vars.begin(), vars.end(), key);
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 1f950a057..b73fd1786 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -77,26 +77,26 @@ using namespace nix;
namespace nix {
-static void dupAttr(const AttrPath & attrPath, const Pos & pos, const Pos & prevPos)
+static void dupAttr(const EvalState & state, const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos)
{
throw ParseError({
.msg = hintfmt("attribute '%1%' already defined at %2%",
- showAttrPath(attrPath), prevPos),
- .errPos = pos
+ showAttrPath(state.symbols, attrPath), state.positions[prevPos]),
+ .errPos = state.positions[pos]
});
}
-static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
+static void dupAttr(const EvalState & state, SymbolIdx attr, const PosIdx pos, const PosIdx prevPos)
{
throw ParseError({
- .msg = hintfmt("attribute '%1%' already defined at %2%", attr, prevPos),
- .errPos = pos
+ .msg = hintfmt("attribute '%1%' already defined at %2%", state.symbols[attr], state.positions[prevPos]),
+ .errPos = state.positions[pos]
});
}
static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
- Expr * e, const PosIdx pos, const nix::PosTable & pt)
+ Expr * e, const PosIdx pos, const nix::EvalState & state)
{
AttrPath::iterator i;
// All attrpaths have at least one attr
@@ -104,15 +104,15 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
// Checking attrPath validity.
// ===========================
for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
- if (i->symbol.set()) {
+ if (i->symbol) {
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
if (j != attrs->attrs.end()) {
if (!j->second.inherited) {
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
- if (!attrs2) dupAttr(attrPath, pt[pos], pt[j->second.pos]);
+ if (!attrs2) dupAttr(state, attrPath, pos, j->second.pos);
attrs = attrs2;
} else
- dupAttr(attrPath, pt[pos], pt[j->second.pos]);
+ dupAttr(state, attrPath, pos, j->second.pos);
} else {
ExprAttrs * nested = new ExprAttrs;
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
@@ -126,7 +126,7 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
}
// Expr insertion.
// ==========================
- if (i->symbol.set()) {
+ if (i->symbol) {
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
if (j != attrs->attrs.end()) {
// This attr path is already defined. However, if both
@@ -139,11 +139,11 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
for (auto & ad : ae->attrs) {
auto j2 = jAttrs->attrs.find(ad.first);
if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
- dupAttr(ad.first, pt[j2->second.pos], pt[ad.second.pos]);
+ dupAttr(state, ad.first, j2->second.pos, ad.second.pos);
jAttrs->attrs.emplace(ad.first, ad.second);
}
} else {
- dupAttr(attrPath, pt[pos], pt[j->second.pos]);
+ dupAttr(state, attrPath, pos, j->second.pos);
}
} else {
// This attr path is not defined. Let's create it.
@@ -157,14 +157,14 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
static Formals * toFormals(ParseData & data, ParserFormals * formals,
- PosIdx pos = noPos, Symbol arg = {})
+ PosIdx pos = noPos, SymbolIdx arg = {})
{
std::sort(formals->formals.begin(), formals->formals.end(),
[] (const auto & a, const auto & b) {
return std::tie(a.name, a.pos) < std::tie(b.name, b.pos);
});
- std::optional<std::pair<Symbol, PosIdx>> duplicate;
+ std::optional<std::pair<SymbolIdx, PosIdx>> duplicate;
for (size_t i = 0; i + 1 < formals->formals.size(); i++) {
if (formals->formals[i].name != formals->formals[i + 1].name)
continue;
@@ -173,7 +173,7 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
}
if (duplicate)
throw ParseError({
- .msg = hintfmt("duplicate formal function argument '%1%'", duplicate->first),
+ .msg = hintfmt("duplicate formal function argument '%1%'", data.symbols[duplicate->first]),
.errPos = data.state.positions[duplicate->second]
});
@@ -181,9 +181,9 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
result.ellipsis = formals->ellipsis;
result.formals = std::move(formals->formals);
- if (arg.set() && result.has(arg))
+ if (arg && result.has(arg))
throw ParseError({
- .msg = hintfmt("duplicate formal function argument '%1%'", arg),
+ .msg = hintfmt("duplicate formal function argument '%1%'", data.symbols[arg]),
.errPos = data.state.positions[pos]
});
@@ -369,15 +369,15 @@ expr_function
: ID ':' expr_function
{ $$ = new ExprLambda(CUR_POS, data->symbols.create($1), 0, $3); }
| '{' formals '}' ':' expr_function
- { $$ = new ExprLambda(CUR_POS, {}, toFormals(*data, $2), $5); }
+ { $$ = new ExprLambda(CUR_POS, toFormals(*data, $2), $5); }
| '{' formals '}' '@' ID ':' expr_function
{
- Symbol arg = data->symbols.create($5);
+ auto arg = data->symbols.create($5);
$$ = new ExprLambda(CUR_POS, arg, toFormals(*data, $2, CUR_POS, arg), $7);
}
| ID '@' '{' formals '}' ':' expr_function
{
- Symbol arg = data->symbols.create($1);
+ auto arg = data->symbols.create($1);
$$ = new ExprLambda(CUR_POS, arg, toFormals(*data, $4, CUR_POS, arg), $7);
}
| ASSERT expr ';' expr_function
@@ -532,13 +532,12 @@ ind_string_parts
;
binds
- : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data), data->state.positions); }
+ : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data), data->state); }
| binds INHERIT attrs ';'
{ $$ = $1;
for (auto & i : *$3) {
if ($$->attrs.find(i.symbol) != $$->attrs.end())
- dupAttr(i.symbol, data->state.positions[makeCurPos(@3, data)],
- data->state.positions[$$->attrs[i.symbol].pos]);
+ dupAttr(data->state, i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos);
auto pos = makeCurPos(@3, data);
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true));
}
@@ -548,8 +547,7 @@ binds
/* !!! Should ensure sharing of the expression in $4. */
for (auto & i : *$6) {
if ($$->attrs.find(i.symbol) != $$->attrs.end())
- dupAttr(i.symbol, data->state.positions[makeCurPos(@6, data)],
- data->state.positions[$$->attrs[i.symbol].pos]);
+ dupAttr(data->state, i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos);
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)));
}
}
@@ -623,8 +621,8 @@ formals
;
formal
- : ID { $$ = new Formal(CUR_POS, data->symbols.create($1), 0); }
- | ID '?' expr { $$ = new Formal(CUR_POS, data->symbols.create($1), $3); }
+ : ID { $$ = new Formal{CUR_POS, data->symbols.create($1), 0}; }
+ | ID '?' expr { $$ = new Formal{CUR_POS, data->symbols.create($1), $3}; }
;
%%
@@ -670,7 +668,7 @@ Expr * EvalState::parse(char * text, size_t length, FileOrigin origin,
if (res) throw ParseError(data.error.value());
- data.result->bindVars(positions, staticEnv);
+ data.result->bindVars(*this, staticEnv);
return data.result;
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 81fb5acfb..5892fe3b1 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -403,7 +403,7 @@ static void prim_typeOf(EvalState & state, const PosIdx pos, Value * * args, Val
case nFloat: t = "float"; break;
case nThunk: abort();
}
- v.mkString(state.symbols.create(t));
+ v.mkString(t);
}
static RegisterPrimOp primop_typeOf({
@@ -584,7 +584,7 @@ typedef std::list<Value *> ValueList;
static Bindings::iterator getAttr(
EvalState & state,
std::string_view funcName,
- Symbol attrSym,
+ SymbolIdx attrSym,
Bindings * attrSet,
const PosIdx pos)
{
@@ -592,7 +592,7 @@ static Bindings::iterator getAttr(
if (value == attrSet->end()) {
hintformat errorMsg = hintfmt(
"attribute '%s' missing for call to '%s'",
- attrSym,
+ state.symbols[attrSym],
funcName
);
@@ -919,7 +919,7 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu
if (args[0]->type() == nString)
printError("trace: %1%", args[0]->string.s);
else
- printError("trace: %1%", *args[0]);
+ printError("trace: %1%", printValue(state, *args[0]));
state.forceValue(*args[1], pos);
v = *args[1];
}
@@ -998,9 +998,9 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
StringSet outputs;
outputs.insert("out");
- for (auto & i : args[0]->attrs->lexicographicOrder()) {
+ for (auto & i : args[0]->attrs->lexicographicOrder(state.symbols)) {
if (i->name == state.sIgnoreNulls) continue;
- const std::string & key = i->name;
+ const std::string & key = state.symbols[i->name];
vomit("processing attribute '%1%'", key);
auto handleHashMode = [&](const std::string_view s) {
@@ -2046,7 +2046,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
PathSet context;
for (auto & attr : *args[0]->attrs) {
- auto & n(attr.name);
+ auto & n(state.symbols[attr.name]);
if (n == "path")
path = state.coerceToPath(attr.pos, *attr.value, context);
else if (attr.name == state.sName)
@@ -2060,7 +2060,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos), htSHA256);
else
throw EvalError({
- .msg = hintfmt("unsupported argument '%1%' to 'addPath'", attr.name),
+ .msg = hintfmt("unsupported argument '%1%' to 'addPath'", state.symbols[attr.name]),
.errPos = state.positions[attr.pos]
});
}
@@ -2126,7 +2126,7 @@ static void prim_attrNames(EvalState & state, const PosIdx pos, Value * * args,
size_t n = 0;
for (auto & i : *args[0]->attrs)
- (v.listElems()[n++] = state.allocValue())->mkString(i.name);
+ (v.listElems()[n++] = state.allocValue())->mkString(state.symbols[i.name]);
std::sort(v.listElems(), v.listElems() + n,
[](Value * v1, Value * v2) { return strcmp(v1->string.s, v2->string.s) < 0; });
@@ -2156,8 +2156,9 @@ static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args,
v.listElems()[n++] = (Value *) &i;
std::sort(v.listElems(), v.listElems() + n,
- [](Value * v1, Value * v2) {
- std::string_view s1 = ((Attr *) v1)->name, s2 = ((Attr *) v2)->name;
+ [&](Value * v1, Value * v2) {
+ std::string_view s1 = state.symbols[((Attr *) v1)->name],
+ s2 = state.symbols[((Attr *) v2)->name];
return s1 < s2;
});
@@ -2312,7 +2313,7 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args
auto attrs = state.buildBindings(args[0]->listSize());
- std::set<Symbol> seen;
+ std::set<SymbolIdx> seen;
for (auto v2 : args[0]->listItems()) {
state.forceAttrs(*v2, pos);
@@ -2327,7 +2328,7 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args
auto name = state.forceStringNoCtx(*j->value, j->pos);
- Symbol sym = state.symbols.create(name);
+ auto sym = state.symbols.create(name);
if (seen.insert(sym).second) {
Bindings::iterator j2 = getAttr(
state,
@@ -2396,7 +2397,7 @@ static RegisterPrimOp primop_intersectAttrs({
static void prim_catAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
- Symbol attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos));
+ auto attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos));
state.forceList(*args[1], pos);
Value * res[args[1]->listSize()];
@@ -2483,7 +2484,7 @@ static void prim_mapAttrs(EvalState & state, const PosIdx pos, Value * * args, V
for (auto & i : *args[1]->attrs) {
Value * vName = state.allocValue();
Value * vFun2 = state.allocValue();
- vName->mkString(i.name);
+ vName->mkString(state.symbols[i.name]);
vFun2->mkApp(args[0], vName);
attrs.alloc(i.name).mkApp(vFun2, i.value);
}
@@ -2515,7 +2516,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
// attribute with the merge function application. this way we need not
// use (slightly slower) temporary storage the GC does not know about.
- std::map<Symbol, std::pair<size_t, Value * *>> attrsSeen;
+ std::map<SymbolIdx, std::pair<size_t, Value * *>> attrsSeen;
state.forceFunction(*args[0], pos);
state.forceList(*args[1], pos);
@@ -2550,7 +2551,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
for (auto & attr : *v.attrs) {
auto name = state.allocValue();
- name->mkString(attr.name);
+ name->mkString(state.symbols[attr.name]);
auto call1 = state.allocValue();
call1->mkApp(args[0], name);
auto call2 = state.allocValue();
@@ -3058,7 +3059,7 @@ static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Va
Value res;
state.callFunction(*args[0], *vElem, res, pos);
auto name = state.forceStringNoCtx(res, pos);
- Symbol sym = state.symbols.create(name);
+ auto sym = state.symbols.create(name);
auto vector = attrs.try_emplace(sym, ValueVector()).first;
vector->second.push_back(vElem);
}
@@ -3932,7 +3933,7 @@ void EvalState::createBaseEnv()
// the parser needs two NUL bytes as terminators; one of them
// is implied by being a C string.
"\0";
- eval(parse(code, sizeof(code), foFile, sDerivationNix, "/", staticBaseEnv), *vDerivation);
+ eval(parse(code, sizeof(code), foFile, derivationNixPath, "/", staticBaseEnv), *vDerivation);
}
diff --git a/src/libexpr/primops/context.cc b/src/libexpr/primops/context.cc
index 5521586ee..979136984 100644
--- a/src/libexpr/primops/context.cc
+++ b/src/libexpr/primops/context.cc
@@ -144,45 +144,46 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
auto sPath = state.symbols.create("path");
auto sAllOutputs = state.symbols.create("allOutputs");
for (auto & i : *args[1]->attrs) {
- if (!state.store->isStorePath(i.name))
+ const auto & name = state.symbols[i.name];
+ if (!state.store->isStorePath(name))
throw EvalError({
- .msg = hintfmt("Context key '%s' is not a store path", i.name),
+ .msg = hintfmt("Context key '%s' is not a store path", name),
.errPos = state.positions[i.pos]
});
if (!settings.readOnlyMode)
- state.store->ensurePath(state.store->parseStorePath(i.name));
+ state.store->ensurePath(state.store->parseStorePath(name));
state.forceAttrs(*i.value, i.pos);
auto iter = i.value->attrs->find(sPath);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, iter->pos))
- context.insert(i.name);
+ context.emplace(name);
}
iter = i.value->attrs->find(sAllOutputs);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, iter->pos)) {
- if (!isDerivation(i.name)) {
+ if (!isDerivation(name)) {
throw EvalError({
- .msg = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", i.name),
+ .msg = hintfmt("Tried to add all-outputs context of %s, which is not a derivation, to a string", name),
.errPos = state.positions[i.pos]
});
}
- context.insert("=" + std::string(i.name));
+ context.insert(concatStrings("=", name));
}
}
iter = i.value->attrs->find(state.sOutputs);
if (iter != i.value->attrs->end()) {
state.forceList(*iter->value, iter->pos);
- if (iter->value->listSize() && !isDerivation(i.name)) {
+ if (iter->value->listSize() && !isDerivation(name)) {
throw EvalError({
- .msg = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", i.name),
+ .msg = hintfmt("Tried to add derivation output context of %s, which is not a derivation, to a string", name),
.errPos = state.positions[i.pos]
});
}
for (auto elem : iter->value->listItems()) {
- auto name = state.forceStringNoCtx(*elem, iter->pos);
- context.insert(concatStrings("!", name, "!", i.name));
+ auto outputName = state.forceStringNoCtx(*elem, iter->pos);
+ context.insert(concatStrings("!", outputName, "!", name));
}
}
}
diff --git a/src/libexpr/primops/fetchClosure.cc b/src/libexpr/primops/fetchClosure.cc
index 90e9e6230..662c9652e 100644
--- a/src/libexpr/primops/fetchClosure.cc
+++ b/src/libexpr/primops/fetchClosure.cc
@@ -15,12 +15,14 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
std::optional<StorePath> toPath;
for (auto & attr : *args[0]->attrs) {
- if (attr.name == "fromPath") {
+ const auto & attrName = state.symbols[attr.name];
+
+ if (attrName == "fromPath") {
PathSet context;
fromPath = state.coerceToStorePath(attr.pos, *attr.value, context);
}
- else if (attr.name == "toPath") {
+ else if (attrName == "toPath") {
state.forceValue(*attr.value, attr.pos);
toCA = true;
if (attr.value->type() != nString || attr.value->string.s != std::string("")) {
@@ -29,12 +31,12 @@ static void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * arg
}
}
- else if (attr.name == "fromStore")
+ else if (attrName == "fromStore")
fromStoreUrl = state.forceStringNoCtx(*attr.value, attr.pos);
else
throw Error({
- .msg = hintfmt("attribute '%s' isn't supported in call to 'fetchClosure'", attr.name),
+ .msg = hintfmt("attribute '%s' isn't supported in call to 'fetchClosure'", attrName),
.errPos = state.positions[pos]
});
}
diff --git a/src/libexpr/primops/fetchMercurial.cc b/src/libexpr/primops/fetchMercurial.cc
index 252492446..249c0934e 100644
--- a/src/libexpr/primops/fetchMercurial.cc
+++ b/src/libexpr/primops/fetchMercurial.cc
@@ -22,7 +22,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
state.forceAttrs(*args[0], pos);
for (auto & attr : *args[0]->attrs) {
- std::string_view n(attr.name);
+ std::string_view n(state.symbols[attr.name]);
if (n == "url")
url = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
else if (n == "rev") {
@@ -38,7 +38,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
name = state.forceStringNoCtx(*attr.value, attr.pos);
else
throw EvalError({
- .msg = hintfmt("unsupported argument '%s' to 'fetchMercurial'", attr.name),
+ .msg = hintfmt("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]),
.errPos = state.positions[attr.pos]
});
}
diff --git a/src/libexpr/primops/fetchTree.cc b/src/libexpr/primops/fetchTree.cc
index cdcae97b6..d7c3c9918 100644
--- a/src/libexpr/primops/fetchTree.cc
+++ b/src/libexpr/primops/fetchTree.cc
@@ -126,20 +126,20 @@ static void fetchTree(
state.forceValue(*attr.value, attr.pos);
if (attr.value->type() == nPath || attr.value->type() == nString) {
auto s = state.coerceToString(attr.pos, *attr.value, context, false, false).toOwned();
- attrs.emplace(attr.name,
- attr.name == "url"
+ attrs.emplace(state.symbols[attr.name],
+ state.symbols[attr.name] == "url"
? type == "git"
? fixURIForGit(s, state)
: fixURI(s, state)
: s);
}
else if (attr.value->type() == nBool)
- attrs.emplace(attr.name, Explicit<bool>{attr.value->boolean});
+ attrs.emplace(state.symbols[attr.name], Explicit<bool>{attr.value->boolean});
else if (attr.value->type() == nInt)
- attrs.emplace(attr.name, uint64_t(attr.value->integer));
+ attrs.emplace(state.symbols[attr.name], uint64_t(attr.value->integer));
else
throw TypeError("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
- attr.name, showType(*attr.value));
+ state.symbols[attr.name], showType(*attr.value));
}
if (!params.allowNameArgument)
@@ -198,7 +198,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
state.forceAttrs(*args[0], pos);
for (auto & attr : *args[0]->attrs) {
- std::string n(attr.name);
+ std::string_view n(state.symbols[attr.name]);
if (n == "url")
url = state.forceStringNoCtx(*attr.value, attr.pos);
else if (n == "sha256")
@@ -207,7 +207,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
name = state.forceStringNoCtx(*attr.value, attr.pos);
else
throw EvalError({
- .msg = hintfmt("unsupported argument '%s' to '%s'", attr.name, who),
+ .msg = hintfmt("unsupported argument '%s' to '%s'", n, who),
.errPos = state.positions[attr.pos]
});
}
diff --git a/src/libexpr/symbol-table.hh b/src/libexpr/symbol-table.hh
index 297605295..d0cd841a0 100644
--- a/src/libexpr/symbol-table.hh
+++ b/src/libexpr/symbol-table.hh
@@ -16,85 +16,90 @@ namespace nix {
class Symbol
{
-private:
- const std::string * s; // pointer into SymbolTable
- Symbol(const std::string * s) : s(s) { };
friend class SymbolTable;
+private:
+ std::string s;
public:
- Symbol() : s(0) { };
-
- bool operator == (const Symbol & s2) const
- {
- return s == s2.s;
- }
+ Symbol(std::string_view s) : s(s) { }
// FIXME: remove
bool operator == (std::string_view s2) const
{
- return s->compare(s2) == 0;
- }
-
- bool operator != (const Symbol & s2) const
- {
- return s != s2.s;
- }
-
- bool operator < (const Symbol & s2) const
- {
- return s < s2.s;
+ return s == s2;
}
operator const std::string & () const
{
- return *s;
+ return s;
}
operator const std::string_view () const
{
- return *s;
- }
-
- bool set() const
- {
return s;
}
friend std::ostream & operator << (std::ostream & str, const Symbol & sym);
};
+class SymbolIdx
+{
+ friend class SymbolTable;
+
+private:
+ uint32_t id;
+
+ explicit SymbolIdx(uint32_t id): id(id) {}
+
+public:
+ SymbolIdx() : id(0) {}
+
+ explicit operator bool() const { return id > 0; }
+
+ bool operator<(const SymbolIdx other) const { return id < other.id; }
+ bool operator==(const SymbolIdx other) const { return id == other.id; }
+ bool operator!=(const SymbolIdx other) const { return id != other.id; }
+};
+
class SymbolTable
{
private:
- std::unordered_map<std::string_view, Symbol> symbols;
- std::list<std::string> store;
+ std::unordered_map<std::string_view, std::pair<const Symbol *, uint32_t>> symbols;
+ ChunkedVector<Symbol, 8192> store{16};
public:
- Symbol create(std::string_view s)
+ SymbolIdx create(std::string_view s)
{
// 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;
+ if (it != symbols.end()) return SymbolIdx(it->second.second + 1);
- auto & rawSym = store.emplace_back(s);
- return symbols.emplace(rawSym, Symbol(&rawSym)).first->second;
+ const auto & [rawSym, idx] = store.add(s);
+ symbols.emplace(rawSym, std::make_pair(&rawSym, idx));
+ return SymbolIdx(idx + 1);
+ }
+
+ const Symbol & operator[](SymbolIdx s) const
+ {
+ if (s.id == 0 || s.id > store.size())
+ abort();
+ return store[s.id - 1];
}
size_t size() const
{
- return symbols.size();
+ return store.size();
}
size_t totalSize() const;
template<typename T>
- void dump(T callback)
+ void dump(T callback) const
{
- for (auto & s : store)
- callback(s);
+ store.forEach(callback);
}
};
diff --git a/src/libexpr/value-to-json.cc b/src/libexpr/value-to-json.cc
index 307934292..68235ad11 100644
--- a/src/libexpr/value-to-json.cc
+++ b/src/libexpr/value-to-json.cc
@@ -50,7 +50,7 @@ void printValueAsJSON(EvalState & state, bool strict,
auto obj(out.object());
StringSet names;
for (auto & j : *v.attrs)
- names.insert(j.name);
+ names.emplace(state.symbols[j.name]);
for (auto & j : names) {
Attr & a(*v.attrs->find(state.symbols.create(j)));
auto placeholder(obj.placeholder(j));
diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc
index d1e0c4778..7c3bf9492 100644
--- a/src/libexpr/value-to-xml.cc
+++ b/src/libexpr/value-to-xml.cc
@@ -22,7 +22,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
const PosIdx pos);
-static void posToXML(XMLAttrs & xmlAttrs, const Pos & pos)
+static void posToXML(EvalState & state, XMLAttrs & xmlAttrs, const Pos & pos)
{
xmlAttrs["path"] = pos.file;
xmlAttrs["line"] = (format("%1%") % pos.line).str();
@@ -36,14 +36,14 @@ static void showAttrs(EvalState & state, bool strict, bool location,
StringSet names;
for (auto & i : attrs)
- names.insert(i.name);
+ names.emplace(state.symbols[i.name]);
for (auto & i : names) {
Attr & a(*attrs.find(state.symbols.create(i)));
XMLAttrs xmlAttrs;
xmlAttrs["name"] = i;
- if (location && a.pos) posToXML(xmlAttrs, state.positions[a.pos]);
+ if (location && a.pos) posToXML(state, xmlAttrs, state.positions[a.pos]);
XMLOpenElement _(doc, "attr", xmlAttrs);
printValueAsXML(state, strict, location,
@@ -134,18 +134,18 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
break;
}
XMLAttrs xmlAttrs;
- if (location) posToXML(xmlAttrs, state.positions[v.lambda.fun->pos]);
+ if (location) posToXML(state, xmlAttrs, state.positions[v.lambda.fun->pos]);
XMLOpenElement _(doc, "function", xmlAttrs);
if (v.lambda.fun->hasFormals()) {
XMLAttrs attrs;
- if (v.lambda.fun->arg.set()) attrs["name"] = v.lambda.fun->arg;
+ if (v.lambda.fun->arg) attrs["name"] = state.symbols[v.lambda.fun->arg];
if (v.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1";
XMLOpenElement _(doc, "attrspat", attrs);
- for (auto & i : v.lambda.fun->formals->lexicographicOrder())
- doc.writeEmptyElement("attr", singletonAttrs("name", i.name));
+ for (auto & i : v.lambda.fun->formals->lexicographicOrder(state.symbols))
+ doc.writeEmptyElement("attr", singletonAttrs("name", state.symbols[i.name]));
} else
- doc.writeEmptyElement("varpat", singletonAttrs("name", v.lambda.fun->arg));
+ doc.writeEmptyElement("varpat", singletonAttrs("name", state.symbols[v.lambda.fun->arg]));
break;
}
diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh
index dc875615c..c46dd4b73 100644
--- a/src/libexpr/value.hh
+++ b/src/libexpr/value.hh
@@ -55,7 +55,7 @@ struct Env;
struct Expr;
struct ExprLambda;
struct PrimOp;
-class Symbol;
+class SymbolIdx;
class PosIdx;
struct Pos;
class StorePath;
@@ -121,11 +121,11 @@ private:
friend std::string showType(const Value & v);
- void print(std::ostream & str, std::set<const void *> * seen) const;
+ void print(const SymbolTable & symbols, std::ostream & str, std::set<const void *> * seen) const;
public:
- void print(std::ostream & str, bool showRepeated = false) const;
+ void print(const SymbolTable & symbols, std::ostream & str, bool showRepeated = false) const;
// Functions needed to distinguish the type
// These should be removed eventually, by putting the functionality that's
@@ -253,7 +253,7 @@ public:
inline void mkString(const Symbol & s)
{
- mkString(((const std::string &) s).c_str());
+ mkString(std::string_view(s).data());
}
inline void mkPath(const char * s)
@@ -410,12 +410,12 @@ public:
#if HAVE_BOEHMGC
typedef std::vector<Value *, traceable_allocator<Value *> > ValueVector;
-typedef std::map<Symbol, Value *, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, Value *> > > ValueMap;
-typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector> > > ValueVectorMap;
+typedef std::map<SymbolIdx, Value *, std::less<SymbolIdx>, traceable_allocator<std::pair<const SymbolIdx, Value *> > > ValueMap;
+typedef std::map<SymbolIdx, ValueVector, std::less<SymbolIdx>, traceable_allocator<std::pair<const SymbolIdx, ValueVector> > > ValueVectorMap;
#else
typedef std::vector<Value *> ValueVector;
-typedef std::map<Symbol, Value *> ValueMap;
-typedef std::map<Symbol, ValueVector> ValueVectorMap;
+typedef std::map<SymbolIdx, Value *> ValueMap;
+typedef std::map<SymbolIdx, ValueVector> ValueVectorMap;
#endif
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index 22bc2b8dd..bd1dd8bee 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -152,6 +152,14 @@ public:
{
return chunks[idx / ChunkSize][idx % ChunkSize];
}
+
+ template<typename Fn>
+ void forEach(Fn fn) const
+ {
+ for (const auto & c : chunks)
+ for (const auto & e : c)
+ fn(e);
+ }
};
}
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 9a68899cd..96f3c3b26 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -1241,7 +1241,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
Attr & a(*attrs.find(i.name));
if(a.value->type() != nString) continue;
XMLAttrs attrs3;
- attrs3["type"] = i.name;
+ attrs3["type"] = globals.state->symbols[i.name];
attrs3["value"] = a.value->string.s;
xml.writeEmptyElement("string", attrs3);
}
diff --git a/src/nix-env/user-env.cc b/src/nix-env/user-env.cc
index 156181634..4b1202be3 100644
--- a/src/nix-env/user-env.cc
+++ b/src/nix-env/user-env.cc
@@ -106,7 +106,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
the store; we need it for future modifications of the
environment. */
std::ostringstream str;
- manifest.print(str, true);
+ manifest.print(state.symbols, str, true);
auto manifestFile = state.store->addTextToStore("env-manifest.nix",
str.str(), references);
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index 3ec0e6e7c..d3144e131 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -31,7 +31,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
bool evalOnly, OutputKind output, bool location, Expr * e)
{
if (parseOnly) {
- std::cout << format("%1%\n") % *e;
+ e->show(state.symbols, std::cout);
+ std::cout << "\n";
return;
}
@@ -55,7 +56,8 @@ void processExpr(EvalState & state, const Strings & attrPaths,
printValueAsJSON(state, strict, vRes, v.determinePos(noPos), std::cout, context);
else {
if (strict) state.forceValueDeep(vRes);
- std::cout << vRes << std::endl;
+ vRes.print(state.symbols, std::cout);
+ std::cout << std::endl;
}
} else {
DrvInfos drvs;
diff --git a/src/nix/app.cc b/src/nix/app.cc
index df7303e15..95ac1cf5c 100644
--- a/src/nix/app.cc
+++ b/src/nix/app.cc
@@ -85,9 +85,9 @@ UnresolvedApp Installable::toApp(EvalState & state)
else if (type == "derivation") {
auto drvPath = cursor->forceDerivation();
- auto outPath = cursor->getAttr(state.sOutPath)->getString();
- auto outputName = cursor->getAttr(state.sOutputName)->getString();
- auto name = cursor->getAttr(state.sName)->getString();
+ auto outPath = cursor->getAttr("outPath")->getString();
+ auto outputName = cursor->getAttr("outputName")->getString();
+ auto name = cursor->getAttr("name")->getString();
auto aPname = cursor->maybeGetAttr("pname");
auto aMeta = cursor->maybeGetAttr("meta");
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
diff --git a/src/nix/eval.cc b/src/nix/eval.cc
index 81474c2d3..967dc8519 100644
--- a/src/nix/eval.cc
+++ b/src/nix/eval.cc
@@ -88,17 +88,19 @@ struct CmdEval : MixJSON, InstallableCommand
else if (v.type() == nAttrs) {
if (mkdir(path.c_str(), 0777) == -1)
throw SysError("creating directory '%s'", path);
- for (auto & attr : *v.attrs)
+ for (auto & attr : *v.attrs) {
+ std::string_view name = state->symbols[attr.name];
try {
- if (attr.name == "." || attr.name == "..")
- throw Error("invalid file name '%s'", attr.name);
- recurse(*attr.value, attr.pos, path + "/" + std::string(attr.name));
+ if (name == "." || name == "..")
+ throw Error("invalid file name '%s'", name);
+ recurse(*attr.value, attr.pos, concatStrings(path, "/", name));
} catch (Error & e) {
e.addTrace(
state->positions[attr.pos],
- hintfmt("while evaluating the attribute '%s'", attr.name));
+ hintfmt("while evaluating the attribute '%s'", name));
throw;
}
+ }
}
else
throw TypeError("value at '%s' is not a string or an attribute set", state->positions[pos]);
@@ -119,7 +121,7 @@ struct CmdEval : MixJSON, InstallableCommand
else {
state->forceValueDeep(*v);
- logger->cout("%s", *v);
+ logger->cout("%s", printValue(*state, *v));
}
}
};
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index 23e5cd24e..c8d8461e4 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -139,11 +139,11 @@ static void enumerateOutputs(EvalState & state, Value & vFlake,
else. This way we can disable IFD for hydraJobs and then enable
it for other outputs. */
if (auto attr = aOutputs->value->attrs->get(sHydraJobs))
- callback(attr->name, *attr->value, attr->pos);
+ callback(state.symbols[attr->name], *attr->value, attr->pos);
for (auto & attr : *aOutputs->value->attrs) {
if (attr.name != sHydraJobs)
- callback(attr.name, *attr.value, attr.pos);
+ callback(state.symbols[attr.name], *attr.value, attr.pos);
}
}
@@ -254,14 +254,6 @@ struct CmdFlakeInfo : CmdFlakeMetadata
}
};
-static bool argHasName(std::string_view arg, std::string_view expected)
-{
- return
- arg == expected
- || arg == "_"
- || (hasPrefix(arg, "_") && arg.substr(1) == expected);
-}
-
struct CmdFlakeCheck : FlakeCommand
{
bool build = true;
@@ -319,6 +311,14 @@ struct CmdFlakeCheck : FlakeCommand
return state->positions[p];
};
+ auto argHasName = [&] (SymbolIdx arg, std::string_view expected) {
+ std::string_view name = state->symbols[arg];
+ return
+ name == expected
+ || name == "_"
+ || (hasPrefix(name, "_") && name.substr(1) == expected);
+ };
+
auto checkSystemName = [&](const std::string & system, const PosIdx pos) {
// FIXME: what's the format of "system"?
if (system.find('-') == std::string::npos)
@@ -390,7 +390,7 @@ struct CmdFlakeCheck : FlakeCommand
} catch (Error & e) {
e.addTrace(
state->positions[attr.pos],
- hintfmt("while evaluating the option '%s'", attr.name));
+ hintfmt("while evaluating the option '%s'", state->symbols[attr.name]));
throw;
}
} else
@@ -414,7 +414,7 @@ struct CmdFlakeCheck : FlakeCommand
for (auto & attr : *v.attrs) {
state->forceAttrs(*attr.value, attr.pos);
- auto attrPath2 = attrPath + "." + (std::string) attr.name;
+ auto attrPath2 = concatStrings(attrPath, ".", state->symbols[attr.name]);
if (state->isDerivation(*attr.value)) {
Activity act(*logger, lvlChatty, actUnknown,
fmt("checking Hydra job '%s'", attrPath2));
@@ -468,7 +468,7 @@ struct CmdFlakeCheck : FlakeCommand
throw Error("template '%s' lacks attribute 'description'", attrPath);
for (auto & attr : *v.attrs) {
- std::string name(attr.name);
+ std::string_view name(state->symbols[attr.name]);
if (name != "path" && name != "description" && name != "welcomeText")
throw Error("template '%s' has unsupported attribute '%s'", attrPath, name);
}
@@ -522,13 +522,14 @@ struct CmdFlakeCheck : FlakeCommand
if (name == "checks") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
state->forceAttrs(*attr.value, attr.pos);
for (auto & attr2 : *attr.value->attrs) {
auto drvPath = checkDerivation(
- fmt("%s.%s.%s", name, attr.name, attr2.name),
+ fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
*attr2.value, attr2.pos);
- if (drvPath && (std::string) attr.name == settings.thisSystem.get())
+ if (drvPath && attr_name == settings.thisSystem.get())
drvPaths.push_back(DerivedPath::Built{*drvPath});
}
}
@@ -537,9 +538,10 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "formatter") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
checkApp(
- fmt("%s.%s", name, attr.name),
+ fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
}
}
@@ -547,11 +549,12 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "packages" || name == "devShells") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
state->forceAttrs(*attr.value, attr.pos);
for (auto & attr2 : *attr.value->attrs)
checkDerivation(
- fmt("%s.%s.%s", name, attr.name, attr2.name),
+ fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
*attr2.value, attr2.pos);
}
}
@@ -559,11 +562,12 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "apps") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
state->forceAttrs(*attr.value, attr.pos);
for (auto & attr2 : *attr.value->attrs)
checkApp(
- fmt("%s.%s.%s", name, attr.name, attr2.name),
+ fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
*attr2.value, attr2.pos);
}
}
@@ -571,9 +575,10 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "defaultPackage" || name == "devShell") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
checkDerivation(
- fmt("%s.%s", name, attr.name),
+ fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
}
}
@@ -581,9 +586,10 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "defaultApp") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
checkApp(
- fmt("%s.%s", name, attr.name),
+ fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
}
}
@@ -591,7 +597,7 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "legacyPackages") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ checkSystemName(state->symbols[attr.name], attr.pos);
// FIXME: do getDerivations?
}
}
@@ -602,7 +608,7 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "overlays") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs)
- checkOverlay(fmt("%s.%s", name, attr.name),
+ checkOverlay(fmt("%s.%s", name, state->symbols[attr.name]),
*attr.value, attr.pos);
}
@@ -612,14 +618,14 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "nixosModules") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs)
- checkModule(fmt("%s.%s", name, attr.name),
+ checkModule(fmt("%s.%s", name, state->symbols[attr.name]),
*attr.value, attr.pos);
}
else if (name == "nixosConfigurations") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs)
- checkNixOSConfiguration(fmt("%s.%s", name, attr.name),
+ checkNixOSConfiguration(fmt("%s.%s", name, state->symbols[attr.name]),
*attr.value, attr.pos);
}
@@ -632,16 +638,17 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "templates") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs)
- checkTemplate(fmt("%s.%s", name, attr.name),
+ checkTemplate(fmt("%s.%s", name, state->symbols[attr.name]),
*attr.value, attr.pos);
}
else if (name == "defaultBundler") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
checkBundler(
- fmt("%s.%s", name, attr.name),
+ fmt("%s.%s", name, attr_name),
*attr.value, attr.pos);
}
}
@@ -649,11 +656,12 @@ struct CmdFlakeCheck : FlakeCommand
else if (name == "bundlers") {
state->forceAttrs(vOutput, pos);
for (auto & attr : *vOutput.attrs) {
- checkSystemName(attr.name, attr.pos);
+ const auto & attr_name = state->symbols[attr.name];
+ checkSystemName(attr_name, attr.pos);
state->forceAttrs(*attr.value, attr.pos);
for (auto & attr2 : *attr.value->attrs) {
checkBundler(
- fmt("%s.%s.%s", name, attr.name, attr2.name),
+ fmt("%s.%s.%s", name, attr_name, state->symbols[attr2.name]),
*attr2.value, attr2.pos);
}
}
@@ -1000,7 +1008,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
auto showDerivation = [&]()
{
- auto name = visitor.getAttr(state->sName)->getString();
+ auto name = visitor.getAttr("name")->getString();
if (json) {
std::optional<std::string> description;
if (auto aMeta = visitor.maybeGetAttr("meta")) {
diff --git a/src/nix/main.cc b/src/nix/main.cc
index 6198681e7..6d0f6ce6e 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -302,7 +302,7 @@ void mainWrapped(int argc, char * * argv)
b["arity"] = primOp->arity;
b["args"] = primOp->args;
b["doc"] = trim(stripIndentation(primOp->doc));
- res[(std::string) builtin.name] = std::move(b);
+ res[state.symbols[builtin.name]] = std::move(b);
}
std::cout << res.dump() << "\n";
return;
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index fd1b95afa..998ff7328 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -73,7 +73,7 @@ struct NixRepl
void initEnv();
void reloadFiles();
void addAttrsToScope(Value & attrs);
- void addVarToScope(const Symbol & name, Value & v);
+ void addVarToScope(const SymbolIdx name, Value & v);
Expr * parseString(std::string s);
void evalString(std::string s, Value & v);
@@ -347,9 +347,9 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
state->forceAttrs(v, noPos);
for (auto & i : *v.attrs) {
- std::string name = i.name;
+ std::string_view name = state->symbols[i.name];
if (name.substr(0, cur2.size()) != cur2) continue;
- completions.insert(prev + expr + "." + name);
+ completions.insert(concatStrings(prev, expr, ".", name));
}
} catch (ParseError & e) {
@@ -464,8 +464,9 @@ bool NixRepl::processLine(std::string line)
const auto [file, line] = [&] () -> std::pair<std::string, uint32_t> {
if (v.type() == nPath || v.type() == nString) {
PathSet context;
- auto filename = state->coerceToString(noPos, v, context);
- return {state->symbols.create(*filename), 0};
+ auto filename = state->coerceToString(noPos, v, context).toOwned();
+ state->symbols.create(filename);
+ return {filename, 0};
} else if (v.isLambda()) {
auto pos = state->positions[v.lambda.fun->pos];
return {pos.file, pos.line};
@@ -672,7 +673,7 @@ void NixRepl::initEnv()
varNames.clear();
for (auto & i : state->staticBaseEnv.vars)
- varNames.insert(i.first);
+ varNames.emplace(state->symbols[i.first]);
}
@@ -702,7 +703,7 @@ void NixRepl::addAttrsToScope(Value & attrs)
for (auto & i : *attrs.attrs) {
staticEnv.vars.emplace_back(i.name, displ);
env->values[displ++] = i.value;
- varNames.insert((std::string) i.name);
+ varNames.emplace(state->symbols[i.name]);
}
staticEnv.sort();
staticEnv.deduplicate();
@@ -710,7 +711,7 @@ void NixRepl::addAttrsToScope(Value & attrs)
}
-void NixRepl::addVarToScope(const Symbol & name, Value & v)
+void NixRepl::addVarToScope(const SymbolIdx name, Value & v)
{
if (displ >= envSize)
throw Error("environment full; cannot add more variables");
@@ -719,7 +720,7 @@ void NixRepl::addVarToScope(const Symbol & name, Value & v)
staticEnv.vars.emplace_back(name, displ);
staticEnv.sort();
env->values[displ++] = &v;
- varNames.insert((std::string) name);
+ varNames.emplace(state->symbols[name]);
}
@@ -812,7 +813,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
typedef std::map<std::string, Value *> Sorted;
Sorted sorted;
for (auto & i : *v.attrs)
- sorted[i.name] = i.value;
+ sorted.emplace(state->symbols[i.name], i.value);
for (auto & i : sorted) {
if (isVarName(i.first))
diff --git a/src/nix/search.cc b/src/nix/search.cc
index e284de95c..8b1e9ae6c 100644
--- a/src/nix/search.cc
+++ b/src/nix/search.cc
@@ -154,7 +154,7 @@ struct CmdSearch : InstallableCommand, MixJSON
recurse();
else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) {
- auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations);
+ auto attr = cursor.maybeGetAttr("recurseForDerivations");
if (attr && attr->getBool())
recurse();
}