forked from lix-project/lix
Make most calls to determinePos() lazy
This commit is contained in:
parent
4c755c3b3f
commit
bd383d1b6f
|
@ -497,7 +497,7 @@ Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::Locked
|
||||||
auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
|
auto aOutputs = vFlake->attrs->get(state.symbols.create("outputs"));
|
||||||
assert(aOutputs);
|
assert(aOutputs);
|
||||||
|
|
||||||
state.forceValue(*aOutputs->value, aOutputs->value->determinePos(noPos));
|
state.forceValue(*aOutputs->value, [&]() { return aOutputs->value->determinePos(noPos); });
|
||||||
|
|
||||||
return aOutputs->value;
|
return aOutputs->value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,12 +15,6 @@ LocalNoInlineNoReturn(void throwEvalError(const Pos & pos, const char * s))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
|
|
||||||
{
|
|
||||||
throw TypeError(s, showType(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v))
|
LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const Value & v))
|
||||||
{
|
{
|
||||||
throw TypeError({
|
throw TypeError({
|
||||||
|
@ -31,6 +25,13 @@ LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const
|
||||||
|
|
||||||
|
|
||||||
void EvalState::forceValue(Value & v, const Pos & pos)
|
void EvalState::forceValue(Value & v, const Pos & pos)
|
||||||
|
{
|
||||||
|
forceValue(v, [&]() { return pos; });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Callable>
|
||||||
|
void EvalState::forceValue(Value & v, Callable getPos)
|
||||||
{
|
{
|
||||||
if (v.isThunk()) {
|
if (v.isThunk()) {
|
||||||
Env * env = v.thunk.env;
|
Env * env = v.thunk.env;
|
||||||
|
@ -47,15 +48,22 @@ void EvalState::forceValue(Value & v, const Pos & pos)
|
||||||
else if (v.isApp())
|
else if (v.isApp())
|
||||||
callFunction(*v.app.left, *v.app.right, v, noPos);
|
callFunction(*v.app.left, *v.app.right, v, noPos);
|
||||||
else if (v.isBlackhole())
|
else if (v.isBlackhole())
|
||||||
throwEvalError(pos, "infinite recursion encountered");
|
throwEvalError(getPos(), "infinite recursion encountered");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void EvalState::forceAttrs(Value & v, const Pos & pos)
|
inline void EvalState::forceAttrs(Value & v, const Pos & pos)
|
||||||
{
|
{
|
||||||
forceValue(v, pos);
|
forceAttrs(v, [&]() { return pos; });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename Callable>
|
||||||
|
inline void EvalState::forceAttrs(Value & v, Callable getPos)
|
||||||
|
{
|
||||||
|
forceValue(v, getPos);
|
||||||
if (v.type() != nAttrs)
|
if (v.type() != nAttrs)
|
||||||
throwTypeError(pos, "value is %1% while a set was expected", v);
|
throwTypeError(getPos(), "value is %1% while a set was expected", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,7 @@ string showType(const Value & v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pos Value::determinePos(const Pos &pos) const
|
Pos Value::determinePos(const Pos & pos) const
|
||||||
{
|
{
|
||||||
switch (internalType) {
|
switch (internalType) {
|
||||||
case tAttrs: return *attrs->pos;
|
case tAttrs: return *attrs->pos;
|
||||||
|
@ -754,6 +754,11 @@ LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
|
||||||
|
{
|
||||||
|
throw TypeError(s, showType(v));
|
||||||
|
}
|
||||||
|
|
||||||
LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const string & s1))
|
LocalNoInlineNoReturn(void throwAssertionError(const Pos & pos, const char * s, const string & s1))
|
||||||
{
|
{
|
||||||
throw AssertionError({
|
throw AssertionError({
|
||||||
|
@ -1138,7 +1143,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
Hence we need __overrides.) */
|
Hence we need __overrides.) */
|
||||||
if (hasOverrides) {
|
if (hasOverrides) {
|
||||||
Value * vOverrides = (*v.attrs)[overrides->second.displ].value;
|
Value * vOverrides = (*v.attrs)[overrides->second.displ].value;
|
||||||
state.forceAttrs(*vOverrides, vOverrides->determinePos(noPos));
|
state.forceAttrs(*vOverrides, [&]() { return vOverrides->determinePos(noPos); });
|
||||||
Bindings * newBnds = state.allocBindings(v.attrs->capacity() + vOverrides->attrs->size());
|
Bindings * newBnds = state.allocBindings(v.attrs->capacity() + vOverrides->attrs->size());
|
||||||
for (auto & i : *v.attrs)
|
for (auto & i : *v.attrs)
|
||||||
newBnds->push_back(i);
|
newBnds->push_back(i);
|
||||||
|
@ -1500,7 +1505,8 @@ void EvalState::incrFunctionCall(ExprLambda * fun)
|
||||||
|
|
||||||
void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||||
{
|
{
|
||||||
Pos pos = fun.determinePos(noPos);
|
auto pos = fun.determinePos(noPos);
|
||||||
|
|
||||||
forceValue(fun, pos);
|
forceValue(fun, pos);
|
||||||
|
|
||||||
if (fun.type() == nAttrs) {
|
if (fun.type() == nAttrs) {
|
||||||
|
@ -1797,7 +1803,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||||
recurse = [&](Value & v) {
|
recurse = [&](Value & v) {
|
||||||
if (!seen.insert(&v).second) return;
|
if (!seen.insert(&v).second) return;
|
||||||
|
|
||||||
forceValue(v, v.determinePos(noPos));
|
forceValue(v, [&]() { return v.determinePos(noPos); });
|
||||||
|
|
||||||
if (v.type() == nAttrs) {
|
if (v.type() == nAttrs) {
|
||||||
for (auto & i : *v.attrs)
|
for (auto & i : *v.attrs)
|
||||||
|
|
|
@ -224,6 +224,9 @@ public:
|
||||||
result. Otherwise, this is a no-op. */
|
result. Otherwise, this is a no-op. */
|
||||||
inline void forceValue(Value & v, const Pos & pos);
|
inline void forceValue(Value & v, const Pos & pos);
|
||||||
|
|
||||||
|
template <typename Callable>
|
||||||
|
inline void forceValue(Value & v, Callable getPos);
|
||||||
|
|
||||||
/* Force a value, then recursively force list elements and
|
/* Force a value, then recursively force list elements and
|
||||||
attributes. */
|
attributes. */
|
||||||
void forceValueDeep(Value & v);
|
void forceValueDeep(Value & v);
|
||||||
|
@ -232,7 +235,12 @@ public:
|
||||||
NixInt forceInt(Value & v, const Pos & pos);
|
NixInt forceInt(Value & v, const Pos & pos);
|
||||||
NixFloat forceFloat(Value & v, const Pos & pos);
|
NixFloat forceFloat(Value & v, const Pos & pos);
|
||||||
bool forceBool(Value & v, const Pos & pos);
|
bool forceBool(Value & v, const Pos & pos);
|
||||||
inline void forceAttrs(Value & v, const Pos & pos);
|
|
||||||
|
void forceAttrs(Value & v, const Pos & pos);
|
||||||
|
|
||||||
|
template <typename Callable>
|
||||||
|
inline void forceAttrs(Value & v, Callable getPos);
|
||||||
|
|
||||||
inline void forceList(Value & v, const Pos & pos);
|
inline void forceList(Value & v, const Pos & pos);
|
||||||
void forceFunction(Value & v, const Pos & pos); // either lambda or primop
|
void forceFunction(Value & v, const Pos & pos); // either lambda or primop
|
||||||
std::string_view forceString(Value & v, const Pos & pos = noPos);
|
std::string_view forceString(Value & v, const Pos & pos = noPos);
|
||||||
|
|
|
@ -172,7 +172,7 @@ StringSet DrvInfo::queryMetaNames()
|
||||||
|
|
||||||
bool DrvInfo::checkMeta(Value & v)
|
bool DrvInfo::checkMeta(Value & v)
|
||||||
{
|
{
|
||||||
state->forceValue(v, v.determinePos(noPos));
|
state->forceValue(v, [&]() { return v.determinePos(noPos); });
|
||||||
if (v.type() == nList) {
|
if (v.type() == nList) {
|
||||||
for (auto elem : v.listItems())
|
for (auto elem : v.listItems())
|
||||||
if (!checkMeta(*elem)) return false;
|
if (!checkMeta(*elem)) return false;
|
||||||
|
@ -278,7 +278,7 @@ static bool getDerivation(EvalState & state, Value & v,
|
||||||
bool ignoreAssertionFailures)
|
bool ignoreAssertionFailures)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
state.forceValue(v, v.determinePos(noPos));
|
state.forceValue(v, [&]() { return v.determinePos(noPos); });
|
||||||
if (!state.isDerivation(v)) return true;
|
if (!state.isDerivation(v)) return true;
|
||||||
|
|
||||||
/* Remove spurious duplicates (e.g., a set like `rec { x =
|
/* Remove spurious duplicates (e.g., a set like `rec { x =
|
||||||
|
|
|
@ -361,7 +361,7 @@ public:
|
||||||
return internalType == tList1 ? 1 : internalType == tList2 ? 2 : bigList.size;
|
return internalType == tList1 ? 1 : internalType == tList2 ? 2 : bigList.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pos determinePos(const Pos &pos) const;
|
Pos determinePos(const Pos & pos) const;
|
||||||
|
|
||||||
/* Check whether forcing this value requires a trivial amount of
|
/* Check whether forcing this value requires a trivial amount of
|
||||||
computation. In particular, function applications are
|
computation. In particular, function applications are
|
||||||
|
|
|
@ -318,7 +318,7 @@ static void main_nix_build(int argc, char * * argv)
|
||||||
|
|
||||||
for (auto & i : attrPaths) {
|
for (auto & i : attrPaths) {
|
||||||
Value & v(*findAlongAttrPath(*state, i, *autoArgs, vRoot).first);
|
Value & v(*findAlongAttrPath(*state, i, *autoArgs, vRoot).first);
|
||||||
state->forceValue(v, v.determinePos(noPos));
|
state->forceValue(v, [&]() { return v.determinePos(noPos); });
|
||||||
getDerivations(*state, v, "", *autoArgs, drvs, false);
|
getDerivations(*state, v, "", *autoArgs, drvs, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
|
|
||||||
/* Evaluate it. */
|
/* Evaluate it. */
|
||||||
debug("evaluating user environment builder");
|
debug("evaluating user environment builder");
|
||||||
state.forceValue(topLevel, topLevel.determinePos(noPos));
|
state.forceValue(topLevel, [&]() { return topLevel.determinePos(noPos); });
|
||||||
PathSet context;
|
PathSet context;
|
||||||
Attr & aDrvPath(*topLevel.attrs->find(state.sDrvPath));
|
Attr & aDrvPath(*topLevel.attrs->find(state.sDrvPath));
|
||||||
auto topLevelDrv = state.store->parseStorePath(state.coerceToPath(*aDrvPath.pos, *aDrvPath.value, context));
|
auto topLevelDrv = state.store->parseStorePath(state.coerceToPath(*aDrvPath.pos, *aDrvPath.value, context));
|
||||||
|
|
|
@ -40,7 +40,7 @@ void processExpr(EvalState & state, const Strings & attrPaths,
|
||||||
|
|
||||||
for (auto & i : attrPaths) {
|
for (auto & i : attrPaths) {
|
||||||
Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot).first);
|
Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot).first);
|
||||||
state.forceValue(v, v.determinePos(noPos));
|
state.forceValue(v, [&]() { return v.determinePos(noPos); });
|
||||||
|
|
||||||
PathSet context;
|
PathSet context;
|
||||||
if (evalOnly) {
|
if (evalOnly) {
|
||||||
|
|
|
@ -673,7 +673,7 @@ void NixRepl::reloadFiles()
|
||||||
|
|
||||||
void NixRepl::addAttrsToScope(Value & attrs)
|
void NixRepl::addAttrsToScope(Value & attrs)
|
||||||
{
|
{
|
||||||
state->forceAttrs(attrs, attrs.determinePos(noPos));
|
state->forceAttrs(attrs, [&]() { return attrs.determinePos(noPos); });
|
||||||
if (displ + attrs.attrs->size() >= envSize)
|
if (displ + attrs.attrs->size() >= envSize)
|
||||||
throw Error("environment full; cannot add more variables");
|
throw Error("environment full; cannot add more variables");
|
||||||
|
|
||||||
|
@ -712,7 +712,7 @@ void NixRepl::evalString(string s, Value & v)
|
||||||
{
|
{
|
||||||
Expr * e = parseString(s);
|
Expr * e = parseString(s);
|
||||||
e->eval(*state, *env, v);
|
e->eval(*state, *env, v);
|
||||||
state->forceValue(v, v.determinePos(noPos));
|
state->forceValue(v, [&]() { return v.determinePos(noPos); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -742,7 +742,7 @@ std::ostream & NixRepl::printValue(std::ostream & str, Value & v, unsigned int m
|
||||||
str.flush();
|
str.flush();
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
|
|
||||||
state->forceValue(v, v.determinePos(noPos));
|
state->forceValue(v, [&]() { return v.determinePos(noPos); });
|
||||||
|
|
||||||
switch (v.type()) {
|
switch (v.type()) {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue