forked from lix-project/lix
'debugMode'
This commit is contained in:
parent
7ddef73d02
commit
0600df86b8
|
@ -118,32 +118,35 @@ ref<EvalState> EvalCommand::getEvalState()
|
||||||
searchPath, getEvalStore(), getStore())
|
searchPath, getEvalStore(), getStore())
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
|
evalState->debugMode = startReplOnEvalErrors;
|
||||||
// TODO move this somewhere else. Its only here to get the evalState ptr!
|
// TODO move this somewhere else. Its only here to get the evalState ptr!
|
||||||
if (startReplOnEvalErrors)
|
// if (startReplOnEvalErrors)
|
||||||
// debuggerHook = [evalState{ref<EvalState>(evalState)}](const Error * error, const Env & env, const Expr & expr) {
|
|
||||||
debuggerHook = [](EvalState & evalState, const Error * error, const Env & env, const Expr & expr) {
|
// // debuggerHook = [evalState{ref<EvalState>(evalState)}](const Error * error, const Env & env, const Expr & expr) {
|
||||||
auto dts =
|
// debuggerHook = [](EvalState & evalState, const Error * error, const Env & env, const Expr & expr) {
|
||||||
error && expr.getPos()
|
// auto dts =
|
||||||
? std::make_unique<DebugTraceStacker>(
|
// error && expr.getPos()
|
||||||
evalState,
|
// ? std::make_unique<DebugTraceStacker>(
|
||||||
DebugTrace {
|
// evalState,
|
||||||
.pos = error->info().errPos ? *error->info().errPos : evalState.positions[expr.getPos()],
|
// DebugTrace {
|
||||||
.expr = expr,
|
// .pos = error->info().errPos ? *error->info().errPos : evalState.positions[expr.getPos()],
|
||||||
.env = env,
|
// .expr = expr,
|
||||||
.hint = error->info().msg,
|
// .env = env,
|
||||||
.isError = true
|
// .hint = error->info().msg,
|
||||||
})
|
// .isError = true
|
||||||
: nullptr;
|
// })
|
||||||
|
// : nullptr;
|
||||||
|
|
||||||
if (error)
|
// if (error)
|
||||||
printError("%s\n\n" ANSI_BOLD "Starting REPL to allow you to inspect the current state of the evaluator.\n" ANSI_NORMAL, error->what());
|
// printError("%s\n\n" ANSI_BOLD "Starting REPL to allow you to inspect the current state of the evaluator.\n" ANSI_NORMAL, error->what());
|
||||||
|
|
||||||
auto se = evalState.getStaticEnv(expr);
|
// auto se = evalState.getStaticEnv(expr);
|
||||||
if (se) {
|
// if (se) {
|
||||||
auto vm = mapStaticEnvBindings(evalState.symbols, *se.get(), env);
|
// auto vm = mapStaticEnvBindings(evalState.symbols, *se.get(), env);
|
||||||
runRepl(evalState, *vm);
|
// runRepl(evalState, *vm);
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
}
|
}
|
||||||
return ref<EvalState>(evalState);
|
return ref<EvalState>(evalState);
|
||||||
}
|
}
|
||||||
|
|
|
@ -280,7 +280,7 @@ void NixRepl::mainLoop(const std::vector<std::string> & files)
|
||||||
// in debugger mode, an EvalError should trigger another repl session.
|
// in debugger mode, an EvalError should trigger another repl session.
|
||||||
// when that session returns the exception will land here. No need to show it again;
|
// when that session returns the exception will land here. No need to show it again;
|
||||||
// show the error for this repl session instead.
|
// show the error for this repl session instead.
|
||||||
if (debuggerHook && !state->debugTraces.empty())
|
if (state->debugMode && !state->debugTraces.empty())
|
||||||
showDebugTrace(std::cout, state->positions, state->debugTraces.front());
|
showDebugTrace(std::cout, state->positions, state->debugTraces.front());
|
||||||
else
|
else
|
||||||
printMsg(lvlError, e.msg());
|
printMsg(lvlError, e.msg());
|
||||||
|
@ -493,7 +493,7 @@ bool NixRepl::processLine(std::string line)
|
||||||
<< " :log <expr> Show logs for a derivation\n"
|
<< " :log <expr> Show logs for a derivation\n"
|
||||||
<< " :te [bool] Enable, disable or toggle showing traces for errors\n"
|
<< " :te [bool] Enable, disable or toggle showing traces for errors\n"
|
||||||
;
|
;
|
||||||
if (debuggerHook) {
|
if (state->debugMode) {
|
||||||
std::cout
|
std::cout
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< " Debug mode commands\n"
|
<< " Debug mode commands\n"
|
||||||
|
@ -508,14 +508,14 @@ bool NixRepl::processLine(std::string line)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (debuggerHook && (command == ":bt" || command == ":backtrace")) {
|
else if (state->debugMode && (command == ":bt" || command == ":backtrace")) {
|
||||||
for (const auto & [idx, i] : enumerate(state->debugTraces)) {
|
for (const auto & [idx, i] : enumerate(state->debugTraces)) {
|
||||||
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 (debuggerHook && (command == ":env")) {
|
else if (state->debugMode && (command == ":env")) {
|
||||||
for (const auto & [idx, i] : enumerate(state->debugTraces)) {
|
for (const auto & [idx, i] : enumerate(state->debugTraces)) {
|
||||||
if (idx == debugTraceIndex) {
|
if (idx == debugTraceIndex) {
|
||||||
printEnvBindings(*state, i.expr, i.env);
|
printEnvBindings(*state, i.expr, i.env);
|
||||||
|
@ -524,7 +524,7 @@ bool NixRepl::processLine(std::string line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (debuggerHook && (command == ":st")) {
|
else if (state->debugMode && (command == ":st")) {
|
||||||
try {
|
try {
|
||||||
// change the DebugTrace index.
|
// change the DebugTrace index.
|
||||||
debugTraceIndex = stoi(arg);
|
debugTraceIndex = stoi(arg);
|
||||||
|
@ -542,13 +542,13 @@ bool NixRepl::processLine(std::string line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (debuggerHook && (command == ":s" || command == ":step")) {
|
else if (state->debugMode && (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->debugStop = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (debuggerHook && (command == ":c" || command == ":continue")) {
|
else if (state->debugMode && (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->debugStop = false;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -463,6 +463,7 @@ EvalState::EvalState(
|
||||||
, emptyBindings(0)
|
, emptyBindings(0)
|
||||||
, store(store)
|
, store(store)
|
||||||
, buildStore(buildStore ? buildStore : store)
|
, buildStore(buildStore ? buildStore : store)
|
||||||
|
, debugMode(false)
|
||||||
, debugStop(false)
|
, debugStop(false)
|
||||||
, debugQuit(false)
|
, debugQuit(false)
|
||||||
, regexCache(makeRegexCache())
|
, regexCache(makeRegexCache())
|
||||||
|
@ -810,6 +811,31 @@ std::unique_ptr<ValMap> mapStaticEnvBindings(const SymbolTable & st, const Stati
|
||||||
return vm;
|
return vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EvalState::debugRepl(const Error * error, const Env & env, const Expr & expr)
|
||||||
|
{
|
||||||
|
auto dts =
|
||||||
|
error && expr.getPos()
|
||||||
|
? std::make_unique<DebugTraceStacker>(
|
||||||
|
*this,
|
||||||
|
DebugTrace {
|
||||||
|
.pos = error->info().errPos ? *error->info().errPos : positions[expr.getPos()],
|
||||||
|
.expr = expr,
|
||||||
|
.env = env,
|
||||||
|
.hint = error->info().msg,
|
||||||
|
.isError = true
|
||||||
|
})
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
printError("%s\n\n" ANSI_BOLD "Starting REPL to allow you to inspect the current state of the evaluator.\n" ANSI_NORMAL, error->what());
|
||||||
|
|
||||||
|
auto se = getStaticEnv(expr);
|
||||||
|
if (se) {
|
||||||
|
auto vm = mapStaticEnvBindings(symbols, *se.get(), env);
|
||||||
|
runRepl(*this, *vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Every "format" object (even temporary) takes up a few hundred bytes
|
/* Every "format" object (even temporary) takes up a few hundred bytes
|
||||||
of stack space, which is a real killer in the recursive
|
of stack space, which is a real killer in the recursive
|
||||||
evaluator. So here are some helper functions for throwing
|
evaluator. So here are some helper functions for throwing
|
||||||
|
@ -1043,8 +1069,8 @@ DebugTraceStacker::DebugTraceStacker(EvalState & evalState, DebugTrace t)
|
||||||
, trace(std::move(t))
|
, trace(std::move(t))
|
||||||
{
|
{
|
||||||
evalState.debugTraces.push_front(trace);
|
evalState.debugTraces.push_front(trace);
|
||||||
if (evalState.debugStop && debuggerHook)
|
if (evalState.debugStop && evalState.debugMode)
|
||||||
debuggerHook(evalState, nullptr, trace.env, trace.expr);
|
evalState.debugRepl(nullptr, trace.env, trace.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::mkString(std::string_view s)
|
void Value::mkString(std::string_view s)
|
||||||
|
@ -1241,7 +1267,7 @@ void EvalState::cacheFile(
|
||||||
fileParseCache[resolvedPath] = e;
|
fileParseCache[resolvedPath] = e;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto dts = debuggerHook
|
auto dts = debugMode
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
*this,
|
*this,
|
||||||
*e,
|
*e,
|
||||||
|
@ -1475,7 +1501,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||||
e->eval(state, env, vTmp);
|
e->eval(state, env, vTmp);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto dts = debuggerHook
|
auto dts = state.debugMode
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
state,
|
state,
|
||||||
*this,
|
*this,
|
||||||
|
@ -1644,7 +1670,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
|
|
||||||
/* Evaluate the body. */
|
/* Evaluate the body. */
|
||||||
try {
|
try {
|
||||||
auto dts = debuggerHook
|
auto dts = debugMode
|
||||||
? makeDebugTraceStacker(
|
? makeDebugTraceStacker(
|
||||||
*this, *lambda.body, env2, positions[lambda.pos],
|
*this, *lambda.body, env2, positions[lambda.pos],
|
||||||
"while evaluating %s",
|
"while evaluating %s",
|
||||||
|
@ -2072,7 +2098,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 = debuggerHook && i.value->isThunk()
|
auto dts = debugMode && 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;
|
||||||
|
|
|
@ -25,9 +25,6 @@ enum RepairFlag : bool;
|
||||||
|
|
||||||
typedef void (* PrimOpFun) (EvalState & state, const PosIdx pos, Value * * args, Value & v);
|
typedef void (* PrimOpFun) (EvalState & state, const PosIdx pos, Value * * args, Value & v);
|
||||||
|
|
||||||
void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env);
|
|
||||||
void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, int lvl = 0);
|
|
||||||
|
|
||||||
struct PrimOp
|
struct PrimOp
|
||||||
{
|
{
|
||||||
PrimOpFun fun;
|
PrimOpFun fun;
|
||||||
|
@ -51,6 +48,11 @@ struct Env
|
||||||
Value * values[0];
|
Value * values[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void runRepl(ref<EvalState> evalState, const ValMap & extraEnv);
|
||||||
|
|
||||||
|
void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env);
|
||||||
|
void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, int lvl = 0);
|
||||||
|
|
||||||
std::unique_ptr<ValMap> mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env);
|
std::unique_ptr<ValMap> mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env);
|
||||||
|
|
||||||
void copyContext(const Value & v, PathSet & context);
|
void copyContext(const Value & v, PathSet & context);
|
||||||
|
@ -127,6 +129,7 @@ public:
|
||||||
RootValue vImportedDrvToDerivation = nullptr;
|
RootValue vImportedDrvToDerivation = nullptr;
|
||||||
|
|
||||||
/* Debugger */
|
/* Debugger */
|
||||||
|
bool debugMode;
|
||||||
bool debugStop;
|
bool debugStop;
|
||||||
bool debugQuit;
|
bool debugQuit;
|
||||||
std::list<DebugTrace> debugTraces;
|
std::list<DebugTrace> debugTraces;
|
||||||
|
@ -140,13 +143,14 @@ public:
|
||||||
return std::shared_ptr<const StaticEnv>();;
|
return std::shared_ptr<const StaticEnv>();;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void debugRepl(const Error * error, const Env & env, const Expr & expr);
|
||||||
|
|
||||||
template<class E>
|
template<class E>
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void debugThrow(const E &error, const Env & env, const Expr & expr)
|
void debugThrow(const E &error, const Env & env, const Expr & expr)
|
||||||
{
|
{
|
||||||
if (debuggerHook)
|
if (debugMode)
|
||||||
debuggerHook(*this, &error, env, expr);
|
debugRepl(&error, env, expr);
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -158,14 +162,15 @@ public:
|
||||||
// Call this in the situation where Expr and Env are inaccessible.
|
// Call this in the situation where Expr and Env are inaccessible.
|
||||||
// The debugger will start in the last context that's in the
|
// The debugger will start in the last context that's in the
|
||||||
// DebugTrace stack.
|
// DebugTrace stack.
|
||||||
if (debuggerHook && !debugTraces.empty()) {
|
if (debugMode && !debugTraces.empty()) {
|
||||||
const DebugTrace & last = debugTraces.front();
|
const DebugTrace & last = debugTraces.front();
|
||||||
debuggerHook(*this, &e, last.env, last.expr);
|
debugRepl(&e, last.env, last.expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SrcToStore srcToStore;
|
SrcToStore srcToStore;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace nix {
|
||||||
|
|
||||||
/* Launch the nix debugger */
|
/* Launch the nix debugger */
|
||||||
|
|
||||||
std::function<void(EvalState & evalState,const Error * error, const Env & env, const Expr & expr)> debuggerHook;
|
// std::function<void(EvalState & evalState,const Error * error, const Env & env, const Expr & expr)> debuggerHook;
|
||||||
|
|
||||||
/* Displaying abstract syntax trees. */
|
/* Displaying abstract syntax trees. */
|
||||||
|
|
||||||
|
@ -303,31 +303,31 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
/* Check whether the variable appears in the environment. If so,
|
/* Check whether the variable appears in the environment. If so,
|
||||||
|
@ -363,7 +363,7 @@ void ExprVar::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
|
|
||||||
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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
e->bindVars(es, env);
|
e->bindVars(es, env);
|
||||||
|
@ -375,7 +375,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
e->bindVars(es, env);
|
e->bindVars(es, env);
|
||||||
|
@ -386,7 +386,7 @@ void ExprOpHasAttr::bindVars(EvalState & es, const std::shared_ptr<const StaticE
|
||||||
|
|
||||||
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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
|
@ -419,7 +419,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
for (auto & i : elems)
|
for (auto & i : elems)
|
||||||
|
@ -428,7 +428,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
auto newEnv = std::make_shared<StaticEnv>(
|
auto newEnv = std::make_shared<StaticEnv>(
|
||||||
|
@ -455,7 +455,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
fun->bindVars(es, env);
|
fun->bindVars(es, env);
|
||||||
|
@ -465,7 +465,7 @@ void ExprCall::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
|
|
||||||
void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
|
||||||
{
|
{
|
||||||
if (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
auto newEnv = std::make_shared<StaticEnv>(false, env.get(), attrs->attrs.size());
|
auto newEnv = std::make_shared<StaticEnv>(false, env.get(), attrs->attrs.size());
|
||||||
|
@ -484,7 +484,7 @@ void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
|
|
||||||
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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
/* Does this `with' have an enclosing `with'? If so, record its
|
/* Does this `with' have an enclosing `with'? If so, record its
|
||||||
|
@ -499,7 +499,7 @@ void ExprWith::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
attrs->bindVars(es, env);
|
attrs->bindVars(es, env);
|
||||||
|
@ -509,7 +509,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
cond->bindVars(es, env);
|
cond->bindVars(es, env);
|
||||||
|
@ -519,7 +519,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
cond->bindVars(es, env);
|
cond->bindVars(es, env);
|
||||||
|
@ -528,7 +528,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
e->bindVars(es, env);
|
e->bindVars(es, env);
|
||||||
|
@ -536,7 +536,7 @@ void ExprOpNot::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
|
||||||
|
|
||||||
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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
for (auto & i : *this->es)
|
for (auto & i : *this->es)
|
||||||
|
@ -545,7 +545,7 @@ 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 (debuggerHook)
|
if (es.debugMode)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ MakeError(UndefinedVarError, Error);
|
||||||
MakeError(MissingArgumentError, EvalError);
|
MakeError(MissingArgumentError, EvalError);
|
||||||
MakeError(RestrictedPathError, Error);
|
MakeError(RestrictedPathError, Error);
|
||||||
|
|
||||||
extern std::function<void(EvalState & evalState, const Error * error, const Env & env, const Expr & expr)> debuggerHook;
|
// extern std::function<void(EvalState & evalState, const Error * error, const Env & env, const Expr & expr)> debuggerHook;
|
||||||
|
|
||||||
/* Position objects. */
|
/* Position objects. */
|
||||||
|
|
||||||
|
|
|
@ -757,7 +757,7 @@ static RegisterPrimOp primop_break({
|
||||||
)",
|
)",
|
||||||
.fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
.fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
if (debuggerHook && !state.debugTraces.empty()) {
|
if (state.debugMode && !state.debugTraces.empty()) {
|
||||||
auto error = Error(ErrorInfo {
|
auto error = Error(ErrorInfo {
|
||||||
.level = lvlInfo,
|
.level = lvlInfo,
|
||||||
.msg = hintfmt("breakpoint reached"),
|
.msg = hintfmt("breakpoint reached"),
|
||||||
|
@ -765,7 +765,7 @@ static RegisterPrimOp primop_break({
|
||||||
});
|
});
|
||||||
|
|
||||||
auto & dt = state.debugTraces.front();
|
auto & dt = state.debugTraces.front();
|
||||||
debuggerHook(state, &error, dt.env, dt.expr);
|
state.debugRepl(&error, dt.env, dt.expr);
|
||||||
|
|
||||||
if (state.debugQuit) {
|
if (state.debugQuit) {
|
||||||
// If the user elects to quit the repl, throw an exception.
|
// If the user elects to quit the repl, throw an exception.
|
||||||
|
@ -879,8 +879,8 @@ static RegisterPrimOp primop_floor({
|
||||||
static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
auto attrs = state.buildBindings(2);
|
auto attrs = state.buildBindings(2);
|
||||||
auto saveDebuggerHook = debuggerHook;
|
auto saveDebugMode = state.debugMode;
|
||||||
debuggerHook = nullptr;
|
state.debugMode = false;
|
||||||
try {
|
try {
|
||||||
state.forceValue(*args[0], pos);
|
state.forceValue(*args[0], pos);
|
||||||
attrs.insert(state.sValue, args[0]);
|
attrs.insert(state.sValue, args[0]);
|
||||||
|
@ -889,7 +889,7 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va
|
||||||
attrs.alloc(state.sValue).mkBool(false);
|
attrs.alloc(state.sValue).mkBool(false);
|
||||||
attrs.alloc("success").mkBool(false);
|
attrs.alloc("success").mkBool(false);
|
||||||
}
|
}
|
||||||
debuggerHook = saveDebuggerHook;
|
state.debugMode = saveDebugMode;
|
||||||
v.mkAttrs(attrs);
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue