diff options
author | piegames <git@piegames.de> | 2024-08-08 18:15:21 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@localhost> | 2024-08-08 18:15:21 +0000 |
commit | e03cd8b3a6f70c60f359fd683c2b25f8eba4da0d (patch) | |
tree | b0c6684b42343e073a9c3cd65db9ddbccceeccd4 /src | |
parent | a957219df2b7f360695f884f45fe4802240b9755 (diff) | |
parent | 28ae24f3f738a50903bd9b9bf8eece84a1075c30 (diff) |
Merge "libexpr: Add experimental pipe operator" into main
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/parser/grammar.hh | 7 | ||||
-rw-r--r-- | src/libexpr/parser/parser.cc | 25 | ||||
-rw-r--r-- | src/libutil/experimental-features.cc | 10 | ||||
-rw-r--r-- | src/libutil/experimental-features.hh | 1 |
4 files changed, 43 insertions, 0 deletions
diff --git a/src/libexpr/parser/grammar.hh b/src/libexpr/parser/grammar.hh index 82df63bc5..2c5a3d1be 100644 --- a/src/libexpr/parser/grammar.hh +++ b/src/libexpr/parser/grammar.hh @@ -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; }; diff --git a/src/libexpr/parser/parser.cc b/src/libexpr/parser/parser.cc index 68aa3ddc5..6d496d141 100644 --- a/src/libexpr/parser/parser.cc +++ b/src/libexpr/parser/parser.cc @@ -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) }; } diff --git a/src/libutil/experimental-features.cc b/src/libutil/experimental-features.cc index 3a834293a..15a18c770 100644 --- a/src/libutil/experimental-features.cc +++ b/src/libutil/experimental-features.cc @@ -167,6 +167,16 @@ constexpr std::array<ExperimentalFeatureDetails, numXpFeatures> xpFeatureDetails )", }, { + .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", .description = R"( diff --git a/src/libutil/experimental-features.hh b/src/libutil/experimental-features.hh index 38889e7bc..121318d23 100644 --- a/src/libutil/experimental-features.hh +++ b/src/libutil/experimental-features.hh @@ -21,6 +21,7 @@ enum struct ExperimentalFeature NixCommand, RecursiveNix, NoUrlLiterals, + PipeOperator, FetchClosure, ReplFlake, AutoAllocateUids, |