libexpr: fully separate evaluator and running evaluation

this finally gives us a witness type we can use to prove that a certain
call graph subtree can't be used in kj promises using only a single new
assumption: if EvalState& is never held as a reference member of a type
and instead only ever passes as an argument or held on the stack we can
be certain that anything that has access to en EvalState ref must never
be run inside a promise and, crucially, that anything that doesn't have
access to an EvalState& *can* be run inside a promise without problems.

Change-Id: I6c15ada479175ad7e6cd3e4a729a5586b3ba30d6
This commit is contained in:
eldritch horrors
2024-12-05 13:30:35 +00:00
parent 07a26fc776
commit 61eed2c97c
45 changed files with 317 additions and 272 deletions
+2 -2
View File
@@ -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<EvalState>(myArgs.searchPath, evalStore, store);
auto evaluator = std::make_unique<Evaluator>(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);
+10 -10
View File
@@ -59,7 +59,7 @@ struct Globals
{
InstallSourceInfo instSource;
Path profile;
std::shared_ptr<EvalState> state;
std::shared_ptr<Evaluator> 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<LocalFSStore>();
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<DrvInfo>
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<EvalState>(new EvalState(myArgs.searchPath, store));
globals.state = std::make_shared<Evaluator>(myArgs.searchPath, store);
globals.state->repair = myArgs.repair;
globals.instSource.nixExprPath = std::make_shared<SourcePath>(
+2 -2
View File
@@ -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<EvalState>(myArgs.searchPath, evalStore, store);
auto & state = evaluator;
auto evaluator = std::make_unique<Evaluator>(myArgs.searchPath, evalStore, store);
auto state = evaluator->begin();
evaluator->repair = myArgs.repair;
Bindings & autoArgs = *myArgs.getAutoArgs(*evaluator);
+4 -4
View File
@@ -102,17 +102,17 @@ ref<Store> EvalCommand::getEvalStore()
return ref<Store>(evalStore);
}
ref<eval_cache::CachingEvalState> EvalCommand::getEvalState()
ref<eval_cache::CachingEvaluator> EvalCommand::getEvaluator()
{
if (!evalState) {
evalState = std::allocate_shared<eval_cache::CachingEvalState>(
evalState = std::allocate_shared<eval_cache::CachingEvaluator>(
TraceableAllocator<EvalState>(), searchPath, getEvalStore(), getStore(),
startReplOnEvalErrors ? AbstractNixRepl::runSimple : nullptr
);
evalState->repair = repair;
}
return ref<eval_cache::CachingEvalState>(evalState);
return ref<eval_cache::CachingEvaluator>(evalState);
}
MixOperateOnOptions::MixOperateOnOptions()
@@ -162,7 +162,7 @@ void BuiltPathsCommand::run(ref<Store> 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
+6 -5
View File
@@ -77,12 +77,12 @@ struct EvalCommand : virtual StoreCommand, MixEvalArgs
ref<Store> getEvalStore();
ref<eval_cache::CachingEvalState> getEvalState();
ref<eval_cache::CachingEvaluator> getEvaluator();
private:
std::shared_ptr<Store> evalStore;
std::shared_ptr<eval_cache::CachingEvalState> evalState;
std::shared_ptr<eval_cache::CachingEvaluator> 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 & evalState,
const std::vector<FlakeRef> & flakeRefs,
std::string_view prefix);
@@ -332,7 +332,8 @@ void completeFlakeRef(AddCompletions & completions, ref<Store> store, std::strin
void completeFlakeRefWithFragment(
AddCompletions & completions,
ref<eval_cache::CachingEvalState> evalState,
EvalState & evalState,
ref<eval_cache::CachingEvaluator> evaluator,
flake::LockFlags lockFlags,
Strings attrPathPrefixes,
const Strings & defaultFlakeAttrPaths,
+2 -2
View File
@@ -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);
+3 -2
View File
@@ -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);
}
+2 -2
View File
@@ -12,7 +12,7 @@
namespace nix {
InstallableAttrPath::InstallableAttrPath(
ref<eval_cache::CachingEvalState> state,
ref<eval_cache::CachingEvaluator> state,
SourceExprCommand & cmd,
Value * v,
const std::string & attrPath,
@@ -92,7 +92,7 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths(EvalState & state)
}
InstallableAttrPath InstallableAttrPath::parse(
ref<eval_cache::CachingEvalState> state,
ref<eval_cache::CachingEvaluator> state,
SourceExprCommand & cmd,
Value * v,
std::string_view prefix,
+2 -2
View File
@@ -20,7 +20,7 @@ class InstallableAttrPath : public InstallableValue
ExtendedOutputsSpec extendedOutputsSpec;
InstallableAttrPath(
ref<eval_cache::CachingEvalState> state,
ref<eval_cache::CachingEvaluator> state,
SourceExprCommand & cmd,
Value * v,
const std::string & attrPath,
@@ -35,7 +35,7 @@ class InstallableAttrPath : public InstallableValue
public:
static InstallableAttrPath parse(
ref<eval_cache::CachingEvalState> state,
ref<eval_cache::CachingEvaluator> state,
SourceExprCommand & cmd,
Value * v,
std::string_view prefix,
+1 -1
View File
@@ -53,7 +53,7 @@ static std::string showAttrPaths(const std::vector<std::string> & paths)
InstallableFlake::InstallableFlake(
SourceExprCommand * cmd,
ref<eval_cache::CachingEvalState> state,
ref<eval_cache::CachingEvaluator> state,
FlakeRef && flakeRef,
std::string_view fragment,
ExtendedOutputsSpec extendedOutputsSpec,
+3 -2
View File
@@ -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<eval_cache::CachingEvalState> state,
ref<eval_cache::CachingEvaluator> state,
FlakeRef && flakeRef,
std::string_view fragment,
ExtendedOutputsSpec extendedOutputsSpec,
@@ -81,7 +82,7 @@ static inline FlakeRef defaultNixpkgsFlakeRef()
}
ref<eval_cache::EvalCache> openEvalCache(
eval_cache::CachingEvalState & state,
eval_cache::CachingEvaluator & state,
std::shared_ptr<flake::LockedFlake> lockedFlake);
}
+3 -7
View File
@@ -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<eval_cache::CachingEvalState> evaluator;
ref<eval_cache::CachingEvalState> state;
ref<eval_cache::CachingEvaluator> evaluator;
InstallableValue(ref<eval_cache::CachingEvalState> evaluator)
: evaluator(evaluator)
, state(evaluator)
{
}
InstallableValue(ref<eval_cache::CachingEvaluator> evaluator) : evaluator(evaluator) {}
virtual ~InstallableValue() { }
+40 -36
View File
@@ -25,12 +25,12 @@ namespace nix {
void completeFlakeInputPath(
AddCompletions & completions,
ref<EvalState> evalState,
EvalState & evalState,
const std::vector<FlakeRef> & 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<eval_cache::CachingEvalState> evalState,
EvalState & evalState,
ref<eval_cache::CachingEvaluator> 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<flake::LockedFlake>(lockFlake(*evalState, flakeRef, lockFlags)));
auto evalCache = openEvalCache(
*evaluator,
std::make_shared<flake::LockedFlake>(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<eval_cache::EvalCache> openEvalCache(
eval_cache::CachingEvalState & state,
eval_cache::CachingEvaluator & state,
std::shared_ptr<flake::LockedFlake> 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<InstallableFlake>(
this,
getEvalState(),
getEvaluator(),
std::move(flakeRef),
fragment,
std::move(extendedOutputsSpec),
@@ -836,7 +840,7 @@ std::vector<FlakeRef> InstallableCommand::getFlakeRefsForCompletion()
void InstallablesCommand::run(ref<Store> store, std::vector<std::string> && 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> store)
{
auto installable = parseInstallable(*getEvalState(), store, _installable);
auto installable = parseInstallable(*getEvaluator()->begin(), store, _installable);
run(store, std::move(installable));
}
+2 -2
View File
@@ -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<ReplInteracter> makeInteracter() {
NixRepl::NixRepl(const SearchPath & searchPath, nix::ref<Store> store, EvalState & state,
std::function<NixRepl::AnnotatedValues()> getValues)
: AbstractNixRepl(state)
, evaluator(state)
, evaluator(state.ctx)
, debugTraceIndex(0)
, getValues(getValues)
, staticEnv(new StaticEnv(nullptr, evaluator.builtins.staticEnv.get()))
+1 -1
View File
@@ -322,7 +322,7 @@ static std::shared_ptr<AttrDb> makeAttrDb(const Hash & fingerprint)
}
}
ref<EvalCache> CachingEvalState::getCacheFor(Hash hash, RootLoader rootLoader)
ref<EvalCache> CachingEvaluator::getCacheFor(Hash hash, RootLoader rootLoader)
{
if (auto it = caches.find(hash); it != caches.end()) {
return it->second;
+2 -2
View File
@@ -22,7 +22,7 @@ typedef std::function<Value *(EvalState &)> 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<Hash, ref<EvalCache>> caches;
public:
using EvalState::EvalState;
using Evaluator::Evaluator;
ref<EvalCache> getCacheFor(Hash hash, RootLoader rootLoader);
};
+24 -19
View File
@@ -305,8 +305,7 @@ EvalPaths::EvalPaths(
}
}
EvalContext::EvalContext(
EvalState & parent,
Evaluator::Evaluator(
const SearchPath & _searchPath,
ref<Store> store,
std::shared_ptr<Store> buildStore,
@@ -330,8 +329,11 @@ EvalContext::EvalContext(
debugRepl ? std::make_unique<DebugState>(
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> store,
std::shared_ptr<Store> buildStore,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl)
: EvalContext(*this, _searchPath, store, buildStore, debugRepl)
box_ptr<EvalState> Evaluator::begin()
{
assert(!activeEval);
return box_ptr<EvalState>::unsafeFromNonnull(std::unique_ptr<EvalState>(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> & staticEnv)
Expr & Evaluator::parseExprFromFile(const SourcePath & path, std::shared_ptr<StaticEnv> & 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> & 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<std::string>(drainFD(0));
+90 -63
View File
@@ -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<DebugState> debug;
EvalErrorContext errors;
EvalContext(
EvalState & parent,
Evaluator(
const SearchPath & _searchPath,
ref<Store> store,
std::shared_ptr<Store> buildStore = nullptr,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> 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> store,
std::shared_ptr<Store> buildStore = nullptr,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> 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> & 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<EvalState> 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> & 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:
/**
+4 -4
View File
@@ -37,7 +37,7 @@ static std::optional<FetchedFlake> lookupInFlakeCache(
}
static std::tuple<fetchers::Tree, FlakeRef, FlakeRef> 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<LockedNode>(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,
+2 -1
View File
@@ -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,
+21 -21
View File
@@ -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<const StaticEnv> & env)
void Expr::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
abort();
}
void ExprInt::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprInt::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
if (es.debug)
es.debug->exprEnvs.insert(std::make_pair(this, env));
}
void ExprFloat::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprFloat::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
if (es.debug)
es.debug->exprEnvs.insert(std::make_pair(this, env));
}
void ExprString::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprString::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
if (es.debug)
es.debug->exprEnvs.insert(std::make_pair(this, env));
}
void ExprPath::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprPath::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
if (es.debug)
es.debug->exprEnvs.insert(std::make_pair(this, env));
}
void ExprVar::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprVar::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> &
this->level = withLevel;
}
void ExprInheritFrom::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprInheritFrom::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
if (es.debug)
es.debug->exprEnvs.insert(std::make_pair(this, env));
}
void ExprSelect::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprSelect::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv>
i.expr->bindVars(es, env);
}
void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprOpHasAttr::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticE
}
std::shared_ptr<const StaticEnv> ExprAttrs::bindInheritSources(
EvalState & es, const std::shared_ptr<const StaticEnv> & env)
Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
if (!inheritFromExprs)
return nullptr;
@@ -423,7 +423,7 @@ std::shared_ptr<const StaticEnv> ExprAttrs::bindInheritSources(
return inner;
}
void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprAttrs::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv>
}
}
void ExprList::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprList::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> &
i->bindVars(es, env);
}
void ExprLambda::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprLambda::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv>
body->bindVars(es, newEnv);
}
void ExprCall::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprCall::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> &
e->bindVars(es, env);
}
void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprLet::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
auto newEnv = [&] () -> std::shared_ptr<const StaticEnv> {
auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), attrs->attrs.size());
@@ -531,7 +531,7 @@ void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
body->bindVars(es, newEnv);
}
void ExprWith::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprWith::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> &
body->bindVars(es, newEnv);
}
void ExprIf::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprIf::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> & e
else_->bindVars(es, env);
}
void ExprAssert::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprAssert::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv>
body->bindVars(es, env);
}
void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprOpNot::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv>
e->bindVars(es, env);
}
void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprConcatStrings::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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_ptr<const Sta
i.second->bindVars(es, env);
}
void ExprPos::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
void ExprPos::bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env)
{
if (es.debug)
es.debug->exprEnvs.insert(std::make_pair(this, env));
+7 -7
View File
@@ -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<const StaticEnv> & env);
virtual void bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> & env) override;
void bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> & env) override;
void bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env) override;
};
struct ExprSelect : Expr
@@ -249,7 +249,7 @@ struct ExprAttrs : Expr
COMMON_METHODS
std::shared_ptr<const StaticEnv> bindInheritSources(
EvalState & es, const std::shared_ptr<const StaticEnv> & env);
Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> & env) override \
void bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & 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<const StaticEnv> & env) override {}
void bindVars(Evaluator & es, const std::shared_ptr<const StaticEnv> & env) override {}
};
extern ExprBlackHole eBlackHole;
+1 -1
View File
@@ -22,7 +22,7 @@
namespace nix {
Expr * EvalState::parse(
Expr * Evaluator::parse(
char * text,
size_t length,
Pos::Origin origin,
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -114,7 +114,7 @@ struct CmdBuild : InstallablesCommand, MixDryRun, MixJSON, MixProfile
void run(ref<Store> store, Installables && installables) override
{
auto state = getEvalState();
auto state = getEvaluator()->begin();
if (dryRun) {
std::vector<DerivedPath> pathsToBuild;
+2 -2
View File
@@ -73,8 +73,8 @@ struct CmdBundle : InstallableCommand
void run(ref<Store> store, ref<Installable> installable) override
{
auto evaluator = getEvalState();
auto evalState = evaluator;
auto evaluator = getEvaluator();
auto evalState = evaluator->begin();
auto const installableValue = InstallableValue::require(installable);
+1 -1
View File
@@ -41,7 +41,7 @@ struct CmdShowDerivation : InstallablesCommand
void run(ref<Store> 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;
+16 -14
View File
@@ -313,6 +313,7 @@ struct Common : InstallableCommand, MixProfile
}
std::string makeRcScript(
EvalState & state,
ref<Store> 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> store, ref<Installable> installable)
StorePath getShellOutPath(EvalState & state, ref<Store> store, ref<Installable> 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<BuildEnvironment, std::string>
getBuildEnvironment(ref<Store> store, ref<Installable> installable)
getBuildEnvironment(EvalState & state, ref<Store> store, ref<Installable> 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> store, ref<Installable> 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<InstallableFlake>(
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<InstallableFlake>();
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> store, ref<Installable> 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));
}
}
};
+1 -1
View File
@@ -124,7 +124,7 @@ struct CmdDiffClosures : SourceExprCommand, MixOperateOnOptions
void run(ref<Store> 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);
+2 -2
View File
@@ -27,8 +27,8 @@ struct CmdEdit : InstallableCommand
void run(ref<Store> store, ref<Installable> installable) override
{
auto evaluator = getEvalState();
auto state = evaluator;
auto evaluator = getEvaluator();
auto state = evaluator->begin();
auto const installableValue = InstallableValue::require(installable);
+2 -2
View File
@@ -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;
+17 -16
View File
@@ -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<FlakeRef> 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<nix::Store> 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<nix::Store> 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<LockedFlake>(lockFlake());
auto evaluator = getEvaluator();
auto state = evaluator->begin();
auto flake = std::make_shared<LockedFlake>(lockFlake(*state));
auto localSystem = std::string(settings.thisSystem.get());
std::function<bool(
+4 -3
View File
@@ -29,12 +29,13 @@ struct CmdFmt : SourceExprCommand {
void run(ref<Store> 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};
+1 -1
View File
@@ -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 {
+3 -3
View File
@@ -254,8 +254,8 @@ static void showHelp(std::vector<std::string> 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();
+3 -2
View File
@@ -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<EvalState>(myArgs.searchPath, store);
auto & state = evaluator;
auto evaluator = std::make_unique<Evaluator>(myArgs.searchPath, store);
auto state = evaluator->begin();
Bindings & autoArgs = *myArgs.getAutoArgs(*evaluator);
+11 -9
View File
@@ -69,11 +69,12 @@ struct CmdProfileInstall : InstallablesCommand, MixDefaultProfile
void run(ref<Store> 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> 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> 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<InstallableFlake>(
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> 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;
+2 -2
View File
@@ -63,8 +63,8 @@ struct CmdRepl : RawInstallablesCommand
void run(ref<Store> store, std::vector<std::string> && 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;
+2 -2
View File
@@ -111,7 +111,7 @@ struct CmdShell : InstallablesCommand, MixEnvironment
void run(ref<Store> 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> store, ref<Installable> installable) override
{
auto state = getEvalState();
auto state = getEvaluator()->begin();
auto installableValue = InstallableValue::require(installable);
+2 -2
View File
@@ -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<nlohmann::json> jsonOut;
if (json) jsonOut = json::object();
+1 -1
View File
@@ -31,7 +31,7 @@ struct CmdCopyLog : virtual CopyCommand, virtual InstallablesCommand
auto dstStore = getDstStore();
auto & dstLogStore = require<LogStore>(*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
+4 -4
View File
@@ -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<EvalState>(SearchPath{}, store);
auto & state = evaluator;
auto evaluator = std::make_unique<Evaluator>(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));
+1 -1
View File
@@ -76,7 +76,7 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
void run(ref<Store> 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);
+1 -1
View File
@@ -31,7 +31,7 @@ TEST(Arguments, lookupFileArg) {
searchPath.elements.push_back(SearchPath::Elem::parse(searchPathElem));
auto store = openStore("dummy://");
auto state = std::make_shared<EvalState>(searchPath, store, store);
auto state = std::make_shared<Evaluator>(searchPath, store, store);
SourcePath const foundUnitData = lookupFileArg(*state, "<example>");
EXPECT_EQ(foundUnitData.path, canonDataPath);
+4 -2
View File
@@ -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<EvalState> statePtr;
EvalState & state;
};