Merge "libexpr: Add experimental pipe operator" into main
This commit is contained in:
@@ -434,6 +434,8 @@ struct op {
|
||||
struct and_ : _op<TAO_PEGTL_STRING("&&"), 12> {};
|
||||
struct or_ : _op<TAO_PEGTL_STRING("||"), 13> {};
|
||||
struct implies : _op<TAO_PEGTL_STRING("->"), 14, kind::rightAssoc> {};
|
||||
struct pipe_right : _op<TAO_PEGTL_STRING("|>"), 15> {};
|
||||
struct pipe_left : _op<TAO_PEGTL_STRING("<|"), 16, kind::rightAssoc> {};
|
||||
};
|
||||
|
||||
struct _expr {
|
||||
@@ -521,6 +523,7 @@ struct _expr {
|
||||
app
|
||||
> {};
|
||||
|
||||
/* Order matters here. The order is the parsing order, not the precedence order: '<=' must be parsed before '<'. */
|
||||
struct _binary_operator : sor<
|
||||
operator_<op::implies>,
|
||||
operator_<op::update>,
|
||||
@@ -529,6 +532,8 @@ struct _expr {
|
||||
operator_<op::minus>,
|
||||
operator_<op::mul>,
|
||||
operator_<op::div>,
|
||||
operator_<op::pipe_right>,
|
||||
operator_<op::pipe_left>,
|
||||
operator_<op::less_eq>,
|
||||
operator_<op::greater_eq>,
|
||||
operator_<op::less>,
|
||||
@@ -649,6 +654,8 @@ struct operator_semantics {
|
||||
grammar::op::minus,
|
||||
grammar::op::mul,
|
||||
grammar::op::div,
|
||||
grammar::op::pipe_right,
|
||||
grammar::op::pipe_left,
|
||||
has_attr
|
||||
> op;
|
||||
};
|
||||
|
||||
@@ -113,6 +113,29 @@ struct ExprState
|
||||
return std::make_unique<ExprCall>(pos, std::make_unique<ExprVar>(fn), std::move(args));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expr> pipe(PosIdx pos, State & state, bool flip = false)
|
||||
{
|
||||
if (!state.xpSettings.isEnabled(Xp::PipeOperator))
|
||||
throw ParseError({
|
||||
.msg = HintFmt("Pipe operator is disabled"),
|
||||
.pos = state.positions[pos]
|
||||
});
|
||||
|
||||
// Reverse the order compared to normal function application: arg |> fn
|
||||
std::unique_ptr<Expr> fn, arg;
|
||||
if (flip) {
|
||||
fn = popExprOnly();
|
||||
arg = popExprOnly();
|
||||
} else {
|
||||
arg = popExprOnly();
|
||||
fn = popExprOnly();
|
||||
}
|
||||
std::vector<std::unique_ptr<Expr>> args{1};
|
||||
args[0] = std::move(arg);
|
||||
|
||||
return std::make_unique<ExprCall>(pos, std::move(fn), std::move(args));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expr> order(PosIdx pos, bool less, State & state)
|
||||
{
|
||||
return call(pos, state.s.lessThan, !less);
|
||||
@@ -162,6 +185,8 @@ struct ExprState
|
||||
[&] (Op::concat) { return applyBinary<ExprOpConcatLists>(pos); },
|
||||
[&] (has_attr & a) { return applyUnary<ExprOpHasAttr>(std::move(a.path)); },
|
||||
[&] (Op::unary_minus) { return negate(pos, state); },
|
||||
[&] (Op::pipe_right) { return pipe(pos, state, true); },
|
||||
[&] (Op::pipe_left) { return pipe(pos, state); },
|
||||
})(op)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -166,6 +166,16 @@ constexpr std::array<ExperimentalFeatureDetails, numXpFeatures> xpFeatureDetails
|
||||
may confuse external tooling.
|
||||
)",
|
||||
},
|
||||
{
|
||||
.tag = Xp::PipeOperator,
|
||||
.name = "pipe-operator",
|
||||
.description = R"(
|
||||
Enable new operators for function application to "pipe" arguments through a chain of functions similar to `lib.pipe`.
|
||||
This implementation is based on Nix [RFC 148](https://github.com/NixOS/rfcs/pull/148).
|
||||
|
||||
Tracking issue: https://git.lix.systems/lix-project/lix/issues/438
|
||||
)",
|
||||
},
|
||||
{
|
||||
.tag = Xp::FetchClosure,
|
||||
.name = "fetch-closure",
|
||||
|
||||
@@ -21,6 +21,7 @@ enum struct ExperimentalFeature
|
||||
NixCommand,
|
||||
RecursiveNix,
|
||||
NoUrlLiterals,
|
||||
PipeOperator,
|
||||
FetchClosure,
|
||||
ReplFlake,
|
||||
AutoAllocateUids,
|
||||
|
||||
Reference in New Issue
Block a user