diff --git a/src/libcmd/command.cc b/src/libcmd/command.cc index ee5102a6a..9cf2ff5e3 100644 --- a/src/libcmd/command.cc +++ b/src/libcmd/command.cc @@ -137,9 +137,10 @@ ref EvalCommand::getEvalState() if (error) printError("%s\n\n" ANSI_BOLD "Starting REPL to allow you to inspect the current state of the evaluator.\n" ANSI_NORMAL, error->what()); - if (expr.staticEnv) { - auto vm = mapStaticEnvBindings(evalState.symbols, *expr.staticEnv.get(), env); - runRepl(*const_cast(&evalState), *vm); + auto se = evalState->getStaticEnv(expr); + if (se) { + auto vm = mapStaticEnvBindings(evalState->symbols, *se.get(), env); + runRepl(evalState, *vm); } }; } diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index cb5d5bb34..5b17f2fb2 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -441,8 +441,9 @@ void NixRepl::loadDebugTraceEnv(DebugTrace & dt) { initEnv(); - if (dt.expr.staticEnv) { - auto vm = mapStaticEnvBindings(state->symbols, *dt.expr.staticEnv.get(), dt.env); + auto se = state->getStaticEnv(dt.expr); + if (se) { + auto vm = mapStaticEnvBindings(state->symbols, *se.get(), dt.env); // add staticenv vars. for (auto & [name, value] : *(vm.get())) @@ -516,7 +517,7 @@ bool NixRepl::processLine(std::string line) else if (debuggerHook && (command == ":env")) { for (const auto & [idx, i] : enumerate(state->debugTraces)) { if (idx == debugTraceIndex) { - printEnvBindings(state->symbols, i.expr, i.env); + printEnvBindings(*state, i.expr, i.env); break; } } @@ -533,7 +534,7 @@ bool NixRepl::processLine(std::string line) std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": "; showDebugTrace(std::cout, state->positions, i); std::cout << std::endl; - printEnvBindings(state->symbols, i.expr, i.env); + printEnvBindings(*state, i.expr, i.env); loadDebugTraceEnv(i); break; } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 3c998f7b6..bd1cbaab5 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -772,12 +772,12 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & } } -// TODO: add accompanying env for With stuff. -void printEnvBindings(const SymbolTable & st, const Expr & expr, const Env & env) +void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env) { // just print the names for now - if (expr.staticEnv) - printEnvBindings(st, *expr.staticEnv.get(), env, 0); + auto se = es.getStaticEnv(expr); + if (se) + printEnvBindings(es.symbols, *se, env, 0); } void mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, ValMap & vm) diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 26717a6f8..5227c7ce1 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -25,7 +25,7 @@ enum RepairFlag : bool; typedef void (* PrimOpFun) (EvalState & state, const PosIdx pos, Value * * args, Value & v); -void printEnvBindings(const SymbolTable & st, const Expr & expr, const Env & env); +void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env); void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, int lvl = 0); struct PrimOp @@ -130,6 +130,16 @@ public: bool debugStop; bool debugQuit; std::list debugTraces; + std::map > exprEnvs; + const std::shared_ptr getStaticEnv(const Expr &expr) const + { + auto i = exprEnvs.find(&expr); + if (i != exprEnvs.end()) + return i->second; + else + return std::shared_ptr();; + } + template [[gnu::noinline, gnu::noreturn]] diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index a7b7b8aad..cb5e1c3f2 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -296,38 +296,39 @@ std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath) /* Computing levels/displacements for variables. */ -void Expr::bindVars(const EvalState & es, const std::shared_ptr & env) +void Expr::bindVars(EvalState & es, const std::shared_ptr & env) { abort(); } -void ExprInt::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprInt::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env;} - -void ExprFloat::bindVars(const EvalState & es, const std::shared_ptr & env) -{ - if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); } -void ExprString::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprFloat::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); } -void ExprPath::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprString::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); } -void ExprVar::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprPath::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); +} + +void ExprVar::bindVars(EvalState & es, const std::shared_ptr & env) +{ + if (debuggerHook) + es.exprEnvs.insert(std::make_pair(this, env)); /* Check whether the variable appears in the environment. If so, set its level and displacement. */ @@ -360,10 +361,10 @@ void ExprVar::bindVars(const EvalState & es, const std::shared_ptrlevel = withLevel; } -void ExprSelect::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprSelect::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); e->bindVars(es, env); if (def) def->bindVars(es, env); @@ -372,10 +373,10 @@ void ExprSelect::bindVars(const EvalState & es, const std::shared_ptrbindVars(es, env); } -void ExprOpHasAttr::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); e->bindVars(es, env); for (auto & i : attrPath) @@ -383,10 +384,10 @@ void ExprOpHasAttr::bindVars(const EvalState & es, const std::shared_ptrbindVars(es, env); } -void ExprAttrs::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); if (recursive) { auto newEnv = std::make_shared(false, env.get(), recursive ? attrs.size() : 0); @@ -416,19 +417,19 @@ void ExprAttrs::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprList::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); for (auto & i : elems) i->bindVars(es, env); } -void ExprLambda::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprLambda::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); auto newEnv = std::make_shared( false, env.get(), @@ -452,20 +453,20 @@ void ExprLambda::bindVars(const EvalState & es, const std::shared_ptrbindVars(es, newEnv); } -void ExprCall::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprCall::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); fun->bindVars(es, env); for (auto e : args) e->bindVars(es, env); } -void ExprLet::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprLet::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); auto newEnv = std::make_shared(false, env.get(), attrs->attrs.size()); @@ -481,10 +482,10 @@ void ExprLet::bindVars(const EvalState & es, const std::shared_ptrbindVars(es, newEnv); } -void ExprWith::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprWith::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); /* Does this `with' have an enclosing `with'? If so, record its level so that `lookupVar' can look up variables in the previous @@ -499,53 +500,53 @@ void ExprWith::bindVars(const EvalState & es, const std::shared_ptrbindVars(es, env); auto newEnv = std::make_shared(true, env.get()); body->bindVars(es, newEnv); } -void ExprIf::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprIf::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); cond->bindVars(es, env); then->bindVars(es, env); else_->bindVars(es, env); } -void ExprAssert::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprAssert::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); cond->bindVars(es, env); body->bindVars(es, env); } -void ExprOpNot::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); e->bindVars(es, env); } -void ExprConcatStrings::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); for (auto & i : *this->es) i.second->bindVars(es, env); } -void ExprPos::bindVars(const EvalState & es, const std::shared_ptr & env) +void ExprPos::bindVars(EvalState & es, const std::shared_ptr & env) { if (debuggerHook) - staticEnv = env; + es.exprEnvs.insert(std::make_pair(this, env)); } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 856676033..80b6afa3e 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -144,18 +144,17 @@ struct Expr { virtual ~Expr() { }; virtual void show(const SymbolTable & symbols, std::ostream & str) const; - virtual void bindVars(const EvalState & es, const std::shared_ptr & env); + virtual void bindVars(EvalState & 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); - std::shared_ptr staticEnv; virtual PosIdx getPos() const { return noPos; } }; #define COMMON_METHODS \ void show(const SymbolTable & symbols, std::ostream & str) const; \ void eval(EvalState & state, Env & env, Value & v); \ - void bindVars(const EvalState & es, const std::shared_ptr & env); + void bindVars(EvalState & es, const std::shared_ptr & env); struct ExprInt : Expr { @@ -402,7 +401,7 @@ struct ExprOpNot : Expr { \ str << "("; e1->show(symbols, str); str << " " s " "; e2->show(symbols, str); str << ")"; \ } \ - void bindVars(const EvalState & es, const std::shared_ptr & env) \ + void bindVars(EvalState & es, const std::shared_ptr & env) \ { \ e1->bindVars(es, env); e2->bindVars(es, env); \ } \