diff options
author | Guillaume Maudoux <guillaume.maudoux@tweag.io> | 2022-10-17 03:05:02 +0200 |
---|---|---|
committer | Guillaume Maudoux <guillaume.maudoux@tweag.io> | 2022-10-17 03:05:02 +0200 |
commit | b945b844a9ce8479872f6280aedde27e2974b7f3 (patch) | |
tree | e5ba8895aeee956f80c5a79d59d8506f2885005b /src/libexpr | |
parent | 3f9f6ae12712b366c038f21de99c8ede6c805be9 (diff) |
Initial frames support
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/eval.cc | 43 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 15 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 6 |
3 files changed, 54 insertions, 10 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 27b333807..050b49833 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -837,6 +837,37 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr & 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> void EvalState::throwErrorWithTrace( PosIdx pos, const char* format, const std::string_view s1, const std::string_view s2, @@ -901,9 +932,9 @@ void EvalState::addErrorTrace(Error & e, const char * s, const std::string & 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( @@ -1164,7 +1195,7 @@ inline bool EvalState::evalBool(Env & env, Expr * e, const PosIdx pos, std::stri Value v; e->eval(*this, env, v); 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; } catch (Error & e) { e.addTrace(positions[pos], errorCtx); @@ -1178,7 +1209,7 @@ inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v, const PosIdx po try { e->eval(*this, env, v); 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) { e.addTrace(positions[pos], errorCtx); throw; @@ -1502,7 +1533,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & auto j = args[0]->attrs->get(i.name); if (!j) { if (!i.def) { - throwErrorWithTrace<TypeError>(lambda.pos, + throwFrameErrorWithTrace<TypeError>(lambda.pos, "function '%1%' called without required argument '%2%'", (lambda.name ? std::string(symbols[lambda.name]) : "anonymous 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) formalNames.insert(symbols[formal.name]); auto suggestions = Suggestions::bestMatches(formalNames, symbols[i.name]); - throwErrorWithTrace<TypeError>(lambda.pos, + throwFrameErrorWithTrace<TypeError>(lambda.pos, "function '%1%' called with unexpected argument '%2%'", (lambda.name ? std::string(symbols[lambda.name]) : "anonymous lambda"), "", &i.name, 0, 0, 0, noPos, "", &suggestions, pos, "from call site", fun.lambda.env, &lambda); diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index fd5ac3e77..3d72d3fe1 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -314,6 +314,19 @@ public: 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> + [[gnu::noinline, gnu::noreturn]] void throwErrorWithTrace( PosIdx pos, const char* format, const std::string_view s1, const std::string_view s2, @@ -340,7 +353,7 @@ public: [[gnu::noinline]] void addErrorTrace(Error & e, const char * s, const std::string & s2) const; [[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: /* Return true iff the value `v' denotes a derivation (i.e. a diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 9be4bbf6a..625b0aa4a 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1171,9 +1171,9 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * } } catch (Error & e) { - e.addTrace(state.positions[posDrvName], - "while evaluating the attribute '%1%' of the derivation '%2%'", - key, drvName); + e.addTrace(state.positions[noPos], + hintfmt("while evaluating the attribute '%1%' of the derivation '%2%'", key, drvName), + true); throw; } } |