The following behaviour was previously present and has been fixed:
lix/lix2 » nix eval --expr '{x."" = 2;}' 'x.""'
{ "" = 2; }
lix/lix2 » nix eval --expr '{x."".y = 2;}' 'x."".y'
error: empty attribute name in selection path 'x."".y'
Change-Id: Iad21988f1191c33a3661c72a6b7f01a8b8b3e6eb
156 lines
3.8 KiB
C++
156 lines
3.8 KiB
C++
#pragma once
|
|
///@file
|
|
|
|
#include "lix/libutil/sync.hh"
|
|
#include "lix/libutil/hash.hh"
|
|
#include "lix/libexpr/eval.hh"
|
|
|
|
#include <functional>
|
|
#include <variant>
|
|
|
|
namespace nix::eval_cache {
|
|
|
|
struct AttrDb;
|
|
class AttrCursor;
|
|
|
|
typedef std::function<Value *(EvalState &)> RootLoader;
|
|
|
|
/**
|
|
* EvalState with caching support. Historically this was part of EvalState,
|
|
* but it was split out to make maintenance easier. This could've been just
|
|
* a pair of EvalState and the cache map, but doing so would currently hide
|
|
* the rather strong connection between EvalState and these caches. At some
|
|
* future time the cache interface should be changed to hide its EvalState.
|
|
*/
|
|
class CachingEvaluator : public Evaluator
|
|
{
|
|
/**
|
|
* A cache for evaluation caches, so as to reuse the same root value if possible
|
|
*/
|
|
std::map<Hash, ref<EvalCache>> caches;
|
|
|
|
public:
|
|
using Evaluator::Evaluator;
|
|
|
|
ref<EvalCache> getCacheFor(Hash hash, RootLoader rootLoader);
|
|
};
|
|
|
|
class EvalCache : public std::enable_shared_from_this<EvalCache>
|
|
{
|
|
friend class AttrCursor;
|
|
|
|
std::shared_ptr<AttrDb> db;
|
|
RootLoader rootLoader;
|
|
RootValue value;
|
|
|
|
Value * getRootValue(EvalState & state);
|
|
|
|
public:
|
|
|
|
EvalCache(
|
|
std::optional<std::reference_wrapper<const Hash>> useCache,
|
|
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 fullattr_t { std::vector<std::string> p; };
|
|
struct missing_t {};
|
|
struct misc_t {};
|
|
struct failed_t {};
|
|
struct int_t { NixInt x; };
|
|
typedef uint64_t AttrId;
|
|
typedef std::pair<AttrId, std::string> AttrKey;
|
|
typedef std::pair<std::string, NixStringContext> string_t;
|
|
|
|
typedef std::variant<
|
|
fullattr_t,
|
|
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>, std::string>> Parent;
|
|
Parent parent;
|
|
RootValue _value;
|
|
std::optional<std::pair<AttrId, AttrValue>> cachedValue;
|
|
|
|
AttrKey getKey();
|
|
|
|
Value & getValue(EvalState & state);
|
|
|
|
public:
|
|
|
|
AttrCursor(
|
|
ref<EvalCache> root,
|
|
Parent parent,
|
|
Value * value = nullptr,
|
|
std::optional<std::pair<AttrId, AttrValue>> && cachedValue = {});
|
|
|
|
std::vector<std::string> getAttrPath(EvalState & state) const;
|
|
|
|
std::vector<std::string> getAttrPath(EvalState & state, std::string_view name) const;
|
|
|
|
std::string getAttrPathStr(EvalState & state) const;
|
|
|
|
std::string getAttrPathStr(EvalState & state, std::string_view name) const;
|
|
|
|
Suggestions getSuggestionsForAttr(EvalState & state, const std::string & name);
|
|
|
|
std::shared_ptr<AttrCursor> maybeGetAttr(EvalState & state, const std::string & name);
|
|
|
|
ref<AttrCursor> getAttr(EvalState & state, const std::string & name);
|
|
|
|
/**
|
|
* Get an attribute along a chain of attrsets. Note that this does
|
|
* not auto-call functors or functions.
|
|
*/
|
|
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(EvalState & state, const std::vector<std::string> & attrPath);
|
|
|
|
std::string getString(EvalState & state);
|
|
|
|
string_t getStringWithContext(EvalState & state);
|
|
|
|
bool getBool(EvalState & state);
|
|
|
|
NixInt getInt(EvalState & state);
|
|
|
|
std::vector<std::string> getListOfStrings(EvalState & state);
|
|
|
|
std::vector<std::string> getAttrs(EvalState & state);
|
|
|
|
bool isDerivation(EvalState & state);
|
|
|
|
Value & forceValue(EvalState & state);
|
|
|
|
/**
|
|
* Force creation of the .drv file in the Nix store.
|
|
*/
|
|
StorePath forceDerivation(EvalState & state);
|
|
};
|
|
|
|
}
|