Skip to content

Commit

Permalink
refactor: Extract EvalState::{runDebugRepl,canDebug}
Browse files Browse the repository at this point in the history
  • Loading branch information
roberth committed May 6, 2024
1 parent b3c9432 commit 15b6cc5
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 15 deletions.
7 changes: 1 addition & 6 deletions src/libexpr/eval-error.cc
Expand Up @@ -74,12 +74,7 @@ EvalErrorBuilder<T>::addTrace(PosIdx pos, std::string_view formatString, const A
template<class T>
void EvalErrorBuilder<T>::debugThrow()
{
if (error.state.debugRepl && !error.state.debugTraces.empty()) {
const DebugTrace & last = error.state.debugTraces.front();
const Env * env = &last.env;
const Expr * expr = &last.expr;
error.state.runDebugRepl(&error, *env, *expr);
}
error.state.runDebugRepl(&error);

// `EvalState` is the only class that can construct an `EvalErrorBuilder`,
// and it does so in dynamic storage. This is the final method called on
Expand Down
18 changes: 18 additions & 0 deletions src/libexpr/eval.cc
Expand Up @@ -785,6 +785,24 @@ class DebuggerGuard {
}
};

bool EvalState::canDebug()
{
return debugRepl && !debugTraces.empty();
}

void EvalState::runDebugRepl(const Error * error)
{
if (!canDebug())
return;

assert(!debugTraces.empty());
const DebugTrace & last = debugTraces.front();
const Env & env = last.env;
const Expr & expr = last.expr;

runDebugRepl(error, env, expr);
}

void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr & expr)
{
// Make sure we have a debugger to run and we're not already in a debugger.
Expand Down
12 changes: 12 additions & 0 deletions src/libexpr/eval.hh
Expand Up @@ -276,6 +276,18 @@ public:
return std::shared_ptr<const StaticEnv>();;
}

/** Whether a debug repl can be started. If `false`, `runDebugRepl(error)` will return without starting a repl. */
bool canDebug();

/** Use front of `debugTraces`; see `runDebugRepl(error,env,expr)` */
void runDebugRepl(const Error * error);

/**
* Run a debug repl with the given error, environment and expression.
* @param error The error to debug, may be nullptr.
* @param env The environment to debug, matching the expression.
* @param expr The expression to debug, matching the environment.
*/
void runDebugRepl(const Error * error, const Env & env, const Expr & expr);

template<class T, typename... Args>
Expand Down
15 changes: 6 additions & 9 deletions src/libexpr/primops.cc
Expand Up @@ -779,15 +779,14 @@ static RegisterPrimOp primop_break({
)",
.fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
if (state.debugRepl && !state.debugTraces.empty()) {
if (state.canDebug()) {
auto error = Error(ErrorInfo {
.level = lvlInfo,
.msg = HintFmt("breakpoint reached"),
.pos = state.positions[pos],
});

auto & dt = state.debugTraces.front();
state.runDebugRepl(&error, dt.env, dt.expr);
state.runDebugRepl(&error);
}

// Return the value we were passed.
Expand Down Expand Up @@ -1017,9 +1016,8 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu
printError("trace: %1%", args[0]->string_view());
else
printError("trace: %1%", ValuePrinter(state, *args[0]));
if (evalSettings.builtinsTraceDebugger && state.debugRepl && !state.debugTraces.empty()) {
const DebugTrace & last = state.debugTraces.front();
state.runDebugRepl(nullptr, last.env, last.expr);
if (evalSettings.builtinsTraceDebugger) {
state.runDebugRepl(nullptr);
}
state.forceValue(*args[1], pos);
v = *args[1];
Expand Down Expand Up @@ -1059,9 +1057,8 @@ static void prim_warn(EvalState & state, const PosIdx pos, Value * * args, Value
if (evalSettings.builtinsAbortOnWarn) {
state.error<Abort>("aborting to reveal stack trace of warning, as abort-on-warn is set").debugThrow();
}
if ((evalSettings.builtinsTraceDebugger || evalSettings.builtinsDebuggerOnWarn) && state.debugRepl && !state.debugTraces.empty()) {
const DebugTrace & last = state.debugTraces.front();
state.runDebugRepl(nullptr, last.env, last.expr);
if (evalSettings.builtinsTraceDebugger || evalSettings.builtinsDebuggerOnWarn) {
state.runDebugRepl(nullptr);
}
state.forceValue(*args[1], pos);
v = *args[1];
Expand Down

0 comments on commit 15b6cc5

Please sign in to comment.