Skip to content

Commit 7cbc0f9

Browse files
authored
Merge pull request #14090 from Radvendii/expr-slim
nixexpr: introduce arena to hold ExprString strings
2 parents c5b3567 + eab467e commit 7cbc0f9

File tree

6 files changed

+79
-39
lines changed

6 files changed

+79
-39
lines changed

src/libexpr/eval.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3217,7 +3217,8 @@ Expr * EvalState::parse(
32173217
docComments = &it->second;
32183218
}
32193219

3220-
auto result = parseExprFromBuf(text, length, origin, basePath, symbols, settings, positions, *docComments, rootFS);
3220+
auto result = parseExprFromBuf(
3221+
text, length, origin, basePath, mem.exprs.alloc, symbols, settings, positions, *docComments, rootFS);
32213222

32223223
result->bindVars(*this, staticEnv);
32233224

src/libexpr/include/nix/expr/eval.hh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ public:
355355
return stats;
356356
}
357357

358+
/**
359+
* Storage for the AST nodes
360+
*/
361+
Exprs exprs;
362+
358363
private:
359364
Statistics stats;
360365
};

src/libexpr/include/nix/expr/nixexpr.hh

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <map>
55
#include <vector>
6+
#include <memory_resource>
67

78
#include "nix/expr/gc-small-vector.hh"
89
#include "nix/expr/value.hh"
@@ -84,6 +85,13 @@ std::string showAttrPath(const SymbolTable & symbols, const AttrPath & attrPath)
8485

8586
using UpdateQueue = SmallTemporaryValueVector<conservativeStackReservation>;
8687

88+
class Exprs
89+
{
90+
std::pmr::monotonic_buffer_resource buffer;
91+
public:
92+
std::pmr::polymorphic_allocator<char> alloc{&buffer};
93+
};
94+
8795
/* Abstract syntax of Nix expressions. */
8896

8997
struct Expr
@@ -173,13 +181,28 @@ struct ExprFloat : Expr
173181

174182
struct ExprString : Expr
175183
{
176-
std::string s;
177184
Value v;
178185

179-
ExprString(std::string && s)
180-
: s(std::move(s))
186+
/**
187+
* This is only for strings already allocated in our polymorphic allocator,
188+
* or that live at least that long (e.g. c++ string literals)
189+
*/
190+
ExprString(const char * s)
181191
{
182-
v.mkStringNoCopy(this->s.data());
192+
v.mkStringNoCopy(s);
193+
};
194+
195+
ExprString(std::pmr::polymorphic_allocator<char> & alloc, std::string_view sv)
196+
{
197+
auto len = sv.length();
198+
if (len == 0) {
199+
v.mkStringNoCopy("");
200+
return;
201+
}
202+
char * s = alloc.allocate(len + 1);
203+
sv.copy(s, len);
204+
s[len] = '\0';
205+
v.mkStringNoCopy(s);
183206
};
184207

185208
Value * maybeThunk(EvalState & state, Env & env) override;

src/libexpr/include/nix/expr/parser-state.hh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct LexerState
7878
struct ParserState
7979
{
8080
const LexerState & lexerState;
81+
std::pmr::polymorphic_allocator<char> & alloc;
8182
SymbolTable & symbols;
8283
PosTable & positions;
8384
Expr * result;
@@ -323,7 +324,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
323324

324325
// Ignore empty strings for a minor optimisation and AST simplification
325326
if (s2 != "") {
326-
es2->emplace_back(i->first, new ExprString(std::move(s2)));
327+
es2->emplace_back(i->first, new ExprString(alloc, s2));
327328
}
328329
};
329330
for (; i != es.end(); ++i, --n) {

src/libexpr/nixexpr.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void ExprFloat::show(const SymbolTable & symbols, std::ostream & str) const
4040

4141
void ExprString::show(const SymbolTable & symbols, std::ostream & str) const
4242
{
43-
printLiteralString(str, s);
43+
printLiteralString(str, v.string_view());
4444
}
4545

4646
void ExprPath::show(const SymbolTable & symbols, std::ostream & str) const

src/libexpr/parser.y

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ Expr * parseExprFromBuf(
5959
size_t length,
6060
Pos::Origin origin,
6161
const SourcePath & basePath,
62+
std::pmr::polymorphic_allocator<char> & alloc,
6263
SymbolTable & symbols,
6364
const EvalSettings & settings,
6465
PosTable & positions,
@@ -135,6 +136,7 @@ static Expr * makeCall(PosIdx pos, Expr * fn, Expr * arg) {
135136
std::vector<nix::AttrName> * attrNames;
136137
std::vector<std::pair<nix::AttrName, nix::PosIdx>> * inheritAttrs;
137138
std::vector<std::pair<nix::PosIdx, nix::Expr *>> * string_parts;
139+
std::variant<nix::Expr *, std::string_view> * to_be_string;
138140
std::vector<std::pair<nix::PosIdx, std::variant<nix::Expr *, nix::StringToken>>> * ind_string_parts;
139141
}
140142

@@ -149,7 +151,8 @@ static Expr * makeCall(PosIdx pos, Expr * fn, Expr * arg) {
149151
%type <inheritAttrs> attrs
150152
%type <string_parts> string_parts_interpolated
151153
%type <ind_string_parts> ind_string_parts
152-
%type <e> path_start string_parts string_attr
154+
%type <e> path_start
155+
%type <to_be_string> string_parts string_attr
153156
%type <id> attr
154157
%token <id> ID
155158
%token <str> STR IND_STR
@@ -304,7 +307,13 @@ expr_simple
304307
}
305308
| INT_LIT { $$ = new ExprInt($1); }
306309
| FLOAT_LIT { $$ = new ExprFloat($1); }
307-
| '"' string_parts '"' { $$ = $2; }
310+
| '"' string_parts '"' {
311+
std::visit(overloaded{
312+
[&](std::string_view str) { $$ = new ExprString(state->alloc, str); },
313+
[&](Expr * expr) { $$ = expr; }},
314+
*$2);
315+
delete $2;
316+
}
308317
| IND_STRING_OPEN ind_string_parts IND_STRING_CLOSE {
309318
$$ = state->stripIndentation(CUR_POS, std::move(*$2));
310319
delete $2;
@@ -315,11 +324,11 @@ expr_simple
315324
$$ = new ExprConcatStrings(CUR_POS, false, $2);
316325
}
317326
| SPATH {
318-
std::string path($1.p + 1, $1.l - 2);
327+
std::string_view path($1.p + 1, $1.l - 2);
319328
$$ = new ExprCall(CUR_POS,
320329
new ExprVar(state->s.findFile),
321330
{new ExprVar(state->s.nixPath),
322-
new ExprString(std::move(path))});
331+
new ExprString(state->alloc, path)});
323332
}
324333
| URI {
325334
static bool noURLLiterals = experimentalFeatureSettings.isEnabled(Xp::NoUrlLiterals);
@@ -328,7 +337,7 @@ expr_simple
328337
.msg = HintFmt("URL literals are disabled"),
329338
.pos = state->positions[CUR_POS]
330339
});
331-
$$ = new ExprString(std::string($1));
340+
$$ = new ExprString(state->alloc, $1);
332341
}
333342
| '(' expr ')' { $$ = $2; }
334343
/* Let expressions `let {..., body = ...}' are just desugared
@@ -345,19 +354,19 @@ expr_simple
345354
;
346355

347356
string_parts
348-
: STR { $$ = new ExprString(std::string($1)); }
349-
| string_parts_interpolated { $$ = new ExprConcatStrings(CUR_POS, true, $1); }
350-
| { $$ = new ExprString(""); }
357+
: STR { $$ = new std::variant<Expr *, std::string_view>($1); }
358+
| string_parts_interpolated { $$ = new std::variant<Expr *, std::string_view>(new ExprConcatStrings(CUR_POS, true, $1)); }
359+
| { $$ = new std::variant<Expr *, std::string_view>(std::string_view()); }
351360
;
352361

353362
string_parts_interpolated
354363
: string_parts_interpolated STR
355-
{ $$ = $1; $1->emplace_back(state->at(@2), new ExprString(std::string($2))); }
364+
{ $$ = $1; $1->emplace_back(state->at(@2), new ExprString(state->alloc, $2)); }
356365
| string_parts_interpolated DOLLAR_CURLY expr '}' { $$ = $1; $1->emplace_back(state->at(@2), $3); }
357366
| DOLLAR_CURLY expr '}' { $$ = new std::vector<std::pair<PosIdx, Expr *>>; $$->emplace_back(state->at(@1), $2); }
358367
| STR DOLLAR_CURLY expr '}' {
359368
$$ = new std::vector<std::pair<PosIdx, Expr *>>;
360-
$$->emplace_back(state->at(@1), new ExprString(std::string($1)));
369+
$$->emplace_back(state->at(@1), new ExprString(state->alloc, $1));
361370
$$->emplace_back(state->at(@2), $3);
362371
}
363372
;
@@ -455,15 +464,16 @@ attrs
455464
: attrs attr { $$ = $1; $1->emplace_back(AttrName(state->symbols.create($2)), state->at(@2)); }
456465
| attrs string_attr
457466
{ $$ = $1;
458-
ExprString * str = dynamic_cast<ExprString *>($2);
459-
if (str) {
460-
$$->emplace_back(AttrName(state->symbols.create(str->s)), state->at(@2));
461-
delete str;
462-
} else
463-
throw ParseError({
464-
.msg = HintFmt("dynamic attributes not allowed in inherit"),
465-
.pos = state->positions[state->at(@2)]
466-
});
467+
std::visit(overloaded {
468+
[&](std::string_view str) { $$->emplace_back(AttrName(state->symbols.create(str)), state->at(@2)); },
469+
[&](Expr * expr) {
470+
throw ParseError({
471+
.msg = HintFmt("dynamic attributes not allowed in inherit"),
472+
.pos = state->positions[state->at(@2)]
473+
});
474+
}
475+
}, *$2);
476+
delete $2;
467477
}
468478
| { $$ = new std::vector<std::pair<AttrName, PosIdx>>; }
469479
;
@@ -472,22 +482,20 @@ attrpath
472482
: attrpath '.' attr { $$ = $1; $1->push_back(AttrName(state->symbols.create($3))); }
473483
| attrpath '.' string_attr
474484
{ $$ = $1;
475-
ExprString * str = dynamic_cast<ExprString *>($3);
476-
if (str) {
477-
$$->push_back(AttrName(state->symbols.create(str->s)));
478-
delete str;
479-
} else
480-
$$->push_back(AttrName($3));
485+
std::visit(overloaded {
486+
[&](std::string_view str) { $$->push_back(AttrName(state->symbols.create(str))); },
487+
[&](Expr * expr) { $$->push_back(AttrName(expr)); }
488+
}, *$3);
489+
delete $3;
481490
}
482491
| attr { $$ = new std::vector<AttrName>; $$->push_back(AttrName(state->symbols.create($1))); }
483492
| string_attr
484493
{ $$ = new std::vector<AttrName>;
485-
ExprString *str = dynamic_cast<ExprString *>($1);
486-
if (str) {
487-
$$->push_back(AttrName(state->symbols.create(str->s)));
488-
delete str;
489-
} else
490-
$$->push_back(AttrName($1));
494+
std::visit(overloaded {
495+
[&](std::string_view str) { $$->push_back(AttrName(state->symbols.create(str))); },
496+
[&](Expr * expr) { $$->push_back(AttrName(expr)); }
497+
}, *$1);
498+
delete $1;
491499
}
492500
;
493501

@@ -498,7 +506,7 @@ attr
498506

499507
string_attr
500508
: '"' string_parts '"' { $$ = $2; }
501-
| DOLLAR_CURLY expr '}' { $$ = $2; }
509+
| DOLLAR_CURLY expr '}' { $$ = new std::variant<Expr *, std::string_view>($2); }
502510
;
503511

504512
expr_list
@@ -538,6 +546,7 @@ Expr * parseExprFromBuf(
538546
size_t length,
539547
Pos::Origin origin,
540548
const SourcePath & basePath,
549+
std::pmr::polymorphic_allocator<char> & alloc,
541550
SymbolTable & symbols,
542551
const EvalSettings & settings,
543552
PosTable & positions,
@@ -552,6 +561,7 @@ Expr * parseExprFromBuf(
552561
};
553562
ParserState state {
554563
.lexerState = lexerState,
564+
.alloc = alloc,
555565
.symbols = symbols,
556566
.positions = positions,
557567
.basePath = basePath,

0 commit comments

Comments
 (0)