Show the exact position of undefined variables
In particular, undefined variable errors in a "with" previously didn't show *any* position information, so this should help a lot in those cases.
This commit is contained in:
parent
a5e0f64db3
commit
6b47de580f
4 changed files with 18 additions and 21 deletions
|
@ -315,7 +315,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||||
return j->value;
|
return j->value;
|
||||||
}
|
}
|
||||||
if (!env->prevWith)
|
if (!env->prevWith)
|
||||||
throwEvalError("undefined variable `%1%'", var.name);
|
throw EvalError(format("undefined variable `%1%' at %2%") % var.name % var.pos);
|
||||||
for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
|
for (unsigned int l = env->prevWith; l; --l, env = env->up) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ void ExprVar::bindVars(const StaticEnv & env)
|
||||||
/* Otherwise, the variable must be obtained from the nearest
|
/* Otherwise, the variable must be obtained from the nearest
|
||||||
enclosing `with'. If there is no `with', then we can issue an
|
enclosing `with'. If there is no `with', then we can issue an
|
||||||
"undefined variable" error now. */
|
"undefined variable" error now. */
|
||||||
if (withLevel == -1) throw EvalError(format("undefined variable `%1%'") % name);
|
if (withLevel == -1) throw ParseError(format("undefined variable `%1%' at %2%") % name % pos);
|
||||||
|
|
||||||
fromWith = true;
|
fromWith = true;
|
||||||
this->level = withLevel;
|
this->level = withLevel;
|
||||||
|
|
|
@ -109,6 +109,7 @@ struct ExprPath : Expr
|
||||||
|
|
||||||
struct ExprVar : Expr
|
struct ExprVar : Expr
|
||||||
{
|
{
|
||||||
|
Pos pos;
|
||||||
Symbol name;
|
Symbol name;
|
||||||
|
|
||||||
/* Whether the variable comes from an environment (e.g. a rec, let
|
/* Whether the variable comes from an environment (e.g. a rec, let
|
||||||
|
@ -124,7 +125,7 @@ struct ExprVar : Expr
|
||||||
unsigned int level;
|
unsigned int level;
|
||||||
unsigned int displ;
|
unsigned int displ;
|
||||||
|
|
||||||
ExprVar(const Symbol & name) : name(name) { };
|
ExprVar(const Pos & pos, const Symbol & name) : pos(pos), name(name) { };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
Value * maybeThunk(EvalState & state, Env & env);
|
Value * maybeThunk(EvalState & state, Env & env);
|
||||||
};
|
};
|
||||||
|
|
|
@ -310,13 +310,13 @@ expr_if
|
||||||
|
|
||||||
expr_op
|
expr_op
|
||||||
: '!' expr_op %prec NOT { $$ = new ExprOpNot($2); }
|
: '!' expr_op %prec NOT { $$ = new ExprOpNot($2); }
|
||||||
| '-' expr_op %prec NEGATE { $$ = new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__sub")), new ExprInt(0)), $2); }
|
| '-' expr_op %prec NEGATE { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__sub")), new ExprInt(0)), $2); }
|
||||||
| expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); }
|
| expr_op EQ expr_op { $$ = new ExprOpEq($1, $3); }
|
||||||
| expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); }
|
| expr_op NEQ expr_op { $$ = new ExprOpNEq($1, $3); }
|
||||||
| expr_op '<' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__lessThan")), $1), $3); }
|
| expr_op '<' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $1), $3); }
|
||||||
| expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__lessThan")), $3), $1)); }
|
| expr_op LEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $3), $1)); }
|
||||||
| expr_op '>' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__lessThan")), $3), $1); }
|
| expr_op '>' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $3), $1); }
|
||||||
| expr_op GEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__lessThan")), $1), $3)); }
|
| expr_op GEQ expr_op { $$ = new ExprOpNot(new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__lessThan")), $1), $3)); }
|
||||||
| expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); }
|
| expr_op AND expr_op { $$ = new ExprOpAnd($1, $3); }
|
||||||
| expr_op OR expr_op { $$ = new ExprOpOr($1, $3); }
|
| expr_op OR expr_op { $$ = new ExprOpOr($1, $3); }
|
||||||
| expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); }
|
| expr_op IMPL expr_op { $$ = new ExprOpImpl($1, $3); }
|
||||||
|
@ -328,9 +328,9 @@ expr_op
|
||||||
l->push_back($3);
|
l->push_back($3);
|
||||||
$$ = new ExprConcatStrings(false, l);
|
$$ = new ExprConcatStrings(false, l);
|
||||||
}
|
}
|
||||||
| expr_op '-' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__sub")), $1), $3); }
|
| expr_op '-' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__sub")), $1), $3); }
|
||||||
| expr_op '*' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__mul")), $1), $3); }
|
| expr_op '*' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__mul")), $1), $3); }
|
||||||
| expr_op '/' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(data->symbols.create("__div")), $1), $3); }
|
| expr_op '/' expr_op { $$ = new ExprApp(new ExprApp(new ExprVar(noPos, data->symbols.create("__div")), $1), $3); }
|
||||||
| expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); }
|
| expr_op CONCAT expr_op { $$ = new ExprOpConcatLists($1, $3); }
|
||||||
| expr_app
|
| expr_app
|
||||||
;
|
;
|
||||||
|
@ -349,12 +349,12 @@ expr_select
|
||||||
| /* Backwards compatibility: because Nixpkgs has a rarely used
|
| /* Backwards compatibility: because Nixpkgs has a rarely used
|
||||||
function named ‘or’, allow stuff like ‘map or [...]’. */
|
function named ‘or’, allow stuff like ‘map or [...]’. */
|
||||||
expr_simple OR_KW
|
expr_simple OR_KW
|
||||||
{ $$ = new ExprApp($1, new ExprVar(data->symbols.create("or"))); }
|
{ $$ = new ExprApp($1, new ExprVar(CUR_POS, data->symbols.create("or"))); }
|
||||||
| expr_simple { $$ = $1; }
|
| expr_simple { $$ = $1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
expr_simple
|
expr_simple
|
||||||
: ID { $$ = new ExprVar(data->symbols.create($1)); }
|
: ID { $$ = new ExprVar(CUR_POS, data->symbols.create($1)); }
|
||||||
| INT { $$ = new ExprInt($1); }
|
| INT { $$ = new ExprInt($1); }
|
||||||
| '"' string_parts '"' {
|
| '"' string_parts '"' {
|
||||||
/* For efficiency, and to simplify parse trees a bit. */
|
/* For efficiency, and to simplify parse trees a bit. */
|
||||||
|
@ -372,10 +372,10 @@ expr_simple
|
||||||
/* The file wasn't found in the search path. However, we can't
|
/* The file wasn't found in the search path. However, we can't
|
||||||
throw an error here, because the expression might never be
|
throw an error here, because the expression might never be
|
||||||
evaluated. So return an expression that lazily calls
|
evaluated. So return an expression that lazily calls
|
||||||
‘abort’. */
|
‘throw’. */
|
||||||
$$ = path2 == ""
|
$$ = path2 == ""
|
||||||
? (Expr * ) new ExprApp(
|
? (Expr * ) new ExprApp(
|
||||||
new ExprVar(data->symbols.create("throw")),
|
new ExprVar(noPos, data->symbols.create("throw")),
|
||||||
new ExprString(data->symbols.create(
|
new ExprString(data->symbols.create(
|
||||||
(format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % path).str())))
|
(format("file `%1%' was not found in the Nix search path (add it using $NIX_PATH or -I)") % path).str())))
|
||||||
: (Expr * ) new ExprPath(path2);
|
: (Expr * ) new ExprPath(path2);
|
||||||
|
@ -413,7 +413,7 @@ binds
|
||||||
if ($$->attrs.find(*i) != $$->attrs.end())
|
if ($$->attrs.find(*i) != $$->attrs.end())
|
||||||
dupAttr(*i, makeCurPos(@3, data), $$->attrs[*i].pos);
|
dupAttr(*i, makeCurPos(@3, data), $$->attrs[*i].pos);
|
||||||
Pos pos = makeCurPos(@3, data);
|
Pos pos = makeCurPos(@3, data);
|
||||||
$$->attrs[*i] = ExprAttrs::AttrDef(new ExprVar(*i), pos, true);
|
$$->attrs[*i] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, *i), pos, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| binds INHERIT '(' expr ')' attrs ';'
|
| binds INHERIT '(' expr ')' attrs ';'
|
||||||
|
@ -495,11 +495,7 @@ Expr * EvalState::parse(const char * text,
|
||||||
|
|
||||||
if (res) throw ParseError(data.error);
|
if (res) throw ParseError(data.error);
|
||||||
|
|
||||||
try {
|
|
||||||
data.result->bindVars(staticEnv);
|
data.result->bindVars(staticEnv);
|
||||||
} catch (Error & e) {
|
|
||||||
throw ParseError(format("%1%, in `%2%'") % e.msg() % path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.result;
|
return data.result;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue