From 8e5fbf4d730b9fcf39eddf5539a206cf19d2cdce Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 4 Apr 2014 22:52:14 +0200 Subject: [PATCH] Show position info in attribute selection errors --- src/libexpr/eval.cc | 14 +++++++------- src/libexpr/nixexpr.hh | 5 +++-- src/libexpr/parser.y | 8 ++++---- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 44d75bd8c..0f7e8e385 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -736,7 +736,7 @@ unsigned long nrLookups = 0; void ExprSelect::eval(EvalState & state, Env & env, Value & v) { Value vTmp; - Pos * pos = 0; + Pos * pos2 = 0; Value * vAttrs = &vTmp; e->eval(state, env, vTmp); @@ -756,21 +756,21 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) return; } } else { - state.forceAttrs(*vAttrs); + state.forceAttrs(*vAttrs, pos); if ((j = vAttrs->attrs->find(name)) == vAttrs->attrs->end()) - throwEvalError("attribute `%1%' missing", showAttrPath(attrPath)); + throwEvalError("attribute `%1%' missing, at %2%", showAttrPath(attrPath), pos); } vAttrs = j->value; - pos = j->pos; - if (state.countCalls && pos) state.attrSelects[*pos]++; + pos2 = j->pos; + if (state.countCalls && pos2) state.attrSelects[*pos2]++; } state.forceValue(*vAttrs); } catch (Error & e) { - if (pos && pos->file != state.sDerivationNix) + if (pos2 && pos2->file != state.sDerivationNix) addErrorPrefix(e, "while evaluating the attribute `%1%' at %2%:\n", - showAttrPath(attrPath), *pos); + showAttrPath(attrPath), *pos2); throw; } diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index f07b85c83..813efbe21 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -149,10 +149,11 @@ struct ExprVar : Expr struct ExprSelect : Expr { + Pos pos; Expr * e, * def; AttrPath attrPath; - ExprSelect(Expr * e, const AttrPath & attrPath, Expr * def) : e(e), def(def), attrPath(attrPath) { }; - ExprSelect(Expr * e, const Symbol & name) : e(e), def(0) { attrPath.push_back(AttrName(name)); }; + ExprSelect(const Pos & pos, Expr * e, const AttrPath & attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(attrPath) { }; + ExprSelect(const Pos & pos, Expr * e, const Symbol & name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); }; COMMON_METHODS }; diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 021f8b026..dbcffff99 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -361,9 +361,9 @@ expr_app expr_select : expr_simple '.' attrpath - { $$ = new ExprSelect($1, *$3, 0); } + { $$ = new ExprSelect(CUR_POS, $1, *$3, 0); } | expr_simple '.' attrpath OR_KW expr_select - { $$ = new ExprSelect($1, *$3, $5); } + { $$ = new ExprSelect(CUR_POS, $1, *$3, $5); } | /* Backwards compatibility: because Nixpkgs has a rarely used function named ‘or’, allow stuff like ‘map or [...]’. */ expr_simple OR_KW @@ -403,7 +403,7 @@ expr_simple /* Let expressions `let {..., body = ...}' are just desugared into `(rec {..., body = ...}).body'. */ | LET '{' binds '}' - { $3->recursive = true; $$ = new ExprSelect($3, data->symbols.create("body")); } + { $3->recursive = true; $$ = new ExprSelect(noPos, $3, data->symbols.create("body")); } | REC '{' binds '}' { $3->recursive = true; $$ = $3; } | '{' binds '}' @@ -458,7 +458,7 @@ binds foreach (AttrPath::iterator, i, *$6) { if ($$->attrs.find(i->symbol) != $$->attrs.end()) dupAttr(i->symbol, makeCurPos(@6, data), $$->attrs[i->symbol].pos); - $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprSelect($4, i->symbol), makeCurPos(@6, data)); + $$->attrs[i->symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i->symbol), makeCurPos(@6, data)); } } | { $$ = new ExprAttrs; }