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…
Reference in a new issue