about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2011-07-06T12·28+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2011-07-06T12·28+0000
commit2b9e29b1c8b6b8e4884a46a3ba71ee795f1f97cd (patch)
tree9b4dd1efce2222e6fdf29ceaaca1f477b77e532b /src
parent5580f3817c37135dcc633d84d1360a17a8878a58 (diff)
* Change the right-hand side of the ‘.’ operator from an attribute to
  an attribute path.  This is a refactoring to support default values.

Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.cc38
-rw-r--r--src/libexpr/nixexpr.cc2
-rw-r--r--src/libexpr/nixexpr.hh5
-rw-r--r--src/libexpr/parser.y6
4 files changed, 33 insertions, 18 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index c307f2a420..4d3a369aa1 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -636,21 +636,35 @@ unsigned long nrLookupSize = 0;
 
 void ExprSelect::eval(EvalState & state, Env & env, Value & v)
 {
-    nrLookups++;
-    Value v2;
-    state.evalAttrs(env, e, v2);
-    nrLookupSize += v2.attrs->size();
-    Bindings::iterator i = v2.attrs->find(name);
-    if (i == v2.attrs->end())
-        throwEvalError("attribute `%1%' missing", name);
-    try {            
-        state.forceValue(*i->value);
+    Value vTmp;
+    Pos * pos = 0;
+    Value * vAttrs = &vTmp;
+
+    state.eval(env, e, vTmp);
+
+    try {
+        
+        foreach (AttrPath::const_iterator, i, attrPath) {
+            nrLookups++;
+            state.forceAttrs(*vAttrs);
+            nrLookupSize += vAttrs->attrs->size();
+            Bindings::iterator j;
+            if ((j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
+                throwEvalError("attribute `%1%' missing", showAttrPath(attrPath));
+            vAttrs = j->value;
+            pos = j->pos;
+        }
+    
+        state.forceValue(*vAttrs);
+        
     } catch (Error & e) {
-        addErrorPrefix(e, "while evaluating the attribute `%1%' at %2%:\n",
-            name, *i->pos);
+        if (pos)
+            addErrorPrefix(e, "while evaluating the attribute `%1%' at %2%:\n",
+                showAttrPath(attrPath), *pos);
         throw;
     }
-    v = *i->value;
+    
+    v = *vAttrs;
 }
 
 
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 5957618702..2632d9f3ff 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -43,7 +43,7 @@ void ExprVar::show(std::ostream & str)
 
 void ExprSelect::show(std::ostream & str)
 {
-    str << "(" << *e << ")." << name;
+    str << "(" << *e << ")." << showAttrPath(attrPath);
 }
 
 void ExprOpHasAttr::show(std::ostream & str)
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 205f579daf..725e30c6fa 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -122,8 +122,9 @@ struct ExprVar : Expr
 struct ExprSelect : Expr
 {
     Expr * e;
-    Symbol name;
-    ExprSelect(Expr * e, const Symbol & name) : e(e), name(name) { };
+    AttrPath attrPath;
+    ExprSelect(Expr * e, const AttrPath & attrPath) : e(e), attrPath(attrPath) { };
+    ExprSelect(Expr * e, const Symbol & name) : e(e) { attrPath.push_back(name); };
     COMMON_METHODS
 };
 
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 073fac1bee..49bd7bfa5f 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -325,8 +325,8 @@ expr_app
   ;
 
 expr_select
-  : expr_select '.' ID
-    { $$ = new ExprSelect($1, data->symbols.create($3)); }
+  : expr_simple '.' attrpath
+    { $$ = new ExprSelect($1, *$3); }
   | expr_simple { $$ = $1; }
   ;
 
@@ -382,7 +382,7 @@ binds
   | binds INHERIT '(' expr ')' ids ';'
     { $$ = $1;
       /* !!! Should ensure sharing of the expression in $4. */
-      foreach (AttrPath::iterator, i, *$6) {
+      foreach (vector<Symbol>::iterator, i, *$6) {
           if ($$->attrs.find(*i) != $$->attrs.end())
               dupAttr(*i, makeCurPos(@6, data), $$->attrs[*i].pos);
           $$->attrs[*i] = ExprAttrs::AttrDef(new ExprSelect($4, *i), makeCurPos(@6, data));