forked from lix-project/lix
incorporate PosIdx changes, symbol changes.
This commit is contained in:
parent
6e19947993
commit
2a5632c70d
|
@ -126,7 +126,7 @@ ref<EvalState> EvalCommand::getEvalState()
|
||||||
new DebugTraceStacker(
|
new DebugTraceStacker(
|
||||||
*evalState,
|
*evalState,
|
||||||
DebugTrace
|
DebugTrace
|
||||||
{.pos = (error->info().errPos ? *error->info().errPos : *expr.getPos()),
|
{.pos = (error->info().errPos ? *error->info().errPos : evalState->positions[expr.getPos()]),
|
||||||
.expr = expr,
|
.expr = expr,
|
||||||
.env = env,
|
.env = env,
|
||||||
.hint = error->info().msg,
|
.hint = error->info().msg,
|
||||||
|
@ -139,7 +139,7 @@ ref<EvalState> EvalCommand::getEvalState()
|
||||||
|
|
||||||
if (expr.staticenv)
|
if (expr.staticenv)
|
||||||
{
|
{
|
||||||
std::unique_ptr<valmap> vm(mapStaticEnvBindings(*expr.staticenv.get(), env));
|
std::unique_ptr<valmap> vm(mapStaticEnvBindings(evalState->symbols, *expr.staticenv.get(), env));
|
||||||
runRepl(evalState, expr, *vm);
|
runRepl(evalState, expr, *vm);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,7 +203,7 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& showDebugTrace(std::ostream &out, const DebugTrace &dt)
|
std::ostream& showDebugTrace(std::ostream &out, const PosTable &positions, const DebugTrace &dt)
|
||||||
{
|
{
|
||||||
if (dt.is_error)
|
if (dt.is_error)
|
||||||
out << ANSI_RED "error: " << ANSI_NORMAL;
|
out << ANSI_RED "error: " << ANSI_NORMAL;
|
||||||
|
@ -211,7 +211,7 @@ std::ostream& showDebugTrace(std::ostream &out, const DebugTrace &dt)
|
||||||
|
|
||||||
// prefer direct pos, but if noPos then try the expr.
|
// prefer direct pos, but if noPos then try the expr.
|
||||||
auto pos = (*dt.pos ? *dt.pos :
|
auto pos = (*dt.pos ? *dt.pos :
|
||||||
(dt.expr.getPos() ? *dt.expr.getPos() : noPos));
|
positions[(dt.expr.getPos() ? dt.expr.getPos() : noPos)]);
|
||||||
|
|
||||||
if (pos) {
|
if (pos) {
|
||||||
printAtPos(pos, out);
|
printAtPos(pos, out);
|
||||||
|
@ -280,7 +280,7 @@ void NixRepl::mainLoop(const std::vector<std::string> & files)
|
||||||
// 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 && !this->state->debugTraces.empty())
|
if (debuggerHook && !this->state->debugTraces.empty())
|
||||||
showDebugTrace(std::cout, this->state->debugTraces.front());
|
showDebugTrace(std::cout, this->state->positions, this->state->debugTraces.front());
|
||||||
else
|
else
|
||||||
printMsg(lvlError, e.msg());
|
printMsg(lvlError, e.msg());
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
|
@ -443,7 +443,7 @@ void NixRepl::loadDebugTraceEnv(DebugTrace &dt)
|
||||||
{
|
{
|
||||||
initEnv();
|
initEnv();
|
||||||
|
|
||||||
auto vm = std::make_unique<valmap>(*(mapStaticEnvBindings(*dt.expr.staticenv.get(), dt.env)));
|
auto vm = std::make_unique<valmap>(*(mapStaticEnvBindings(this->state->symbols, *dt.expr.staticenv.get(), dt.env)));
|
||||||
|
|
||||||
// add staticenv vars.
|
// add staticenv vars.
|
||||||
for (auto & [name, value] : *(vm.get())) {
|
for (auto & [name, value] : *(vm.get())) {
|
||||||
|
@ -514,7 +514,7 @@ bool NixRepl::processLine(std::string line)
|
||||||
iter != this->state->debugTraces.end();
|
iter != this->state->debugTraces.end();
|
||||||
++iter, ++idx) {
|
++iter, ++idx) {
|
||||||
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
||||||
showDebugTrace(std::cout, *iter);
|
showDebugTrace(std::cout, this->state->positions, *iter);
|
||||||
}
|
}
|
||||||
} else if (arg == "env") {
|
} else if (arg == "env") {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
@ -523,7 +523,7 @@ bool NixRepl::processLine(std::string line)
|
||||||
++iter, ++idx) {
|
++iter, ++idx) {
|
||||||
if (idx == this->debugTraceIndex)
|
if (idx == this->debugTraceIndex)
|
||||||
{
|
{
|
||||||
printEnvBindings(iter->expr, iter->env);
|
printEnvBindings(state->symbols,iter->expr, iter->env);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -544,9 +544,9 @@ bool NixRepl::processLine(std::string line)
|
||||||
if (idx == this->debugTraceIndex)
|
if (idx == this->debugTraceIndex)
|
||||||
{
|
{
|
||||||
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
std::cout << "\n" << ANSI_BLUE << idx << ANSI_NORMAL << ": ";
|
||||||
showDebugTrace(std::cout, *iter);
|
showDebugTrace(std::cout, this->state->positions, *iter);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
printEnvBindings(iter->expr, iter->env);
|
printEnvBindings(state->symbols,iter->expr, iter->env);
|
||||||
loadDebugTraceEnv(*iter);
|
loadDebugTraceEnv(*iter);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ void EvalState::forceValue(Value & v, Callable getPos)
|
||||||
else if (v.isApp())
|
else if (v.isApp())
|
||||||
callFunction(*v.app.left, *v.app.right, v, noPos);
|
callFunction(*v.app.left, *v.app.right, v, noPos);
|
||||||
else if (v.isBlackhole())
|
else if (v.isBlackhole())
|
||||||
throwEvalError(getPos(), "infinite recursion encountered", *this);
|
throwEvalError(getPos(), "infinite recursion encountered");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ inline void EvalState::forceAttrs(Value & v, Callable getPos)
|
||||||
{
|
{
|
||||||
forceValue(v, getPos);
|
forceValue(v, getPos);
|
||||||
if (v.type() != nAttrs)
|
if (v.type() != nAttrs)
|
||||||
throwTypeError(getPos(), "value is %1% while a set was expected", v, *this);
|
throwTypeError(getPos(), "value is %1% while a set was expected", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ inline void EvalState::forceList(Value & v, const PosIdx pos)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceValue(v, pos);
|
||||||
if (!v.isList())
|
if (!v.isList())
|
||||||
throwTypeError(pos, "value is %1% while a list was expected", v, *this);
|
throwTypeError(pos, "value is %1% while a list was expected", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -714,19 +714,19 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
|
||||||
|
|
||||||
|
|
||||||
// just for the current level of StaticEnv, not the whole chain.
|
// just for the current level of StaticEnv, not the whole chain.
|
||||||
void printStaticEnvBindings(const StaticEnv &se)
|
void printStaticEnvBindings(const SymbolTable &st, const StaticEnv &se)
|
||||||
{
|
{
|
||||||
std::cout << ANSI_MAGENTA;
|
std::cout << ANSI_MAGENTA;
|
||||||
for (auto i = se.vars.begin(); i != se.vars.end(); ++i)
|
for (auto i = se.vars.begin(); i != se.vars.end(); ++i)
|
||||||
{
|
{
|
||||||
std::cout << i->first << " ";
|
std::cout << st[i->first] << " ";
|
||||||
}
|
}
|
||||||
std::cout << ANSI_NORMAL;
|
std::cout << ANSI_NORMAL;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// just for the current level of Env, not the whole chain.
|
// just for the current level of Env, not the whole chain.
|
||||||
void printWithBindings(const Env &env)
|
void printWithBindings(const SymbolTable &st, const Env &env)
|
||||||
{
|
{
|
||||||
if (env.type == Env::HasWithAttrs)
|
if (env.type == Env::HasWithAttrs)
|
||||||
{
|
{
|
||||||
|
@ -734,7 +734,7 @@ void printWithBindings(const Env &env)
|
||||||
std::cout << ANSI_MAGENTA;
|
std::cout << ANSI_MAGENTA;
|
||||||
Bindings::iterator j = env.values[0]->attrs->begin();
|
Bindings::iterator j = env.values[0]->attrs->begin();
|
||||||
while (j != env.values[0]->attrs->end()) {
|
while (j != env.values[0]->attrs->end()) {
|
||||||
std::cout << j->name << " ";
|
std::cout << st[j->name] << " ";
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
std::cout << ANSI_NORMAL;
|
std::cout << ANSI_NORMAL;
|
||||||
|
@ -742,16 +742,16 @@ void printWithBindings(const Env &env)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printEnvBindings(const StaticEnv &se, const Env &env, int lvl)
|
void printEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env, int lvl)
|
||||||
{
|
{
|
||||||
std::cout << "Env level " << lvl << std::endl;
|
std::cout << "Env level " << lvl << std::endl;
|
||||||
|
|
||||||
if (se.up && env.up) {
|
if (se.up && env.up) {
|
||||||
std::cout << "static: ";
|
std::cout << "static: ";
|
||||||
printStaticEnvBindings(se);
|
printStaticEnvBindings(st, se);
|
||||||
printWithBindings(env);
|
printWithBindings(st, env);
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
printEnvBindings(*se.up, *env.up, ++lvl);
|
printEnvBindings(st, *se.up, *env.up, ++lvl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -759,41 +759,41 @@ void printEnvBindings(const StaticEnv &se, const Env &env, int lvl)
|
||||||
// for the top level, don't print the double underscore ones; they are in builtins.
|
// for the top level, don't print the double underscore ones; they are in builtins.
|
||||||
for (auto i = se.vars.begin(); i != se.vars.end(); ++i)
|
for (auto i = se.vars.begin(); i != se.vars.end(); ++i)
|
||||||
{
|
{
|
||||||
if (((std::string)i->first).substr(0,2) != "__")
|
if (((std::string)st[i->first]).substr(0,2) != "__")
|
||||||
std::cout << i->first << " ";
|
std::cout << st[i->first] << " ";
|
||||||
}
|
}
|
||||||
std::cout << ANSI_NORMAL;
|
std::cout << ANSI_NORMAL;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
printWithBindings(env); // probably nothing there for the top level.
|
printWithBindings(st, env); // probably nothing there for the top level.
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add accompanying env for With stuff.
|
// TODO: add accompanying env for With stuff.
|
||||||
void printEnvBindings(const Expr &expr, const Env &env)
|
void printEnvBindings(const SymbolTable &st, const Expr &expr, const Env &env)
|
||||||
{
|
{
|
||||||
// just print the names for now
|
// just print the names for now
|
||||||
if (expr.staticenv)
|
if (expr.staticenv)
|
||||||
{
|
{
|
||||||
printEnvBindings(*expr.staticenv.get(), env, 0);
|
printEnvBindings(st, *expr.staticenv.get(), env, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mapStaticEnvBindings(const StaticEnv &se, const Env &env, valmap & vm)
|
void mapStaticEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env, valmap & vm)
|
||||||
{
|
{
|
||||||
// add bindings for the next level up first, so that the bindings for this level
|
// add bindings for the next level up first, so that the bindings for this level
|
||||||
// override the higher levels.
|
// override the higher levels.
|
||||||
// The top level bindings (builtins) are skipped since they are added for us by initEnv()
|
// The top level bindings (builtins) are skipped since they are added for us by initEnv()
|
||||||
if (env.up && se.up) {
|
if (env.up && se.up) {
|
||||||
mapStaticEnvBindings(*se.up, *env.up, vm);
|
mapStaticEnvBindings(st, *se.up, *env.up, vm);
|
||||||
|
|
||||||
if (env.type == Env::HasWithAttrs)
|
if (env.type == Env::HasWithAttrs)
|
||||||
{
|
{
|
||||||
// add 'with' bindings.
|
// add 'with' bindings.
|
||||||
Bindings::iterator j = env.values[0]->attrs->begin();
|
Bindings::iterator j = env.values[0]->attrs->begin();
|
||||||
while (j != env.values[0]->attrs->end()) {
|
while (j != env.values[0]->attrs->end()) {
|
||||||
vm[j->name] = j->value;
|
vm[st[j->name]] = j->value;
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -802,24 +802,45 @@ void mapStaticEnvBindings(const StaticEnv &se, const Env &env, valmap & vm)
|
||||||
// iterate through staticenv bindings and add them.
|
// iterate through staticenv bindings and add them.
|
||||||
for (auto iter = se.vars.begin(); iter != se.vars.end(); ++iter)
|
for (auto iter = se.vars.begin(); iter != se.vars.end(); ++iter)
|
||||||
{
|
{
|
||||||
vm[iter->first] = env.values[iter->second];
|
vm[st[iter->first]] = env.values[iter->second];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valmap * mapStaticEnvBindings(const StaticEnv &se, const Env &env)
|
valmap * mapStaticEnvBindings(const SymbolTable &st,const StaticEnv &se, const Env &env)
|
||||||
{
|
{
|
||||||
auto vm = new valmap();
|
auto vm = new valmap();
|
||||||
mapStaticEnvBindings(se, env, *vm);
|
mapStaticEnvBindings(st, se, env, *vm);
|
||||||
return vm;
|
return vm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EvalState::debugLastTrace(Error & e) const {
|
||||||
|
// call this in the situation where Expr and Env are inaccessible. The debugger will start in the last context
|
||||||
|
// that's in the DebugTrace stack.
|
||||||
|
if (debuggerHook && !debugTraces.empty()) {
|
||||||
|
const DebugTrace &last = debugTraces.front();
|
||||||
|
debuggerHook(&e, last.env, last.expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
exceptions. */
|
exceptions. */
|
||||||
|
void EvalState::throwEvalError(const PosIdx pos, const char * s, Env & env, Expr &expr) const
|
||||||
|
{
|
||||||
|
auto error = EvalError({
|
||||||
|
.msg = hintfmt(s),
|
||||||
|
.errPos = positions[pos]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (debuggerHook)
|
||||||
|
debuggerHook(&error, env, expr);
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
void EvalState::throwEvalError(const PosIdx pos, const char * s) const
|
void EvalState::throwEvalError(const PosIdx pos, const char * s) const
|
||||||
{
|
{
|
||||||
|
@ -828,25 +849,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s) const
|
||||||
.errPos = positions[pos]
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
|
|
||||||
if (debuggerHook && !debugTraces.empty()) {
|
debugLastTrace(error);
|
||||||
DebugTrace &last = debugTraces.front();
|
|
||||||
debuggerHook(&error, last.env, last.expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v) const
|
|
||||||
{
|
|
||||||
auto error = TypeError({
|
|
||||||
.msg = hintfmt(s, showType(v)),
|
|
||||||
.errPos = positions[pos]
|
|
||||||
});
|
|
||||||
|
|
||||||
if (debuggerHook && !debugTraces.empty()) {
|
|
||||||
DebugTrace &last = debugTraces.front();
|
|
||||||
debuggerHook(&error, last.env, last.expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -855,23 +858,11 @@ void EvalState::throwEvalError(const char * s, const std::string & s2) const
|
||||||
{
|
{
|
||||||
auto error = EvalError(s, s2);
|
auto error = EvalError(s, s2);
|
||||||
|
|
||||||
if (debuggerHook && !debugTraces.empty()) {
|
debugLastTrace(error);
|
||||||
DebugTrace &last = debugTraces.front();
|
|
||||||
debuggerHook(&error, last.env, last.expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::debugLastTrace(Error & e) {
|
|
||||||
// call this in the situation where Expr and Env are inaccessible. The debugger will start in the last context
|
|
||||||
// that's in the DebugTrace stack.
|
|
||||||
if (debuggerHook && !debugTraces.empty()) {
|
|
||||||
DebugTrace &last = debugTraces.front();
|
|
||||||
debuggerHook(&e, last.env, last.expr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EvalState::throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
void EvalState::throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
||||||
const std::string & s2, Env & env, Expr &expr) const
|
const std::string & s2, Env & env, Expr &expr) const
|
||||||
{
|
{
|
||||||
|
@ -899,16 +890,43 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::throwEvalError(const char * s, const std::string & s2, const std::string & s3, Env & env, Expr &expr) const
|
void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::string & s2, Env & env, Expr &expr) const
|
||||||
{
|
{
|
||||||
auto error = EvalError({
|
auto error = EvalError({
|
||||||
.msg = hintfmt(s),
|
.msg = hintfmt(s, s2),
|
||||||
.errPos = pos
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
|
|
||||||
if (debuggerHook)
|
if (debuggerHook)
|
||||||
debuggerHook(&error, env, expr);
|
debuggerHook(&error, env, expr);
|
||||||
|
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvalState::throwEvalError(const char * s, const std::string & s2,
|
||||||
|
const std::string & s3) const
|
||||||
|
{
|
||||||
|
auto error = EvalError({
|
||||||
|
.msg = hintfmt(s, s2),
|
||||||
|
.errPos = positions[noPos]
|
||||||
|
});
|
||||||
|
|
||||||
|
debugLastTrace(error);
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::string & s2,
|
||||||
|
const std::string & s3) const
|
||||||
|
{
|
||||||
|
auto error = EvalError({
|
||||||
|
.msg = hintfmt(s, s2),
|
||||||
|
.errPos = positions[pos]
|
||||||
|
});
|
||||||
|
|
||||||
|
debugLastTrace(error);
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,7 +935,7 @@ void EvalState::throwEvalError(const PosIdx pos, const char * s, const std::stri
|
||||||
{
|
{
|
||||||
auto error = EvalError({
|
auto error = EvalError({
|
||||||
.msg = hintfmt(s, s2),
|
.msg = hintfmt(s, s2),
|
||||||
.errPos = pos
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
|
|
||||||
if (debuggerHook)
|
if (debuggerHook)
|
||||||
|
@ -966,6 +984,31 @@ void EvalState::throwEvalError(const PosIdx p1, const char * s, const Symbol sym
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v) const
|
||||||
|
{
|
||||||
|
auto error = TypeError({
|
||||||
|
.msg = hintfmt(s, showType(v)),
|
||||||
|
.errPos = positions[pos]
|
||||||
|
});
|
||||||
|
|
||||||
|
debugLastTrace(error);
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvalState::throwTypeError(const PosIdx pos, const char * s, const Value & v, Env & env, Expr &expr) const
|
||||||
|
{
|
||||||
|
auto error = TypeError({
|
||||||
|
.msg = hintfmt(s, showType(v)),
|
||||||
|
.errPos = positions[pos]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (debuggerHook)
|
||||||
|
debuggerHook(&error, env, expr);
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
void EvalState::throwTypeError(const PosIdx pos, const char * s) const
|
void EvalState::throwTypeError(const PosIdx pos, const char * s) const
|
||||||
{
|
{
|
||||||
auto error = TypeError({
|
auto error = TypeError({
|
||||||
|
@ -973,7 +1016,7 @@ void EvalState::throwTypeError(const PosIdx pos, const char * s) const
|
||||||
.errPos = positions[pos]
|
.errPos = positions[pos]
|
||||||
});
|
});
|
||||||
|
|
||||||
evalState.debugLastTrace(error);
|
debugLastTrace(error);
|
||||||
|
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
@ -1010,9 +1053,8 @@ void EvalState::throwTypeError(const PosIdx pos, const Suggestions & suggestions
|
||||||
void EvalState::throwTypeError(const char * s, const Value & v, Env & env, Expr &expr) const
|
void EvalState::throwTypeError(const char * s, const Value & v, Env & env, Expr &expr) const
|
||||||
{
|
{
|
||||||
auto error = TypeError({
|
auto error = TypeError({
|
||||||
.msg = hintfmt(s, fun.showNamePos(), s2),
|
.msg = hintfmt(s, showType(v)),
|
||||||
.errPos = pos,
|
.errPos = positions[expr.getPos()],
|
||||||
.suggestions = suggestions,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (debuggerHook)
|
if (debuggerHook)
|
||||||
|
@ -1070,8 +1112,8 @@ void EvalState::addErrorTrace(Error & e, const PosIdx pos, const char * s, const
|
||||||
e.addTrace(positions[pos], s, s2);
|
e.addTrace(positions[pos], s, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalNoInline(std::unique_ptr<DebugTraceStacker>
|
std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(EvalState &state, Expr &expr, Env &env,
|
||||||
makeDebugTraceStacker(EvalState &state, Expr &expr, Env &env, std::optional<ErrPos> pos, const char * s, const std::string & s2))
|
std::optional<ErrPos> pos, const char * s, const std::string & s2)
|
||||||
{
|
{
|
||||||
return std::unique_ptr<DebugTraceStacker>(
|
return std::unique_ptr<DebugTraceStacker>(
|
||||||
new DebugTraceStacker(
|
new DebugTraceStacker(
|
||||||
|
@ -1150,7 +1192,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||||
return j->value;
|
return j->value;
|
||||||
}
|
}
|
||||||
if (!env->prevWith)
|
if (!env->prevWith)
|
||||||
throwUndefinedVarError(var.pos, "undefined variable '%1%'", symbols[var.name], *env, var);
|
throwUndefinedVarError(var.pos, "undefined variable '%1%'", symbols[var.name], *env, const_cast<ExprVar&>(var));
|
||||||
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
for (size_t l = env->prevWith; l; --l, env = env->up) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1293,7 +1335,7 @@ void EvalState::cacheFile(
|
||||||
*this,
|
*this,
|
||||||
*e,
|
*e,
|
||||||
this->baseEnv,
|
this->baseEnv,
|
||||||
(e->getPos() ? std::optional(ErrPos(*e->getPos())) : std::nullopt),
|
(e->getPos() ? std::optional(ErrPos(positions[e->getPos()])) : std::nullopt),
|
||||||
"while evaluating the file '%1%':", resolvedPath)
|
"while evaluating the file '%1%':", resolvedPath)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
|
@ -1528,7 +1570,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||||
state,
|
state,
|
||||||
*this,
|
*this,
|
||||||
env,
|
env,
|
||||||
*pos2,
|
state.positions[pos2],
|
||||||
"while evaluating the attribute '%1%'",
|
"while evaluating the attribute '%1%'",
|
||||||
showAttrPath(state, env, attrPath))
|
showAttrPath(state, env, attrPath))
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
@ -1694,10 +1736,10 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
try {
|
try {
|
||||||
auto dts =
|
auto dts =
|
||||||
debuggerHook ?
|
debuggerHook ?
|
||||||
makeDebugTraceStacker(*this, *lambda.body, env2, lambda.pos,
|
makeDebugTraceStacker(*this, *lambda.body, env2, positions[lambda.pos],
|
||||||
"while evaluating %s",
|
"while evaluating %s",
|
||||||
(lambda.name.set()
|
(lambda.name
|
||||||
? "'" + (std::string) lambda.name + "'"
|
? concatStrings("'", symbols[lambda.name], "'")
|
||||||
: "anonymous lambda"))
|
: "anonymous lambda"))
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
|
@ -1786,7 +1828,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
throwTypeError(pos, "attempt to call something which is not a function but %1%", vCur, *this);
|
throwTypeError(pos, "attempt to call something which is not a function but %1%", vCur);
|
||||||
}
|
}
|
||||||
|
|
||||||
vRes = vCur;
|
vRes = vCur;
|
||||||
|
@ -1855,7 +1897,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||||
Nix attempted to evaluate a function as a top level expression; in
|
Nix attempted to evaluate a function as a top level expression; in
|
||||||
this case it must have its arguments supplied either by default
|
this case it must have its arguments supplied either by default
|
||||||
values, or passed explicitly with '--arg' or '--argstr'. See
|
values, or passed explicitly with '--arg' or '--argstr'. See
|
||||||
https://nixos.org/manual/nix/stable/#ss-functions.)", symbols[i.name],,
|
https://nixos.org/manual/nix/stable/#ss-functions.)", symbols[i.name],
|
||||||
*fun.lambda.env, *fun.lambda.fun);
|
*fun.lambda.env, *fun.lambda.fun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2092,7 +2134,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||||
v.mkFloat(nf);
|
v.mkFloat(nf);
|
||||||
else if (firstType == nPath) {
|
else if (firstType == nPath) {
|
||||||
if (!context.empty())
|
if (!context.empty())
|
||||||
state.throwEvalError(pos, "a string that refers to a store path cannot be appended to a path", env, *this););
|
state.throwEvalError(pos, "a string that refers to a store path cannot be appended to a path", env, *this);
|
||||||
v.mkPath(canonPath(str()));
|
v.mkPath(canonPath(str()));
|
||||||
} else
|
} else
|
||||||
v.mkStringMove(c_str(), context);
|
v.mkStringMove(c_str(), context);
|
||||||
|
@ -2124,8 +2166,8 @@ void EvalState::forceValueDeep(Value & v)
|
||||||
debuggerHook ?
|
debuggerHook ?
|
||||||
// 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.
|
||||||
(i.value->isThunk() ?
|
(i.value->isThunk() ?
|
||||||
makeDebugTraceStacker(*this, *v.thunk.expr, *v.thunk.env, *i.pos,
|
makeDebugTraceStacker(*this, *v.thunk.expr, *v.thunk.env, positions[i.pos],
|
||||||
"while evaluating the attribute '%1%'", i.name)
|
"while evaluating the attribute '%1%'", symbols[i.name])
|
||||||
: nullptr)
|
: nullptr)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
|
@ -2150,7 +2192,7 @@ NixInt EvalState::forceInt(Value & v, const PosIdx pos)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceValue(v, pos);
|
||||||
if (v.type() != nInt)
|
if (v.type() != nInt)
|
||||||
throwTypeError(pos, "value is %1% while an integer was expected", v, *this);
|
throwTypeError(pos, "value is %1% while an integer was expected", v);
|
||||||
|
|
||||||
return v.integer;
|
return v.integer;
|
||||||
}
|
}
|
||||||
|
@ -2162,7 +2204,7 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos)
|
||||||
if (v.type() == nInt)
|
if (v.type() == nInt)
|
||||||
return v.integer;
|
return v.integer;
|
||||||
else if (v.type() != nFloat)
|
else if (v.type() != nFloat)
|
||||||
throwTypeError(pos, "value is %1% while a float was expected", v, *this);
|
throwTypeError(pos, "value is %1% while a float was expected", v);
|
||||||
return v.fpoint;
|
return v.fpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2171,7 +2213,7 @@ bool EvalState::forceBool(Value & v, const PosIdx pos)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceValue(v, pos);
|
||||||
if (v.type() != nBool)
|
if (v.type() != nBool)
|
||||||
throwTypeError(pos, "value is %1% while a Boolean was expected", v, *this);
|
throwTypeError(pos, "value is %1% while a Boolean was expected", v);
|
||||||
return v.boolean;
|
return v.boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2186,7 +2228,7 @@ void EvalState::forceFunction(Value & v, const PosIdx pos)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceValue(v, pos);
|
||||||
if (v.type() != nFunction && !isFunctor(v))
|
if (v.type() != nFunction && !isFunctor(v))
|
||||||
throwTypeError(pos, "value is %1% while a function was expected", v, *this);
|
throwTypeError(pos, "value is %1% while a function was expected", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2194,7 +2236,7 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceValue(v, pos);
|
||||||
if (v.type() != nString) {
|
if (v.type() != nString) {
|
||||||
throwTypeError(pos, "value is %1% while a string was expected", v, *this);
|
throwTypeError(pos, "value is %1% while a string was expected", v);
|
||||||
}
|
}
|
||||||
return v.string.s;
|
return v.string.s;
|
||||||
}
|
}
|
||||||
|
@ -2254,10 +2296,10 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos)
|
||||||
if (v.string.context) {
|
if (v.string.context) {
|
||||||
if (pos)
|
if (pos)
|
||||||
throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
throwEvalError(pos, "the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||||
v.string.s, v.string.context[0], *this);
|
v.string.s, v.string.context[0]);
|
||||||
else
|
else
|
||||||
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
throwEvalError("the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||||
v.string.s, v.string.context[0], *this);
|
v.string.s, v.string.context[0]);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
@ -2312,7 +2354,7 @@ BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet
|
||||||
return std::move(*maybeString);
|
return std::move(*maybeString);
|
||||||
auto i = v.attrs->find(sOutPath);
|
auto i = v.attrs->find(sOutPath);
|
||||||
if (i == v.attrs->end())
|
if (i == v.attrs->end())
|
||||||
throwTypeError(pos, "cannot coerce a set to a string", *this);
|
throwTypeError(pos, "cannot coerce a set to a string");
|
||||||
return coerceToString(pos, *i->value, context, coerceMore, copyToStore);
|
return coerceToString(pos, *i->value, context, coerceMore, copyToStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2341,14 +2383,14 @@ BackedStringView EvalState::coerceToString(const PosIdx pos, Value & v, PathSet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throwTypeError(pos, "cannot coerce %1% to a string", v, *this);
|
throwTypeError(pos, "cannot coerce %1% to a string", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string EvalState::copyPathToStore(PathSet & context, const Path & path)
|
std::string EvalState::copyPathToStore(PathSet & context, const Path & path)
|
||||||
{
|
{
|
||||||
if (nix::isDerivation(path))
|
if (nix::isDerivation(path))
|
||||||
throwEvalError("file names are not allowed to end in '%1%'", drvExtension, *this);
|
throwEvalError("file names are not allowed to end in '%1%'", drvExtension);
|
||||||
|
|
||||||
Path dstPath;
|
Path dstPath;
|
||||||
auto i = srcToStore.find(path);
|
auto i = srcToStore.find(path);
|
||||||
|
@ -2373,7 +2415,7 @@ Path EvalState::coerceToPath(const PosIdx pos, Value & v, PathSet & context)
|
||||||
{
|
{
|
||||||
auto path = coerceToString(pos, v, context, false, false).toOwned();
|
auto path = coerceToString(pos, v, context, false, false).toOwned();
|
||||||
if (path == "" || path[0] != '/')
|
if (path == "" || path[0] != '/')
|
||||||
throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path, *this);
|
throwEvalError(pos, "string '%1%' doesn't represent an absolute path", path);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2466,8 +2508,7 @@ bool EvalState::eqValues(Value & v1, Value & v2)
|
||||||
default:
|
default:
|
||||||
throwEvalError("cannot compare %1% with %2%",
|
throwEvalError("cannot compare %1% with %2%",
|
||||||
showType(v1),
|
showType(v1),
|
||||||
showType(v2),
|
showType(v2));
|
||||||
*this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ 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 Expr &expr, const Env &env);
|
void printEnvBindings(const SymbolTable &st, const Expr &expr, const Env &env);
|
||||||
void printEnvBindings(const StaticEnv &se, const Env &env, int lvl = 0);
|
void printEnvBindings(const SymbolTable &st, const StaticEnv &se, const Env &env, int lvl = 0);
|
||||||
|
|
||||||
struct PrimOp
|
struct PrimOp
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ struct Env
|
||||||
Value * values[0];
|
Value * values[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
valmap * mapStaticEnvBindings(const StaticEnv &se, const Env &env);
|
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);
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ public:
|
||||||
bool debugStop;
|
bool debugStop;
|
||||||
bool debugQuit;
|
bool debugQuit;
|
||||||
std::list<DebugTrace> debugTraces;
|
std::list<DebugTrace> debugTraces;
|
||||||
void debugLastTrace(Error & e);
|
void debugLastTrace(Error & e) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SrcToStore srcToStore;
|
SrcToStore srcToStore;
|
||||||
|
@ -273,35 +273,66 @@ public:
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const PosIdx pos, const char * s) const;
|
void throwEvalError(const PosIdx pos, const char * s) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const PosIdx pos, const char * s, const Value & v) const;
|
void throwEvalError(const PosIdx pos, const char * s,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const char * s, const std::string & s2) const;
|
void throwEvalError(const char * s, const std::string & s2) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
|
||||||
const std::string & s2) const;
|
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
|
||||||
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2) const;
|
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const char * s, const std::string & s2, const std::string & s3) const;
|
void throwEvalError(const char * s, const std::string & s2,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwEvalError(const char * s, const std::string & s2, const std::string & s3,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3) const;
|
void throwEvalError(const PosIdx pos, const char * s, const std::string & s2, const std::string & s3) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwEvalError(const PosIdx p1, const char * s, const Symbol sym, const PosIdx p2) const;
|
void throwEvalError(const char * s, const std::string & s2, const std::string & s3) const;
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwEvalError(const PosIdx pos, const Suggestions & suggestions, const char * s, const std::string & s2,
|
||||||
|
Env & env, Expr &expr) const;
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwEvalError(const PosIdx p1, const char * s, const Symbol sym, const PosIdx p2,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwTypeError(const PosIdx pos, const char * s, const Value & v) const;
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwTypeError(const PosIdx pos, const char * s, const Value & v,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const PosIdx pos, const char * s) const;
|
void throwTypeError(const PosIdx pos, const char * s) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const Symbol s2) const;
|
void throwTypeError(const PosIdx pos, const char * s,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s,
|
void throwTypeError(const PosIdx pos, const char * s, const ExprLambda & fun, const Symbol s2,
|
||||||
const ExprLambda & fun, const Symbol s2) const;
|
Env & env, Expr & expr) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwTypeError(const char * s, const Value & v) const;
|
void throwTypeError(const PosIdx pos, const Suggestions & suggestions, const char * s, const ExprLambda & fun, const Symbol s2,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwAssertionError(const PosIdx pos, const char * s, const std::string & s1) const;
|
void throwTypeError(const char * s, const Value & v,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwUndefinedVarError(const PosIdx pos, const char * s, const std::string & s1) const;
|
void throwAssertionError(const PosIdx pos, const char * s, const std::string & s1,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwMissingArgumentError(const PosIdx pos, const char * s, const std::string & s1) const;
|
void throwUndefinedVarError(const PosIdx pos, const char * s, const std::string & s1,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwMissingArgumentError(const PosIdx pos, const char * s, const std::string & s1,
|
||||||
|
Env & env, Expr & expr) const;
|
||||||
|
|
||||||
[[gnu::noinline]]
|
[[gnu::noinline]]
|
||||||
void addErrorTrace(Error & e, const char * s, const std::string & s2) const;
|
void addErrorTrace(Error & e, const char * s, const std::string & s2) const;
|
||||||
|
@ -480,7 +511,7 @@ private:
|
||||||
class DebugTraceStacker {
|
class DebugTraceStacker {
|
||||||
public:
|
public:
|
||||||
DebugTraceStacker(EvalState &evalState, DebugTrace t);
|
DebugTraceStacker(EvalState &evalState, DebugTrace t);
|
||||||
~DebugTraceStacker()
|
~DebugTraceStacker()
|
||||||
{
|
{
|
||||||
// assert(evalState.debugTraces.front() == trace);
|
// assert(evalState.debugTraces.front() == trace);
|
||||||
evalState.debugTraces.pop_front();
|
evalState.debugTraces.pop_front();
|
||||||
|
|
|
@ -437,11 +437,11 @@ void ExprLambda::bindVars(const EvalState & es, const std::shared_ptr<const Stat
|
||||||
new StaticEnv(
|
new StaticEnv(
|
||||||
false, env.get(),
|
false, env.get(),
|
||||||
(hasFormals() ? formals->formals.size() : 0) +
|
(hasFormals() ? formals->formals.size() : 0) +
|
||||||
(!arg ? 0 : 1));
|
(!arg ? 0 : 1)));
|
||||||
|
|
||||||
Displacement displ = 0;
|
Displacement displ = 0;
|
||||||
|
|
||||||
if (arg) newEnv.vars.emplace_back(arg, displ++);
|
if (arg) newEnv->vars.emplace_back(arg, displ++);
|
||||||
|
|
||||||
if (hasFormals()) {
|
if (hasFormals()) {
|
||||||
for (auto & i : formals->formals)
|
for (auto & i : formals->formals)
|
||||||
|
@ -506,7 +506,7 @@ void ExprWith::bindVars(const EvalState & es, const std::shared_ptr<const Static
|
||||||
staticenv = env;
|
staticenv = env;
|
||||||
|
|
||||||
attrs->bindVars(es, env);
|
attrs->bindVars(es, env);
|
||||||
StaticEnv newEnv(true, &env);
|
auto newEnv = std::shared_ptr<StaticEnv>(new StaticEnv(true, env.get()));
|
||||||
body->bindVars(es, newEnv);
|
body->bindVars(es, newEnv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -278,7 +278,12 @@ struct ExprList : Expr
|
||||||
{
|
{
|
||||||
std::vector<Expr *> elems;
|
std::vector<Expr *> elems;
|
||||||
ExprList() { };
|
ExprList() { };
|
||||||
const PosIdx getPos() const { return pos; }
|
const PosIdx getPos() const
|
||||||
|
{ if (elems.empty())
|
||||||
|
return noPos;
|
||||||
|
else
|
||||||
|
return elems.front()->getPos();
|
||||||
|
}
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -389,7 +394,7 @@ struct ExprOpNot : Expr
|
||||||
{
|
{
|
||||||
Expr * e;
|
Expr * e;
|
||||||
ExprOpNot(Expr * e) : e(e) { };
|
ExprOpNot(Expr * e) : e(e) { };
|
||||||
const Pos* getPos() const { return 0; }
|
const PosIdx getPos() const { return noPos; }
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -774,12 +774,14 @@ static RegisterPrimOp primop_break({
|
||||||
.doc = R"(
|
.doc = R"(
|
||||||
In debug mode, pause Nix expression evaluation and enter the repl.
|
In debug mode, pause Nix expression evaluation and enter the repl.
|
||||||
)",
|
)",
|
||||||
.fun = [](EvalState & state, const Pos & pos, Value * * args, Value & v)
|
.fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
|
PathSet context;
|
||||||
|
auto s = state.coerceToString(pos, *args[0], context).toOwned();
|
||||||
auto error = Error(ErrorInfo{
|
auto error = Error(ErrorInfo{
|
||||||
.level = lvlInfo,
|
.level = lvlInfo,
|
||||||
.msg = hintfmt("breakpoint reached; value was %1%", *args[0]),
|
.msg = hintfmt("breakpoint reached; value was %1%", s),
|
||||||
.errPos = pos,
|
.errPos = state.positions[pos],
|
||||||
});
|
});
|
||||||
if (debuggerHook && !state.debugTraces.empty())
|
if (debuggerHook && !state.debugTraces.empty())
|
||||||
{
|
{
|
||||||
|
@ -791,7 +793,7 @@ static RegisterPrimOp primop_break({
|
||||||
throw Error(ErrorInfo{
|
throw Error(ErrorInfo{
|
||||||
.level = lvlInfo,
|
.level = lvlInfo,
|
||||||
.msg = hintfmt("quit from debugger"),
|
.msg = hintfmt("quit from debugger"),
|
||||||
.errPos = noPos,
|
.errPos = state.positions[noPos],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue