libexpr: Remove various default constructions of Values

Progress towards #744

Change-Id: I138ecf7ab712ea570ecbf506c7b6f6be6a6a6964
This commit is contained in:
skye
2026-03-17 15:48:12 -04:00
parent 8b99b75698
commit 51c6d6a2e8
10 changed files with 60 additions and 72 deletions
+1 -5
View File
@@ -42,11 +42,7 @@ void processExpr(EvalState & state, const Strings & attrPaths,
NixStringContext context;
if (evalOnly) {
Value vRes;
if (autoArgs.empty())
vRes = v;
else
vRes = state.autoCallFunction(autoArgs, v, noPos);
Value vRes = autoArgs.empty() ? v : state.autoCallFunction(autoArgs, v, noPos);
if (output == okRaw)
std::cout << *state.coerceToString(noPos, vRes, context, "while generating the nix-instantiate output", StringCoercionMode::Strict);
// We intentionally don't output a newline here. The default PS1 for Bash in NixOS starts with a newline
+3 -5
View File
@@ -183,11 +183,9 @@ Bindings * MixEvalArgs::getAutoArgs(Evaluator & state)
{
auto res = state.buildBindings(autoArgs.size());
for (auto & i : autoArgs) {
Value v;
if (i.second[0] == 'E')
v = state.evalLazily(state.parseExprFromString(i.second.substr(1), CanonPath::fromCwd()));
else
v = {NewValueAs::string, ((std::string_view) i.second).substr(1)};
Value v = i.second[0] == 'E'
? state.evalLazily(state.parseExprFromString(i.second.substr(1), CanonPath::fromCwd()))
: Value{NewValueAs::string, ((std::string_view) i.second).substr(1)};
res.insert(state.symbols.create(i.first), v);
}
return res.finish();
+11 -11
View File
@@ -446,18 +446,18 @@ Installables SourceExprCommand::parseInstallables(
throw UsageError("'--file' and '--expr' are exclusive");
auto evaluator = getEvaluator();
Value vFile;
if (file == "-") {
auto & e = evaluator->parseStdin();
vFile = state.eval(e);
}
else if (file)
vFile = state.evalFile(state.aio.blockOn(lookupFileArg(*evaluator, *file)).unwrap());
else {
auto & e = evaluator->parseExprFromString(*expr, CanonPath::fromCwd());
vFile = state.eval(e);
}
Value vFile = [&](NeverAsync = {}) {
if (file == "-") {
auto & e = evaluator->parseStdin();
return state.eval(e);
} else if (file) {
return state.evalFile(state.aio.blockOn(lookupFileArg(*evaluator, *file)).unwrap());
} else {
auto & e = evaluator->parseExprFromString(*expr, CanonPath::fromCwd());
return state.eval(e);
}
}();
for (auto & s : ss) {
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(s);
+3 -7
View File
@@ -1318,12 +1318,10 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
.kind = ReplLoadKind::Flake,
};
Value v;
try {
loaded.remove(loadable);
loaded.push_back(loadable);
v = flake::callFlake(
Value v = flake::callFlake(
state,
flake::lockFlake(
state,
@@ -1451,7 +1449,6 @@ Value NixRepl::getReplOverlaysEvalFunction()
}
auto evalReplInitFilesPath = CanonPath::root + "repl-overlays.nix";
*replOverlaysEvalFunction = Value{};
auto code =
#include "repl-overlays.nix.gen.hh"
;
@@ -1461,16 +1458,15 @@ Value NixRepl::getReplOverlaysEvalFunction()
evaluator.builtins.staticEnv
);
**replOverlaysEvalFunction = state.eval(expr);
*replOverlaysEvalFunction = state.eval(expr);
return **replOverlaysEvalFunction;
}
Value NixRepl::replOverlays()
{
Value replInits;
auto replInitStorage = evaluator.mem.newList(evalSettings.replOverlays.get().size());
replInits = {NewValueAs::list, replInitStorage};
Value replInits = {NewValueAs::list, replInitStorage};
size_t i = 0;
for (auto path : evalSettings.replOverlays.get()) {
+8 -7
View File
@@ -163,13 +163,14 @@ findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & au
std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v, std::string what)
{
Value v2;
try {
auto dummyArgs = state.ctx.mem.allocBindings(0);
v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v).first;
} catch (Error &) {
throw NoPositionInfo("package '%s' has no source location information", what);
}
Value v2 = [&]() {
try {
auto dummyArgs = state.ctx.mem.allocBindings(0);
return findAlongAttrPath(state, "meta.position", *dummyArgs, v).first;
} catch (Error &) {
throw NoPositionInfo("package '%s' has no source location information", what);
}
}();
// FIXME: is it possible to extract the Pos object instead of doing this
// toString + parsing?
+3 -2
View File
@@ -72,8 +72,9 @@ public:
const Attr * get(Symbol name)
{
Attr key(name, {});
iterator i = std::lower_bound(begin(), end(), key);
iterator i = std::lower_bound(begin(), end(), name, [](const Attr & value, const Symbol & compare) {
return value.name < compare;
});
if (i != end() && i->name == name) return &*i;
return nullptr;
}
+17 -16
View File
@@ -162,18 +162,18 @@ Value ExprSet::eval(EvalState & state, Env & env)
* http://github.com/NixOS/nix/issues/7012. Any accesses to the output attrset will thus infrec.
*/
Value vBackup = v;
Value nameVal;
Symbol nameSym;
{
KJ_DEFER(v = vBackup);
v = Value{NewValueAs::blackhole};
nameVal = i.nameExpr->eval(state, *dynamicEnv);
Value nameVal = i.nameExpr->eval(state, *dynamicEnv);
state.forceValue(nameVal, i.pos);
if (nameVal.type() == nNull) {
continue;
}
state.forceStringNoCtx(nameVal, i.pos, "while evaluating the name of a dynamic attribute");
nameSym = state.ctx.symbols.create(nameVal.str());
}
auto nameSym = state.ctx.symbols.create(nameVal.str());
auto j = v.attrs()->get(nameSym);
if (j) {
state.ctx.errors
@@ -617,19 +617,20 @@ Value ExprSelect::eval(EvalState & state, Env & env)
// Position for the current selector in this select chain.
PosIdx posCurrentSyntax;
Value baseSelectee;
try {
// Evaluate the original thing we're selecting on.
baseSelectee = e->eval(state, env);
} catch (Error & e) {
// clang-format off
e.addTrace(state.ctx.positions[getPos()], HintFmt(
"while evaluating an expression to select '%s' on it",
showAttrPath(state.ctx.symbols, attrPath)
));
// clang-format on
throw;
}
Value baseSelectee = [&]() {
try {
// Evaluate the original thing we're selecting on.
return e->eval(state, env);
} catch (Error & e) {
// clang-format off
e.addTrace(state.ctx.positions[getPos()], HintFmt(
"while evaluating an expression to select '%s' on it",
showAttrPath(state.ctx.symbols, attrPath)
));
// clang-format on
throw;
}
}();
try {
// With the original selectee evaluated, we'll walk the selection path starting
+2 -2
View File
@@ -733,13 +733,13 @@ void mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const En
// add 'with' bindings.
Bindings::iterator j = env.values[0].attrs()->begin();
while (j != env.values[0].attrs()->end()) {
vm[std::string(st[j->name])] = j->value;
vm.insert_or_assign(std::string(st[j->name]), j->value);
++j;
}
} else {
// iterate through staticenv bindings and add them.
for (auto & i : se.vars)
vm[std::string(st[i.first])] = env.values[i.second];
vm.insert_or_assign(std::string(st[i.first]), env.values[i.second]);
}
}
}
+4 -8
View File
@@ -942,10 +942,7 @@ LockedFlake lockFlake(
Value callFlake(EvalState & state, const LockedFlake & lockedFlake)
{
Value vLocks;
Value vRootSubdir;
vLocks = {NewValueAs::string, lockedFlake.lockFile.to_string()};
Value vLocks = {NewValueAs::string, lockedFlake.lockFile.to_string()};
Value vRootSrc = emitTreeAttrs(
state.ctx,
@@ -955,14 +952,13 @@ Value callFlake(EvalState & state, const LockedFlake & lockedFlake)
lockedFlake.flake.forceDirty
);
vRootSubdir = {NewValueAs::string, lockedFlake.flake.lockedRef.subdir};
Value vRootSubdir = {NewValueAs::string, lockedFlake.flake.lockedRef.subdir};
if (!state.ctx.caches.vCallFlake) {
state.ctx.caches.vCallFlake = allocRootValue({});
*state.ctx.caches.vCallFlake = state.eval(state.ctx.parseExprFromString(
state.ctx.caches.vCallFlake = allocRootValue(state.eval(state.ctx.parseExprFromString(
#include "call-flake.nix.gen.hh"
, CanonPath::root
));
)));
}
Value vTmp1 = state.callFunction(*state.ctx.caches.vCallFlake, vLocks, noPos);
+8 -9
View File
@@ -211,11 +211,11 @@ static void import(EvalState & state, Value & vPath, Value * vScope, Value & v)
Value w{NewValueAs::attrs, attrs.finish()};
if (!state.ctx.caches.vImportedDrvToDerivation) {
state.ctx.caches.vImportedDrvToDerivation = allocRootValue({});
*state.ctx.caches.vImportedDrvToDerivation = state.eval(state.ctx.parseExprFromString(
state.ctx.caches.vImportedDrvToDerivation =
allocRootValue(state.eval(state.ctx.parseExprFromString(
#include "imported-drv-to-derivation.nix.gen.hh"
, CanonPath::root
));
, CanonPath::root
)));
}
state.forceFunction(
@@ -1702,11 +1702,10 @@ static void addPath(
/* Call the filter function. The first argument is the path,
the second is a string indicating the type of the file. */
Value arg1;
if (isInDir(p, realPath))
arg1 = {NewValueAs::string, path + "/" + std::string(p, realPath.size() + 1)};
else
arg1 = {NewValueAs::string, p};
Value arg1 = {
NewValueAs::string,
isInDir(p, realPath) ? path + "/" + std::string(p, realPath.size() + 1) : p
};
Value arg2 =
{NewValueAs::string,