aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc23
1 files changed, 13 insertions, 10 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index ce466ded4..d259d58a3 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -367,6 +367,14 @@ bool EvalState::evalBool(Env & env, Expr * e)
}
+void EvalState::evalAttrs(Env & env, Expr * e, Value & v)
+{
+ eval(env, e, v);
+ if (v.type != tAttrs)
+ throwTypeError("value is %1% while an attribute set was expected", showType(v));
+}
+
+
void Expr::eval(EvalState & state, Env & env, Value & v)
{
abort();
@@ -481,8 +489,7 @@ void ExprVar::eval(EvalState & state, Env & env, Value & v)
void ExprSelect::eval(EvalState & state, Env & env, Value & v)
{
Value v2;
- state.eval(env, e, v2);
- state.forceAttrs(v2); // !!! eval followed by force is slightly inefficient
+ state.evalAttrs(env, e, v2);
Bindings::iterator i = v2.attrs->find(name);
if (i == v2.attrs->end())
throwEvalError("attribute `%1%' missing", name);
@@ -499,8 +506,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
{
Value vAttrs;
- state.eval(env, e, vAttrs);
- state.forceAttrs(vAttrs);
+ state.evalAttrs(env, e, vAttrs);
mkBool(v, vAttrs.attrs->find(name) != vAttrs.attrs->end());
}
@@ -640,8 +646,7 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
Env & env2(state.allocEnv(1));
env2.up = &env;
- state.eval(env, attrs, env2.values[0]);
- state.forceAttrs(env2.values[0]);
+ state.evalAttrs(env, attrs, env2.values[0]);
/* If there is an enclosing `with', copy all attributes that don't
appear in this `with'. */
@@ -725,13 +730,11 @@ void ExprOpImpl::eval(EvalState & state, Env & env, Value & v)
void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
{
Value v2;
- state.eval(env, e1, v2);
- state.forceAttrs(v2);
+ state.evalAttrs(env, e1, v2);
state.cloneAttrs(v2, v);
- state.eval(env, e2, v2);
- state.forceAttrs(v2);
+ state.evalAttrs(env, e2, v2);
foreach (Bindings::iterator, i, *v2.attrs)
mkCopy((*v.attrs)[i->first], i->second);