aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/parser.y
diff options
context:
space:
mode:
authorpennae <github@quasiparticle.net>2022-03-04 19:31:59 +0100
committerpennae <github@quasiparticle.net>2022-04-21 21:46:06 +0200
commit6526d1676ba5a645f65d751e7529ccd273579017 (patch)
tree62e94d270447a99ba7ea4a4093b6235c721f1985 /src/libexpr/parser.y
parent34b72775cfe755db1bc61cb950c25759c0694be4 (diff)
replace most Pos objects/ptrs with indexes into a position table
Pos objects are somewhat wasteful as they duplicate the origin file name and input type for each object. on files that produce more than one Pos when parsed this a sizeable waste of memory (one pointer per Pos). the same goes for ptr<Pos> on 64 bit machines: parsing enough source to require 8 bytes to locate a position would need at least 8GB of input and 64GB of expression memory. it's not likely that we'll hit that any time soon, so we can use a uint32_t index to locate positions instead.
Diffstat (limited to 'src/libexpr/parser.y')
-rw-r--r--src/libexpr/parser.y78
1 files changed, 40 insertions, 38 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 49c401603..0052a8070 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -32,12 +32,12 @@ namespace nix {
SymbolTable & symbols;
Expr * result;
Path basePath;
- Symbol file;
- FileOrigin origin;
+ PosTable::Origin origin;
std::optional<ErrorInfo> error;
- ParseData(EvalState & state)
+ ParseData(EvalState & state, PosTable::Origin origin)
: state(state)
, symbols(state.symbols)
+ , origin(std::move(origin))
{ };
};
@@ -96,7 +96,7 @@ static void dupAttr(Symbol attr, const Pos & pos, const Pos & prevPos)
static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
- Expr * e, const Pos & pos)
+ Expr * e, const PosIdx pos, const nix::PosTable & pt)
{
AttrPath::iterator i;
// All attrpaths have at least one attr
@@ -109,10 +109,10 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
if (j != attrs->attrs.end()) {
if (!j->second.inherited) {
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
- if (!attrs2) dupAttr(attrPath, pos, j->second.pos);
+ if (!attrs2) dupAttr(attrPath, pt[pos], pt[j->second.pos]);
attrs = attrs2;
} else
- dupAttr(attrPath, pos, j->second.pos);
+ dupAttr(attrPath, pt[pos], pt[j->second.pos]);
} else {
ExprAttrs * nested = new ExprAttrs;
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
@@ -139,11 +139,11 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
for (auto & ad : ae->attrs) {
auto j2 = jAttrs->attrs.find(ad.first);
if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
- dupAttr(ad.first, j2->second.pos, ad.second.pos);
+ dupAttr(ad.first, pt[j2->second.pos], pt[ad.second.pos]);
jAttrs->attrs.emplace(ad.first, ad.second);
}
} else {
- dupAttr(attrPath, pos, j->second.pos);
+ dupAttr(attrPath, pt[pos], pt[j->second.pos]);
}
} else {
// This attr path is not defined. Let's create it.
@@ -157,14 +157,14 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
static Formals * toFormals(ParseData & data, ParserFormals * formals,
- Pos pos = noPos, Symbol arg = {})
+ PosIdx pos = noPos, Symbol arg = {})
{
std::sort(formals->formals.begin(), formals->formals.end(),
[] (const auto & a, const auto & b) {
return std::tie(a.name, a.pos) < std::tie(b.name, b.pos);
});
- std::optional<std::pair<Symbol, Pos>> duplicate;
+ std::optional<std::pair<Symbol, PosIdx>> duplicate;
for (size_t i = 0; i + 1 < formals->formals.size(); i++) {
if (formals->formals[i].name != formals->formals[i + 1].name)
continue;
@@ -174,7 +174,7 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
if (duplicate)
throw ParseError({
.msg = hintfmt("duplicate formal function argument '%1%'", duplicate->first),
- .errPos = duplicate->second
+ .errPos = data.state.positions[duplicate->second]
});
Formals result;
@@ -184,7 +184,7 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
if (arg.set() && result.has(arg))
throw ParseError({
.msg = hintfmt("duplicate formal function argument '%1%'", arg),
- .errPos = pos
+ .errPos = data.state.positions[pos]
});
delete formals;
@@ -192,8 +192,8 @@ static Formals * toFormals(ParseData & data, ParserFormals * formals,
}
-static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols,
- std::vector<std::pair<Pos, std::variant<Expr *, StringToken> > > & es)
+static Expr * stripIndentation(const PosIdx pos, SymbolTable & symbols,
+ std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken> > > & es)
{
if (es.empty()) return new ExprString("");
@@ -233,7 +233,7 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols,
}
/* Strip spaces from each line. */
- std::vector<std::pair<Pos, Expr *> > * es2 = new std::vector<std::pair<Pos, Expr *> >;
+ auto * es2 = new std::vector<std::pair<PosIdx, Expr *> >;
atStartOfLine = true;
size_t curDropped = 0;
size_t n = es.size();
@@ -284,9 +284,9 @@ static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols,
}
-static inline Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
+static inline PosIdx makeCurPos(const YYLTYPE & loc, ParseData * data)
{
- return Pos(data->origin, data->file, loc.first_line, loc.first_column);
+ return data->state.positions.add(data->origin, loc.first_line, loc.first_column);
}
#define CUR_POS makeCurPos(*yylocp, data)
@@ -299,7 +299,7 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
{
data->error = {
.msg = hintfmt(error),
- .errPos = makeCurPos(*loc, data)
+ .errPos = data->state.positions[makeCurPos(*loc, data)]
};
}
@@ -320,8 +320,8 @@ void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * err
StringToken uri;
StringToken str;
std::vector<nix::AttrName> * attrNames;
- std::vector<std::pair<nix::Pos, nix::Expr *> > * string_parts;
- std::vector<std::pair<nix::Pos, std::variant<nix::Expr *, StringToken> > > * ind_string_parts;
+ std::vector<std::pair<nix::PosIdx, nix::Expr *> > * string_parts;
+ std::vector<std::pair<nix::PosIdx, std::variant<nix::Expr *, StringToken> > > * ind_string_parts;
}
%type <e> start expr expr_function expr_if expr_op
@@ -388,7 +388,7 @@ expr_function
{ if (!$2->dynamicAttrs.empty())
throw ParseError({
.msg = hintfmt("dynamic attributes not allowed in let"),
- .errPos = CUR_POS
+ .errPos = data->state.positions[CUR_POS]
});
$$ = new ExprLet($2, $4);
}
@@ -415,7 +415,7 @@ expr_op
| expr_op UPDATE expr_op { $$ = new ExprOpUpdate(CUR_POS, $1, $3); }
| expr_op '?' attrpath { $$ = new ExprOpHasAttr($1, *$3); }
| expr_op '+' expr_op
- { $$ = new ExprConcatStrings(CUR_POS, false, new std::vector<std::pair<Pos, Expr *> >({{makeCurPos(@1, data), $1}, {makeCurPos(@3, data), $3}})); }
+ { $$ = new ExprConcatStrings(CUR_POS, false, new std::vector<std::pair<PosIdx, Expr *> >({{makeCurPos(@1, data), $1}, {makeCurPos(@3, data), $3}})); }
| expr_op '-' expr_op { $$ = new ExprCall(CUR_POS, new ExprVar(data->symbols.create("__sub")), {$1, $3}); }
| expr_op '*' expr_op { $$ = new ExprCall(CUR_POS, new ExprVar(data->symbols.create("__mul")), {$1, $3}); }
| expr_op '/' expr_op { $$ = new ExprCall(CUR_POS, new ExprVar(data->symbols.create("__div")), {$1, $3}); }
@@ -477,7 +477,7 @@ expr_simple
if (noURLLiterals)
throw ParseError({
.msg = hintfmt("URL literals are disabled"),
- .errPos = CUR_POS
+ .errPos = data->state.positions[CUR_POS]
});
$$ = new ExprString(std::string($1));
}
@@ -503,9 +503,9 @@ string_parts_interpolated
: string_parts_interpolated STR
{ $$ = $1; $1->emplace_back(makeCurPos(@2, data), new ExprString(std::string($2))); }
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $3); }
- | DOLLAR_CURLY expr '}' { $$ = new std::vector<std::pair<Pos, Expr *> >; $$->emplace_back(makeCurPos(@1, data), $2); }
+ | DOLLAR_CURLY expr '}' { $$ = new std::vector<std::pair<PosIdx, Expr *> >; $$->emplace_back(makeCurPos(@1, data), $2); }
| STR DOLLAR_CURLY expr '}' {
- $$ = new std::vector<std::pair<Pos, Expr *> >;
+ $$ = new std::vector<std::pair<PosIdx, Expr *> >;
$$->emplace_back(makeCurPos(@1, data), new ExprString(std::string($1)));
$$->emplace_back(makeCurPos(@2, data), $3);
}
@@ -528,17 +528,18 @@ path_start
ind_string_parts
: ind_string_parts IND_STR { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $2); }
| ind_string_parts DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(makeCurPos(@2, data), $3); }
- | { $$ = new std::vector<std::pair<Pos, std::variant<Expr *, StringToken> > >; }
+ | { $$ = new std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken> > >; }
;
binds
- : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data)); }
+ : binds attrpath '=' expr ';' { $$ = $1; addAttr($$, *$2, $4, makeCurPos(@2, data), data->state.positions); }
| binds INHERIT attrs ';'
{ $$ = $1;
for (auto & i : *$3) {
if ($$->attrs.find(i.symbol) != $$->attrs.end())
- dupAttr(i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos);
- Pos pos = makeCurPos(@3, data);
+ dupAttr(i.symbol, data->state.positions[makeCurPos(@3, data)],
+ data->state.positions[$$->attrs[i.symbol].pos]);
+ auto pos = makeCurPos(@3, data);
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true));
}
}
@@ -547,7 +548,8 @@ binds
/* !!! Should ensure sharing of the expression in $4. */
for (auto & i : *$6) {
if ($$->attrs.find(i.symbol) != $$->attrs.end())
- dupAttr(i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos);
+ dupAttr(i.symbol, data->state.positions[makeCurPos(@6, data)],
+ data->state.positions[$$->attrs[i.symbol].pos]);
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)));
}
}
@@ -565,7 +567,7 @@ attrs
} else
throw ParseError({
.msg = hintfmt("dynamic attributes not allowed in inherit"),
- .errPos = makeCurPos(@2, data)
+ .errPos = data->state.positions[makeCurPos(@2, data)]
});
}
| { $$ = new AttrPath; }
@@ -646,19 +648,19 @@ Expr * EvalState::parse(char * text, size_t length, FileOrigin origin,
const PathView path, const PathView basePath, StaticEnv & staticEnv)
{
yyscan_t scanner;
- ParseData data(*this);
- data.origin = origin;
+ Symbol file;
switch (origin) {
case foFile:
- data.file = data.symbols.create(path);
+ file = symbols.create(path);
break;
case foStdin:
case foString:
- data.file = data.symbols.create(text);
+ file = symbols.create(text);
break;
default:
assert(false);
}
+ ParseData data(*this, {file, origin});
data.basePath = basePath;
yylex_init(&scanner);
@@ -668,7 +670,7 @@ Expr * EvalState::parse(char * text, size_t length, FileOrigin origin,
if (res) throw ParseError(data.error.value());
- data.result->bindVars(staticEnv);
+ data.result->bindVars(positions, staticEnv);
return data.result;
}
@@ -760,7 +762,7 @@ Path EvalState::findFile(const std::string_view path)
}
-Path EvalState::findFile(SearchPath & searchPath, const std::string_view path, const Pos & pos)
+Path EvalState::findFile(SearchPath & searchPath, const std::string_view path, const PosIdx pos)
{
for (auto & i : searchPath) {
std::string suffix;
@@ -787,7 +789,7 @@ Path EvalState::findFile(SearchPath & searchPath, const std::string_view path, c
? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)"
: "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)",
path),
- .errPos = pos
+ .errPos = positions[pos]
});
}