Show function names in error messages
Functions in Nix are anonymous, but if they're assigned to a variable/attribute, we can use the variable/attribute name in error messages, e.g. while evaluating `concatMapStrings' at `/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs/pkgs/lib/strings.nix:18:25': ...
This commit is contained in:
		
							parent
							
								
									1b3a03f161
								
							
						
					
					
						commit
						18a48d80a0
					
				
					 5 changed files with 43 additions and 8 deletions
				
			
		|  | @ -247,6 +247,11 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos, const | ||||||
|     throw TypeError(format(s) % pos % s2); |     throw TypeError(format(s) % pos % s2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s1, const string & s2)) | ||||||
|  | { | ||||||
|  |     throw TypeError(format(s) % s1 % s2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos)) | LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos)) | ||||||
| { | { | ||||||
|     throw TypeError(format(s) % pos); |     throw TypeError(format(s) % pos); | ||||||
|  | @ -755,8 +760,8 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) | ||||||
|         foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) { |         foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) { | ||||||
|             Bindings::iterator j = arg.attrs->find(i->name); |             Bindings::iterator j = arg.attrs->find(i->name); | ||||||
|             if (j == arg.attrs->end()) { |             if (j == arg.attrs->end()) { | ||||||
|                 if (!i->def) throwTypeError("function at %1% called without required argument `%2%'", |                 if (!i->def) throwTypeError("%1% called without required argument `%2%'", | ||||||
|                     fun.lambda.fun->pos, i->name); |                     fun.lambda.fun->showNamePos(), i->name); | ||||||
|                 env2.values[displ++] = i->def->maybeThunk(*this, env2); |                 env2.values[displ++] = i->def->maybeThunk(*this, env2); | ||||||
|             } else { |             } else { | ||||||
|                 attrsUsed++; |                 attrsUsed++; | ||||||
|  | @ -771,7 +776,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) | ||||||
|                user. */ |                user. */ | ||||||
|             foreach (Bindings::iterator, i, *arg.attrs) |             foreach (Bindings::iterator, i, *arg.attrs) | ||||||
|                 if (fun.lambda.fun->formals->argNames.find(i->name) == fun.lambda.fun->formals->argNames.end()) |                 if (fun.lambda.fun->formals->argNames.find(i->name) == fun.lambda.fun->formals->argNames.end()) | ||||||
|                     throwTypeError("function at %1% called with unexpected argument `%2%'", fun.lambda.fun->pos, i->name); |                     throwTypeError("%1% called with unexpected argument `%2%'", fun.lambda.fun->showNamePos(), i->name); | ||||||
|             abort(); // can't happen
 |             abort(); // can't happen
 | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -782,7 +787,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v) | ||||||
|     try { |     try { | ||||||
|         fun.lambda.fun->body->eval(*this, env2, v); |         fun.lambda.fun->body->eval(*this, env2, v); | ||||||
|     } catch (Error & e) { |     } catch (Error & e) { | ||||||
|         addErrorPrefix(e, "while evaluating the function at %1%:\n", fun.lambda.fun->pos); |         addErrorPrefix(e, "while evaluating %1%:\n", fun.lambda.fun->showNamePos()); | ||||||
|         throw; |         throw; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -324,4 +324,24 @@ void ExprConcatStrings::bindVars(const StaticEnv & env) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | /* Storing function names. */ | ||||||
|  | 
 | ||||||
|  | void Expr::setName(Symbol & name) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void ExprLambda::setName(Symbol & name) | ||||||
|  | { | ||||||
|  |     this->name = name; | ||||||
|  |     body->setName(name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | string ExprLambda::showNamePos() | ||||||
|  | { | ||||||
|  |     return (format("%1% at %2%") % (name.set() ? "`" + (string) name + "'" : "an anonymous function") % pos).str(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -63,6 +63,7 @@ struct Expr | ||||||
|     virtual void bindVars(const StaticEnv & env); |     virtual void bindVars(const StaticEnv & env); | ||||||
|     virtual void eval(EvalState & state, Env & env, Value & v); |     virtual void eval(EvalState & state, Env & env, Value & v); | ||||||
|     virtual Value * maybeThunk(EvalState & state, Env & env); |     virtual Value * maybeThunk(EvalState & state, Env & env); | ||||||
|  |     virtual void setName(Symbol & name); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| std::ostream & operator << (std::ostream & str, Expr & e); | std::ostream & operator << (std::ostream & str, Expr & e); | ||||||
|  | @ -197,6 +198,7 @@ struct Formals | ||||||
| struct ExprLambda : Expr | struct ExprLambda : Expr | ||||||
| { | { | ||||||
|     Pos pos; |     Pos pos; | ||||||
|  |     Symbol name; | ||||||
|     Symbol arg; |     Symbol arg; | ||||||
|     bool matchAttrs; |     bool matchAttrs; | ||||||
|     Formals * formals; |     Formals * formals; | ||||||
|  | @ -208,6 +210,8 @@ struct ExprLambda : Expr | ||||||
|             throw ParseError(format("duplicate formal function argument `%1%' at %2%") |             throw ParseError(format("duplicate formal function argument `%1%' at %2%") | ||||||
|                 % arg % pos); |                 % arg % pos); | ||||||
|     }; |     }; | ||||||
|  |     void setName(Symbol & name); | ||||||
|  |     string showNamePos(); | ||||||
|     COMMON_METHODS |     COMMON_METHODS | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -104,6 +104,7 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath, | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |     e->setName(attrPath.back()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,17 +28,17 @@ private: | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     Symbol() : s(0) { }; |     Symbol() : s(0) { }; | ||||||
|      | 
 | ||||||
|     bool operator == (const Symbol & s2) const |     bool operator == (const Symbol & s2) const | ||||||
|     { |     { | ||||||
|         return s == s2.s; |         return s == s2.s; | ||||||
|     } |     } | ||||||
|      | 
 | ||||||
|     bool operator != (const Symbol & s2) const |     bool operator != (const Symbol & s2) const | ||||||
|     { |     { | ||||||
|         return s != s2.s; |         return s != s2.s; | ||||||
|     } |     } | ||||||
|      | 
 | ||||||
|     bool operator < (const Symbol & s2) const |     bool operator < (const Symbol & s2) const | ||||||
|     { |     { | ||||||
|         return s < s2.s; |         return s < s2.s; | ||||||
|  | @ -49,6 +49,11 @@ public: | ||||||
|         return *s; |         return *s; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     bool set() const | ||||||
|  |     { | ||||||
|  |         return s; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     bool empty() const |     bool empty() const | ||||||
|     { |     { | ||||||
|         return s->empty(); |         return s->empty(); | ||||||
|  | @ -66,7 +71,7 @@ inline std::ostream & operator << (std::ostream & str, const Symbol & sym) | ||||||
| class SymbolTable | class SymbolTable | ||||||
| { | { | ||||||
| private: | private: | ||||||
| #if HAVE_TR1_UNORDERED_SET  | #if HAVE_TR1_UNORDERED_SET | ||||||
|     typedef std::tr1::unordered_set<string> Symbols; |     typedef std::tr1::unordered_set<string> Symbols; | ||||||
| #else | #else | ||||||
|     typedef std::set<string> Symbols; |     typedef std::set<string> Symbols; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue