forked from lix-project/lix
* 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
|
@ -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…
Reference in a new issue