aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-09-22 15:16:09 +0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-09-22 16:05:00 +0200
commit831fc8ea21fc730388e9359fcafed279c8ec413d (patch)
treeda4e05c847ceaad584463af1b24b8a8c9e2f82a0 /src/libexpr/eval.cc
parent1e0a799bef4696b1f71d4a25fd117a2f59708f21 (diff)
Make forceValueDeep work on values with cycles
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc29
1 files 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<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);
}