* 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:
		
							parent
							
								
									c82782f9a5
								
							
						
					
					
						commit
						84ce7ac76f
					
				
					 6 changed files with 56 additions and 56 deletions
				
			
		|  | @ -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. */ | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|        } |        } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -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; } | ||||||
|   ; |   ; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue