diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index d934470108..ccd359ba7c 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -236,24 +236,17 @@ void mkPath(Value & v, const char * s) } -Value * EvalState::lookupVar(Env * env, const Symbol & name) +Value * EvalState::lookupVar(Env * env, const VarRef & var) { -#if 0 - /* First look for a regular variable binding for `name'. */ - Bindings::iterator i = env2->bindings.find(name); - if (i != env2->bindings.end()) return &i->second; - } - - /* Otherwise, look for a `with' attribute set containing `name'. - Inner `withs' take precedence (i.e. `with {x=1;}; with {x=2;}; - x' evaluates to 2). */ - for (Env * env2 = env; env2; env2 = env2->up) { - Bindings::iterator i = env2->bindings.find(sWith); - if (i == env2->bindings.end()) continue; - Bindings::iterator j = i->second.attrs->find(name); - if (j != i->second.attrs->end()) return &j->second; - } -#endif + 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; + } else + return &env->values[var.displ]; } @@ -481,18 +474,9 @@ void ExprList::eval(EvalState & state, Env & env, Value & v) void ExprVar::eval(EvalState & state, Env & env, Value & v) { - Env * env2 = &env; - for (unsigned int l = level; l; --l, env2 = env2->up) ; - - if (fromWith) { - Bindings::iterator j = env2->values[0].attrs->find(name); - if (j == env2->values[0].attrs->end()) - throwEvalError("undefined variable `%1%'", name); - v = j->second; - } else { - state.forceValue(env2->values[displ]); - v = env2->values[displ]; - } + Value * v2 = state.lookupVar(&env, info); + state.forceValue(*v2); + v = *v2; } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index a24b7345ef..bc61c84ea7 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -238,7 +238,7 @@ private: void addPrimOp(const string & name, unsigned int arity, PrimOp primOp); - Value * lookupVar(Env * env, const Symbol & name); + Value * lookupVar(Env * env, const VarRef & var); friend class ExprVar; friend class ExprAttrs; diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index ab4fa6cba3..03b849a389 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -38,7 +38,7 @@ void ExprPath::show(std::ostream & str) void ExprVar::show(std::ostream & str) { - str << name; + str << info.name; } void ExprSelect::show(std::ostream & str) @@ -157,7 +157,7 @@ void ExprPath::bindVars(const StaticEnv & env) { } -void ExprVar::bindVars(const StaticEnv & env) +void VarRef::bind(const StaticEnv & env) { /* Check whether the variable appears in the environment. If so, set its level and displacement. */ @@ -187,6 +187,11 @@ void ExprVar::bindVars(const StaticEnv & env) this->level = withLevel; } +void ExprVar::bindVars(const StaticEnv & env) +{ + info.bind(env); +} + void ExprSelect::bindVars(const StaticEnv & env) { e->bindVars(env); diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index f9ed34f58a..ffea7049fd 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -78,7 +78,7 @@ struct ExprPath : Expr COMMON_METHODS }; -struct ExprVar : Expr +struct VarRef { Symbol name; @@ -94,8 +94,15 @@ struct ExprVar : Expr levels up from the current one.*/ unsigned int level; unsigned int displ; - - ExprVar(const Symbol & name) : name(name) { }; + + VarRef(const Symbol & name) : name(name) { }; + void bind(const StaticEnv & env); +}; + +struct ExprVar : Expr +{ + VarRef info; + ExprVar(const Symbol & name) : info(name) { }; COMMON_METHODS };