about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc40
-rw-r--r--src/libexpr/eval.hh4
2 files changed, 23 insertions, 21 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 904a95d16034..f891496a7568 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -307,25 +307,26 @@ void mkPath(Value & v, const char * s)
 inline Value * EvalState::lookupVar(Env * env, const VarRef & var, bool noEval)
 {
     for (unsigned int l = var.level; l; --l, env = env->up) ;
-    
-    if (var.fromWith) {
-        while (1) {
-            if (!env->values[0]) {
-                if (noEval) return 0;
-                env->values[0] = allocValue();
-                evalAttrs(*env->up, env->withAttrs, *env->values[0]);
-            }
-            Bindings::iterator j = env->values[0]->attrs->find(var.name);
-            if (j != env->values[0]->attrs->end()) {
-                if (countCalls && j->pos) attrSelects[*j->pos]++;
-                return j->value;
-            }
-            if (env->prevWith == 0)
-                throwEvalError("undefined variable `%1%'", var.name);
-            for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
+
+    if (!var.fromWith) return env->values[var.displ];
+
+    while (1) {
+        if (!env->haveWithAttrs) {
+            if (noEval) return 0;
+            Expr * attrs = (Expr *) env->values[0];
+            env->values[0] = allocValue();
+            evalAttrs(*env->up, attrs, *env->values[0]);
+            env->haveWithAttrs = true;
         }
-    } else
-        return env->values[var.displ];
+        Bindings::iterator j = env->values[0]->attrs->find(var.name);
+        if (j != env->values[0]->attrs->end()) {
+            if (countCalls && j->pos) attrSelects[*j->pos]++;
+            return j->value;
+        }
+        if (!env->prevWith)
+            throwEvalError("undefined variable `%1%'", var.name);
+        for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
+    }
 }
 
 
@@ -829,7 +830,8 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
     Env & env2(state.allocEnv(1));
     env2.up = &env;
     env2.prevWith = prevWith;
-    env2.withAttrs = attrs;
+    env2.haveWithAttrs = false;
+    env2.values[0] = (Value *) attrs;
 
     body->eval(state, env2, v);
 }
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index c820b28f49ae..6f6b2a9009fe 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -52,8 +52,8 @@ struct PrimOp
 struct Env
 {
     Env * up;
-    unsigned int prevWith; // nr of levels up to next `with' environment
-    Expr * withAttrs;
+    unsigned short prevWith; // nr of levels up to next `with' environment
+    bool haveWithAttrs;
     Value * values[0];
 };