1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-20 01:09:37 +01:00

Use the cache in nix search

Not optimal atm, possibly because we don’t cache the evaluation failures
This commit is contained in:
regnat 2021-06-09 16:23:26 +02:00
parent a6aaf81103
commit 9102508f33
5 changed files with 161 additions and 17 deletions

View file

@ -1284,6 +1284,43 @@ bool EvalState::getAttrField(Value & attrs, const std::vector<Symbol> & selector
return true;
}
void EvalState::getAttrFieldThrow(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest)
{
if (!getAttrField(attrs, selector, pos, dest))
throw Error("Missing attribute path '%s'", "ImTooLazyToImplementThisRightNow");
}
std::vector<Attr> EvalState::getFields(Value & attrs, const Pos & pos)
{
auto eval_cache = attrs.getEvalCache();
if (eval_cache.isEmpty()) {
forceValue(attrs, pos);
eval_cache = attrs.getEvalCache();
}
if (auto attrNames = eval_cache.listChildren(symbols)) {
bool everythingCached = true;
std::vector<Attr> res;
for (auto & attrName : *attrNames) {
auto newValue = allocValue();
try {
if (lazyGetAttrField(attrs, {attrName}, pos, *newValue)) {
res.push_back(Attr(attrName, newValue));
} else {
everythingCached = false;
break;
}
} catch (Error &) {
everythingCached = false;
}
}
if (everythingCached) return res;
}
forceValue(attrs);
auto attrsStart = attrs.attrs->attrs;
return std::vector<Attr>(attrsStart, attrsStart + attrs.attrs->size());
}
void ExprSelect::eval(EvalState & state, Env & env, Value & v)
{
Value vTmp;
@ -1493,6 +1530,20 @@ std::optional<tree_cache::AttrValue> ValueCache::getRawValue()
return rawCache->getCachedValue();
}
std::optional<std::vector<Symbol>> ValueCache::listChildren(SymbolTable& symbols)
{
auto ret = std::vector<Symbol>();
if (rawCache) {
auto cachedValue = rawCache->getCachedValue();
if (std::get_if<tree_cache::attributeSet_t>(&cachedValue)) {
for (auto & fieldStr : rawCache->getChildren())
ret.push_back(symbols.create(fieldStr));
}
return ret;
}
return std::nullopt;
}
void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
{
if (auto evalCache = fun.getEvalCache(); !evalCache.isEmpty()) {

View file

@ -359,6 +359,12 @@ public:
// Similar to `getAttrField`, but if the cache says that the result is an
// attribute set, just return a thunk to it rather than forcing it.
bool lazyGetAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest);
// Similar to `getAttrField`, but throws an `Error` if the field cant be
// found
void getAttrFieldThrow(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest);
std::vector<Attr> getFields(Value & attrs, const Pos & pos);
};