forked from lix-project/lix
eldritch horrors
08252967a8
While preparing PRs like #9753, I've had to change error messages in
dozens of code paths. It would be nice if instead of
EvalError("expected 'boolean' but found '%1%'", showType(v))
we could write
TypeError(v, "boolean")
or similar. Then, changing the error message could be a mechanical
refactor with the compiler pointing out places the constructor needs to
be changed, rather than the error-prone process of grepping through the
codebase. Structured errors would also help prevent the "same" error
from having multiple slightly different messages, and could be a first
step towards error codes / an error index.
This PR reworks the exception infrastructure in `libexpr` to
support exception types with different constructor signatures than
`BaseError`. Actually refactoring the exceptions to use structured data
will come in a future PR (this one is big enough already, as it has to
touch every exception in `libexpr`).
The core design is in `eval-error.hh`. Generally, errors like this:
state.error("'%s' is not a string", getAttrPathStr())
.debugThrow<TypeError>()
are transformed like this:
state.error<TypeError>("'%s' is not a string", getAttrPathStr())
.debugThrow()
The type annotation has moved from `ErrorBuilder::debugThrow` to
`EvalState::error`.
(cherry picked from commit c6a89c1a1659b31694c0fbcd21d78a6dd521c732)
Change-Id: Iced91ba4e00ca9e801518071fb43798936cbd05a
140 lines
2.9 KiB
C++
140 lines
2.9 KiB
C++
#pragma once
|
|
///@file
|
|
|
|
#include "sync.hh"
|
|
#include "hash.hh"
|
|
#include "eval.hh"
|
|
|
|
#include <functional>
|
|
#include <variant>
|
|
|
|
namespace nix::eval_cache {
|
|
|
|
struct AttrDb;
|
|
class AttrCursor;
|
|
|
|
class EvalCache : public std::enable_shared_from_this<EvalCache>
|
|
{
|
|
friend class AttrCursor;
|
|
|
|
std::shared_ptr<AttrDb> db;
|
|
EvalState & state;
|
|
typedef std::function<Value *()> RootLoader;
|
|
RootLoader rootLoader;
|
|
RootValue value;
|
|
|
|
Value * getRootValue();
|
|
|
|
public:
|
|
|
|
EvalCache(
|
|
std::optional<std::reference_wrapper<const Hash>> useCache,
|
|
EvalState & state,
|
|
RootLoader rootLoader);
|
|
|
|
ref<AttrCursor> getRoot();
|
|
};
|
|
|
|
enum AttrType {
|
|
Placeholder = 0,
|
|
FullAttrs = 1,
|
|
String = 2,
|
|
Missing = 3,
|
|
Misc = 4,
|
|
Failed = 5,
|
|
Bool = 6,
|
|
ListOfStrings = 7,
|
|
Int = 8,
|
|
};
|
|
|
|
struct placeholder_t {};
|
|
struct missing_t {};
|
|
struct misc_t {};
|
|
struct failed_t {};
|
|
struct int_t { NixInt x; };
|
|
typedef uint64_t AttrId;
|
|
typedef std::pair<AttrId, Symbol> AttrKey;
|
|
typedef std::pair<std::string, NixStringContext> string_t;
|
|
|
|
typedef std::variant<
|
|
std::vector<Symbol>,
|
|
string_t,
|
|
placeholder_t,
|
|
missing_t,
|
|
misc_t,
|
|
failed_t,
|
|
bool,
|
|
int_t,
|
|
std::vector<std::string>
|
|
> AttrValue;
|
|
|
|
class AttrCursor : public std::enable_shared_from_this<AttrCursor>
|
|
{
|
|
friend class EvalCache;
|
|
|
|
ref<EvalCache> root;
|
|
typedef std::optional<std::pair<std::shared_ptr<AttrCursor>, Symbol>> Parent;
|
|
Parent parent;
|
|
RootValue _value;
|
|
std::optional<std::pair<AttrId, AttrValue>> cachedValue;
|
|
|
|
AttrKey getKey();
|
|
|
|
Value & getValue();
|
|
|
|
public:
|
|
|
|
AttrCursor(
|
|
ref<EvalCache> root,
|
|
Parent parent,
|
|
Value * value = nullptr,
|
|
std::optional<std::pair<AttrId, AttrValue>> && cachedValue = {});
|
|
|
|
std::vector<Symbol> getAttrPath() const;
|
|
|
|
std::vector<Symbol> getAttrPath(Symbol name) const;
|
|
|
|
std::string getAttrPathStr() const;
|
|
|
|
std::string getAttrPathStr(Symbol name) const;
|
|
|
|
Suggestions getSuggestionsForAttr(Symbol name);
|
|
|
|
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false);
|
|
|
|
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
|
|
|
|
ref<AttrCursor> getAttr(Symbol name, bool forceErrors = false);
|
|
|
|
ref<AttrCursor> getAttr(std::string_view name);
|
|
|
|
/**
|
|
* Get an attribute along a chain of attrsets. Note that this does
|
|
* not auto-call functors or functions.
|
|
*/
|
|
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false);
|
|
|
|
std::string getString();
|
|
|
|
string_t getStringWithContext();
|
|
|
|
bool getBool();
|
|
|
|
NixInt getInt();
|
|
|
|
std::vector<std::string> getListOfStrings();
|
|
|
|
std::vector<Symbol> getAttrs();
|
|
|
|
bool isDerivation();
|
|
|
|
Value & forceValue();
|
|
|
|
/**
|
|
* Force creation of the .drv file in the Nix store.
|
|
*/
|
|
StorePath forceDerivation();
|
|
};
|
|
|
|
}
|