From bc20e54e0044e08c68a7af1f1e12d001baba8a74 Mon Sep 17 00:00:00 2001 From: Ben Burdette Date: Wed, 22 Dec 2021 19:40:08 -0700 Subject: [PATCH] stack traces basically working --- src/libcmd/repl.cc | 20 ++++++++++++ src/libexpr/eval.cc | 72 +++++++++++++++++++++++++++++++++----------- src/libutil/error.hh | 3 ++ 3 files changed, 78 insertions(+), 17 deletions(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index 2a925df64..3289aea3e 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -448,6 +448,26 @@ bool NixRepl::processLine(string line) else if (command == ":d" || command == ":debug") { std::cout << "debug: '" << arg << "'" << std::endl; if (arg == "stack") { + std::cout << "eval stack:" << std::endl; + for (auto iter = this->state->debugTraces.begin(); + iter != this->state->debugTraces.end(); ++iter) { + std::cout << "\n" << "… " << iter->hint.str() << "\n"; + + if (iter->pos.has_value() && (*iter->pos)) { + auto pos = iter->pos.value(); + std::cout << "\n"; + printAtPos(pos, std::cout); + + auto loc = getCodeLines(pos); + if (loc.has_value()) { + std::cout << "\n"; + printCodeLines(std::cout, "", pos, *loc); + std::cout << "\n"; + } + } + } + + } else if (arg == "error") { if (this->debugError.has_value()) { diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 00d2c1643..c46113560 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -38,6 +38,23 @@ namespace nix { std::function debuggerHook; +class DebugTraceStacker { + public: + DebugTraceStacker(EvalState &evalState, Trace t) + :evalState(evalState), trace(t) + { + evalState.debugTraces.push_front(t); + } + ~DebugTraceStacker() { + // assert(evalState.debugTraces.front() == trace); + evalState.debugTraces.pop_front(); + } + + EvalState &evalState; + Trace trace; + +}; + static char * dupString(const char * s) { char * t; @@ -1110,23 +1127,6 @@ void EvalState::resetFileCache() fileParseCache.clear(); } -class DebugTraceStacker { - public: - DebugTraceStacker(EvalState &evalState, Trace t) - :evalState(evalState), trace(t) - { - evalState.debugTraces.push_front(t); - } - ~DebugTraceStacker() { - // assert(evalState.debugTraces.front() == trace); - evalState.debugTraces.pop_front(); - } - - EvalState &evalState; - Trace trace; - -}; - // class DebugTraceStacker { // DebugTraceStacker(std::ref evalState, std::ref t) // :evalState(evalState), trace(t) @@ -1387,6 +1387,17 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) e->eval(state, env, vTmp); try { + std::unique_ptr dts = + debuggerHook ? + std::unique_ptr( + new DebugTraceStacker( + state, + Trace { .pos = *pos2, + .hint = hintfmt( + "while evaluating the attribute '%1%'", + showAttrPath(state, env, attrPath)) + })) + : std::unique_ptr(); for (auto & i : attrPath) { state.nrLookups++; @@ -1530,6 +1541,21 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & /* Evaluate the body. */ try { + std::unique_ptr dts = + debuggerHook ? + std::unique_ptr( + new DebugTraceStacker( + *this, + Trace { .pos = lambda.pos, + .hint = hintfmt( + "while evaluating %s", + (lambda.name.set() + ? "'" + (string) lambda.name + "'" + : "anonymous lambda")) + })) + : std::unique_ptr(); + + lambda.body->eval(*this, env2, vCur); } catch (Error & e) { std::cout << "eval showErrorInfo showTrace: " << loggerSettings.showTrace.get() << std::endl; @@ -1924,6 +1950,18 @@ void EvalState::forceValueDeep(Value & v) if (v.type() == nAttrs) { for (auto & i : *v.attrs) try { + std::unique_ptr dts = + debuggerHook ? + std::unique_ptr( + new DebugTraceStacker( + *this, + Trace { .pos = *i.pos, + .hint = hintfmt( + "while evaluating the attribute '%1%'", i.name) + })) + : std::unique_ptr(); + + recurse(*i.value); } catch (Error & e) { addErrorTrace(e, *i.pos, "while evaluating the attribute '%1%'", i.name); diff --git a/src/libutil/error.hh b/src/libutil/error.hh index b6670c8b2..06301f709 100644 --- a/src/libutil/error.hh +++ b/src/libutil/error.hh @@ -106,6 +106,9 @@ void printCodeLines(std::ostream & out, const ErrPos & errPos, const LinesOfCode & loc); +void printAtPos(const ErrPos & pos, std::ostream & out); + + struct Trace { std::optional pos; hintformat hint;