libexpr: move debug repl state into own struct
just to keep debug-related state closer together. eventually this will
also allow us to not allocate debugger state altogether unless needed.
Change-Id: Id83fea75d96d0ecbe21683cb1b57dd5b11b13535
This commit is contained in:
parent
e635db77e3
commit
003883306d
|
@ -118,7 +118,7 @@ ref<EvalState> EvalCommand::getEvalState()
|
||||||
evalState->repair = repair;
|
evalState->repair = repair;
|
||||||
|
|
||||||
if (startReplOnEvalErrors) {
|
if (startReplOnEvalErrors) {
|
||||||
evalState->debugRepl = &AbstractNixRepl::runSimple;
|
evalState->debug.repl = &AbstractNixRepl::runSimple;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return ref<EvalState>(evalState);
|
return ref<EvalState>(evalState);
|
||||||
|
|
|
@ -285,7 +285,7 @@ ReplExitStatus NixRepl::mainLoop()
|
||||||
{
|
{
|
||||||
if (isFirstRepl) {
|
if (isFirstRepl) {
|
||||||
std::string_view debuggerNotice = "";
|
std::string_view debuggerNotice = "";
|
||||||
if (state.debugRepl) {
|
if (state.debug.repl) {
|
||||||
debuggerNotice = " debugger";
|
debuggerNotice = " debugger";
|
||||||
}
|
}
|
||||||
notice("Lix %1%%2%\nType :? for help.", nixVersion, debuggerNotice);
|
notice("Lix %1%%2%\nType :? for help.", nixVersion, debuggerNotice);
|
||||||
|
@ -310,7 +310,7 @@ ReplExitStatus NixRepl::mainLoop()
|
||||||
// number of chars as the prompt.
|
// number of chars as the prompt.
|
||||||
if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
|
if (!interacter->getLine(input, input.empty() ? ReplPromptType::ReplPrompt : ReplPromptType::ContinuationPrompt)) {
|
||||||
// Ctrl-D should exit the debugger.
|
// Ctrl-D should exit the debugger.
|
||||||
state.debugStop = false;
|
state.debug.stop = false;
|
||||||
logger->cout("");
|
logger->cout("");
|
||||||
// TODO: Should Ctrl-D exit just the current debugger session or
|
// TODO: Should Ctrl-D exit just the current debugger session or
|
||||||
// the entire program?
|
// the entire program?
|
||||||
|
@ -366,7 +366,7 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.debugRepl) {
|
if (state.debug.repl) {
|
||||||
for (auto const & colonCmd : this->DEBUG_COMMANDS) {
|
for (auto const & colonCmd : this->DEBUG_COMMANDS) {
|
||||||
if (colonCmd.starts_with(prefix)) {
|
if (colonCmd.starts_with(prefix)) {
|
||||||
completions.insert(std::string(colonCmd));
|
completions.insert(std::string(colonCmd));
|
||||||
|
@ -416,9 +416,9 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Temporarily disable the debugger, to avoid re-entering readline. */
|
/* Temporarily disable the debugger, to avoid re-entering readline. */
|
||||||
auto debug_repl = state.debugRepl;
|
auto debug_repl = state.debug.repl;
|
||||||
state.debugRepl = nullptr;
|
state.debug.repl = nullptr;
|
||||||
Finally restoreDebug([&]() { state.debugRepl = debug_repl; });
|
Finally restoreDebug([&]() { state.debug.repl = debug_repl; });
|
||||||
try {
|
try {
|
||||||
/* This is an expression that should evaluate to an
|
/* This is an expression that should evaluate to an
|
||||||
attribute set. Evaluate it to get the names of the
|
attribute set. Evaluate it to get the names of the
|
||||||
|
@ -485,7 +485,7 @@ void NixRepl::loadDebugTraceEnv(DebugTrace & dt)
|
||||||
{
|
{
|
||||||
initEnv();
|
initEnv();
|
||||||
|
|
||||||
auto se = state.getStaticEnv(dt.expr);
|
auto se = state.debug.staticEnvFor(dt.expr);
|
||||||
if (se) {
|
if (se) {
|
||||||
auto vm = mapStaticEnvBindings(state.symbols, *se.get(), dt.env);
|
auto vm = mapStaticEnvBindings(state.symbols, *se.get(), dt.env);
|
||||||
|
|
||||||
|
@ -541,7 +541,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||||
<< " errors\n"
|
<< " errors\n"
|
||||||
<< " :?, :help Brings up this help menu\n"
|
<< " :?, :help Brings up this help menu\n"
|
||||||
;
|
;
|
||||||
if (state.debugRepl) {
|
if (state.debug.repl) {
|
||||||
std::cout
|
std::cout
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< " Debug mode commands\n"
|
<< " Debug mode commands\n"
|
||||||
|
@ -556,15 +556,15 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (state.debugRepl && (command == ":bt" || command == ":backtrace")) {
|
else if (state.debug.repl && (command == ":bt" || command == ":backtrace")) {
|
||||||
for (const auto & [idx, i] : enumerate(state.debugTraces)) {
|
for (const auto & [idx, i] : enumerate(state.debug.traces)) {
|
||||||
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
||||||
showDebugTrace(std::cout, state.positions, i);
|
showDebugTrace(std::cout, state.positions, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (state.debugRepl && (command == ":env")) {
|
else if (state.debug.repl && (command == ":env")) {
|
||||||
for (const auto & [idx, i] : enumerate(state.debugTraces)) {
|
for (const auto & [idx, i] : enumerate(state.debug.traces)) {
|
||||||
if (idx == debugTraceIndex) {
|
if (idx == debugTraceIndex) {
|
||||||
printEnvBindings(state, i.expr, i.env);
|
printEnvBindings(state, i.expr, i.env);
|
||||||
break;
|
break;
|
||||||
|
@ -572,13 +572,13 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (state.debugRepl && (command == ":st")) {
|
else if (state.debug.repl && (command == ":st")) {
|
||||||
try {
|
try {
|
||||||
// change the DebugTrace index.
|
// change the DebugTrace index.
|
||||||
debugTraceIndex = stoi(arg);
|
debugTraceIndex = stoi(arg);
|
||||||
} catch (...) { }
|
} catch (...) { }
|
||||||
|
|
||||||
for (const auto & [idx, i] : enumerate(state.debugTraces)) {
|
for (const auto & [idx, i] : enumerate(state.debug.traces)) {
|
||||||
if (idx == debugTraceIndex) {
|
if (idx == debugTraceIndex) {
|
||||||
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
||||||
showDebugTrace(std::cout, state.positions, i);
|
showDebugTrace(std::cout, state.positions, i);
|
||||||
|
@ -590,15 +590,15 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (state.debugRepl && (command == ":s" || command == ":step")) {
|
else if (state.debug.repl && (command == ":s" || command == ":step")) {
|
||||||
// set flag to stop at next DebugTrace; exit repl.
|
// set flag to stop at next DebugTrace; exit repl.
|
||||||
state.debugStop = true;
|
state.debug.stop = true;
|
||||||
return ProcessLineResult::Continue;
|
return ProcessLineResult::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (state.debugRepl && (command == ":c" || command == ":continue")) {
|
else if (state.debug.repl && (command == ":c" || command == ":continue")) {
|
||||||
// set flag to run to next breakpoint or end of program; exit repl.
|
// set flag to run to next breakpoint or end of program; exit repl.
|
||||||
state.debugStop = false;
|
state.debug.stop = false;
|
||||||
return ProcessLineResult::Continue;
|
return ProcessLineResult::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,7 +771,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (command == ":q" || command == ":quit") {
|
else if (command == ":q" || command == ":quit") {
|
||||||
state.debugStop = false;
|
state.debug.stop = false;
|
||||||
return ProcessLineResult::Quit;
|
return ProcessLineResult::Quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ EvalErrorBuilder<T> & EvalErrorBuilder<T>::withFrame(const Env & env, const Expr
|
||||||
// NOTE: This is abusing side-effects.
|
// NOTE: This is abusing side-effects.
|
||||||
// TODO: check compatibility with nested debugger calls.
|
// TODO: check compatibility with nested debugger calls.
|
||||||
// TODO: What side-effects??
|
// TODO: What side-effects??
|
||||||
error.state.debugTraces.push_front(DebugTrace{
|
error.state.debug.traces.push_front(DebugTrace{
|
||||||
.pos = error.state.positions[expr.getPos()],
|
.pos = error.state.positions[expr.getPos()],
|
||||||
.expr = expr,
|
.expr = expr,
|
||||||
.env = env,
|
.env = env,
|
||||||
|
@ -74,11 +74,11 @@ EvalErrorBuilder<T>::addTrace(PosIdx pos, std::string_view formatString, const A
|
||||||
template<class T>
|
template<class T>
|
||||||
void EvalErrorBuilder<T>::debugThrow()
|
void EvalErrorBuilder<T>::debugThrow()
|
||||||
{
|
{
|
||||||
if (error.state.debugRepl && !error.state.debugTraces.empty()) {
|
if (error.state.debug.repl && !error.state.debug.traces.empty()) {
|
||||||
const DebugTrace & last = error.state.debugTraces.front();
|
const DebugTrace & last = error.state.debug.traces.front();
|
||||||
const Env * env = &last.env;
|
const Env * env = &last.env;
|
||||||
const Expr * expr = &last.expr;
|
const Expr * expr = &last.expr;
|
||||||
error.state.runDebugRepl(&error, *env, *expr);
|
error.state.debug.runDebugRepl(error.state, &error, *env, *expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// `EvalState` is the only class that can construct an `EvalErrorBuilder`,
|
// `EvalState` is the only class that can construct an `EvalErrorBuilder`,
|
||||||
|
|
|
@ -262,9 +262,6 @@ EvalState::EvalState(
|
||||||
, derivationInternal(rootPath(CanonPath("/builtin/derivation.nix")))
|
, derivationInternal(rootPath(CanonPath("/builtin/derivation.nix")))
|
||||||
, store(store)
|
, store(store)
|
||||||
, buildStore(buildStore ? buildStore : store)
|
, buildStore(buildStore ? buildStore : store)
|
||||||
, debugRepl(nullptr)
|
|
||||||
, debugStop(false)
|
|
||||||
, trylevel(0)
|
|
||||||
, regexCache(makeRegexCache())
|
, regexCache(makeRegexCache())
|
||||||
#if HAVE_BOEHMGC
|
#if HAVE_BOEHMGC
|
||||||
, valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
|
, valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
|
||||||
|
@ -590,7 +587,7 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env &
|
||||||
void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env)
|
void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env)
|
||||||
{
|
{
|
||||||
// just print the names for now
|
// just print the names for now
|
||||||
auto se = es.getStaticEnv(expr);
|
auto se = es.debug.staticEnvFor(expr);
|
||||||
if (se)
|
if (se)
|
||||||
printEnvBindings(es.symbols, *se, env, 0);
|
printEnvBindings(es.symbols, *se, env, 0);
|
||||||
}
|
}
|
||||||
|
@ -639,18 +636,20 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void EvalState::runDebugRepl(const EvalError * error, const Env & env, const Expr & expr)
|
void DebugState::runDebugRepl(
|
||||||
|
EvalState & evalState, 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.
|
// Make sure we have a debugger to run and we're not already in a debugger.
|
||||||
if (!debugRepl || inDebugger)
|
if (!repl || inDebugger)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto dts =
|
auto dts =
|
||||||
error && expr.getPos()
|
error && expr.getPos()
|
||||||
? std::make_unique<DebugTraceStacker>(
|
? std::make_unique<DebugTraceStacker>(
|
||||||
*this,
|
evalState,
|
||||||
DebugTrace {
|
DebugTrace {
|
||||||
.pos = error->info().pos ? error->info().pos : positions[expr.getPos()],
|
.pos = error->info().pos ? error->info().pos : evalState.positions[expr.getPos()],
|
||||||
.expr = expr,
|
.expr = expr,
|
||||||
.env = env,
|
.env = env,
|
||||||
.hint = error->info().msg,
|
.hint = error->info().msg,
|
||||||
|
@ -666,11 +665,11 @@ void EvalState::runDebugRepl(const EvalError * error, const Env & env, const Exp
|
||||||
printError("This exception occurred in a 'tryEval' call. Use " ANSI_GREEN "--ignore-try" ANSI_NORMAL " to skip these.\n");
|
printError("This exception occurred in a 'tryEval' call. Use " ANSI_GREEN "--ignore-try" ANSI_NORMAL " to skip these.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto se = getStaticEnv(expr);
|
auto se = staticEnvFor(expr);
|
||||||
if (se) {
|
if (se) {
|
||||||
auto vm = mapStaticEnvBindings(symbols, *se.get(), env);
|
auto vm = mapStaticEnvBindings(evalState.symbols, *se.get(), env);
|
||||||
DebuggerGuard _guard(inDebugger);
|
DebuggerGuard _guard(inDebugger);
|
||||||
auto exitStatus = (debugRepl)(*this, *vm);
|
auto exitStatus = repl(evalState, *vm);
|
||||||
switch (exitStatus) {
|
switch (exitStatus) {
|
||||||
case ReplExitStatus::QuitAll:
|
case ReplExitStatus::QuitAll:
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -718,9 +717,9 @@ DebugTraceStacker::DebugTraceStacker(EvalState & evalState, DebugTrace t)
|
||||||
: evalState(evalState)
|
: evalState(evalState)
|
||||||
, trace(std::move(t))
|
, trace(std::move(t))
|
||||||
{
|
{
|
||||||
evalState.debugTraces.push_front(trace);
|
evalState.debug.traces.push_front(trace);
|
||||||
if (evalState.debugStop && evalState.debugRepl)
|
if (evalState.debug.stop && evalState.debug.repl)
|
||||||
evalState.runDebugRepl(nullptr, trace.env, trace.expr);
|
evalState.debug.runDebugRepl(evalState, nullptr, trace.env, trace.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||||
|
@ -955,7 +954,7 @@ void EvalState::cacheFile(
|
||||||
fileParseCache[resolvedPath] = e;
|
fileParseCache[resolvedPath] = e;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto dts = debugRepl
|
auto dts = debug.repl
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
*this,
|
*this,
|
||||||
*e,
|
*e,
|
||||||
|
@ -1173,7 +1172,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||||
*i.second.chooseByKind(&env2, &env, inheritEnv));
|
*i.second.chooseByKind(&env2, &env, inheritEnv));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto dts = state.debugRepl
|
auto dts = state.debug.repl
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
state,
|
state,
|
||||||
*this,
|
*this,
|
||||||
|
@ -1258,7 +1257,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto dts = state.debugRepl
|
auto dts = state.debug.repl
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
state,
|
state,
|
||||||
*this,
|
*this,
|
||||||
|
@ -1576,7 +1575,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
|
|
||||||
/* Evaluate the body. */
|
/* Evaluate the body. */
|
||||||
try {
|
try {
|
||||||
auto dts = debugRepl
|
auto dts = debug.repl
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
*this, *lambda.body, env2, positions[lambda.pos],
|
*this, *lambda.body, env2, positions[lambda.pos],
|
||||||
"while calling %s",
|
"while calling %s",
|
||||||
|
@ -1715,7 +1714,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
|
|
||||||
void ExprCall::eval(EvalState & state, Env & env, Value & v)
|
void ExprCall::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
auto dts = state.debugRepl
|
auto dts = state.debug.repl
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
state,
|
state,
|
||||||
*this,
|
*this,
|
||||||
|
@ -2088,7 +2087,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||||
for (auto & i : *v.attrs)
|
for (auto & i : *v.attrs)
|
||||||
try {
|
try {
|
||||||
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
|
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
|
||||||
auto dts = debugRepl && i.value->isThunk()
|
auto dts = debug.repl && i.value->isThunk()
|
||||||
? makeDebugTraceStacker(*this, *i.value->thunk.expr, *i.value->thunk.env, positions[i.pos],
|
? makeDebugTraceStacker(*this, *i.value->thunk.expr, *i.value->thunk.env, positions[i.pos],
|
||||||
"while evaluating the attribute '%1%'", symbols[i.name])
|
"while evaluating the attribute '%1%'", symbols[i.name])
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
|
@ -152,6 +152,28 @@ struct DebugTrace {
|
||||||
bool isError;
|
bool isError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DebugState
|
||||||
|
{
|
||||||
|
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> repl;
|
||||||
|
bool stop = false;
|
||||||
|
bool inDebugger = false;
|
||||||
|
std::list<DebugTrace> traces;
|
||||||
|
std::map<const Expr *, const std::shared_ptr<const StaticEnv>> exprEnvs;
|
||||||
|
int trylevel = 0;
|
||||||
|
|
||||||
|
void runDebugRepl(
|
||||||
|
EvalState & evalState, const EvalError * error, const Env & env, const Expr & expr
|
||||||
|
);
|
||||||
|
|
||||||
|
const std::shared_ptr<const StaticEnv> staticEnvFor(const Expr & expr) const
|
||||||
|
{
|
||||||
|
if (auto i = exprEnvs.find(&expr); i != exprEnvs.end()) {
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct StaticSymbols
|
struct StaticSymbols
|
||||||
{
|
{
|
||||||
|
@ -202,25 +224,7 @@ public:
|
||||||
RootValue vCallFlake = nullptr;
|
RootValue vCallFlake = nullptr;
|
||||||
RootValue vImportedDrvToDerivation = nullptr;
|
RootValue vImportedDrvToDerivation = nullptr;
|
||||||
|
|
||||||
/**
|
DebugState debug;
|
||||||
* Debugger
|
|
||||||
*/
|
|
||||||
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl;
|
|
||||||
bool debugStop;
|
|
||||||
bool inDebugger = false;
|
|
||||||
int trylevel;
|
|
||||||
std::list<DebugTrace> debugTraces;
|
|
||||||
std::map<const Expr*, const std::shared_ptr<const StaticEnv>> exprEnvs;
|
|
||||||
const std::shared_ptr<const StaticEnv> getStaticEnv(const Expr & expr) const
|
|
||||||
{
|
|
||||||
auto i = exprEnvs.find(&expr);
|
|
||||||
if (i != exprEnvs.end())
|
|
||||||
return i->second;
|
|
||||||
else
|
|
||||||
return std::shared_ptr<const StaticEnv>();;
|
|
||||||
}
|
|
||||||
|
|
||||||
void runDebugRepl(const EvalError * error, const Env & env, const Expr & expr);
|
|
||||||
|
|
||||||
template<class T, typename... Args>
|
template<class T, typename... Args>
|
||||||
[[nodiscard, gnu::noinline]]
|
[[nodiscard, gnu::noinline]]
|
||||||
|
@ -760,7 +764,7 @@ struct DebugTraceStacker {
|
||||||
DebugTraceStacker(EvalState & evalState, DebugTrace t);
|
DebugTraceStacker(EvalState & evalState, DebugTrace t);
|
||||||
~DebugTraceStacker()
|
~DebugTraceStacker()
|
||||||
{
|
{
|
||||||
evalState.debugTraces.pop_front();
|
evalState.debug.traces.pop_front();
|
||||||
}
|
}
|
||||||
EvalState & evalState;
|
EvalState & evalState;
|
||||||
DebugTrace trace;
|
DebugTrace trace;
|
||||||
|
|
|
@ -302,32 +302,32 @@ void Expr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env
|
||||||
|
|
||||||
void ExprInt::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprInt::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprFloat::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprFloat::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprString::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprString::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprPath::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprPath::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprVar::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprVar::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
fromWith = nullptr;
|
fromWith = nullptr;
|
||||||
|
|
||||||
|
@ -364,14 +364,14 @@ void ExprVar::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
|
|
||||||
void ExprInheritFrom::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprInheritFrom::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprSelect::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprSelect::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
e->bindVars(es, env);
|
e->bindVars(es, env);
|
||||||
if (def) def->bindVars(es, env);
|
if (def) def->bindVars(es, env);
|
||||||
|
@ -382,8 +382,8 @@ void ExprSelect::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
|
||||||
|
|
||||||
void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
e->bindVars(es, env);
|
e->bindVars(es, env);
|
||||||
for (auto & i : attrPath)
|
for (auto & i : attrPath)
|
||||||
|
@ -414,8 +414,8 @@ std::shared_ptr<const StaticEnv> ExprAttrs::bindInheritSources(
|
||||||
|
|
||||||
void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
auto newEnv = [&] () -> std::shared_ptr<const StaticEnv> {
|
auto newEnv = [&] () -> std::shared_ptr<const StaticEnv> {
|
||||||
|
@ -453,8 +453,8 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
|
||||||
|
|
||||||
void ExprList::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprList::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
for (auto & i : elems)
|
for (auto & i : elems)
|
||||||
i->bindVars(es, env);
|
i->bindVars(es, env);
|
||||||
|
@ -462,8 +462,8 @@ void ExprList::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
|
|
||||||
void ExprLambda::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprLambda::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
auto newEnv = std::make_shared<StaticEnv>(
|
auto newEnv = std::make_shared<StaticEnv>(
|
||||||
nullptr, env.get(),
|
nullptr, env.get(),
|
||||||
|
@ -489,8 +489,8 @@ void ExprLambda::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
|
||||||
|
|
||||||
void ExprCall::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprCall::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
fun->bindVars(es, env);
|
fun->bindVars(es, env);
|
||||||
for (auto & e : args)
|
for (auto & e : args)
|
||||||
|
@ -514,16 +514,16 @@ void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
for (auto & i : attrs->attrs)
|
for (auto & i : attrs->attrs)
|
||||||
i.second.e->bindVars(es, i.second.chooseByKind(newEnv, env, inheritFromEnv));
|
i.second.e->bindVars(es, i.second.chooseByKind(newEnv, env, inheritFromEnv));
|
||||||
|
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
body->bindVars(es, newEnv);
|
body->bindVars(es, newEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprWith::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprWith::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
parentWith = nullptr;
|
parentWith = nullptr;
|
||||||
for (auto * e = env.get(); e && !parentWith; e = e->up)
|
for (auto * e = env.get(); e && !parentWith; e = e->up)
|
||||||
|
@ -548,8 +548,8 @@ void ExprWith::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
|
|
||||||
void ExprIf::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprIf::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
cond->bindVars(es, env);
|
cond->bindVars(es, env);
|
||||||
then->bindVars(es, env);
|
then->bindVars(es, env);
|
||||||
|
@ -558,8 +558,8 @@ void ExprIf::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & e
|
||||||
|
|
||||||
void ExprAssert::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprAssert::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
cond->bindVars(es, env);
|
cond->bindVars(es, env);
|
||||||
body->bindVars(es, env);
|
body->bindVars(es, env);
|
||||||
|
@ -567,16 +567,16 @@ void ExprAssert::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
|
||||||
|
|
||||||
void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
e->bindVars(es, env);
|
e->bindVars(es, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
for (auto & i : this->es)
|
for (auto & i : this->es)
|
||||||
i.second->bindVars(es, env);
|
i.second->bindVars(es, env);
|
||||||
|
@ -584,8 +584,8 @@ void ExprConcatStrings::bindVars(EvalState & es, const std::shared_ptr<const Sta
|
||||||
|
|
||||||
void ExprPos::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprPos::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (es.debugRepl)
|
if (es.debug.repl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.debug.exprEnvs.insert(std::make_pair(this, env));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -566,15 +566,15 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a
|
||||||
|
|
||||||
static void prim_break(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_break(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
if (state.debugRepl && !state.debugTraces.empty()) {
|
if (state.debug.repl && !state.debug.traces.empty()) {
|
||||||
auto error = EvalError(state, ErrorInfo {
|
auto error = EvalError(state, ErrorInfo {
|
||||||
.level = lvlInfo,
|
.level = lvlInfo,
|
||||||
.msg = HintFmt("breakpoint reached"),
|
.msg = HintFmt("breakpoint reached"),
|
||||||
.pos = state.positions[pos],
|
.pos = state.positions[pos],
|
||||||
});
|
});
|
||||||
|
|
||||||
auto & dt = state.debugTraces.front();
|
auto & dt = state.debug.traces.front();
|
||||||
state.runDebugRepl(&error, dt.env, dt.expr);
|
state.debug.runDebugRepl(state, &error, dt.env, dt.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the value we were passed.
|
// Return the value we were passed.
|
||||||
|
@ -638,14 +638,14 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va
|
||||||
auto attrs = state.buildBindings(2);
|
auto attrs = state.buildBindings(2);
|
||||||
|
|
||||||
/* increment state.trylevel, and decrement it when this function returns. */
|
/* increment state.trylevel, and decrement it when this function returns. */
|
||||||
MaintainCount trylevel(state.trylevel);
|
MaintainCount trylevel(state.debug.trylevel);
|
||||||
|
|
||||||
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> savedDebugRepl;
|
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> savedDebugRepl;
|
||||||
if (state.debugRepl && evalSettings.ignoreExceptionsDuringTry)
|
if (state.debug.repl && evalSettings.ignoreExceptionsDuringTry)
|
||||||
{
|
{
|
||||||
/* to prevent starting the repl from exceptions withing a tryEval, null it. */
|
/* to prevent starting the repl from exceptions withing a tryEval, null it. */
|
||||||
savedDebugRepl = state.debugRepl;
|
savedDebugRepl = state.debug.repl;
|
||||||
state.debugRepl = nullptr;
|
state.debug.repl = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -659,7 +659,7 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va
|
||||||
|
|
||||||
// restore the debugRepl pointer if we saved it earlier.
|
// restore the debugRepl pointer if we saved it earlier.
|
||||||
if (savedDebugRepl)
|
if (savedDebugRepl)
|
||||||
state.debugRepl = savedDebugRepl;
|
state.debug.repl = savedDebugRepl;
|
||||||
|
|
||||||
v.mkAttrs(attrs);
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
@ -697,9 +697,9 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu
|
||||||
printError("trace: %1%", args[0]->string.s);
|
printError("trace: %1%", args[0]->string.s);
|
||||||
else
|
else
|
||||||
printError("trace: %1%", ValuePrinter(state, *args[0]));
|
printError("trace: %1%", ValuePrinter(state, *args[0]));
|
||||||
if (evalSettings.builtinsTraceDebugger && state.debugRepl && !state.debugTraces.empty()) {
|
if (evalSettings.builtinsTraceDebugger && state.debug.repl && !state.debug.traces.empty()) {
|
||||||
const DebugTrace & last = state.debugTraces.front();
|
const DebugTrace & last = state.debug.traces.front();
|
||||||
state.runDebugRepl(nullptr, last.env, last.expr);
|
state.debug.runDebugRepl(state, nullptr, last.env, last.expr);
|
||||||
}
|
}
|
||||||
state.forceValue(*args[1], pos);
|
state.forceValue(*args[1], pos);
|
||||||
v = *args[1];
|
v = *args[1];
|
||||||
|
|
Loading…
Reference in a new issue