From 831fc8ea21fc730388e9359fcafed279c8ec413d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 22 Sep 2014 15:16:09 +0200 Subject: [PATCH] Make forceValueDeep work on values with cycles --- src/libexpr/eval.cc | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index f1212cd22..43d8f1399 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1183,17 +1183,28 @@ void ExprPos::eval(EvalState & state, Env & env, Value & v) void EvalState::forceValueDeep(Value & v) { - forceValue(v); + std::set seen; - if (v.type == tAttrs) { - foreach (Bindings::iterator, i, *v.attrs) - forceValueDeep(*i->value); - } + std::function recurse; - else if (v.type == tList) { - for (unsigned int n = 0; n < v.list.length; ++n) - forceValueDeep(*v.list.elems[n]); - } + recurse = [&](Value & v) { + if (seen.find(&v) != seen.end()) return; + seen.insert(&v); + + forceValue(v); + + if (v.type == tAttrs) { + foreach (Bindings::iterator, i, *v.attrs) + recurse(*i->value); + } + + else if (v.type == tList) { + for (unsigned int n = 0; n < v.list.length; ++n) + recurse(*v.list.elems[n]); + } + }; + + recurse(v); }