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.cc24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 538325601..cd3edecaa 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -247,6 +247,11 @@ LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2, con
throw EvalError(format(s) % s2 % s3);
}
+LocalNoInlineNoReturn(void throwEvalError(const char * s, const Symbol & sym, const Pos & p1, const Pos & p2))
+{
+ throw EvalError(format(s) % sym % p1 % p2);
+}
+
LocalNoInlineNoReturn(void throwTypeError(const char * s))
{
throw TypeError(s);
@@ -557,12 +562,14 @@ void ExprPath::eval(EvalState & state, Env & env, Value & v)
void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
{
state.mkAttrs(v, attrs.size());
+ Env *dynamicEnv = &env;
if (recursive) {
/* Create a new environment that contains the attributes in
this `rec'. */
Env & env2(state.allocEnv(attrs.size()));
env2.up = &env;
+ dynamicEnv = &env2;
AttrDefs::iterator overrides = attrs.find(state.sOverrides);
bool hasOverrides = overrides != attrs.end();
@@ -605,9 +612,24 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
}
}
- else {
+ else
foreach (AttrDefs::iterator, i, attrs)
v.attrs->push_back(Attr(i->first, i->second.e->maybeThunk(state, env), &i->second.pos));
+
+ /* dynamic attrs apply *after* rec and __overrides */
+ foreach (DynamicAttrDefs::iterator, i, dynamicAttrs) {
+ Value nameVal;
+ i->nameExpr->eval(state, *dynamicEnv, nameVal);
+ state.forceStringNoCtx(nameVal);
+ Symbol nameSym = state.symbols.create(nameVal.string.s);
+ Bindings::iterator j = v.attrs->find(nameSym);
+ if (j != v.attrs->end())
+ throwEvalError("dynamic attribute `%1%' at %2% already defined at %3%", nameSym, i->pos, *j->pos);
+
+ i->valueExpr->setName(nameSym);
+ /* Keep sorted order so find can catch duplicates */
+ v.attrs->insert(lower_bound(v.attrs->begin(), v.attrs->end(), Attr(nameSym, 0)),
+ Attr(nameSym, i->valueExpr->maybeThunk(state, *dynamicEnv), &i->pos));
}
}