forked from lix-project/lix
Initial frames support
This commit is contained in:
parent
3f9f6ae127
commit
b945b844a9
|
@ -836,6 +836,37 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr &
|
||||||
evaluator. So here are some helper functions for throwing
|
evaluator. So here are some helper functions for throwing
|
||||||
exceptions. */
|
exceptions. */
|
||||||
|
|
||||||
|
template <typename ErrorType>
|
||||||
|
void EvalState::throwFrameErrorWithTrace(
|
||||||
|
PosIdx pos, const char* format,
|
||||||
|
const std::string_view s1, const std::string_view s2,
|
||||||
|
const Symbol * sym1, const Symbol * sym2,
|
||||||
|
Value * val1, Value * val2,
|
||||||
|
PosIdx pos1,
|
||||||
|
const std::string_view s3,
|
||||||
|
const Suggestions * suggestions,
|
||||||
|
PosIdx tracePos, const std::string_view traceStr,
|
||||||
|
Env * env, Expr * expr)
|
||||||
|
{
|
||||||
|
hintformat f(format);
|
||||||
|
if (!s1.empty()) { f = f % s1; }
|
||||||
|
if (!s2.empty()) { f = f % s2; }
|
||||||
|
if (sym1) { f = f % symbols[*sym1]; }
|
||||||
|
if (sym2) { f = f % symbols[*sym2]; }
|
||||||
|
if (val1) { f = f % showType(*val1); }
|
||||||
|
if (val2) { f = f % showType(*val2); }
|
||||||
|
if (pos1) { f = f % positions[pos1]; }
|
||||||
|
if (!s3.empty()) { f = f % s3; }
|
||||||
|
|
||||||
|
auto e = ErrorType(ErrorInfo {
|
||||||
|
.msg = f,
|
||||||
|
.errPos = positions[pos],
|
||||||
|
.suggestions = suggestions ? *suggestions : Suggestions(),
|
||||||
|
});
|
||||||
|
e.addTrace(positions[tracePos], traceStr, true);
|
||||||
|
debugThrow(e, env, expr);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ErrorType>
|
template <typename ErrorType>
|
||||||
void EvalState::throwErrorWithTrace(
|
void EvalState::throwErrorWithTrace(
|
||||||
PosIdx pos, const char* format,
|
PosIdx pos, const char* format,
|
||||||
|
@ -901,9 +932,9 @@ void EvalState::addErrorTrace(Error & e, const char * s, const std::string & s2)
|
||||||
e.addTrace(std::nullopt, s, s2);
|
e.addTrace(std::nullopt, s, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::addErrorTrace(Error & e, const PosIdx pos, const char * s, const std::string & s2) const
|
void EvalState::addErrorTrace(Error & e, const PosIdx pos, const char * s, const std::string & s2, bool frame) const
|
||||||
{
|
{
|
||||||
e.addTrace(positions[pos], s, s2);
|
e.addTrace(positions[pos], hintfmt(s, s2), frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(
|
static std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(
|
||||||
|
@ -1164,7 +1195,7 @@ inline bool EvalState::evalBool(Env & env, Expr * e, const PosIdx pos, std::stri
|
||||||
Value v;
|
Value v;
|
||||||
e->eval(*this, env, v);
|
e->eval(*this, env, v);
|
||||||
if (v.type() != nBool)
|
if (v.type() != nBool)
|
||||||
throwError<TypeError>(pos, "value is %1% while a Boolean was expected", "", "", 0, 0, &v, 0, noPos, "", 0, &env, e);
|
throwError<TypeError>(noPos, "value is %1% while a Boolean was expected", "", "", 0, 0, &v, 0, noPos, "", 0, &env, e);
|
||||||
return v.boolean;
|
return v.boolean;
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(positions[pos], errorCtx);
|
e.addTrace(positions[pos], errorCtx);
|
||||||
|
@ -1178,7 +1209,7 @@ inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v, const PosIdx po
|
||||||
try {
|
try {
|
||||||
e->eval(*this, env, v);
|
e->eval(*this, env, v);
|
||||||
if (v.type() != nAttrs)
|
if (v.type() != nAttrs)
|
||||||
throwError<TypeError>(pos, "value is %1% while a set was expected", "", "", 0, 0, &v, 0, noPos, "", 0, &env, e);
|
throwError<TypeError>(noPos, "value is %1% while a set was expected", "", "", 0, 0, &v, 0, noPos, "", 0, &env, e);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(positions[pos], errorCtx);
|
e.addTrace(positions[pos], errorCtx);
|
||||||
throw;
|
throw;
|
||||||
|
@ -1502,7 +1533,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
auto j = args[0]->attrs->get(i.name);
|
auto j = args[0]->attrs->get(i.name);
|
||||||
if (!j) {
|
if (!j) {
|
||||||
if (!i.def) {
|
if (!i.def) {
|
||||||
throwErrorWithTrace<TypeError>(lambda.pos,
|
throwFrameErrorWithTrace<TypeError>(lambda.pos,
|
||||||
"function '%1%' called without required argument '%2%'",
|
"function '%1%' called without required argument '%2%'",
|
||||||
(lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), "",
|
(lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), "",
|
||||||
&i.name, 0, 0, 0, noPos, "", 0, pos, "from call site", fun.lambda.env, &lambda);
|
&i.name, 0, 0, 0, noPos, "", 0, pos, "from call site", fun.lambda.env, &lambda);
|
||||||
|
@ -1525,7 +1556,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
for (auto & formal : lambda.formals->formals)
|
for (auto & formal : lambda.formals->formals)
|
||||||
formalNames.insert(symbols[formal.name]);
|
formalNames.insert(symbols[formal.name]);
|
||||||
auto suggestions = Suggestions::bestMatches(formalNames, symbols[i.name]);
|
auto suggestions = Suggestions::bestMatches(formalNames, symbols[i.name]);
|
||||||
throwErrorWithTrace<TypeError>(lambda.pos,
|
throwFrameErrorWithTrace<TypeError>(lambda.pos,
|
||||||
"function '%1%' called with unexpected argument '%2%'",
|
"function '%1%' called with unexpected argument '%2%'",
|
||||||
(lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), "",
|
(lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), "",
|
||||||
&i.name, 0, 0, 0, noPos, "", &suggestions, pos, "from call site", fun.lambda.env, &lambda);
|
&i.name, 0, 0, 0, noPos, "", &suggestions, pos, "from call site", fun.lambda.env, &lambda);
|
||||||
|
|
|
@ -312,6 +312,19 @@ public:
|
||||||
std::string_view forceString(Value & v, PathSet & context, const PosIdx pos, std::string_view errorCtx);
|
std::string_view forceString(Value & v, PathSet & context, const PosIdx pos, std::string_view errorCtx);
|
||||||
std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx);
|
std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx);
|
||||||
|
|
||||||
|
template <typename ErrorType>
|
||||||
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
|
void throwFrameErrorWithTrace(
|
||||||
|
PosIdx pos, const char* format,
|
||||||
|
const std::string_view s1, const std::string_view s2,
|
||||||
|
const Symbol * sym1, const Symbol * sym2,
|
||||||
|
Value * val1, Value * val2,
|
||||||
|
PosIdx pos1,
|
||||||
|
const std::string_view s3,
|
||||||
|
const Suggestions * suggestions,
|
||||||
|
PosIdx tracePos, const std::string_view traceStr,
|
||||||
|
Env * env, Expr * expr);
|
||||||
|
|
||||||
template <typename ErrorType>
|
template <typename ErrorType>
|
||||||
[[gnu::noinline, gnu::noreturn]]
|
[[gnu::noinline, gnu::noreturn]]
|
||||||
void throwErrorWithTrace(
|
void throwErrorWithTrace(
|
||||||
|
@ -340,7 +353,7 @@ public:
|
||||||
[[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;
|
||||||
[[gnu::noinline]]
|
[[gnu::noinline]]
|
||||||
void addErrorTrace(Error & e, const PosIdx pos, const char * s, const std::string & s2) const;
|
void addErrorTrace(Error & e, const PosIdx pos, const char * s, const std::string & s2, bool frame = false) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/* Return true iff the value `v' denotes a derivation (i.e. a
|
/* Return true iff the value `v' denotes a derivation (i.e. a
|
||||||
|
|
|
@ -1171,9 +1171,9 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(state.positions[posDrvName],
|
e.addTrace(state.positions[noPos],
|
||||||
"while evaluating the attribute '%1%' of the derivation '%2%'",
|
hintfmt("while evaluating the attribute '%1%' of the derivation '%2%'", key, drvName),
|
||||||
key, drvName);
|
true);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,9 @@ namespace nix {
|
||||||
|
|
||||||
const std::string nativeSystem = SYSTEM;
|
const std::string nativeSystem = SYSTEM;
|
||||||
|
|
||||||
void BaseError::addTrace(std::optional<ErrPos> e, hintformat hint)
|
void BaseError::addTrace(std::optional<ErrPos> e, hintformat hint, bool frame)
|
||||||
{
|
{
|
||||||
err.traces.push_front(Trace { .pos = e, .hint = hint });
|
err.traces.push_front(Trace { .pos = e, .hint = hint, .frame = frame });
|
||||||
}
|
}
|
||||||
|
|
||||||
// c++ std::exception descendants must have a 'const char* what()' function.
|
// c++ std::exception descendants must have a 'const char* what()' function.
|
||||||
|
@ -382,6 +382,7 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
bool frameOnly = false;
|
||||||
if (!einfo.traces.empty()) {
|
if (!einfo.traces.empty()) {
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
for (auto iter = einfo.traces.rbegin(); iter != einfo.traces.rend(); ++iter) {
|
for (auto iter = einfo.traces.rbegin(); iter != einfo.traces.rend(); ++iter) {
|
||||||
|
@ -391,7 +392,11 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter->hint.str().empty()) continue;
|
if (iter->hint.str().empty()) continue;
|
||||||
|
if (frameOnly && !iter->frame) continue;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
frameOnly = iter->frame;
|
||||||
|
|
||||||
oss << "\n" << "… " << iter->hint.str() << "\n";
|
oss << "\n" << "… " << iter->hint.str() << "\n";
|
||||||
|
|
||||||
if (iter->pos.has_value() && (*iter->pos)) {
|
if (iter->pos.has_value() && (*iter->pos)) {
|
||||||
|
|
|
@ -110,6 +110,7 @@ void printAtPos(const ErrPos & pos, std::ostream & out);
|
||||||
struct Trace {
|
struct Trace {
|
||||||
std::optional<ErrPos> pos;
|
std::optional<ErrPos> pos;
|
||||||
hintformat hint;
|
hintformat hint;
|
||||||
|
bool frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ErrorInfo {
|
struct ErrorInfo {
|
||||||
|
@ -188,7 +189,7 @@ public:
|
||||||
addTrace(e, hintfmt(std::string(fs), args...));
|
addTrace(e, hintfmt(std::string(fs), args...));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTrace(std::optional<ErrPos> e, hintformat hint);
|
void addTrace(std::optional<ErrPos> e, hintformat hint, bool frame = false);
|
||||||
|
|
||||||
bool hasTrace() const { return !err.traces.empty(); }
|
bool hasTrace() const { return !err.traces.empty(); }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue