diff --git a/lix/legacy/nix-build.cc b/lix/legacy/nix-build.cc index 0929033fb..0642a995b 100644 --- a/lix/legacy/nix-build.cc +++ b/lix/legacy/nix-build.cc @@ -198,9 +198,9 @@ static void main_nix_build(std::string programName, Strings argv) auto store = openStore(); auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store; - auto evaluator = std::make_unique(myArgs.searchPath, evalStore, store); + auto evaluator = std::make_unique(myArgs.searchPath, evalStore, store); evaluator->repair = myArgs.repair; - auto & state = evaluator; + auto state = evaluator->begin(); if (myArgs.repair) buildMode = bmRepair; auto autoArgs = myArgs.getAutoArgs(*evaluator); diff --git a/lix/legacy/nix-env.cc b/lix/legacy/nix-env.cc index 053e5d09b..58353fc32 100644 --- a/lix/legacy/nix-env.cc +++ b/lix/legacy/nix-env.cc @@ -59,7 +59,7 @@ struct Globals { InstallSourceInfo instSource; Path profile; - std::shared_ptr state; + std::shared_ptr state; bool dryRun; bool preserveInstalled; bool removeAll; @@ -107,7 +107,7 @@ static bool isNixExpr(const SourcePath & path, struct InputAccessor::Stat & st) static constexpr size_t maxAttrs = 1024; -static void getAllExprs(EvalState & state, +static void getAllExprs(Evaluator & state, const SourcePath & path, StringSet & seen, BindingsBuilder & attrs) { StringSet namesSorted; @@ -177,7 +177,7 @@ static void loadSourceExpr(EvalState & state, const SourcePath & path, Value & v auto attrs = state.ctx.buildBindings(maxAttrs); attrs.alloc("_combineChannels").mkList(0); StringSet seen; - getAllExprs(state, path, seen, attrs); + getAllExprs(state.ctx, path, seen, attrs); v.mkAttrs(attrs); } @@ -511,7 +511,7 @@ static void installDerivations(Globals & globals, { debug("installing derivations"); - auto state = globals.state; + auto state = globals.state->begin(); /* Get the set of user environment elements to be installed. */ DrvInfos newElems, newElemsTmp; @@ -592,7 +592,7 @@ static void upgradeDerivations(Globals & globals, { debug("upgrading derivations"); - auto state = globals.state; + auto state = globals.state->begin(); /* Upgrade works as follows: we take all currently installed derivations, and for any derivation matching any selector, look @@ -718,7 +718,7 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs) std::string flagValue = *arg++; DrvNames selectors = drvNamesFromArgs(Strings(arg, opArgs.end())); - auto state = globals.state; + auto state = globals.state->begin(); while (true) { std::string lockToken = optimisticLockProfile(globals.profile); @@ -748,7 +748,7 @@ static void opSetFlag(Globals & globals, Strings opFlags, Strings opArgs) static void opSet(Globals & globals, Strings opFlags, Strings opArgs) { - auto state = globals.state; + auto state = globals.state->begin(); auto store2 = globals.state->store.dynamic_pointer_cast(); if (!store2) throw Error("--set is not supported for this Nix store"); @@ -797,7 +797,7 @@ static void opSet(Globals & globals, Strings opFlags, Strings opArgs) static void uninstallDerivations(Globals & globals, Strings & selectors, Path & profile) { - auto state = globals.state; + auto state = globals.state->begin(); while (true) { auto lockToken = optimisticLockProfile(profile); @@ -1003,7 +1003,7 @@ static void queryJSON(EvalState & state, Globals & globals, std::vector static void opQuery(Globals & globals, Strings opFlags, Strings opArgs) { auto & store { *globals.state->store }; - auto state = globals.state; + auto state = globals.state->begin(); Strings remaining; std::string attrPath; @@ -1533,7 +1533,7 @@ static int main_nix_env(std::string programName, Strings argv) auto store = openStore(); - globals.state = std::shared_ptr(new EvalState(myArgs.searchPath, store)); + globals.state = std::make_shared(myArgs.searchPath, store); globals.state->repair = myArgs.repair; globals.instSource.nixExprPath = std::make_shared( diff --git a/lix/legacy/nix-instantiate.cc b/lix/legacy/nix-instantiate.cc index 629c06eb4..201de62e4 100644 --- a/lix/legacy/nix-instantiate.cc +++ b/lix/legacy/nix-instantiate.cc @@ -157,8 +157,8 @@ static int main_nix_instantiate(std::string programName, Strings argv) auto store = openStore(); auto evalStore = myArgs.evalStoreUrl ? openStore(*myArgs.evalStoreUrl) : store; - auto evaluator = std::make_unique(myArgs.searchPath, evalStore, store); - auto & state = evaluator; + auto evaluator = std::make_unique(myArgs.searchPath, evalStore, store); + auto state = evaluator->begin(); evaluator->repair = myArgs.repair; Bindings & autoArgs = *myArgs.getAutoArgs(*evaluator); diff --git a/lix/libcmd/command.cc b/lix/libcmd/command.cc index 5e12cc4dc..90739101d 100644 --- a/lix/libcmd/command.cc +++ b/lix/libcmd/command.cc @@ -102,17 +102,17 @@ ref EvalCommand::getEvalStore() return ref(evalStore); } -ref EvalCommand::getEvalState() +ref EvalCommand::getEvaluator() { if (!evalState) { - evalState = std::allocate_shared( + evalState = std::allocate_shared( TraceableAllocator(), searchPath, getEvalStore(), getStore(), startReplOnEvalErrors ? AbstractNixRepl::runSimple : nullptr ); evalState->repair = repair; } - return ref(evalState); + return ref(evalState); } MixOperateOnOptions::MixOperateOnOptions() @@ -162,7 +162,7 @@ void BuiltPathsCommand::run(ref store, Installables && installables) for (auto & p : store->queryAllValidPaths()) paths.emplace_back(BuiltPath::Opaque{p}); } else { - paths = Installable::toBuiltPaths(*getEvalState(), getEvalStore(), store, realiseMode, operateOn, installables); + paths = Installable::toBuiltPaths(*getEvaluator()->begin(), getEvalStore(), store, realiseMode, operateOn, installables); if (recursive) { // XXX: This only computes the store path closure, ignoring // intermediate realisations diff --git a/lix/libcmd/command.hh b/lix/libcmd/command.hh index 478032116..3a55b1532 100644 --- a/lix/libcmd/command.hh +++ b/lix/libcmd/command.hh @@ -77,12 +77,12 @@ struct EvalCommand : virtual StoreCommand, MixEvalArgs ref getEvalStore(); - ref getEvalState(); + ref getEvaluator(); private: std::shared_ptr evalStore; - std::shared_ptr evalState; + std::shared_ptr evalState; }; /** @@ -127,7 +127,7 @@ struct SourceExprCommand : virtual Args, MixFlakeOptions /** * Complete an installable from the given prefix. */ - void completeInstallable(AddCompletions & completions, std::string_view prefix); + void completeInstallable(EvalState & state, AddCompletions & completions, std::string_view prefix); /** * Convenience wrapper around the underlying function to make setting the @@ -324,7 +324,7 @@ struct MixEnvironment : virtual Args { void completeFlakeInputPath( AddCompletions & completions, - ref evalState, + EvalState & evalState, const std::vector & flakeRefs, std::string_view prefix); @@ -332,7 +332,8 @@ void completeFlakeRef(AddCompletions & completions, ref store, std::strin void completeFlakeRefWithFragment( AddCompletions & completions, - ref evalState, + EvalState & evalState, + ref evaluator, flake::LockFlags lockFlags, Strings attrPathPrefixes, const Strings & defaultFlakeAttrPaths, diff --git a/lix/libcmd/common-eval-args.cc b/lix/libcmd/common-eval-args.cc index 4cf6b43af..26e0380c0 100644 --- a/lix/libcmd/common-eval-args.cc +++ b/lix/libcmd/common-eval-args.cc @@ -171,7 +171,7 @@ MixEvalArgs::MixEvalArgs() }); } -Bindings * MixEvalArgs::getAutoArgs(EvalState & state) +Bindings * MixEvalArgs::getAutoArgs(Evaluator & state) { auto res = state.buildBindings(autoArgs.size()); for (auto & i : autoArgs) { @@ -187,7 +187,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state) return res.finish(); } -SourcePath lookupFileArg(EvalState & state, std::string_view fileArg) +SourcePath lookupFileArg(Evaluator & state, std::string_view fileArg) { if (EvalSettings::isPseudoUrl(fileArg)) { auto const url = EvalSettings::resolvePseudoUrl(fileArg); diff --git a/lix/libcmd/common-eval-args.hh b/lix/libcmd/common-eval-args.hh index 51ca70b19..1d42ee5e4 100644 --- a/lix/libcmd/common-eval-args.hh +++ b/lix/libcmd/common-eval-args.hh @@ -1,6 +1,7 @@ #pragma once ///@file +#include "lix/libexpr/eval.hh" #include "lix/libutil/args.hh" #include "lix/libmain/common-args.hh" #include "lix/libexpr/search-path.hh" @@ -18,7 +19,7 @@ struct MixEvalArgs : virtual Args, virtual MixRepair MixEvalArgs(); - Bindings * getAutoArgs(EvalState & state); + Bindings * getAutoArgs(Evaluator & state); SearchPath searchPath; @@ -48,6 +49,6 @@ private: * * @exception nix::ThrownError for failed search path lookup. Probably others. */ -SourcePath lookupFileArg(EvalState & state, std::string_view fileArg); +SourcePath lookupFileArg(Evaluator & state, std::string_view fileArg); } diff --git a/lix/libcmd/installable-attr-path.cc b/lix/libcmd/installable-attr-path.cc index 28bcb351b..11035206c 100644 --- a/lix/libcmd/installable-attr-path.cc +++ b/lix/libcmd/installable-attr-path.cc @@ -12,7 +12,7 @@ namespace nix { InstallableAttrPath::InstallableAttrPath( - ref state, + ref state, SourceExprCommand & cmd, Value * v, const std::string & attrPath, @@ -92,7 +92,7 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths(EvalState & state) } InstallableAttrPath InstallableAttrPath::parse( - ref state, + ref state, SourceExprCommand & cmd, Value * v, std::string_view prefix, diff --git a/lix/libcmd/installable-attr-path.hh b/lix/libcmd/installable-attr-path.hh index d040c634f..ce76307e6 100644 --- a/lix/libcmd/installable-attr-path.hh +++ b/lix/libcmd/installable-attr-path.hh @@ -20,7 +20,7 @@ class InstallableAttrPath : public InstallableValue ExtendedOutputsSpec extendedOutputsSpec; InstallableAttrPath( - ref state, + ref state, SourceExprCommand & cmd, Value * v, const std::string & attrPath, @@ -35,7 +35,7 @@ class InstallableAttrPath : public InstallableValue public: static InstallableAttrPath parse( - ref state, + ref state, SourceExprCommand & cmd, Value * v, std::string_view prefix, diff --git a/lix/libcmd/installable-flake.cc b/lix/libcmd/installable-flake.cc index 5264af0b9..3db1f6031 100644 --- a/lix/libcmd/installable-flake.cc +++ b/lix/libcmd/installable-flake.cc @@ -53,7 +53,7 @@ static std::string showAttrPaths(const std::vector & paths) InstallableFlake::InstallableFlake( SourceExprCommand * cmd, - ref state, + ref state, FlakeRef && flakeRef, std::string_view fragment, ExtendedOutputsSpec extendedOutputsSpec, diff --git a/lix/libcmd/installable-flake.hh b/lix/libcmd/installable-flake.hh index d7be2d93d..a608e702a 100644 --- a/lix/libcmd/installable-flake.hh +++ b/lix/libcmd/installable-flake.hh @@ -2,6 +2,7 @@ ///@file #include "lix/libcmd/installable-value.hh" +#include "lix/libexpr/eval.hh" namespace nix { @@ -40,7 +41,7 @@ struct InstallableFlake : InstallableValue InstallableFlake( SourceExprCommand * cmd, - ref state, + ref state, FlakeRef && flakeRef, std::string_view fragment, ExtendedOutputsSpec extendedOutputsSpec, @@ -81,7 +82,7 @@ static inline FlakeRef defaultNixpkgsFlakeRef() } ref openEvalCache( - eval_cache::CachingEvalState & state, + eval_cache::CachingEvaluator & state, std::shared_ptr lockedFlake); } diff --git a/lix/libcmd/installable-value.hh b/lix/libcmd/installable-value.hh index 66d35ee4e..23dd66901 100644 --- a/lix/libcmd/installable-value.hh +++ b/lix/libcmd/installable-value.hh @@ -3,6 +3,7 @@ #include "lix/libcmd/installables.hh" #include "lix/libexpr/eval-cache.hh" +#include "lix/libexpr/eval.hh" #include "lix/libexpr/flake/flake.hh" namespace nix { @@ -70,14 +71,9 @@ struct ExtraPathInfoValue : ExtraPathInfo */ struct InstallableValue : Installable { - ref evaluator; - ref state; + ref evaluator; - InstallableValue(ref evaluator) - : evaluator(evaluator) - , state(evaluator) - { - } + InstallableValue(ref evaluator) : evaluator(evaluator) {} virtual ~InstallableValue() { } diff --git a/lix/libcmd/installables.cc b/lix/libcmd/installables.cc index 700f5115a..d2d64730d 100644 --- a/lix/libcmd/installables.cc +++ b/lix/libcmd/installables.cc @@ -25,12 +25,12 @@ namespace nix { void completeFlakeInputPath( AddCompletions & completions, - ref evalState, + EvalState & evalState, const std::vector & flakeRefs, std::string_view prefix) { for (auto & flakeRef : flakeRefs) { - auto flake = flake::getFlake(*evalState, flakeRef, true); + auto flake = flake::getFlake(evalState, flakeRef, true); for (auto & input : flake.inputs) if (input.first.starts_with(prefix)) completions.add(input.first); @@ -86,9 +86,9 @@ MixFlakeOptions::MixFlakeOptions() }}, .completer = {[&](AddCompletions & completions, size_t n, std::string_view prefix) { if (n == 0) { - completeFlakeInputPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix); + completeFlakeInputPath(completions, *getEvaluator()->begin(), getFlakeRefsForCompletion(), prefix); } else if (n == 1) { - completeFlakeRef(completions, getEvalState()->store, prefix); + completeFlakeRef(completions, getEvaluator()->store, prefix); } }} }); @@ -121,7 +121,7 @@ MixFlakeOptions::MixFlakeOptions() .category = category, .labels = {"flake-url"}, .handler = {[&](std::string flakeRef) { - auto evalState = getEvalState(); + auto evalState = getEvaluator()->begin(); auto flake = flake::lockFlake( *evalState, parseFlakeRef(flakeRef, absPath(".")), @@ -137,7 +137,7 @@ MixFlakeOptions::MixFlakeOptions() } }}, .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { - completeFlakeRef(completions, getEvalState()->store, prefix); + completeFlakeRef(completions, getEvaluator()->store, prefix); }} }); } @@ -202,28 +202,28 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes() Args::CompleterClosure SourceExprCommand::getCompleteInstallable() { return [this](AddCompletions & completions, size_t, std::string_view prefix) { - completeInstallable(completions, prefix); + completeInstallable(*getEvaluator()->begin(), completions, prefix); }; } -void SourceExprCommand::completeInstallable(AddCompletions & completions, std::string_view prefix) +void SourceExprCommand::completeInstallable(EvalState & state, AddCompletions & completions, std::string_view prefix) { try { if (file) { completions.setType(AddCompletions::Type::Attrs); evalSettings.pureEval.override(false); - auto state = getEvalState(); - state->paths.allowedPaths.reset(); + auto evaluator = getEvaluator(); + evaluator->paths.allowedPaths.reset(); - Expr & e = state->parseExprFromFile( - resolveExprPath(state->paths.checkSourcePath(lookupFileArg(*state, *file))) - ); + Expr & e = evaluator->parseExprFromFile( + resolveExprPath(evaluator->paths.checkSourcePath(lookupFileArg(*evaluator, *file))) + ); Value root; - state->eval(e, root); + state.eval(e, root); - auto autoArgs = getAutoArgs(*state); + auto autoArgs = getAutoArgs(*evaluator); std::string prefix_ = std::string(prefix); auto sep = prefix_.rfind('.'); @@ -236,15 +236,15 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s prefix_ = ""; } - auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root); + auto [v, pos] = findAlongAttrPath(state, prefix_, *autoArgs, root); Value &v1(*v); - state->forceValue(v1, pos); + state.forceValue(v1, pos); Value v2; - state->autoCallFunction(*autoArgs, v1, v2); + state.autoCallFunction(*autoArgs, v1, v2); if (v2.type() == nAttrs) { for (auto & i : *v2.attrs) { - std::string name = state->symbols[i.name]; + std::string name = evaluator->symbols[i.name]; if (name.find(searchWord) == 0) { if (prefix_ == "") completions.add(name); @@ -256,7 +256,8 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s } else { completeFlakeRefWithFragment( completions, - getEvalState(), + state, + getEvaluator(), lockFlags, getDefaultFlakeAttrPathPrefixes(), getDefaultFlakeAttrPaths(), @@ -269,7 +270,8 @@ void SourceExprCommand::completeInstallable(AddCompletions & completions, std::s void completeFlakeRefWithFragment( AddCompletions & completions, - ref evalState, + EvalState & evalState, + ref evaluator, flake::LockFlags lockFlags, Strings attrPathPrefixes, const Strings & defaultFlakeAttrPaths, @@ -280,7 +282,7 @@ void completeFlakeRefWithFragment( try { auto hash = prefix.find('#'); if (hash == std::string::npos) { - completeFlakeRef(completions, evalState->store, prefix); + completeFlakeRef(completions, evaluator->store, prefix); } else { completions.setType(AddCompletions::Type::Attrs); @@ -293,8 +295,10 @@ void completeFlakeRefWithFragment( auto flakeRefS = std::string(prefix.substr(0, hash)); auto flakeRef = parseFlakeRef(expandTilde(flakeRefS), absPath(".")); - auto evalCache = openEvalCache(*evalState, - std::make_shared(lockFlake(*evalState, flakeRef, lockFlags))); + auto evalCache = openEvalCache( + *evaluator, + std::make_shared(lockFlake(evalState, flakeRef, lockFlags)) + ); auto root = evalCache->getRoot(); @@ -317,12 +321,12 @@ void completeFlakeRefWithFragment( attrPath.pop_back(); } - auto attr = root->findAlongAttrPath(*evalState, attrPath); + auto attr = root->findAlongAttrPath(evalState, attrPath); if (!attr) continue; - for (auto & attr2 : (*attr)->getAttrs(*evalState)) { + for (auto & attr2 : (*attr)->getAttrs(evalState)) { if (std::string_view attr2s = attr2; attr2s.starts_with(lastAttr)) { - auto attrPath2 = (*attr)->getAttrPath(*evalState, attr2s); + auto attrPath2 = (*attr)->getAttrPath(evalState, attr2s); /* Strip the attrpath prefix. */ attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); completions.add(flakeRefS + "#" + prefixRoot + concatStringsSep(".", attrPath2)); @@ -334,7 +338,7 @@ void completeFlakeRefWithFragment( attrpaths. */ if (fragment.empty()) { for (auto & attrPath : defaultFlakeAttrPaths) { - auto attr = root->findAlongAttrPath(*evalState, parseAttrPath(attrPath)); + auto attr = root->findAlongAttrPath(evalState, parseAttrPath(attrPath)); if (!attr) continue; completions.add(flakeRefS + "#" + prefixRoot); } @@ -392,7 +396,7 @@ static StorePath getDeriver( } ref openEvalCache( - eval_cache::CachingEvalState & state, + eval_cache::CachingEvaluator & state, std::shared_ptr lockedFlake) { auto fingerprint = evalSettings.useEvalCache && evalSettings.pureEval @@ -435,10 +439,10 @@ Installables SourceExprCommand::parseInstallables( // FIXME: backward compatibility hack if (file) { evalSettings.pureEval.override(false); - getEvalState()->paths.allowedPaths.reset(); + getEvaluator()->paths.allowedPaths.reset(); } - auto evaluator = getEvalState(); + auto evaluator = getEvaluator(); auto vFile = evaluator->mem.allocValue(); if (file == "-") { @@ -446,9 +450,9 @@ Installables SourceExprCommand::parseInstallables( state.eval(e, *vFile); } else if (file) - state.evalFile(lookupFileArg(state, *file), *vFile); + state.evalFile(lookupFileArg(*evaluator, *file), *vFile); else { - auto & e = state.parseExprFromString(*expr, CanonPath::fromCwd()); + auto & e = evaluator->parseExprFromString(*expr, CanonPath::fromCwd()); state.eval(e, *vFile); } @@ -486,7 +490,7 @@ Installables SourceExprCommand::parseInstallables( auto [flakeRef, fragment] = parseFlakeRefWithFragment(std::string { prefix }, absPath(".")); result.push_back(make_ref( this, - getEvalState(), + getEvaluator(), std::move(flakeRef), fragment, std::move(extendedOutputsSpec), @@ -836,7 +840,7 @@ std::vector InstallableCommand::getFlakeRefsForCompletion() void InstallablesCommand::run(ref store, std::vector && rawInstallables) { - auto installables = parseInstallables(*getEvalState(), store, rawInstallables); + auto installables = parseInstallables(*getEvaluator()->begin(), store, rawInstallables); run(store, std::move(installables)); } @@ -853,7 +857,7 @@ InstallableCommand::InstallableCommand() void InstallableCommand::run(ref store) { - auto installable = parseInstallable(*getEvalState(), store, _installable); + auto installable = parseInstallable(*getEvaluator()->begin(), store, _installable); run(store, std::move(installable)); } diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index 55e5229db..56f9387ec 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -119,7 +119,7 @@ struct NixRepl }; /* clang-format: on */ - EvalState & evaluator; + Evaluator & evaluator; size_t debugTraceIndex; Strings loadedFiles; @@ -232,7 +232,7 @@ static box_ptr makeInteracter() { NixRepl::NixRepl(const SearchPath & searchPath, nix::ref store, EvalState & state, std::function getValues) : AbstractNixRepl(state) - , evaluator(state) + , evaluator(state.ctx) , debugTraceIndex(0) , getValues(getValues) , staticEnv(new StaticEnv(nullptr, evaluator.builtins.staticEnv.get())) diff --git a/lix/libexpr/eval-cache.cc b/lix/libexpr/eval-cache.cc index fb414a509..1287c5e4d 100644 --- a/lix/libexpr/eval-cache.cc +++ b/lix/libexpr/eval-cache.cc @@ -322,7 +322,7 @@ static std::shared_ptr makeAttrDb(const Hash & fingerprint) } } -ref CachingEvalState::getCacheFor(Hash hash, RootLoader rootLoader) +ref CachingEvaluator::getCacheFor(Hash hash, RootLoader rootLoader) { if (auto it = caches.find(hash); it != caches.end()) { return it->second; diff --git a/lix/libexpr/eval-cache.hh b/lix/libexpr/eval-cache.hh index b5fdf97ca..bd6ed0128 100644 --- a/lix/libexpr/eval-cache.hh +++ b/lix/libexpr/eval-cache.hh @@ -22,7 +22,7 @@ typedef std::function RootLoader; * the rather strong connection between EvalState and these caches. At some * future time the cache interface should be changed to hide its EvalState. */ -class CachingEvalState : public EvalState +class CachingEvaluator : public Evaluator { /** * A cache for evaluation caches, so as to reuse the same root value if possible @@ -30,7 +30,7 @@ class CachingEvalState : public EvalState std::map> caches; public: - using EvalState::EvalState; + using Evaluator::Evaluator; ref getCacheFor(Hash hash, RootLoader rootLoader); }; diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 20a368dba..3e1963350 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -305,8 +305,7 @@ EvalPaths::EvalPaths( } } -EvalContext::EvalContext( - EvalState & parent, +Evaluator::Evaluator( const SearchPath & _searchPath, ref store, std::shared_ptr buildStore, @@ -330,8 +329,11 @@ EvalContext::EvalContext( debugRepl ? std::make_unique( positions, symbols, - [&parent, debugRepl](const ValMap & extraEnv) { return debugRepl(parent, extraEnv); } - ) + [this, debugRepl](const ValMap & extraEnv) { + return activeEval + ? debugRepl(*activeEval, extraEnv) + : ReplExitStatus::Continue; + }) : nullptr } , errors{positions, debug.get()} @@ -341,17 +343,20 @@ EvalContext::EvalContext( static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes"); } -EvalState::EvalState( - const SearchPath & _searchPath, - ref store, - std::shared_ptr buildStore, - std::function debugRepl) - : EvalContext(*this, _searchPath, store, buildStore, debugRepl) +box_ptr Evaluator::begin() { + assert(!activeEval); + return box_ptr::unsafeFromNonnull(std::unique_ptr(new EvalState(*this))); +} + +EvalState::EvalState(Evaluator & ctx) : ctx(ctx) +{ + ctx.activeEval = this; } EvalState::~EvalState() { + ctx.activeEval = nullptr; } @@ -788,7 +793,7 @@ Value EvalMemory::newList(size_t size) } -void EvalState::evalLazily(Expr & e, Value & v) +void Evaluator::evalLazily(Expr & e, Value & v) { v.mkThunk(&builtins.env, e); stats.nrThunks++; @@ -2531,7 +2536,7 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v } } -bool EvalState::fullGC() { +bool Evaluator::fullGC() { #if HAVE_BOEHMGC GC_gcollect(); // Check that it ran. We might replace this with a version that uses more @@ -2545,7 +2550,7 @@ bool EvalState::fullGC() { #endif } -void EvalState::maybePrintStats() +void Evaluator::maybePrintStats() { bool showStats = getEnv("NIX_SHOW_STATS").value_or("0") != "0"; @@ -2560,7 +2565,7 @@ void EvalState::maybePrintStats() } } -void EvalState::printStatistics() +void Evaluator::printStatistics() { struct rusage buf; getrusage(RUSAGE_SELF, &buf); @@ -2700,20 +2705,20 @@ SourcePath resolveExprPath(SourcePath path) } -Expr & EvalState::parseExprFromFile(const SourcePath & path) +Expr & Evaluator::parseExprFromFile(const SourcePath & path) { return parseExprFromFile(path, builtins.staticEnv); } -Expr & EvalState::parseExprFromFile(const SourcePath & path, std::shared_ptr & staticEnv) +Expr & Evaluator::parseExprFromFile(const SourcePath & path, std::shared_ptr & staticEnv) { auto buffer = path.readFile(); return *parse(buffer.data(), buffer.size(), Pos::Origin(path), path.parent(), staticEnv); } -Expr & EvalState::parseExprFromString( +Expr & Evaluator::parseExprFromString( std::string s_, const SourcePath & basePath, std::shared_ptr & staticEnv, @@ -2725,7 +2730,7 @@ Expr & EvalState::parseExprFromString( } -Expr & EvalState::parseExprFromString( +Expr & Evaluator::parseExprFromString( std::string s, const SourcePath & basePath, const FeatureSettings & featureSettings @@ -2735,7 +2740,7 @@ Expr & EvalState::parseExprFromString( } -Expr & EvalState::parseStdin() +Expr & Evaluator::parseStdin() { //Activity act(*logger, lvlTalkative, "parsing standard input"); auto s = make_ref(drainFD(0)); diff --git a/lix/libexpr/eval.hh b/lix/libexpr/eval.hh index c05d9a120..cadc99032 100644 --- a/lix/libexpr/eval.hh +++ b/lix/libexpr/eval.hh @@ -4,6 +4,7 @@ #include "lix/libexpr/attr-set.hh" #include "lix/libexpr/eval-error.hh" #include "lix/libexpr/gc-alloc.hh" +#include "lix/libutil/box_ptr.hh" #include "lix/libutil/generator.hh" #include "lix/libutil/types.hh" #include "lix/libexpr/value.hh" @@ -484,8 +485,13 @@ struct EvalStatistics void addCall(ExprLambda & fun); }; -class EvalContext +class Evaluator { + friend class EvalBuiltins; + friend class EvalState; + + EvalState * activeEval = nullptr; + public: SymbolTable symbols; PosTable positions; @@ -510,35 +516,17 @@ public: std::unique_ptr debug; EvalErrorContext errors; - EvalContext( - EvalState & parent, + Evaluator( const SearchPath & _searchPath, ref store, std::shared_ptr buildStore = nullptr, std::function debugRepl = nullptr ); - EvalContext(const EvalContext &) = delete; - EvalContext(EvalContext &&) = delete; - EvalContext & operator=(const EvalContext &) = delete; - EvalContext & operator=(EvalContext &&) = delete; -}; - - -class EvalState : public EvalContext -{ - friend class EvalBuiltins; - -public: - EvalState & ctx{*this}; - - EvalState( - const SearchPath & _searchPath, - ref store, - std::shared_ptr buildStore = nullptr, - std::function debugRepl = nullptr - ); - ~EvalState(); + Evaluator(const Evaluator &) = delete; + Evaluator(Evaluator &&) = delete; + Evaluator & operator=(const Evaluator &) = delete; + Evaluator & operator=(Evaluator &&) = delete; /** * Parse a Nix expression from the specified file. @@ -563,6 +551,84 @@ public: Expr & parseStdin(); + /** + * Creates a thunk that will evaluate the given expression when forced. + */ + void evalLazily(Expr & e, Value & v); + +private: + Expr * parse( + char * text, + size_t length, + Pos::Origin origin, + const SourcePath & basePath, + std::shared_ptr & staticEnv, + const FeatureSettings & xpSettings = featureSettings); + +public: + BindingsBuilder buildBindings(size_t capacity) + { + return mem.buildBindings(symbols, capacity); + } + + /** + * Print statistics, if enabled. + * + * Performs a full memory GC before printing the statistics, so that the + * GC statistics are more accurate. + */ + void maybePrintStats(); + + /** + * Print statistics, unconditionally, cheaply, without performing a GC first. + */ + void printStatistics(); + + /** + * Perform a full memory garbage collection - not incremental. + * + * @return true if Nix was built with GC and a GC was performed, false if not. + * The return value is currently not thread safe - just the return value. + */ + bool fullGC(); + + /** + * Create an `EvalState` in prepation to evaluate some amount of Nix code. + * + * While preparation of evaluation can be done with Evaluator itself only, + * actually evaluating things requires an EvalState. This function creates + * an EvalState and returns it. At most one EvalState per Evaluator may be + * live at any given point, and references to this EvalState must not live + * anywhere except in the returned box, local variables, or arguments. Any + * reference held in an object type is illegal, be it in a lambda capture, + * a pointer member of an object, a hidden member such as arguments passed + * to functions by `std::thread` or `std::async`—all references held where + * they could be copied are moved from are disallowed. EvalState is thus a + * witness type that a given thread may evaluate nix code and must *never* + * be run inside `kj::Promise` context. This is due to a kj limitation, in + * which it is not possible to block on a promise while already running in + * a promise without doing this blocking on a different event loop/thread. + */ + box_ptr begin(); +}; + + +class EvalState +{ + friend class Evaluator; + + explicit EvalState(Evaluator & ctx); + +public: + Evaluator & ctx; + + EvalState(const EvalState &) = delete; + EvalState(EvalState &&) = delete; + EvalState & operator=(const EvalState &) = delete; + EvalState & operator=(EvalState &&) = delete; + + ~EvalState(); + /** * Evaluate an expression read from the given file to normal form. */ @@ -577,11 +643,6 @@ public: */ void eval(Expr & e, Value & v); - /** - * Creates a thunk that will evaluate the given expression when forced. - */ - void evalLazily(Expr & e, Value & v); - /** * Evaluation the expression, then verify that it has the expected * type. @@ -690,14 +751,6 @@ private: friend struct ExprAttrs; friend struct ExprLet; - Expr * parse( - char * text, - size_t length, - Pos::Origin origin, - const SourcePath & basePath, - std::shared_ptr & staticEnv, - const FeatureSettings & xpSettings = featureSettings); - /** * Current Nix call stack depth, used with `max-call-depth` setting to throw stack overflow hopefully before we run out of system stack. */ @@ -728,11 +781,6 @@ public: */ void autoCallFunction(Bindings & args, Value & fun, Value & res); - BindingsBuilder buildBindings(size_t capacity) - { - return ctx.mem.buildBindings(ctx.symbols, capacity); - } - void mkPos(Value & v, PosIdx pos); /** @@ -772,27 +820,6 @@ public: void concatLists(Value & v, size_t nrLists, Value * * lists, const PosIdx pos, std::string_view errorCtx); - /** - * Print statistics, if enabled. - * - * Performs a full memory GC before printing the statistics, so that the - * GC statistics are more accurate. - */ - void maybePrintStats(); - - /** - * Print statistics, unconditionally, cheaply, without performing a GC first. - */ - void printStatistics(); - - /** - * Perform a full memory garbage collection - not incremental. - * - * @return true if Nix was built with GC and a GC was performed, false if not. - * The return value is currently not thread safe - just the return value. - */ - bool fullGC(); - private: /** diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index 199e7b082..8ccdf7373 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -37,7 +37,7 @@ static std::optional lookupInFlakeCache( } static std::tuple fetchOrSubstituteTree( - EvalState & state, + Evaluator & state, const FlakeRef & originalRef, bool allowLookup, FlakeCache & flakeCache) @@ -217,7 +217,7 @@ static Flake getFlake( InputPath lockRootPath) { auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state, originalRef, allowLookup, flakeCache); + state.ctx, originalRef, allowLookup, flakeCache); // We need to guard against symlink attacks, but before we start doing // filesystem operations we should make sure there's a flake.nix in the @@ -634,7 +634,7 @@ LockedFlake lockFlake( else { auto [sourceInfo, resolvedRef, lockedRef] = fetchOrSubstituteTree( - state, *input.ref, useRegistries, flakeCache); + state.ctx, *input.ref, useRegistries, flakeCache); auto childNode = make_ref(lockedRef, ref, false); @@ -782,7 +782,7 @@ void callFlake(EvalState & state, vLocks->mkString(lockedFlake.lockFile.to_string()); emitTreeAttrs( - state, + state.ctx, *lockedFlake.flake.sourceInfo, lockedFlake.flake.lockedRef.input, *vRootSrc, diff --git a/lix/libexpr/flake/flake.hh b/lix/libexpr/flake/flake.hh index b978a7ad2..b61b3fb62 100644 --- a/lix/libexpr/flake/flake.hh +++ b/lix/libexpr/flake/flake.hh @@ -1,6 +1,7 @@ #pragma once ///@file +#include "lix/libexpr/eval.hh" #include "lix/libutil/types.hh" #include "lix/libexpr/flake/flakeref.hh" #include "lix/libexpr/flake/lockfile.hh" @@ -192,7 +193,7 @@ void callFlake( } void emitTreeAttrs( - EvalState & state, + Evaluator & state, const fetchers::Tree & tree, const fetchers::Input & input, Value & v, diff --git a/lix/libexpr/nixexpr.cc b/lix/libexpr/nixexpr.cc index 376b03f04..1f51fbf45 100644 --- a/lix/libexpr/nixexpr.cc +++ b/lix/libexpr/nixexpr.cc @@ -295,36 +295,36 @@ std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath) /* Computing levels/displacements for variables. */ -void Expr::bindVars(EvalState & es, const std::shared_ptr & env) +void Expr::bindVars(Evaluator & es, const std::shared_ptr & env) { abort(); } -void ExprInt::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprInt::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); } -void ExprFloat::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprFloat::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); } -void ExprString::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprString::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); } -void ExprPath::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprPath::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); } -void ExprVar::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprVar::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -373,13 +373,13 @@ void ExprVar::bindVars(EvalState & es, const std::shared_ptr & this->level = withLevel; } -void ExprInheritFrom::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprInheritFrom::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); } -void ExprSelect::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprSelect::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -391,7 +391,7 @@ void ExprSelect::bindVars(EvalState & es, const std::shared_ptr i.expr->bindVars(es, env); } -void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprOpHasAttr::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -403,7 +403,7 @@ void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr ExprAttrs::bindInheritSources( - EvalState & es, const std::shared_ptr & env) + Evaluator & es, const std::shared_ptr & env) { if (!inheritFromExprs) return nullptr; @@ -423,7 +423,7 @@ std::shared_ptr ExprAttrs::bindInheritSources( return inner; } -void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprAttrs::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -462,7 +462,7 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr } } -void ExprList::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprList::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -471,7 +471,7 @@ void ExprList::bindVars(EvalState & es, const std::shared_ptr & i->bindVars(es, env); } -void ExprLambda::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprLambda::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -498,7 +498,7 @@ void ExprLambda::bindVars(EvalState & es, const std::shared_ptr body->bindVars(es, newEnv); } -void ExprCall::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprCall::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -508,7 +508,7 @@ void ExprCall::bindVars(EvalState & es, const std::shared_ptr & e->bindVars(es, env); } -void ExprLet::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprLet::bindVars(Evaluator & es, const std::shared_ptr & env) { auto newEnv = [&] () -> std::shared_ptr { auto newEnv = std::make_shared(nullptr, env.get(), attrs->attrs.size()); @@ -531,7 +531,7 @@ void ExprLet::bindVars(EvalState & es, const std::shared_ptr & body->bindVars(es, newEnv); } -void ExprWith::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprWith::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -557,7 +557,7 @@ void ExprWith::bindVars(EvalState & es, const std::shared_ptr & body->bindVars(es, newEnv); } -void ExprIf::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprIf::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -567,7 +567,7 @@ void ExprIf::bindVars(EvalState & es, const std::shared_ptr & e else_->bindVars(es, env); } -void ExprAssert::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprAssert::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -576,7 +576,7 @@ void ExprAssert::bindVars(EvalState & es, const std::shared_ptr body->bindVars(es, env); } -void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprOpNot::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -584,7 +584,7 @@ void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr e->bindVars(es, env); } -void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprConcatStrings::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); @@ -593,7 +593,7 @@ void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptrbindVars(es, env); } -void ExprPos::bindVars(EvalState & es, const std::shared_ptr & env) +void ExprPos::bindVars(Evaluator & es, const std::shared_ptr & env) { if (es.debug) es.debug->exprEnvs.insert(std::make_pair(this, env)); diff --git a/lix/libexpr/nixexpr.hh b/lix/libexpr/nixexpr.hh index 292ed18ef..bf2a3e8dc 100644 --- a/lix/libexpr/nixexpr.hh +++ b/lix/libexpr/nixexpr.hh @@ -18,7 +18,7 @@ namespace nix { struct Env; struct Value; -class EvalState; +class Evaluator; struct ExprWith; struct StaticEnv; @@ -59,7 +59,7 @@ public: virtual ~Expr() { }; virtual void show(const SymbolTable & symbols, std::ostream & str) const; - virtual void bindVars(EvalState & es, const std::shared_ptr & env); + virtual void bindVars(Evaluator & es, const std::shared_ptr & env); virtual void eval(EvalState & state, Env & env, Value & v); virtual Value * maybeThunk(EvalState & state, Env & env); virtual void setName(Symbol name); @@ -69,7 +69,7 @@ public: #define COMMON_METHODS \ void show(const SymbolTable & symbols, std::ostream & str) const override; \ void eval(EvalState & state, Env & env, Value & v) override; \ - void bindVars(EvalState & es, const std::shared_ptr & env) override; + void bindVars(Evaluator & es, const std::shared_ptr & env) override; struct ExprInt : Expr { @@ -163,7 +163,7 @@ struct ExprInheritFrom : ExprVar } void show(SymbolTable const & symbols, std::ostream & str) const override; - void bindVars(EvalState & es, const std::shared_ptr & env) override; + void bindVars(Evaluator & es, const std::shared_ptr & env) override; }; struct ExprSelect : Expr @@ -249,7 +249,7 @@ struct ExprAttrs : Expr COMMON_METHODS std::shared_ptr bindInheritSources( - EvalState & es, const std::shared_ptr & env); + Evaluator & es, const std::shared_ptr & env); Env * buildInheritFromEnv(EvalState & state, Env & up); void showBindings(const SymbolTable & symbols, std::ostream & str) const; }; @@ -424,7 +424,7 @@ struct ExprOpNot : Expr { \ str << "("; e1->show(symbols, str); str << " " s " "; e2->show(symbols, str); str << ")"; \ } \ - void bindVars(EvalState & es, const std::shared_ptr & env) override \ + void bindVars(Evaluator & es, const std::shared_ptr & env) override \ { \ e1->bindVars(es, env); e2->bindVars(es, env); \ } \ @@ -464,7 +464,7 @@ struct ExprBlackHole : Expr { void show(const SymbolTable & symbols, std::ostream & str) const override {} void eval(EvalState & state, Env & env, Value & v) override; - void bindVars(EvalState & es, const std::shared_ptr & env) override {} + void bindVars(Evaluator & es, const std::shared_ptr & env) override {} }; extern ExprBlackHole eBlackHole; diff --git a/lix/libexpr/parser/parser.cc b/lix/libexpr/parser/parser.cc index 82862e999..85c2000e5 100644 --- a/lix/libexpr/parser/parser.cc +++ b/lix/libexpr/parser/parser.cc @@ -22,7 +22,7 @@ namespace nix { -Expr * EvalState::parse( +Expr * Evaluator::parse( char * text, size_t length, Pos::Origin origin, diff --git a/lix/libexpr/primops/fetchTree.cc b/lix/libexpr/primops/fetchTree.cc index f382144dd..c81d5ae91 100644 --- a/lix/libexpr/primops/fetchTree.cc +++ b/lix/libexpr/primops/fetchTree.cc @@ -15,7 +15,7 @@ namespace nix { void emitTreeAttrs( - EvalState & state, + Evaluator & state, const fetchers::Tree & tree, const fetchers::Input & input, Value & v, @@ -196,7 +196,7 @@ static void fetchTree( state.ctx.paths.allowPath(tree.storePath); - emitTreeAttrs(state, tree, input2, v, params.emptyRevFallback, false); + emitTreeAttrs(state.ctx, tree, input2, v, params.emptyRevFallback, false); } static void prim_fetchTree(EvalState & state, const PosIdx pos, Value * * args, Value & v) diff --git a/lix/nix/build.cc b/lix/nix/build.cc index bd7e1a84b..cdd6c3b70 100644 --- a/lix/nix/build.cc +++ b/lix/nix/build.cc @@ -114,7 +114,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile void run(ref store, Installables && installables) override { - auto state = getEvalState(); + auto state = getEvaluator()->begin(); if (dryRun) { std::vector pathsToBuild; diff --git a/lix/nix/bundle.cc b/lix/nix/bundle.cc index aa6d51c09..bf2ba002e 100644 --- a/lix/nix/bundle.cc +++ b/lix/nix/bundle.cc @@ -73,8 +73,8 @@ struct CmdBundle : InstallableCommand void run(ref store, ref installable) override { - auto evaluator = getEvalState(); - auto evalState = evaluator; + auto evaluator = getEvaluator(); + auto evalState = evaluator->begin(); auto const installableValue = InstallableValue::require(installable); diff --git a/lix/nix/derivation-show.cc b/lix/nix/derivation-show.cc index fc290b7db..0053b8f0a 100644 --- a/lix/nix/derivation-show.cc +++ b/lix/nix/derivation-show.cc @@ -41,7 +41,7 @@ struct CmdShowDerivation : InstallablesCommand void run(ref store, Installables && installables) override { - auto drvPaths = Installable::toDerivations(*getEvalState(), store, installables, true); + auto drvPaths = Installable::toDerivations(*getEvaluator()->begin(), store, installables, true); if (recursive) { StorePathSet closure; diff --git a/lix/nix/develop.cc b/lix/nix/develop.cc index 439f33fc8..4e420ce9d 100644 --- a/lix/nix/develop.cc +++ b/lix/nix/develop.cc @@ -313,6 +313,7 @@ struct Common : InstallableCommand, MixProfile } std::string makeRcScript( + EvalState & state, ref store, const BuildEnvironment & buildEnvironment, const Path & tmpDir, @@ -364,9 +365,9 @@ struct Common : InstallableCommand, MixProfile /* Substitute redirects. */ for (auto & [installable_, dir_] : redirects) { auto dir = absPath(dir_); - auto installable = parseInstallable(*getEvalState(), store, installable_); + auto installable = parseInstallable(state, store, installable_); auto builtPaths = Installable::toStorePathSet( - *getEvalState(), getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable}); + state, getEvalStore(), store, Realise::Nothing, OperateOn::Output, {installable}); for (auto & path: builtPaths) { auto from = store->printStorePath(path); if (script.find(from) == std::string::npos) @@ -438,13 +439,13 @@ struct Common : InstallableCommand, MixProfile return res; } - StorePath getShellOutPath(ref store, ref installable) + StorePath getShellOutPath(EvalState & state, ref store, ref installable) { auto path = installable->getStorePath(); if (path && path->to_string().ends_with("-env")) return *path; else { - auto drvs = Installable::toDerivations(*getEvalState(), store, {installable}); + auto drvs = Installable::toDerivations(state, store, {installable}); if (drvs.size() != 1) throw Error("'%s' needs to evaluate to a single derivation, but it evaluated to %d derivations", @@ -457,9 +458,9 @@ struct Common : InstallableCommand, MixProfile } std::pair - getBuildEnvironment(ref store, ref installable) + getBuildEnvironment(EvalState & state, ref store, ref installable) { - auto shellOutPath = getShellOutPath(store, installable); + auto shellOutPath = getShellOutPath(state, store, installable); auto strPath = store->printStorePath(shellOutPath); @@ -547,16 +548,16 @@ struct CmdDevelop : Common, MixEnvironment void run(ref store, ref installable) override { - auto evaluator = getEvalState(); - auto state = evaluator; + auto evaluator = getEvaluator(); + auto state = evaluator->begin(); - auto [buildEnvironment, gcroot] = getBuildEnvironment(store, installable); + auto [buildEnvironment, gcroot] = getBuildEnvironment(*state, store, installable); auto [rcFileFd, rcFilePath] = createTempFile("nix-shell"); AutoDelete tmpDir(createTempDir("", "nix-develop"), true); - auto script = makeRcScript(store, buildEnvironment, (Path) tmpDir); + auto script = makeRcScript(*state, store, buildEnvironment, (Path) tmpDir); if (verbosity >= lvlDebug) script += "set -x\n"; @@ -611,7 +612,7 @@ struct CmdDevelop : Common, MixEnvironment auto bashInstallable = make_ref( this, - state, + evaluator, std::move(nixpkgs), "bashInteractive", ExtendedOutputsSpec::Default(), @@ -651,7 +652,7 @@ struct CmdDevelop : Common, MixEnvironment // chdir if installable is a flake of type git+file or path auto installableFlake = installable.dynamic_pointer_cast(); if (installableFlake) { - auto sourcePath = installableFlake->getLockedFlake(*getEvalState())->flake.resolvedRef.input.getSourcePath(); + auto sourcePath = installableFlake->getLockedFlake(*state)->flake.resolvedRef.input.getSourcePath(); if (sourcePath) { if (chdir(sourcePath->c_str()) == -1) { throw SysError("chdir to '%s' failed", *sourcePath); @@ -682,7 +683,8 @@ struct CmdPrintDevEnv : Common, MixJSON void run(ref store, ref installable) override { - auto buildEnvironment = getBuildEnvironment(store, installable).first; + auto state = getEvaluator()->begin(); + auto buildEnvironment = getBuildEnvironment(*state, store, installable).first; logger->pause(); @@ -690,7 +692,7 @@ struct CmdPrintDevEnv : Common, MixJSON logger->writeToStdout(buildEnvironment.toJSON()); } else { AutoDelete tmpDir(createTempDir("", "nix-dev-env"), true); - logger->writeToStdout(makeRcScript(store, buildEnvironment, tmpDir)); + logger->writeToStdout(makeRcScript(*state, store, buildEnvironment, tmpDir)); } } }; diff --git a/lix/nix/diff-closures.cc b/lix/nix/diff-closures.cc index b44ed1c8f..33f72b653 100644 --- a/lix/nix/diff-closures.cc +++ b/lix/nix/diff-closures.cc @@ -124,7 +124,7 @@ struct CmdDiffClosures : SourceExprCommand, MixOperateOnOptions void run(ref store) override { - auto state = getEvalState(); + auto state = getEvaluator()->begin(); auto before = parseInstallable(*state, store, _before); auto beforePath = Installable::toStorePath(*state, getEvalStore(), store, Realise::Outputs, operateOn, before); auto after = parseInstallable(*state, store, _after); diff --git a/lix/nix/edit.cc b/lix/nix/edit.cc index fabfca3d1..46b818327 100644 --- a/lix/nix/edit.cc +++ b/lix/nix/edit.cc @@ -27,8 +27,8 @@ struct CmdEdit : InstallableCommand void run(ref store, ref installable) override { - auto evaluator = getEvalState(); - auto state = evaluator; + auto evaluator = getEvaluator(); + auto state = evaluator->begin(); auto const installableValue = InstallableValue::require(installable); diff --git a/lix/nix/eval.cc b/lix/nix/eval.cc index 942e7f122..31d1a2ac2 100644 --- a/lix/nix/eval.cc +++ b/lix/nix/eval.cc @@ -61,8 +61,8 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption auto const installableValue = InstallableValue::require(installable); - auto evaluator = getEvalState(); - auto state = evaluator; + auto evaluator = getEvaluator(); + auto state = evaluator->begin(); auto [v, pos] = installableValue->toValue(*state); NixStringContext context; diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 3aa93ddaa..c0797e225 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -51,9 +51,9 @@ public: return parseFlakeRef(flakeUrl, absPath(".")); //FIXME } - LockedFlake lockFlake() + LockedFlake lockFlake(EvalState & state) { - return flake::lockFlake(*getEvalState(), getFlakeRef(), lockFlags); + return flake::lockFlake(state, getFlakeRef(), lockFlags); } std::vector getFlakeRefsForCompletion() override @@ -98,7 +98,7 @@ public: } }}, .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { - completeFlakeInputPath(completions, getEvalState(), getFlakeRefsForCompletion(), prefix); + completeFlakeInputPath(completions, *getEvaluator()->begin(), getFlakeRefsForCompletion(), prefix); }} }); @@ -123,7 +123,7 @@ public: lockFlags.writeLockFile = true; lockFlags.applyNixConfig = true; - lockFlake(); + lockFlake(*getEvaluator()->begin()); } }; @@ -163,7 +163,7 @@ struct CmdFlakeLock : FlakeCommand lockFlags.writeLockFile = true; lockFlags.applyNixConfig = true; - lockFlake(); + lockFlake(*getEvaluator()->begin()); } }; @@ -208,7 +208,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON void run(nix::ref store) override { - auto lockedFlake = lockFlake(); + auto lockedFlake = lockFlake(*getEvaluator()->begin()); auto & flake = lockedFlake.flake; auto formatTime = [](time_t time) -> std::string { std::ostringstream os{}; @@ -358,11 +358,11 @@ struct CmdFlakeCheck : FlakeCommand evalSettings.enableImportFromDerivation.setDefault(false); } - auto evaluator = getEvalState(); - auto state = evaluator; + auto evaluator = getEvaluator(); + auto state = evaluator->begin(); lockFlags.applyNixConfig = true; - auto flake = lockFlake(); + auto flake = lockFlake(*state); auto localSystem = std::string(settings.thisSystem.get()); bool hasErrors = false; @@ -840,7 +840,8 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand .completer = {[&](AddCompletions & completions, size_t, std::string_view prefix) { completeFlakeRefWithFragment( completions, - getEvalState(), + *getEvaluator()->begin(), + getEvaluator(), lockFlags, defaultTemplateAttrPathsPrefixes, defaultTemplateAttrPaths, @@ -853,8 +854,8 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand { auto flakeDir = absPath(destDir); - auto evaluator = getEvalState(); - auto evalState = evaluator; + auto evaluator = getEvaluator(); + auto evalState = evaluator->begin(); auto [templateFlakeRef, templateName] = parseFlakeRefWithFragment(templateUrl, absPath(".")); @@ -1049,7 +1050,7 @@ struct CmdFlakeArchive : FlakeCommand, MixJSON, MixDryRun void run(nix::ref store) override { - auto flake = lockFlake(); + auto flake = lockFlake(*getEvaluator()->begin()); StorePathSet sources; @@ -1132,9 +1133,9 @@ struct CmdFlakeShow : FlakeCommand, MixJSON { evalSettings.enableImportFromDerivation.setDefault(false); - auto evaluator = getEvalState(); - auto state = evaluator; - auto flake = std::make_shared(lockFlake()); + auto evaluator = getEvaluator(); + auto state = evaluator->begin(); + auto flake = std::make_shared(lockFlake(*state)); auto localSystem = std::string(settings.thisSystem.get()); std::function store) override { - auto evalState = getEvalState(); + auto evaluator = getEvaluator(); auto evalStore = getEvalStore(); + auto state = evaluator->begin(); - auto installable_ = parseInstallable(*evalState, store, "."); + auto installable_ = parseInstallable(*state, store, "."); auto & installable = InstallableValue::require(*installable_); - auto app = installable.toApp(*evalState).resolve(*evalState, evalStore, store); + auto app = installable.toApp(*state).resolve(*state, evalStore, store); Strings programArgs{app.program}; diff --git a/lix/nix/log.cc b/lix/nix/log.cc index 1dd853d8e..5081da95d 100644 --- a/lix/nix/log.cc +++ b/lix/nix/log.cc @@ -30,7 +30,7 @@ struct CmdLog : InstallableCommand subs.push_front(store); - auto b = installable->toDerivedPath(*getEvalState()); + auto b = installable->toDerivedPath(*getEvaluator()->begin()); // For compat with CLI today, TODO revisit auto oneUp = std::visit(overloaded { diff --git a/lix/nix/main.cc b/lix/nix/main.cc index 5ec41c69e..9e1bf1376 100644 --- a/lix/nix/main.cc +++ b/lix/nix/main.cc @@ -254,8 +254,8 @@ static void showHelp(std::vector subcommand, NixArgs & toplevel) evalSettings.restrictEval.override(false); evalSettings.pureEval.override(false); - EvalState evaluator({}, openStore("dummy://")); - auto * state = &evaluator; + Evaluator evaluator({}, openStore("dummy://")); + auto state = evaluator.begin(); auto vGenerateManpage = evaluator.mem.allocValue(); state->eval(evaluator.parseExprFromString( @@ -411,7 +411,7 @@ void mainWrapped(int argc, char * * argv) | Xp::FetchClosure | Xp::DynamicDerivations); evalSettings.pureEval.override(false); - EvalState state({}, openStore("dummy://")); + Evaluator state({}, openStore("dummy://")); auto res = nlohmann::json::object(); res["builtins"] = ({ auto builtinsJson = nlohmann::json::object(); diff --git a/lix/nix/prefetch.cc b/lix/nix/prefetch.cc index 04fed2ba0..9457ad797 100644 --- a/lix/nix/prefetch.cc +++ b/lix/nix/prefetch.cc @@ -1,4 +1,5 @@ #include "lix/libcmd/command.hh" +#include "lix/libexpr/eval.hh" #include "lix/libmain/common-args.hh" #include "lix/libmain/loggers.hh" #include "lix/libmain/shared.hh" @@ -185,8 +186,8 @@ static int main_nix_prefetch_url(std::string programName, Strings argv) setLogFormat(LogFormat::bar); auto store = openStore(); - auto evaluator = std::make_unique(myArgs.searchPath, store); - auto & state = evaluator; + auto evaluator = std::make_unique(myArgs.searchPath, store); + auto state = evaluator->begin(); Bindings & autoArgs = *myArgs.getAutoArgs(*evaluator); diff --git a/lix/nix/profile.cc b/lix/nix/profile.cc index cd55a32bf..37e9c8a95 100644 --- a/lix/nix/profile.cc +++ b/lix/nix/profile.cc @@ -69,11 +69,12 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile void run(ref store, Installables && installables) override { - ProfileManifest manifest(*getEvalState(), *profile); + auto state = getEvaluator()->begin(); + ProfileManifest manifest(*state, *profile); auto builtPaths = builtPathsPerInstallable( Installable::build2( - *getEvalState(), getEvalStore(), store, Realise::Outputs, installables, bmNormal)); + *state, getEvalStore(), store, Realise::Outputs, installables, bmNormal)); for (auto & installable : installables) { ProfileElement element; @@ -240,7 +241,7 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem void run(ref store) override { - ProfileManifest oldManifest(*getEvalState(), *profile); + ProfileManifest oldManifest(*getEvaluator()->begin(), *profile); auto matchers = getMatchers(store); @@ -289,7 +290,8 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf void run(ref store) override { - ProfileManifest manifest(*getEvalState(), *profile); + auto state = getEvaluator()->begin(); + ProfileManifest manifest(*state, *profile); auto matchers = getMatchers(store); @@ -334,7 +336,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf auto installable = make_ref( this, - getEvalState(), + getEvaluator(), FlakeRef(element.source->originalRef), "", element.source->outputs, @@ -343,7 +345,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf lockFlags ); - auto derivedPaths = installable->toDerivedPaths(*getEvalState()); + auto derivedPaths = installable->toDerivedPaths(*state); if (derivedPaths.empty()) { continue; } @@ -393,7 +395,7 @@ struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProf auto builtPaths = builtPathsPerInstallable( Installable::build2( - *getEvalState(), getEvalStore(), store, Realise::Outputs, installables, bmNormal)); + *state, getEvalStore(), store, Realise::Outputs, installables, bmNormal)); for (size_t i = 0; i < installables.size(); ++i) { auto & installable = installables.at(i); @@ -424,7 +426,7 @@ struct CmdProfileList : virtual EvalCommand, virtual StoreCommand, MixDefaultPro void run(ref store) override { - ProfileManifest manifest(*getEvalState(), *profile); + ProfileManifest manifest(*getEvaluator()->begin(), *profile); if (json) { std::cout << manifest.toJSON(*store).dump() << "\n"; @@ -509,7 +511,7 @@ struct CmdProfileHistory : virtual StoreCommand, EvalCommand, MixDefaultProfile bool first = true; for (auto & gen : gens) { - ProfileManifest manifest(*getEvalState(), gen.path); + ProfileManifest manifest(*getEvaluator()->begin(), gen.path); if (!first) logger->cout(""); first = false; diff --git a/lix/nix/repl.cc b/lix/nix/repl.cc index c6ba796ac..655824fdf 100644 --- a/lix/nix/repl.cc +++ b/lix/nix/repl.cc @@ -63,8 +63,8 @@ struct CmdRepl : RawInstallablesCommand void run(ref store, std::vector && rawInstallables) override { - auto evaluator = getEvalState(); - auto state = evaluator; + auto evaluator = getEvaluator(); + auto state = evaluator->begin(); auto getValues = [&]()->AbstractNixRepl::AnnotatedValues{ auto installables = parseInstallables(*state, store, rawInstallables); AbstractNixRepl::AnnotatedValues values; diff --git a/lix/nix/run.cc b/lix/nix/run.cc index 8df68c343..e4b8a0035 100644 --- a/lix/nix/run.cc +++ b/lix/nix/run.cc @@ -111,7 +111,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment void run(ref store, Installables && installables) override { - auto outPaths = Installable::toStorePaths(*getEvalState(), getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables); + auto outPaths = Installable::toStorePaths(*getEvaluator()->begin(), getEvalStore(), store, Realise::Outputs, OperateOn::Output, installables); auto accessor = store->getFSAccessor(); @@ -200,7 +200,7 @@ struct CmdRun : InstallableCommand void run(ref store, ref installable) override { - auto state = getEvalState(); + auto state = getEvaluator()->begin(); auto installableValue = InstallableValue::require(installable); diff --git a/lix/nix/search.cc b/lix/nix/search.cc index 275dfbbb3..58c8a3890 100644 --- a/lix/nix/search.cc +++ b/lix/nix/search.cc @@ -84,8 +84,8 @@ struct CmdSearch : InstallableCommand, MixJSON for (auto & re : excludeRes) excludeRegexes.emplace_back(re, std::regex::extended | std::regex::icase); - auto evaluator = getEvalState(); - auto state = evaluator; + auto evaluator = getEvaluator(); + auto state = evaluator->begin(); std::optional jsonOut; if (json) jsonOut = json::object(); diff --git a/lix/nix/store-copy-log.cc b/lix/nix/store-copy-log.cc index 617024071..26b3c2fa1 100644 --- a/lix/nix/store-copy-log.cc +++ b/lix/nix/store-copy-log.cc @@ -31,7 +31,7 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand auto dstStore = getDstStore(); auto & dstLogStore = require(*dstStore); - for (auto & drvPath : Installable::toDerivations(*getEvalState(), getEvalStore(), installables, true)) { + for (auto & drvPath : Installable::toDerivations(*getEvaluator()->begin(), getEvalStore(), installables, true)) { if (auto log = srcLogStore.getBuildLog(drvPath)) dstLogStore.addBuildLog(drvPath, *log); else diff --git a/lix/nix/upgrade-nix.cc b/lix/nix/upgrade-nix.cc index 5a457aa15..a49b1f08d 100644 --- a/lix/nix/upgrade-nix.cc +++ b/lix/nix/upgrade-nix.cc @@ -218,9 +218,9 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand // nb: nothing actually gets evaluated here. // The ProfileManifest constructor only evaluates anything for manifest.nix // profiles, which this is not. - auto evalState = this->getEvalState(); + auto evalState = this->getEvaluator(); - ProfileManifest manifest(*evalState, profileDir); + ProfileManifest manifest(*evalState->begin(), profileDir); // Find which profile element has Nix in it. // It should be impossible to *not* have Nix, since we grabbed this @@ -288,8 +288,8 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand auto [res, content] = getFileTransfer()->download(storePathsUrl); auto data = content->drain(); - auto evaluator = std::make_unique(SearchPath{}, store); - auto & state = evaluator; + auto evaluator = std::make_unique(SearchPath{}, store); + auto state = evaluator->begin(); auto v = evaluator->mem.allocValue(); state->eval(evaluator->parseExprFromString(data, CanonPath("/no-such-path")), *v); Bindings & bindings(*evaluator->mem.allocBindings(0)); diff --git a/lix/nix/why-depends.cc b/lix/nix/why-depends.cc index 1a5246bb4..5ebc7cdd3 100644 --- a/lix/nix/why-depends.cc +++ b/lix/nix/why-depends.cc @@ -76,7 +76,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions void run(ref store) override { - auto state = getEvalState(); + auto state = getEvaluator()->begin(); auto package = parseInstallable(*state, store, _package); auto packagePath = Installable::toStorePath(*state, getEvalStore(), store, Realise::Outputs, operateOn, package); diff --git a/tests/unit/libcmd/args.cc b/tests/unit/libcmd/args.cc index dfb3ac3bd..4283dd663 100644 --- a/tests/unit/libcmd/args.cc +++ b/tests/unit/libcmd/args.cc @@ -31,7 +31,7 @@ TEST(Arguments, lookupFileArg) { searchPath.elements.push_back(SearchPath::Elem::parse(searchPathElem)); auto store = openStore("dummy://"); - auto state = std::make_shared(searchPath, store, store); + auto state = std::make_shared(searchPath, store, store); SourcePath const foundUnitData = lookupFileArg(*state, ""); EXPECT_EQ(foundUnitData.path, canonDataPath); diff --git a/tests/unit/libexpr-support/tests/libexpr.hh b/tests/unit/libexpr-support/tests/libexpr.hh index 41ccc2c72..aab674942 100644 --- a/tests/unit/libexpr-support/tests/libexpr.hh +++ b/tests/unit/libexpr-support/tests/libexpr.hh @@ -24,7 +24,8 @@ namespace nix { LibExprTest() : LibStoreTest() , evaluator({}, store) - , state(evaluator) + , statePtr(evaluator.begin()) + , state(*statePtr) { } Value eval(std::string input, bool forceValue = true, const FeatureSettings & fSettings = featureSettings) { @@ -40,7 +41,8 @@ namespace nix { return evaluator.symbols.create(value); } - EvalState evaluator; + Evaluator evaluator; + box_ptr statePtr; EvalState & state; };