forked from lix-project/lix
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
This commit is contained in:
parent
0bfa58ff53
commit
ef1d62ec6c
5 changed files with 37 additions and 25 deletions
|
@ -106,14 +106,11 @@ ref<eval_cache::CachingEvalState> EvalCommand::getEvalState()
|
|||
{
|
||||
if (!evalState) {
|
||||
evalState = std::allocate_shared<eval_cache::CachingEvalState>(
|
||||
TraceableAllocator<EvalState>(), searchPath, getEvalStore(), getStore()
|
||||
TraceableAllocator<EvalState>(), searchPath, getEvalStore(), getStore(),
|
||||
startReplOnEvalErrors ? AbstractNixRepl::runSimple : nullptr
|
||||
);
|
||||
|
||||
evalState->repair = repair;
|
||||
|
||||
if (startReplOnEvalErrors) {
|
||||
evalState->debug = std::make_unique<DebugState>(&AbstractNixRepl::runSimple);
|
||||
};
|
||||
}
|
||||
return ref<eval_cache::CachingEvalState>(evalState);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ void EvalErrorBuilder<T>::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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -274,7 +274,8 @@ EvalBuiltins::EvalBuiltins(
|
|||
EvalState::EvalState(
|
||||
const SearchPath & _searchPath,
|
||||
ref<Store> store,
|
||||
std::shared_ptr<Store> buildStore)
|
||||
std::shared_ptr<Store> buildStore,
|
||||
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> 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<DebugState>(
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -143,23 +143,29 @@ struct DebugState
|
|||
{
|
||||
private:
|
||||
std::weak_ptr<const DebugTrace> latestTrace;
|
||||
const PosTable & positions;
|
||||
const SymbolTable & symbols;
|
||||
|
||||
public:
|
||||
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> repl;
|
||||
std::function<ReplExitStatus(ValMap const & extraEnv)> errorCallback;
|
||||
bool stop = false;
|
||||
bool inDebugger = false;
|
||||
std::map<const Expr *, const std::shared_ptr<const StaticEnv>> exprEnvs;
|
||||
int trylevel = 0;
|
||||
|
||||
explicit DebugState(std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> repl)
|
||||
: repl(repl)
|
||||
explicit DebugState(
|
||||
const PosTable & positions,
|
||||
const SymbolTable & symbols,
|
||||
std::function<ReplExitStatus(ValMap const & extraEnv)> 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<const StaticEnv> staticEnvFor(const Expr & expr) const
|
||||
{
|
||||
|
@ -409,7 +415,9 @@ public:
|
|||
EvalState(
|
||||
const SearchPath & _searchPath,
|
||||
ref<Store> store,
|
||||
std::shared_ptr<Store> buildStore = nullptr);
|
||||
std::shared_ptr<Store> buildStore = nullptr,
|
||||
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl = nullptr
|
||||
);
|
||||
~EvalState();
|
||||
|
||||
/**
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in a new issue