nix repl: Put EvalState on the heap

See 0629601da1.
This commit is contained in:
Eelco Dolstra 2020-03-19 13:52:28 +01:00
parent b244e65cdb
commit ef74fafc03
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE

View file

@ -48,7 +48,7 @@ namespace nix {
struct NixRepl : gc struct NixRepl : gc
{ {
string curDir; string curDir;
EvalState state; std::unique_ptr<EvalState> state;
Bindings * autoArgs; Bindings * autoArgs;
Strings loadedFiles; Strings loadedFiles;
@ -126,8 +126,8 @@ string removeWhitespace(string s)
NixRepl::NixRepl(const Strings & searchPath, nix::ref<Store> store) NixRepl::NixRepl(const Strings & searchPath, nix::ref<Store> store)
: state(searchPath, store) : state(std::make_unique<EvalState>(searchPath, store))
, staticEnv(false, &state.staticBaseEnv) , staticEnv(false, &state->staticBaseEnv)
, historyFile(getDataDir() + "/nix/repl-history") , historyFile(getDataDir() + "/nix/repl-history")
{ {
curDir = absPath("."); curDir = absPath(".");
@ -356,8 +356,8 @@ StringSet NixRepl::completePrefix(string prefix)
Expr * e = parseString(expr); Expr * e = parseString(expr);
Value v; Value v;
e->eval(state, *env, v); e->eval(*state, *env, v);
state.forceAttrs(v); state->forceAttrs(v);
for (auto & i : *v.attrs) { for (auto & i : *v.attrs) {
string name = i.name; string name = i.name;
@ -412,11 +412,11 @@ bool isVarName(const string & s)
Path NixRepl::getDerivationPath(Value & v) { Path NixRepl::getDerivationPath(Value & v) {
auto drvInfo = getDerivation(state, v, false); auto drvInfo = getDerivation(*state, v, false);
if (!drvInfo) if (!drvInfo)
throw Error("expression does not evaluate to a derivation, so I can't build it"); throw Error("expression does not evaluate to a derivation, so I can't build it");
Path drvPath = drvInfo->queryDrvPath(); Path drvPath = drvInfo->queryDrvPath();
if (drvPath == "" || !state.store->isValidPath(state.store->parseStorePath(drvPath))) if (drvPath == "" || !state->store->isValidPath(state->store->parseStorePath(drvPath)))
throw Error("expression did not evaluate to a valid derivation"); throw Error("expression did not evaluate to a valid derivation");
return drvPath; return drvPath;
} }
@ -462,12 +462,12 @@ bool NixRepl::processLine(string line)
} }
else if (command == ":l" || command == ":load") { else if (command == ":l" || command == ":load") {
state.resetFileCache(); state->resetFileCache();
loadFile(arg); loadFile(arg);
} }
else if (command == ":r" || command == ":reload") { else if (command == ":r" || command == ":reload") {
state.resetFileCache(); state->resetFileCache();
reloadFiles(); reloadFiles();
} }
@ -479,13 +479,13 @@ bool NixRepl::processLine(string line)
if (v.type == tPath || v.type == tString) { if (v.type == tPath || v.type == tString) {
PathSet context; PathSet context;
auto filename = state.coerceToString(noPos, v, context); auto filename = state->coerceToString(noPos, v, context);
pos.file = state.symbols.create(filename); pos.file = state->symbols.create(filename);
} else if (v.type == tLambda) { } else if (v.type == tLambda) {
pos = v.lambda.fun->pos; pos = v.lambda.fun->pos;
} else { } else {
// assume it's a derivation // assume it's a derivation
pos = findDerivationFilename(state, v, arg); pos = findDerivationFilename(*state, v, arg);
} }
// Open in EDITOR // Open in EDITOR
@ -495,7 +495,7 @@ bool NixRepl::processLine(string line)
runProgram(editor, args); runProgram(editor, args);
// Reload right after exiting the editor // Reload right after exiting the editor
state.resetFileCache(); state->resetFileCache();
reloadFiles(); reloadFiles();
} }
@ -508,7 +508,7 @@ bool NixRepl::processLine(string line)
Value v, f, result; Value v, f, result;
evalString(arg, v); evalString(arg, v);
evalString("drv: (import <nixpkgs> {}).runCommand \"shell\" { buildInputs = [ drv ]; } \"\"", f); evalString("drv: (import <nixpkgs> {}).runCommand \"shell\" { buildInputs = [ drv ]; } \"\"", f);
state.callFunction(f, v, result, Pos()); state->callFunction(f, v, result, Pos());
Path drvPath = getDerivationPath(result); Path drvPath = getDerivationPath(result);
runProgram(settings.nixBinDir + "/nix-shell", Strings{drvPath}); runProgram(settings.nixBinDir + "/nix-shell", Strings{drvPath});
@ -524,10 +524,10 @@ bool NixRepl::processLine(string line)
but doing it in a child makes it easier to recover from but doing it in a child makes it easier to recover from
problems / SIGINT. */ problems / SIGINT. */
if (runProgram(settings.nixBinDir + "/nix", Strings{"build", "--no-link", drvPath}) == 0) { if (runProgram(settings.nixBinDir + "/nix", Strings{"build", "--no-link", drvPath}) == 0) {
auto drv = readDerivation(*state.store, drvPath); auto drv = readDerivation(*state->store, drvPath);
std::cout << std::endl << "this derivation produced the following outputs:" << std::endl; std::cout << std::endl << "this derivation produced the following outputs:" << std::endl;
for (auto & i : drv.outputs) for (auto & i : drv.outputs)
std::cout << fmt(" %s -> %s\n", i.first, state.store->printStorePath(i.second.path)); std::cout << fmt(" %s -> %s\n", i.first, state->store->printStorePath(i.second.path));
} }
} else if (command == ":i") { } else if (command == ":i") {
runProgram(settings.nixBinDir + "/nix-env", Strings{"-i", drvPath}); runProgram(settings.nixBinDir + "/nix-env", Strings{"-i", drvPath});
@ -557,11 +557,11 @@ bool NixRepl::processLine(string line)
isVarName(name = removeWhitespace(string(line, 0, p)))) isVarName(name = removeWhitespace(string(line, 0, p))))
{ {
Expr * e = parseString(string(line, p + 1)); Expr * e = parseString(string(line, p + 1));
Value & v(*state.allocValue()); Value & v(*state->allocValue());
v.type = tThunk; v.type = tThunk;
v.thunk.env = env; v.thunk.env = env;
v.thunk.expr = e; v.thunk.expr = e;
addVarToScope(state.symbols.create(name), v); addVarToScope(state->symbols.create(name), v);
} else { } else {
Value v; Value v;
evalString(line, v); evalString(line, v);
@ -578,21 +578,21 @@ void NixRepl::loadFile(const Path & path)
loadedFiles.remove(path); loadedFiles.remove(path);
loadedFiles.push_back(path); loadedFiles.push_back(path);
Value v, v2; Value v, v2;
state.evalFile(lookupFileArg(state, path), v); state->evalFile(lookupFileArg(*state, path), v);
state.autoCallFunction(*autoArgs, v, v2); state->autoCallFunction(*autoArgs, v, v2);
addAttrsToScope(v2); addAttrsToScope(v2);
} }
void NixRepl::initEnv() void NixRepl::initEnv()
{ {
env = &state.allocEnv(envSize); env = &state->allocEnv(envSize);
env->up = &state.baseEnv; env->up = &state->baseEnv;
displ = 0; displ = 0;
staticEnv.vars.clear(); staticEnv.vars.clear();
varNames.clear(); varNames.clear();
for (auto & i : state.staticBaseEnv.vars) for (auto & i : state->staticBaseEnv.vars)
varNames.insert(i.first); varNames.insert(i.first);
} }
@ -616,7 +616,7 @@ void NixRepl::reloadFiles()
void NixRepl::addAttrsToScope(Value & attrs) void NixRepl::addAttrsToScope(Value & attrs)
{ {
state.forceAttrs(attrs); state->forceAttrs(attrs);
for (auto & i : *attrs.attrs) for (auto & i : *attrs.attrs)
addVarToScope(i.name, *i.value); addVarToScope(i.name, *i.value);
std::cout << format("Added %1% variables.") % attrs.attrs->size() << std::endl; std::cout << format("Added %1% variables.") % attrs.attrs->size() << std::endl;
@ -635,7 +635,7 @@ void NixRepl::addVarToScope(const Symbol & name, Value & v)
Expr * NixRepl::parseString(string s) Expr * NixRepl::parseString(string s)
{ {
Expr * e = state.parseExprFromString(s, curDir, staticEnv); Expr * e = state->parseExprFromString(s, curDir, staticEnv);
return e; return e;
} }
@ -643,8 +643,8 @@ Expr * NixRepl::parseString(string s)
void NixRepl::evalString(string s, Value & v) void NixRepl::evalString(string s, Value & v)
{ {
Expr * e = parseString(s); Expr * e = parseString(s);
e->eval(state, *env, v); e->eval(*state, *env, v);
state.forceValue(v); state->forceValue(v);
} }
@ -674,7 +674,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
str.flush(); str.flush();
checkInterrupt(); checkInterrupt();
state.forceValue(v); state->forceValue(v);
switch (v.type) { switch (v.type) {
@ -703,13 +703,13 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
case tAttrs: { case tAttrs: {
seen.insert(&v); seen.insert(&v);
bool isDrv = state.isDerivation(v); bool isDrv = state->isDerivation(v);
if (isDrv) { if (isDrv) {
str << "«derivation "; str << "«derivation ";
Bindings::iterator i = v.attrs->find(state.sDrvPath); Bindings::iterator i = v.attrs->find(state->sDrvPath);
PathSet context; PathSet context;
Path drvPath = i != v.attrs->end() ? state.coerceToPath(*i->pos, *i->value, context) : "???"; Path drvPath = i != v.attrs->end() ? state->coerceToPath(*i->pos, *i->value, context) : "???";
str << drvPath << "»"; str << drvPath << "»";
} }
@ -812,7 +812,7 @@ struct CmdRepl : StoreCommand, MixEvalArgs
void run(ref<Store> store) override void run(ref<Store> store) override
{ {
auto repl = std::make_unique<NixRepl>(searchPath, openStore()); auto repl = std::make_unique<NixRepl>(searchPath, openStore());
repl->autoArgs = getAutoArgs(repl->state); repl->autoArgs = getAutoArgs(*repl->state);
repl->mainLoop(files); repl->mainLoop(files);
} }
}; };