libexpr: replace Bindings::find by Bindings::get

In preparations for a new representation of bindings that will make it
impossible to write an efficient `Bindings::find`.

Change-Id: I4e5a25b8d37d01b5728f7fe43978ceda2ab1b9b6
Signed-off-by: Raito Bezarius <raito@lix.systems>
Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
This commit is contained in:
Raito Bezarius
2025-09-20 23:46:16 +02:00
co-authored by Sergei Zimmerman
parent 257e910247
commit a20a83b0a7
12 changed files with 206 additions and 123 deletions
+1 -1
View File
@@ -1299,7 +1299,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
XMLOpenElement m(xml, "meta", attrs2);
Bindings & attrs = *v->attrs;
for (auto &i : attrs) {
const Attr & a(*attrs.find(i.name));
const Attr & a(*attrs.get(i.name));
if(a.value->type() != nString) continue;
XMLAttrs attrs3;
attrs3["type"] = globals.state->symbols[i.name];
+2 -2
View File
@@ -114,9 +114,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
debug("evaluating user environment builder");
state.forceValue(topLevel, noPos);
NixStringContext context;
const Attr & aDrvPath(*topLevel.attrs->find(state.ctx.s.drvPath));
const Attr & aDrvPath(*topLevel.attrs->get(state.ctx.s.drvPath));
auto topLevelDrv = state.coerceToStorePath(aDrvPath.pos, *aDrvPath.value, context, "");
const Attr & aOutPath(*topLevel.attrs->find(state.ctx.s.outPath));
const Attr & aOutPath(*topLevel.attrs->get(state.ctx.s.outPath));
auto topLevelOut = state.coerceToStorePath(aOutPath.pos, *aOutPath.value, context, "");
/* Realise the resulting store expression. */
+2 -2
View File
@@ -111,8 +111,8 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
.debugThrow();
}
Bindings::iterator a = v->attrs->find(state.ctx.symbols.create(attr));
if (a == v->attrs->end()) {
auto a = v->attrs->get(state.ctx.symbols.create(attr));
if (!a) {
std::set<std::string> attrNames;
for (auto & attr : *v->attrs)
attrNames.emplace(state.ctx.symbols[attr.name]);
+1 -9
View File
@@ -71,15 +71,7 @@ public:
attrs[size_++] = attr;
}
iterator find(Symbol name)
{
Attr key(name, 0);
iterator i = std::lower_bound(begin(), end(), key);
if (i != end() && i->name == name) return i;
return end();
}
Attr * get(Symbol name)
const Attr * get(Symbol name)
{
Attr key(name, 0);
iterator i = std::lower_bound(begin(), end(), key);
+36 -26
View File
@@ -592,7 +592,7 @@ Value * EvalBuiltins::addPrimOp(PrimOp && primOp)
Value & EvalBuiltins::get(const std::string & name)
{
return *env.values[0]->attrs->find(symbols.create(name))->value;
return *env.values[0]->attrs->get(symbols.create(name))->value;
}
@@ -833,8 +833,8 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
auto * fromWith = var.fromWith;
while (1) {
forceAttrs(*env->values[0], fromWith->pos, "while evaluating the first subexpression of a with expression");
Bindings::iterator j = env->values[0]->attrs->find(var.name);
if (j != env->values[0]->attrs->end()) {
auto j = env->values[0]->attrs->get(var.name);
if (j) {
if (ctx.stats.countCalls) ctx.stats.attrSelects[j->pos]++;
return j->value;
}
@@ -1154,9 +1154,18 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v)
continue;
state.forceStringNoCtx(nameVal, i.pos, "while evaluating the name of a dynamic attribute");
auto nameSym = state.ctx.symbols.create(nameVal.str());
Bindings::iterator j = v.attrs->find(nameSym);
if (j != v.attrs->end())
state.ctx.errors.make<EvalError>("dynamic attribute '%1%' already defined at %2%", state.ctx.symbols[nameSym], state.ctx.positions[j->pos]).atPos(i.pos).withFrame(env, *this).debugThrow();
auto j = v.attrs->get(nameSym);
if (j) {
state.ctx.errors
.make<EvalError>(
"dynamic attribute '%1%' already defined at %2%",
state.ctx.symbols[nameSym],
state.ctx.positions[j->pos]
)
.atPos(i.pos)
.withFrame(env, *this)
.debugThrow();
}
i.valueExpr->setName(nameSym);
/* Keep sorted order so find can catch duplicates */
@@ -1315,8 +1324,8 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
// Now that we know this is actually an attrset, try to find an attr
// with the selected name.
Bindings::iterator attrIt = vCurrent->attrs->find(name);
if (attrIt == vCurrent->attrs->end()) {
auto attrIt = vCurrent->attrs->get(name);
if (!attrIt) {
// If we have an `or` provided default, then we'll use that.
if (def != nullptr) {
@@ -1368,11 +1377,9 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
for (auto & i : attrPath) {
state.forceValue(*vAttrs, getPos());
Bindings::iterator j;
const Attr * j;
auto name = getName(i, state, env);
if (vAttrs->type() != nAttrs ||
(j = vAttrs->attrs->find(name)) == vAttrs->attrs->end())
{
if (vAttrs->type() != nAttrs || (j = vAttrs->attrs->get(name)) == nullptr) {
v.mkBool(false);
return;
} else {
@@ -1740,8 +1747,8 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res, PosI
forceValue(fun, pos);
if (fun.type() == nAttrs) {
auto found = fun.attrs->find(ctx.s.functor);
if (found != fun.attrs->end()) {
auto found = fun.attrs->get(ctx.s.functor);
if (found) {
Value * v = ctx.mem.allocValue();
callFunction(*found->value, fun, *v, pos);
forceValue(*v, pos);
@@ -1770,8 +1777,8 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res, PosI
} else {
// Otherwise, only pass the arguments that the function accepts
for (auto & i : pattern->formals) {
Bindings::iterator j = args.find(i.name);
if (j != args.end()) {
auto j = args.get(i.name);
if (j) {
attrs.insert(*j);
} else if (!i.def) {
ctx.errors.make<MissingArgumentError>(R"(cannot evaluate a function that has an argument without a value ('%1%')
@@ -2184,7 +2191,7 @@ bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx
bool EvalState::isFunctor(Value & fun)
{
return fun.type() == nAttrs && fun.attrs->find(ctx.s.functor) != fun.attrs->end();
return fun.type() == nAttrs && fun.attrs->get(ctx.s.functor);
}
@@ -2259,8 +2266,10 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::s
bool EvalState::isDerivation(Value & v)
{
if (v.type() != nAttrs) return false;
Bindings::iterator i = v.attrs->find(ctx.s.type);
if (i == v.attrs->end()) return false;
auto i = v.attrs->get(ctx.s.type);
if (!i) {
return false;
}
forceValue(*i->value, i->pos);
if (i->value->type() != nString) return false;
return i->value->str() == "derivation";
@@ -2270,8 +2279,8 @@ bool EvalState::isDerivation(Value & v)
std::optional<std::string> EvalState::tryAttrsToString(const PosIdx pos, Value & v,
NixStringContext & context, StringCoercionMode mode, bool copyToStore)
{
auto i = v.attrs->find(ctx.s.toString);
if (i != v.attrs->end()) {
auto i = v.attrs->get(ctx.s.toString);
if (i) {
Value v1;
try {
callFunction(*i->value, v, v1, i->pos);
@@ -2319,8 +2328,8 @@ BackedStringView EvalState::coerceToString(
auto maybeString = tryAttrsToString(pos, v, context, mode, copyToStore);
if (maybeString)
return std::move(*maybeString);
auto i = v.attrs->find(ctx.s.outPath);
if (i == v.attrs->end()) {
auto i = v.attrs->get(ctx.s.outPath);
if (!i) {
ctx.errors.make<TypeError>(
"cannot coerce %1% to a string: %2%",
showType(v),
@@ -2537,10 +2546,11 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
/* If both sets denote a derivation (type = "derivation"),
then compare their outPaths. */
if (isDerivation(v1) && isDerivation(v2)) {
Bindings::iterator i = v1.attrs->find(ctx.s.outPath);
Bindings::iterator j = v2.attrs->find(ctx.s.outPath);
if (i != v1.attrs->end() && j != v2.attrs->end())
auto i = v1.attrs->get(ctx.s.outPath);
auto j = v2.attrs->get(ctx.s.outPath);
if (i && j) {
return eqValues(*i->value, *j->value, pos, errorCtx);
}
}
if (v1.attrs->size() != v2.attrs->size()) return false;
+44 -20
View File
@@ -64,8 +64,10 @@ try {
std::string DrvInfo::queryName(EvalState & state)
{
if (name == "" && attrs) {
auto i = attrs->find(state.ctx.s.name);
if (i == attrs->end()) state.ctx.errors.make<TypeError>("derivation name missing").debugThrow();
auto i = attrs->get(state.ctx.s.name);
if (!i) {
state.ctx.errors.make<TypeError>("derivation name missing").debugThrow();
}
name = state.forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
}
return name;
@@ -75,8 +77,12 @@ std::string DrvInfo::queryName(EvalState & state)
std::string DrvInfo::querySystem(EvalState & state)
{
if (system == "" && attrs) {
auto i = attrs->find(state.ctx.s.system);
system = i == attrs->end() ? "unknown" : state.forceStringNoCtx(*i->value, i->pos, "while evaluating the 'system' attribute of a derivation");
auto i = attrs->get(state.ctx.s.system);
system = !i
? "unknown"
: state.forceStringNoCtx(
*i->value, i->pos, "while evaluating the 'system' attribute of a derivation"
);
}
return system;
}
@@ -85,12 +91,18 @@ std::string DrvInfo::querySystem(EvalState & state)
std::optional<StorePath> DrvInfo::queryDrvPath(EvalState & state)
{
if (!drvPath && attrs) {
Bindings::iterator i = attrs->find(state.ctx.s.drvPath);
auto i = attrs->get(state.ctx.s.drvPath);
NixStringContext context;
if (i == attrs->end())
if (!i) {
drvPath = {std::nullopt};
else
drvPath = {state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation")};
} else {
drvPath = {state.coerceToStorePath(
i->pos,
*i->value,
context,
"while evaluating the 'drvPath' attribute of a derivation"
)};
}
}
return drvPath.value_or(std::nullopt);
}
@@ -107,10 +119,13 @@ StorePath DrvInfo::requireDrvPath(EvalState & state)
StorePath DrvInfo::queryOutPath(EvalState & state)
{
if (!outPath && attrs) {
Bindings::iterator i = attrs->find(state.ctx.s.outPath);
auto i = attrs->get(state.ctx.s.outPath);
NixStringContext context;
if (i != attrs->end())
outPath = state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the output path of a derivation");
if (i) {
outPath = state.coerceToStorePath(
i->pos, *i->value, context, "while evaluating the output path of a derivation"
);
}
}
if (!outPath)
throw UnimplementedError("CA derivations are not yet supported");
@@ -257,8 +272,11 @@ DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state, bool withPaths, bool o
std::string DrvInfo::queryOutputName(EvalState & state)
{
if (outputName == "" && attrs) {
Bindings::iterator i = attrs->find(state.ctx.s.outputName);
outputName = i != attrs->end() ? state.forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : "";
auto i = attrs->get(state.ctx.s.outputName);
outputName = i ? state.forceStringNoCtx(
*i->value, noPos, "while evaluating the output name of a derivation"
)
: "";
}
return outputName;
}
@@ -268,8 +286,10 @@ Bindings * DrvInfo::getMeta(EvalState & state)
{
if (meta) return meta;
if (!attrs) return 0;
Bindings::iterator a = attrs->find(state.ctx.s.meta);
if (a == attrs->end()) return 0;
auto a = attrs->get(state.ctx.s.meta);
if (!a) {
return 0;
}
state.forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation");
meta = a->value->attrs;
return meta;
@@ -295,8 +315,10 @@ bool DrvInfo::checkMeta(EvalState & state, Value & v)
return true;
}
else if (v.type() == nAttrs) {
Bindings::iterator i = v.attrs->find(state.ctx.s.outPath);
if (i != v.attrs->end()) return false;
auto i = v.attrs->get(state.ctx.s.outPath);
if (i) {
return false;
}
for (auto & i : *v.attrs)
if (!checkMeta(state, *i.value)) return false;
return true;
@@ -309,8 +331,10 @@ bool DrvInfo::checkMeta(EvalState & state, Value & v)
Value * DrvInfo::queryMeta(EvalState & state, const std::string & name)
{
if (!getMeta(state)) return 0;
Bindings::iterator a = meta->find(state.ctx.symbols.create(name));
if (a == meta->end() || !checkMeta(state, *a->value)) return 0;
auto a = meta->get(state.ctx.symbols.create(name));
if (!a || !checkMeta(state, *a->value)) {
return 0;
}
return a->value;
}
@@ -473,7 +497,7 @@ static void getDerivations(EvalState & state, Value & vIn, PosIdx pos,
// FIXME: what the fuck???
/* !!! undocumented hackery to support combining channels in
nix-env.cc. */
bool combineChannels = v.attrs->find(state.ctx.symbols.create("_combineChannels")) != v.attrs->end();
bool combineChannels = v.attrs->get(state.ctx.symbols.create("_combineChannels"));
/* Consider the attributes in sorted order to get more
deterministic behaviour in nix-env operations (e.g. when
+74 -35
View File
@@ -486,14 +486,11 @@ using UnsafeValueList = std::list<Value *, gc_allocator<Value *>>;
using UnsafeValueList = std::list<Value *>;
#endif
static Bindings::iterator getAttr(
EvalState & state,
Symbol attrSym,
Bindings * attrSet,
std::string_view errorCtx)
static const Attr *
getAttr(EvalState & state, Symbol attrSym, Bindings * attrSet, std::string_view errorCtx)
{
Bindings::iterator value = attrSet->find(attrSym);
if (value == attrSet->end()) {
auto value = attrSet->get(attrSym);
if (!value) {
state.ctx.errors.make<TypeError>("attribute '%s' missing", state.ctx.symbols[attrSym]).withTrace(noPos, errorCtx).debugThrow();
}
return value;
@@ -504,7 +501,12 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
state.forceAttrs(*args[0], noPos, "while evaluating the first argument passed to builtins.genericClosure");
/* Get the start set. */
Bindings::iterator startSet = getAttr(state, state.ctx.s.startSet, args[0]->attrs, "in the attrset passed as argument to builtins.genericClosure");
auto startSet = getAttr(
state,
state.ctx.s.startSet,
args[0]->attrs,
"in the attrset passed as argument to builtins.genericClosure"
);
state.forceList(*startSet->value, noPos, "while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure");
@@ -518,7 +520,12 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
}
/* Get the operator. */
Bindings::iterator op = getAttr(state, state.ctx.s.operator_, args[0]->attrs, "in the attrset passed as argument to builtins.genericClosure");
auto op = getAttr(
state,
state.ctx.s.operator_,
args[0]->attrs,
"in the attrset passed as argument to builtins.genericClosure"
);
state.forceFunction(*op->value, noPos, "while evaluating the 'operator' attribute passed as argument to builtins.genericClosure");
/* Construct the closure by applying the operator to elements of
@@ -535,7 +542,12 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
state.forceAttrs(*e, noPos, "while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure");
Bindings::iterator key = getAttr(state, state.ctx.s.key, e->attrs, "in one of the attrsets generated by (or initially passed to) builtins.genericClosure");
auto key = getAttr(
state,
state.ctx.s.key,
e->attrs,
"in one of the attrsets generated by (or initially passed to) builtins.genericClosure"
);
state.forceValue(*key->value, noPos);
if (!doneKeys.insert(key->value).second) continue;
@@ -738,7 +750,12 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
Bindings * attrs = args[0]->attrs;
/* Figure out the name first (for stack backtraces). */
Bindings::iterator nameAttr = getAttr(state, state.ctx.s.name, attrs, "in the attrset passed as argument to builtins.derivationStrict");
auto nameAttr = getAttr(
state,
state.ctx.s.name,
attrs,
"in the attrset passed as argument to builtins.derivationStrict"
);
std::string drvName;
try {
@@ -782,18 +799,29 @@ drvName, Bindings * attrs, Value & v)
{
/* Check whether attributes should be passed as a JSON file. */
std::optional<JSON> jsonObject;
auto attr = attrs->find(state.ctx.s.structuredAttrs);
if (attr != attrs->end() &&
state.forceBool(*attr->value, attr->pos,
"while evaluating the `__structuredAttrs` "
"attribute passed to builtins.derivationStrict"))
auto attr = attrs->get(state.ctx.s.structuredAttrs);
if (attr
&& state.forceBool(
*attr->value,
attr->pos,
"while evaluating the `__structuredAttrs` "
"attribute passed to builtins.derivationStrict"
))
{
jsonObject = JSON::object();
}
/* Check whether null attributes should be ignored. */
bool ignoreNulls = false;
attr = attrs->find(state.ctx.s.ignoreNulls);
if (attr != attrs->end())
ignoreNulls = state.forceBool(*attr->value, attr->pos, "while evaluating the `__ignoreNulls` attribute " "passed to builtins.derivationStrict");
attr = attrs->get(state.ctx.s.ignoreNulls);
if (attr) {
ignoreNulls = state.forceBool(
*attr->value,
attr->pos,
"while evaluating the `__ignoreNulls` attribute "
"passed to builtins.derivationStrict"
);
}
/* Build the derivation expression by processing the attributes. */
Derivation drv;
@@ -1277,9 +1305,15 @@ static void prim_findFile(EvalState & state, Value * * args, Value & v)
state.forceAttrs(*v2, noPos, "while evaluating an element of the list passed to builtins.findFile");
std::string prefix;
Bindings::iterator i = v2->attrs->find(state.ctx.s.prefix);
if (i != v2->attrs->end())
prefix = state.forceStringNoCtx(*i->value, noPos, "while evaluating the `prefix` attribute of an element of the list passed to builtins.findFile");
auto i = v2->attrs->get(state.ctx.s.prefix);
if (i) {
prefix = state.forceStringNoCtx(
*i->value,
noPos,
"while evaluating the `prefix` attribute of an element of the list passed to "
"builtins.findFile"
);
}
i = getAttr(state, state.ctx.s.path, v2->attrs, "in an element of the __nixPath");
@@ -1650,7 +1684,7 @@ void prim_getAttr(EvalState & state, Value * * args, Value & v)
{
auto attr = state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.getAttr");
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.getAttr");
Bindings::iterator i = getAttr(
auto i = getAttr(
state,
state.ctx.symbols.create(attr),
args[1]->attrs,
@@ -1667,11 +1701,12 @@ static void prim_unsafeGetAttrPos(EvalState & state, Value * * args, Value & v)
{
auto attr = state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.unsafeGetAttrPos");
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.unsafeGetAttrPos");
Bindings::iterator i = args[1]->attrs->find(state.ctx.symbols.create(attr));
if (i == args[1]->attrs->end())
auto i = args[1]->attrs->get(state.ctx.symbols.create(attr));
if (!i) {
v.mkNull();
else
} else {
state.mkPos(v, i->pos);
}
}
// access to exact position information (ie, line and colum numbers) is deferred
@@ -1727,7 +1762,7 @@ static void prim_hasAttr(EvalState & state, Value * * args, Value & v)
{
auto attr = state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.hasAttr");
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.hasAttr");
v.mkBool(args[1]->attrs->find(state.ctx.symbols.create(attr)) != args[1]->attrs->end());
v.mkBool(args[1]->attrs->get(state.ctx.symbols.create(attr)));
}
/* Determine whether the argument is a set. */
@@ -1781,13 +1816,14 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
for (auto v2 : args[0]->listItems()) {
state.forceAttrs(*v2, noPos, "while evaluating an element of the list passed to builtins.listToAttrs");
Bindings::iterator j = getAttr(state, state.ctx.s.name, v2->attrs, "in a {name=...; value=...;} pair");
auto j = getAttr(state, state.ctx.s.name, v2->attrs, "in a {name=...; value=...;} pair");
auto name = state.forceStringNoCtx(*j->value, j->pos, "while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs");
auto sym = state.ctx.symbols.create(name);
if (seen.insert(sym).second) {
Bindings::iterator j2 = getAttr(state, state.ctx.s.value, v2->attrs, "in a {name=...; value=...;} pair");
auto j2 =
getAttr(state, state.ctx.s.value, v2->attrs, "in a {name=...; value=...;} pair");
attrs.insert(sym, j2->value, j2->pos);
}
}
@@ -1845,16 +1881,18 @@ static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v)
if (left.size() < right.size()) {
for (auto & l : left) {
Bindings::iterator r = right.find(l.name);
if (r != right.end())
auto r = right.get(l.name);
if (r) {
attrs.insert(*r);
}
}
}
else {
for (auto & r : right) {
Bindings::iterator l = left.find(r.name);
if (l != left.end())
auto l = left.get(r.name);
if (l) {
attrs.insert(r);
}
}
}
@@ -1871,9 +1909,10 @@ static void prim_catAttrs(EvalState & state, Value * * args, Value & v)
for (auto v2 : args[1]->listItems()) {
state.forceAttrs(*v2, noPos, "while evaluating an element in the list passed as second argument to builtins.catAttrs");
Bindings::iterator i = v2->attrs->find(attrName);
if (i != v2->attrs->end())
auto i = v2->attrs->get(attrName);
if (i) {
res[found++] = i->value;
}
}
v = state.ctx.mem.newList(found);
+26 -13
View File
@@ -182,17 +182,26 @@ static void prim_appendContext(EvalState & state, Value * * args, Value & v)
if (!settings.readOnlyMode)
state.aio.blockOn(state.ctx.store->ensurePath(namePath));
state.forceAttrs(*i.value, i.pos, "while evaluating the value of a string context");
auto iter = i.value->attrs->find(state.ctx.s.path);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, iter->pos, "while evaluating the `path` attribute of a string context"))
context.emplace(NixStringContextElem::Opaque {
auto a = i.value->attrs->get(state.ctx.s.path);
if (a) {
if (state.forceBool(
*a->value, a->pos, "while evaluating the `path` attribute of a string context"
))
{
context.emplace(NixStringContextElem::Opaque{
.path = namePath,
});
}
}
iter = i.value->attrs->find(sAllOutputs);
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, iter->pos, "while evaluating the `allOutputs` attribute of a string context")) {
a = i.value->attrs->get(sAllOutputs);
if (a) {
if (state.forceBool(
*a->value,
a->pos,
"while evaluating the `allOutputs` attribute of a string context"
))
{
if (!isDerivation(name)) {
state.ctx.errors.make<EvalError>(
"tried to add all-outputs context of %s, which is not a derivation, to a string",
@@ -205,17 +214,21 @@ static void prim_appendContext(EvalState & state, Value * * args, Value & v)
}
}
iter = i.value->attrs->find(state.ctx.s.outputs);
if (iter != i.value->attrs->end()) {
state.forceList(*iter->value, iter->pos, "while evaluating the `outputs` attribute of a string context");
if (iter->value->listSize() && !isDerivation(name)) {
a = i.value->attrs->get(state.ctx.s.outputs);
if (a) {
state.forceList(
*a->value, a->pos, "while evaluating the `outputs` attribute of a string context"
);
if (a->value->listSize() && !isDerivation(name)) {
state.ctx.errors.make<EvalError>(
"tried to add derivation output context of %s, which is not a derivation, to a string",
name
).atPos(i.pos).debugThrow();
}
for (auto elem : iter->value->listItems()) {
auto outputName = state.forceStringNoCtx(*elem, iter->pos, "while evaluating an output name within a string context");
for (auto elem : a->value->listItems()) {
auto outputName = state.forceStringNoCtx(
*elem, a->pos, "while evaluating an output name within a string context"
);
context.emplace(NixStringContextElem::Built {
.drvPath = makeConstantStorePath(namePath),
.output = std::string { outputName },
+6 -3
View File
@@ -232,11 +232,14 @@ private:
void printDerivation(Value & v)
{
Bindings::iterator i = v.attrs->find(state.ctx.s.drvPath);
auto i = v.attrs->get(state.ctx.s.drvPath);
NixStringContext context;
std::string storePath;
if (i != v.attrs->end())
storePath = state.ctx.store->printStorePath(state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation"));
if (i) {
storePath = state.ctx.store->printStorePath(state.coerceToStorePath(
i->pos, *i->value, context, "while evaluating the drvPath of a derivation"
));
}
if (options.ansiColors)
output << ANSI_GREEN;
+5 -4
View File
@@ -51,14 +51,14 @@ JSON printValueAsJSON(EvalState & state, bool strict,
out = *maybeString;
break;
}
auto i = v.attrs->find(state.ctx.s.outPath);
if (i == v.attrs->end()) {
auto i = v.attrs->get(state.ctx.s.outPath);
if (!i) {
out = JSON::object();
StringSet names;
for (auto & j : *v.attrs)
names.emplace(state.ctx.symbols[j.name]);
for (auto & j : names) {
const Attr & a(*v.attrs->find(state.ctx.symbols.create(j)));
const Attr & a(*v.attrs->get(state.ctx.symbols.create(j)));
try {
out[j] = printValueAsJSON(state, strict, *a.value, a.pos, context, copyToStore);
} catch (Error & e) {
@@ -67,8 +67,9 @@ JSON printValueAsJSON(EvalState & state, bool strict,
throw;
}
}
} else
} else {
return printValueAsJSON(state, strict, *i->value, i->pos, context, copyToStore);
}
break;
}
+6 -6
View File
@@ -36,7 +36,7 @@ static void showAttrs(EvalState & state, bool strict, bool location,
names.emplace(state.ctx.symbols[i.name]);
for (auto & i : names) {
const Attr & a(*attrs.find(state.ctx.symbols.create(i)));
const Attr & a(*attrs.get(state.ctx.symbols.create(i)));
XMLAttrs xmlAttrs;
xmlAttrs["name"] = i;
@@ -85,18 +85,18 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
if (state.isDerivation(v)) {
XMLAttrs xmlAttrs;
Bindings::iterator a = v.attrs->find(state.ctx.symbols.create("derivation"));
auto a = v.attrs->get(state.ctx.symbols.create("derivation"));
Path drvPath;
a = v.attrs->find(state.ctx.s.drvPath);
if (a != v.attrs->end()) {
a = v.attrs->get(state.ctx.s.drvPath);
if (a) {
if (strict) state.forceValue(*a->value, a->pos);
if (a->value->type() == nString)
xmlAttrs["drvPath"] = drvPath = a->value->str();
}
a = v.attrs->find(state.ctx.s.outPath);
if (a != v.attrs->end()) {
a = v.attrs->get(state.ctx.s.outPath);
if (a) {
if (strict) state.forceValue(*a->value, a->pos);
if (a->value->type() == nString) {
xmlAttrs["outPath"] = a->value->str();
+3 -2
View File
@@ -35,9 +35,10 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url)
vMirrors);
state.forceAttrs(vMirrors, noPos, "while evaluating the set of all mirrors");
auto mirrorList = vMirrors.attrs->find(state.ctx.symbols.create(mirrorName));
if (mirrorList == vMirrors.attrs->end())
auto mirrorList = vMirrors.attrs->get(state.ctx.symbols.create(mirrorName));
if (!mirrorList) {
throw Error("unknown mirror name '%s'", mirrorName);
}
state.forceList(*mirrorList->value, noPos, "while evaluating one mirror configuration");
if (mirrorList->value->listSize() < 1)