Skip to content

Commit 687dd38

Browse files
committed
parser.y: abstract new into a function on Exprs
so it can easily be swapped out for other implementations
1 parent 62729ff commit 687dd38

File tree

4 files changed

+111
-75
lines changed

4 files changed

+111
-75
lines changed

src/libexpr/eval.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3216,8 +3216,8 @@ Expr * EvalState::parse(
32163216
docComments = &it->second;
32173217
}
32183218

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

32223222
result->bindVars(*this, staticEnv);
32233223

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

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,6 @@ std::string showAttrPath(const SymbolTable & symbols, std::span<const AttrName>
9191

9292
using UpdateQueue = SmallTemporaryValueVector<conservativeStackReservation>;
9393

94-
class Exprs
95-
{
96-
std::pmr::monotonic_buffer_resource buffer;
97-
public:
98-
std::pmr::polymorphic_allocator<char> alloc{&buffer};
99-
};
100-
10194
/* Abstract syntax of Nix expressions. */
10295

10396
struct Expr
@@ -810,6 +803,49 @@ struct ExprBlackHole : Expr
810803

811804
extern ExprBlackHole eBlackHole;
812805

806+
class Exprs
807+
{
808+
std::pmr::monotonic_buffer_resource buffer;
809+
public:
810+
std::pmr::polymorphic_allocator<char> alloc{&buffer};
811+
812+
template<class C>
813+
[[gnu::always_inline]]
814+
C * add(auto &&... args)
815+
{
816+
return new C(std::forward<decltype(args)>(args)...);
817+
}
818+
819+
// we define some calls to add explicitly so that the argument can be passed in as initializer lists
820+
template<class C>
821+
[[gnu::always_inline]]
822+
C * add(const PosIdx & pos, Expr * fun, std::vector<Expr *> && args)
823+
requires(std::same_as<C, ExprCall>)
824+
{
825+
return new C(pos, fun, std::move(args));
826+
}
827+
828+
template<class C>
829+
[[gnu::always_inline]]
830+
C * add(const PosIdx & pos, Expr * fun, std::vector<Expr *> && args, PosIdx && cursedOrEndPos)
831+
requires(std::same_as<C, ExprCall>)
832+
{
833+
return new C(pos, fun, std::move(args), std::move(cursedOrEndPos));
834+
}
835+
836+
template<class C>
837+
[[gnu::always_inline]]
838+
C *
839+
add(std::pmr::polymorphic_allocator<char> & alloc,
840+
const PosIdx & pos,
841+
bool forceString,
842+
const std::vector<std::pair<PosIdx, Expr *>> & es)
843+
requires(std::same_as<C, ExprConcatStrings>)
844+
{
845+
return alloc.new_object<C>(alloc, pos, forceString, es);
846+
}
847+
};
848+
813849
/* Static environments are used to map variable names onto (level,
814850
displacement) pairs used to obtain the value of the variable at
815851
runtime. */

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ inline void ParserState::addAttr(
132132
dupAttr(attrPath, pos, j->second.pos);
133133
}
134134
} else {
135-
nested = new ExprAttrs;
135+
nested = exprs.add<ExprAttrs>();
136136
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(nested, pos);
137137
}
138138
} else {
139-
nested = new ExprAttrs;
139+
nested = exprs.add<ExprAttrs>();
140140
attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(i->expr, nested, pos));
141141
}
142142
attrs = nested;
@@ -240,7 +240,7 @@ inline Expr *
240240
ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken>>> && es)
241241
{
242242
if (es.empty())
243-
return new ExprString("");
243+
return exprs.add<ExprString>("");
244244

245245
/* Figure out the minimum indentation. Note that by design
246246
whitespace-only final lines are not taken into account. (So
@@ -322,7 +322,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
322322

323323
// Ignore empty strings for a minor optimisation and AST simplification
324324
if (s2 != "") {
325-
es2.emplace_back(i->first, new ExprString(exprs.alloc, s2));
325+
es2.emplace_back(i->first, exprs.add<ExprString>(exprs.alloc, s2));
326326
}
327327
};
328328
for (; i != es.end(); ++i, --n) {
@@ -332,7 +332,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
332332
// If there is nothing at all, return the empty string directly.
333333
// This also ensures that equivalent empty strings result in the same ast, which is helpful when testing formatters.
334334
if (es2.size() == 0) {
335-
auto * const result = new ExprString("");
335+
auto * const result = exprs.add<ExprString>("");
336336
return result;
337337
}
338338

@@ -341,7 +341,7 @@ ParserState::stripIndentation(const PosIdx pos, std::vector<std::pair<PosIdx, st
341341
auto * const result = (es2)[0].second;
342342
return result;
343343
}
344-
return new ExprConcatStrings(exprs.alloc, pos, true, std::move(es2));
344+
return exprs.add<ExprConcatStrings>(exprs.alloc, pos, true, std::move(es2));
345345
}
346346

347347
inline PosIdx LexerState::at(const ParserLocation & loc)

0 commit comments

Comments
 (0)