Files
lix/lix/libexpr/eval-error.hh
T
eldritch horrors a65e9e5828 libexpr: extract eval error creation into new type
this will let us pass the capability to create debuggable eval errors
without having to pass an entire EvalState. we could pass symbols and
debug states around just as easily, but if we add new capabilities to
our debugger we might have to change many more places than with this.

Change-Id: I2f8893012e5d98a986ef1fc888234c2dd8d5e096
2024-12-03 20:38:41 +01:00

98 lines
2.4 KiB
C++

#pragma once
///@file
#include "lix/libutil/box_ptr.hh"
#include "lix/libutil/error.hh"
#include "lix/libutil/types.hh"
#include "lix/libexpr/pos-idx.hh"
#include "lix/libexpr/pos-table.hh"
namespace nix {
struct DebugState;
struct DebugTrace;
struct Env;
struct Expr;
struct Value;
class EvalState;
template<class T>
class EvalErrorBuilder;
class EvalError : public Error
{
template<class T>
friend class EvalErrorBuilder;
std::shared_ptr<const DebugTrace> frame;
public:
using Error::Error;
};
MakeError(ParseError, Error);
MakeError(AssertionError, EvalError);
MakeError(ThrownError, AssertionError);
MakeError(Abort, EvalError);
MakeError(TypeError, EvalError);
MakeError(UndefinedVarError, EvalError);
MakeError(MissingArgumentError, EvalError);
MakeError(RestrictedPathError, Error);
MakeError(InfiniteRecursionError, EvalError);
/**
* Represents an exception due to an invalid path; that is, it does not exist.
* It corresponds to `!Store::validPath()`.
*/
struct InvalidPathError : public EvalError
{
public:
Path path;
InvalidPathError(const Path & path)
: EvalError("path '%s' did not exist in the store during evaluation", path)
{
}
};
template<class T>
class [[nodiscard]] EvalErrorBuilder final
{
const PosTable & positions;
DebugState * debug;
box_ptr<T> error;
public:
template<typename... Args>
explicit EvalErrorBuilder(const PosTable & positions, DebugState * debug, const Args &... args)
: positions(positions)
, debug{debug}
, error(make_box_ptr<T>(args...))
{
}
[[gnu::noinline]] EvalErrorBuilder<T> withExitStatus(unsigned int exitStatus) &&;
[[gnu::noinline]] EvalErrorBuilder<T> atPos(PosIdx pos) &&;
[[gnu::noinline]] EvalErrorBuilder<T> atPos(Value & value, PosIdx fallback = noPos) &&;
[[gnu::noinline]] EvalErrorBuilder<T> withTrace(PosIdx pos, const std::string_view text) &&;
[[gnu::noinline]] EvalErrorBuilder<T> withSuggestions(Suggestions & s) &&;
[[gnu::noinline]] EvalErrorBuilder<T> withFrame(const Env & e, const Expr & ex) &&;
[[gnu::noinline]] EvalErrorBuilder<T> addTrace(PosIdx pos, HintFmt hint) &&;
template<typename... Args>
[[gnu::noinline]] EvalErrorBuilder<T>
addTrace(PosIdx pos, std::string_view formatString, const Args &... formatArgs) &&;
/**
* Throw the underlying exception.
*/
[[gnu::noinline, gnu::noreturn]] void debugThrow() &&;
};
}