aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Burdette <bburdette@protonmail.com>2022-02-03 13:15:21 -0700
committerBen Burdette <bburdette@protonmail.com>2022-02-03 13:15:21 -0700
commit412d58f0bb65104b0065dbf721a92b9e5dcdcdbb (patch)
tree69b0043bdeccfbef9bae2de5dad01407fa4ae313
parent990bec78d30c5e23cd6aa83a6f98b1d4199bd8c3 (diff)
break() primop; step and go debug commands
-rw-r--r--src/libcmd/repl.cc16
-rw-r--r--src/libexpr/eval.cc3
-rw-r--r--src/libexpr/eval.hh1
-rw-r--r--src/libexpr/primops.cc22
4 files changed, 40 insertions, 2 deletions
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc
index e66cf4430..5c14c7d3e 100644
--- a/src/libcmd/repl.cc
+++ b/src/libcmd/repl.cc
@@ -439,7 +439,11 @@ bool NixRepl::processLine(string line)
<< " :d <cmd> Debug mode commands\n"
<< " :d stack Show call stack\n"
<< " :d env Show env stack\n"
- << " :d error Show current error\n";
+ << " :d error Show current error\n"
+ << " :d go Go until end of program, exception, or builtins.break().\n"
+ << " :d step Go one step\n"
+ ;
+
}
else if (command == ":d" || command == ":debug") {
@@ -476,6 +480,16 @@ bool NixRepl::processLine(string line)
notice("error information not available");
}
}
+ else if (arg == "step") {
+ // set flag and exit repl.
+ state->debugStop = true;
+ return false;
+ }
+ else if (arg == "go") {
+ // set flag and exit repl.
+ state->debugStop = false;
+ return false;
+ }
}
else if (command == ":a" || command == ":add") {
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 7b3745e52..426cff2d3 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -417,6 +417,7 @@ EvalState::EvalState(
, repair(NoRepair)
, store(store)
, buildStore(buildStore ? buildStore : store)
+ , debugStop(true)
, regexCache(makeRegexCache())
, baseEnv(allocEnv(128))
, staticBaseEnv(new StaticEnv(false, 0))
@@ -930,7 +931,7 @@ DebugTraceStacker::DebugTraceStacker(EvalState &evalState, DebugTrace t)
:evalState(evalState), trace(t)
{
evalState.debugTraces.push_front(t);
- if (debuggerHook)
+ if (evalState.debugStop && debuggerHook)
debuggerHook(0, t.env, t.expr);
}
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 1a097ab8c..649fda778 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -115,6 +115,7 @@ public:
RootValue vCallFlake = nullptr;
RootValue vImportedDrvToDerivation = nullptr;
+ bool debugStop;
std::list<DebugTrace> debugTraces;
private:
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 66265f917..3a54e1490 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -710,6 +710,28 @@ static RegisterPrimOp primop_genericClosure(RegisterPrimOp::Info {
.fun = prim_genericClosure,
});
+static RegisterPrimOp primop_break({
+ .name = "break",
+ .args = {},
+ .doc = R"(
+ In debug mode, pause Nix expression evaluation and enter the repl.
+ )",
+ .fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
+ {
+ // PathSet context;
+ // string s = state.coerceToString(pos, *args[0], context);
+ if (debuggerHook && !state.debugTraces.empty())
+ {
+ auto &dt = state.debugTraces.front();
+ // std::optional<ErrPos> pos;
+ // const Expr &expr;
+ // const Env &env;
+ // hintformat hint;
+ debuggerHook(nullptr, dt.env, dt.expr);
+ }
+ }
+});
+
static RegisterPrimOp primop_abort({
.name = "abort",
.args = {"s"},