* Store attribute positions in the AST and report duplicate attribute

errors with position info.
* For all positions, use the position of the first character of the
  first token, rather than the last character of the first token plus
  one.
This commit is contained in:
Eelco Dolstra 2010-05-06 16:46:48 +00:00
parent c82782f9a5
commit 84ce7ac76f
6 changed files with 56 additions and 56 deletions

View File

@ -192,11 +192,6 @@ LocalNoInlineNoReturn(void throwAssertionError(const char * s, const Pos & pos))
throw AssertionError(format(s) % pos); throw AssertionError(format(s) % pos);
} }
LocalNoInline(void addErrorPrefix(Error & e, const char * s))
{
e.addPrefix(s);
}
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2)) LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2))
{ {
e.addPrefix(format(s) % s2); e.addPrefix(format(s) % s2);
@ -207,11 +202,6 @@ LocalNoInline(void addErrorPrefix(Error & e, const char * s, const Pos & pos))
e.addPrefix(format(s) % pos); e.addPrefix(format(s) % pos);
} }
LocalNoInline(void addErrorPrefix(Error & e, const char * s, const string & s2, const string & s3))
{
e.addPrefix(format(s) % s2 % s3);
}
void mkString(Value & v, const char * s) void mkString(Value & v, const char * s)
{ {
@ -426,7 +416,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
foreach (Attrs::iterator, i, attrs) { foreach (Attrs::iterator, i, attrs) {
Value & v2 = (*v.attrs)[i->first]; Value & v2 = (*v.attrs)[i->first];
mkCopy(v2, env2.values[displ]); mkCopy(v2, env2.values[displ]);
mkThunk(env2.values[displ++], env2, i->second); mkThunk(env2.values[displ++], env2, i->second.first);
} }
/* The inherited attributes, on the other hand, are /* The inherited attributes, on the other hand, are
@ -443,7 +433,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
else { else {
foreach (Attrs::iterator, i, attrs) { foreach (Attrs::iterator, i, attrs) {
Value & v2 = (*v.attrs)[i->first]; Value & v2 = (*v.attrs)[i->first];
mkThunk(v2, env, i->second); mkThunk(v2, env, i->second.first);
} }
foreach (list<VarRef>::iterator, i, inherited) { foreach (list<VarRef>::iterator, i, inherited) {
@ -466,7 +456,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
/* The recursive attributes are evaluated in the new /* The recursive attributes are evaluated in the new
environment. */ environment. */
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
mkThunk(env2.values[displ++], env2, i->second); mkThunk(env2.values[displ++], env2, i->second.first);
/* The inherited attributes, on the other hand, are evaluated in /* The inherited attributes, on the other hand, are evaluated in
the original environment. */ the original environment. */

View File

@ -19,13 +19,16 @@ namespace nix {
static void initLoc(YYLTYPE * loc) static void initLoc(YYLTYPE * loc)
{ {
loc->first_line = 1; loc->first_line = loc->last_line = 1;
loc->first_column = 1; loc->first_column = loc->last_column = 1;
} }
static void adjustLoc(YYLTYPE * loc, const char * s, size_t len) static void adjustLoc(YYLTYPE * loc, const char * s, size_t len)
{ {
loc->first_line = loc->last_line;
loc->first_column = loc->last_column;
while (len--) { while (len--) {
switch (*s++) { switch (*s++) {
case '\r': case '\r':
@ -33,11 +36,11 @@ static void adjustLoc(YYLTYPE * loc, const char * s, size_t len)
s++; s++;
/* fall through */ /* fall through */
case '\n': case '\n':
++loc->first_line; ++loc->last_line;
loc->first_column = 1; loc->last_column = 1;
break; break;
default: default:
++loc->first_column; ++loc->last_column;
} }
} }
} }

View File

@ -58,7 +58,7 @@ void ExprAttrs::show(std::ostream & str)
foreach (list<VarRef>::iterator, i, inherited) foreach (list<VarRef>::iterator, i, inherited)
str << "inherit " << i->name << "; "; str << "inherit " << i->name << "; ";
foreach (Attrs::iterator, i, attrs) foreach (Attrs::iterator, i, attrs)
str << i->first << " = " << *i->second << "; "; str << i->first << " = " << *i->second.first << "; ";
str << "}"; str << "}";
} }
@ -94,7 +94,7 @@ void ExprLet::show(std::ostream & str)
foreach (list<VarRef>::iterator, i, attrs->inherited) foreach (list<VarRef>::iterator, i, attrs->inherited)
str << "inherit " << i->name << "; "; str << "inherit " << i->name << "; ";
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
str << i->first << " = " << *i->second << "; "; str << i->first << " = " << *i->second.first << "; ";
str << "in " << *body; str << "in " << *body;
} }
@ -138,6 +138,9 @@ std::ostream & operator << (std::ostream & str, const Pos & pos)
} }
Pos noPos;
/* Computing levels/displacements for variables. */ /* Computing levels/displacements for variables. */
void Expr::bindVars(const StaticEnv & env) void Expr::bindVars(const StaticEnv & env)
@ -218,12 +221,12 @@ void ExprAttrs::bindVars(const StaticEnv & env)
} }
foreach (ExprAttrs::Attrs::iterator, i, attrs) foreach (ExprAttrs::Attrs::iterator, i, attrs)
i->second->bindVars(newEnv); i->second.first->bindVars(newEnv);
} }
else { else {
foreach (ExprAttrs::Attrs::iterator, i, attrs) foreach (ExprAttrs::Attrs::iterator, i, attrs)
i->second->bindVars(env); i->second.first->bindVars(env);
foreach (list<VarRef>::iterator, i, inherited) foreach (list<VarRef>::iterator, i, inherited)
i->bind(env); i->bind(env);
@ -270,7 +273,7 @@ void ExprLet::bindVars(const StaticEnv & env)
} }
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs) foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
i->second->bindVars(newEnv); i->second.first->bindVars(newEnv);
body->bindVars(newEnv); body->bindVars(newEnv);
} }

View File

@ -23,8 +23,13 @@ struct Pos
{ {
string file; string file;
unsigned int line, column; unsigned int line, column;
Pos() : line(0), column(0) { };
Pos(const string & file, unsigned int line, unsigned int column)
: file(file), line(line), column(column) { };
}; };
extern Pos noPos;
std::ostream & operator << (std::ostream & str, const Pos & pos); std::ostream & operator << (std::ostream & str, const Pos & pos);
@ -125,10 +130,11 @@ struct ExprOpHasAttr : Expr
struct ExprAttrs : Expr struct ExprAttrs : Expr
{ {
bool recursive; bool recursive;
typedef std::map<Symbol, Expr *> Attrs; typedef std::pair<Expr *, Pos> Attr;
typedef std::map<Symbol, Attr> Attrs;
Attrs attrs; Attrs attrs;
list<VarRef> inherited; list<VarRef> inherited;
set<Symbol> attrNames; // used during parsing std::map<Symbol, Pos> attrNames; // used during parsing
ExprAttrs() : recursive(false) { }; ExprAttrs() : recursive(false) { };
COMMON_METHODS COMMON_METHODS
}; };

View File

@ -61,18 +61,18 @@ static string showAttrPath(const vector<Symbol> & attrPath)
} }
static void dupAttr(const vector<Symbol> & attrPath, const Pos & pos) static void dupAttr(const vector<Symbol> & attrPath, const Pos & pos, const Pos & prevPos)
{ {
throw ParseError(format("attribute `%1%' at %2% already defined at <SOMEWHERE>") throw ParseError(format("attribute `%1%' at %2% already defined at %3%")
% showAttrPath(attrPath) % pos); % showAttrPath(attrPath) % pos % prevPos);
} }
static void dupAttr(Symbol attr, const Pos & pos) static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
{ {
vector<Symbol> attrPath; attrPath.push_back(attr); vector<Symbol> attrPath; attrPath.push_back(attr);
throw ParseError(format("attribute `%1%' at %2% already defined at <SOMEWHERE>") throw ParseError(format("attribute `%1%' at %2% already defined at %3%")
% showAttrPath(attrPath) % pos); % showAttrPath(attrPath) % pos % prevPos);
} }
@ -82,19 +82,20 @@ static void addAttr(ExprAttrs * attrs, const vector<Symbol> & attrPath,
unsigned int n = 0; unsigned int n = 0;
foreach (vector<Symbol>::const_iterator, i, attrPath) { foreach (vector<Symbol>::const_iterator, i, attrPath) {
n++; n++;
if (attrs->attrs[*i]) { ExprAttrs::Attrs::iterator j = attrs->attrs.find(*i);
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(attrs->attrs[*i]); if (j != attrs->attrs.end()) {
if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos); ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.first);
if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos, j->second.second);
attrs = attrs2; attrs = attrs2;
} else { } else {
if (attrs->attrNames.find(*i) != attrs->attrNames.end()) if (attrs->attrNames.find(*i) != attrs->attrNames.end())
dupAttr(attrPath, pos); dupAttr(attrPath, pos, attrs->attrNames[*i]);
attrs->attrNames.insert(*i); attrs->attrNames[*i] = pos;
if (n == attrPath.size()) if (n == attrPath.size())
attrs->attrs[*i] = e; attrs->attrs[*i] = ExprAttrs::Attr(e, pos);
else { else {
ExprAttrs * nested = new ExprAttrs; ExprAttrs * nested = new ExprAttrs;
attrs->attrs[*i] = nested; attrs->attrs[*i] = ExprAttrs::Attr(nested, pos);
attrs = nested; attrs = nested;
} }
} }
@ -205,16 +206,12 @@ void backToString(yyscan_t scanner);
void backToIndString(yyscan_t scanner); void backToIndString(yyscan_t scanner);
static Pos makeCurPos(YYLTYPE * loc, ParseData * data) static Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
{ {
Pos pos; return Pos(data->path, loc.first_line, loc.first_column);
pos.file = data->path;
pos.line = loc->first_line;
pos.column = loc->first_column;
return pos;
} }
#define CUR_POS makeCurPos(yylocp, data) #define CUR_POS makeCurPos(*yylocp, data)
} }
@ -223,7 +220,7 @@ static Pos makeCurPos(YYLTYPE * loc, ParseData * data)
void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error) void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error)
{ {
data->error = (format("%1%, at %2%") data->error = (format("%1%, at %2%")
% error % makeCurPos(loc, data)).str(); % error % makeCurPos(*loc, data)).str();
} }
@ -374,14 +371,14 @@ ind_string_parts
; ;
binds binds
: binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, CUR_POS); } : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); }
| binds INHERIT ids ';' | binds INHERIT ids ';'
{ $$ = $1; { $$ = $1;
foreach (vector<Symbol>::iterator, i, *$3) { foreach (vector<Symbol>::iterator, i, *$3) {
if ($$->attrNames.find(*i) != $$->attrNames.end()) if ($$->attrNames.find(*i) != $$->attrNames.end())
dupAttr(*i, CUR_POS); dupAttr(*i, makeCurPos(@3, data), $$->attrNames[*i]);
$$->inherited.push_back(*i); $$->inherited.push_back(*i);
$$->attrNames.insert(*i); $$->attrNames[*i] = makeCurPos(@3, data);
} }
} }
| binds INHERIT '(' expr ')' ids ';' | binds INHERIT '(' expr ')' ids ';'
@ -389,11 +386,11 @@ binds
/* !!! Should ensure sharing of the expression in $4. */ /* !!! Should ensure sharing of the expression in $4. */
foreach (vector<Symbol>::iterator, i, *$6) { foreach (vector<Symbol>::iterator, i, *$6) {
if ($$->attrNames.find(*i) != $$->attrNames.end()) if ($$->attrNames.find(*i) != $$->attrNames.end())
dupAttr(*i, CUR_POS); dupAttr(*i, makeCurPos(@6, data), $$->attrNames[*i]);
$$->attrs[*i] = new ExprSelect($4, *i); $$->attrs[*i] = ExprAttrs::Attr(new ExprSelect($4, *i), makeCurPos(@6, data));
$$->attrNames.insert(*i); $$->attrNames[*i] = makeCurPos(@6, data);
} }}
}
| { $$ = new ExprAttrs; } | { $$ = new ExprAttrs; }
; ;

View File

@ -132,7 +132,7 @@ static void getAllExprs(EvalState & state,
if (hasSuffix(attrName, ".nix")) if (hasSuffix(attrName, ".nix"))
attrName = string(attrName, 0, attrName.size() - 4); attrName = string(attrName, 0, attrName.size() - 4);
attrs.attrs[state.symbols.create(attrName)] = attrs.attrs[state.symbols.create(attrName)] =
parseExprFromFile(state, absPath(path2)); ExprAttrs::Attr(parseExprFromFile(state, absPath(path2)), noPos);
} }
else else
/* `path2' is a directory (with no default.nix in it); /* `path2' is a directory (with no default.nix in it);
@ -153,7 +153,8 @@ static Expr * loadSourceExpr(EvalState & state, const Path & path)
for a user to have a ~/.nix-defexpr directory that includes for a user to have a ~/.nix-defexpr directory that includes
some system-wide directory). */ some system-wide directory). */
ExprAttrs * attrs = new ExprAttrs; ExprAttrs * attrs = new ExprAttrs;
attrs->attrs[state.symbols.create("_combineChannels")] = new ExprList(); attrs->attrs[state.symbols.create("_combineChannels")] =
ExprAttrs::Attr(new ExprList(), noPos);
getAllExprs(state, path, *attrs); getAllExprs(state, path, *attrs);
return attrs; return attrs;
} }