From ef1d62ec6c2774f74a0029647f49032a123066af Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Tue, 3 Dec 2024 20:38:41 +0100 Subject: [PATCH] libexpr: abstract DebugState from EvalState this is necessary to share a debug state between multiple eval states. while doings so makes little sense at present it will be necessary for async io support since eval states must be async io roots, which means we must create them as needed from a shared evaluation context object. Change-Id: Id9d4b37aae40706f65c741e3b961855582e035ab --- lix/libcmd/command.cc | 7 ++----- lix/libexpr/eval-error.cc | 2 +- lix/libexpr/eval.cc | 25 ++++++++++++++++--------- lix/libexpr/eval.hh | 24 ++++++++++++++++-------- lix/libexpr/primops.cc | 4 ++-- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/lix/libcmd/command.cc b/lix/libcmd/command.cc index 362782fe1..4f489b361 100644 --- a/lix/libcmd/command.cc +++ b/lix/libcmd/command.cc @@ -106,14 +106,11 @@ ref EvalCommand::getEvalState() { if (!evalState) { evalState = std::allocate_shared( - TraceableAllocator(), searchPath, getEvalStore(), getStore() + TraceableAllocator(), searchPath, getEvalStore(), getStore(), + startReplOnEvalErrors ? AbstractNixRepl::runSimple : nullptr ); evalState->repair = repair; - - if (startReplOnEvalErrors) { - evalState->debug = std::make_unique(&AbstractNixRepl::runSimple); - }; } return ref(evalState); } diff --git a/lix/libexpr/eval-error.cc b/lix/libexpr/eval-error.cc index 3b79288fa..671b515e1 100644 --- a/lix/libexpr/eval-error.cc +++ b/lix/libexpr/eval-error.cc @@ -78,7 +78,7 @@ void EvalErrorBuilder::debugThrow() if (auto last = state.debug->traces().next()) { const Env * env = &(*last)->env; const Expr * expr = &(*last)->expr; - state.debug->runDebugRepl(state, &error, *env, *expr); + state.debug->onEvalError(&error, *env, *expr); } } diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index faa9ece46..44d741ce7 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -274,7 +274,8 @@ EvalBuiltins::EvalBuiltins( EvalState::EvalState( const SearchPath & _searchPath, ref store, - std::shared_ptr buildStore) + std::shared_ptr buildStore, + std::function debugRepl) : s(symbols) , searchPath([&] { SearchPath searchPath; @@ -290,6 +291,14 @@ EvalState::EvalState( , repair(NoRepair) , store(store) , buildStore(buildStore ? buildStore : store) + , debug{ + debugRepl ? std::make_unique( + positions, + symbols, + [this, debugRepl](const ValMap & extraEnv) { return debugRepl(*this, extraEnv); } + ) + : nullptr + } { countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0"; @@ -637,9 +646,7 @@ public: } }; -void DebugState::runDebugRepl( - EvalState & evalState, const EvalError * error, const Env & env, const Expr & expr -) +void DebugState::onEvalError(const EvalError * error, const Env & env, const Expr & expr) { // Make sure we have a debugger to run and we're not already in a debugger. if (inDebugger) @@ -648,7 +655,7 @@ void DebugState::runDebugRepl( auto dts = error && expr.getPos() ? addTrace(DebugTrace { - .pos = error->info().pos ? error->info().pos : evalState.positions[expr.getPos()], + .pos = error->info().pos ? error->info().pos : positions[expr.getPos()], .expr = expr, .env = env, .hint = error->info().msg, @@ -666,9 +673,9 @@ void DebugState::runDebugRepl( auto se = staticEnvFor(expr); if (se) { - auto vm = mapStaticEnvBindings(evalState.symbols, *se.get(), env); + auto vm = mapStaticEnvBindings(symbols, *se.get(), env); DebuggerGuard _guard(inDebugger); - auto exitStatus = repl(evalState, *vm); + auto exitStatus = errorCallback(*vm); switch (exitStatus) { case ReplExitStatus::QuitAll: if (error) @@ -718,8 +725,8 @@ static DebugState::TraceFrame makeDebugTraceStacker( .hint = HintFmt(formatArgs...), .isError = false, }); - if (state.debug->stop && state.debug->repl) - state.debug->runDebugRepl(state, nullptr, env, expr); + if (state.debug->stop && state.debug->errorCallback) + state.debug->onEvalError(nullptr, env, expr); return trace; } diff --git a/lix/libexpr/eval.hh b/lix/libexpr/eval.hh index 304284e33..4906975ae 100644 --- a/lix/libexpr/eval.hh +++ b/lix/libexpr/eval.hh @@ -143,23 +143,29 @@ struct DebugState { private: std::weak_ptr latestTrace; + const PosTable & positions; + const SymbolTable & symbols; public: - std::function repl; + std::function errorCallback; bool stop = false; bool inDebugger = false; std::map> exprEnvs; int trylevel = 0; - explicit DebugState(std::function repl) - : repl(repl) + explicit DebugState( + const PosTable & positions, + const SymbolTable & symbols, + std::function errorCallback + ) + : positions(positions) + , symbols(symbols) + , errorCallback(errorCallback) { - assert(repl); + assert(errorCallback); } - void runDebugRepl( - EvalState & evalState, const EvalError * error, const Env & env, const Expr & expr - ); + void onEvalError(const EvalError * error, const Env & env, const Expr & expr); const std::shared_ptr staticEnvFor(const Expr & expr) const { @@ -409,7 +415,9 @@ public: EvalState( const SearchPath & _searchPath, ref store, - std::shared_ptr buildStore = nullptr); + std::shared_ptr buildStore = nullptr, + std::function debugRepl = nullptr + ); ~EvalState(); /** diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 614ec1f26..aba5d43ec 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -579,7 +579,7 @@ static void prim_break(EvalState & state, const PosIdx pos, Value * * args, Valu .pos = state.positions[pos], }); - state.debug->runDebugRepl(state, &error, (*trace)->env, (*trace)->expr); + state.debug->onEvalError(&error, (*trace)->env, (*trace)->expr); } // Return the value we were passed. @@ -705,7 +705,7 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu ? state.debug->traces().next() : std::nullopt) { - state.debug->runDebugRepl(state, nullptr, (*last)->env, (*last)->expr); + state.debug->onEvalError(nullptr, (*last)->env, (*last)->expr); } state.forceValue(*args[1], pos); v = *args[1];