diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-07-06 10:58:17 +0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2011-07-06 10:58:17 +0000 |
commit | 56370378023fc84eb0153b991f4138f6acd011e3 (patch) | |
tree | 19034285effef61c373eef092e91f717c4cea020 /src/libexpr/eval.cc | |
parent | 34f4b91820796381d04c6e00ea5e805cf53d25da (diff) | |
download | guix-56370378023fc84eb0153b991f4138f6acd011e3.tar.gz |
* In the ‘?’ operator, allow attribute paths. For instance, you can
write ‘attrs ? a.b’ to test whether ‘attrs’ has an attribute ‘a’ containing an attribute ‘b’. This is more convenient than ‘attrs ? a && attrs.a ? b’. Slight change in the semantics: it's no longer an error if the left-hand side of ‘?’ is not an attribute set. In that case it just returns false. So, ‘null ? foo’ no longer throws an error.
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 949f45e787..c307f2a420 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -656,9 +656,25 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) { - Value vAttrs; - state.evalAttrs(env, e, vAttrs); - mkBool(v, vAttrs.attrs->find(name) != vAttrs.attrs->end()); + Value vTmp; + Value * vAttrs = &vTmp; + + state.eval(env, e, vTmp); + + foreach (AttrPath::const_iterator, i, attrPath) { + state.forceValue(*vAttrs); + Bindings::iterator j; + if (vAttrs->type != tAttrs || + (j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end()) + { + mkBool(v, false); + return; + } else { + vAttrs = j->value; + } + } + + mkBool(v, true); } |