diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2010-04-22T15·08+0000 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2010-04-22T15·08+0000 |
commit | 0bc468f195e37a8a5f4f8b36ae6c92459e8ca652 (patch) | |
tree | f4057161b6bb181e2899dbe85816e68819327097 /src/libexpr/eval.cc | |
parent | ee0384fb966b7a9bd202fa6fb447788be30c4ce4 (diff) |
* Simplify the implementation of `with'. This gives a 7% speedup in
evaluating the NixOS system configuration.
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r-- | src/libexpr/eval.cc | 34 |
1 files changed, 9 insertions, 25 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 9acd42310850..b4f12c8a9c94 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -246,10 +246,14 @@ Value * EvalState::lookupVar(Env * env, const VarRef & var) for (unsigned int l = var.level; l; --l, env = env->up) ; if (var.fromWith) { - Bindings::iterator j = env->values[0].attrs->find(var.name); - if (j == env->values[0].attrs->end()) - throwEvalError("undefined variable `%1%'", var.name); - return &j->second; + while (1) { + Bindings::iterator j = env->values[0].attrs->find(var.name); + if (j != env->values[0].attrs->end()) + return &j->second; + if (env->prevWith == 0) + throwEvalError("undefined variable `%1%'", var.name); + for (unsigned int l = env->prevWith; l; --l, env = env->up) ; + } } else return &env->values[var.displ]; } @@ -656,30 +660,10 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) { Env & env2(state.allocEnv(1)); env2.up = &env; + env2.prevWith = prevWith; state.evalAttrs(env, attrs, env2.values[0]); - /* If there is an enclosing `with', copy all attributes that don't - appear in this `with'. */ - if (prevWith != -1) { - Env * env3 = &env; - for (unsigned int l = prevWith; l; --l, env3 = env3->up) ; - - /* Because the first `with' may be a shallow copy of another - attribute set (through a tCopy node), we need to clone its - `attrs' before modifying them. */ - Bindings * old(env2.values[0].attrs); - state.mkAttrs(env2.values[0]); - foreach (Bindings::iterator, i, *old) - mkCopy((*env2.values[0].attrs)[i->first], i->second); - - foreach (Bindings::iterator, i, *env3->values[0].attrs) { - Bindings::iterator j = env2.values[0].attrs->find(i->first); - if (j == env2.values[0].attrs->end()) - mkCopy((*env2.values[0].attrs)[i->first], i->second); - } - } - state.eval(env2, body, v); } |