diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-09-22T13·16+0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2014-09-22T14·05+0200 |
commit | 831fc8ea21fc730388e9359fcafed279c8ec413d (patch) | |
tree | da4e05c847ceaad584463af1b24b8a8c9e2f82a0 /src | |
parent | 1e0a799bef4696b1f71d4a25fd117a2f59708f21 (diff) |
Make forceValueDeep work on values with cycles
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/eval.cc | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index f1212cd22542..43d8f1399e09 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<const Value *> seen; - if (v.type == tAttrs) { - foreach (Bindings::iterator, i, *v.attrs) - forceValueDeep(*i->value); - } + std::function<void(Value & v)> 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); } |