Skip to content

Commit

Permalink
Merge pull request #1083 from tweag/nix/update
Browse files Browse the repository at this point in the history
Implementation of the update operator for nix/nickel
  • Loading branch information
francois-caddet authored Jan 30, 2023
2 parents b81e298 + 12267c2 commit 3763151
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/nix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl ToNickel for NixBinOp {
match self.operator().unwrap() {
Concat => make::op2(BinaryOp::ArrayConcat(), lhs, rhs),
// TODO: the Nix `//` operator.
Update => unimplemented!(),
Update => mk_app!(crate::stdlib::compat::update(), lhs, rhs),

// Use a compatibility function to be able to merge strings with the same operator used
// for addition.
Expand Down
8 changes: 8 additions & 0 deletions src/stdlib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ pub mod compat {
use crate::term::make::op1;
use crate::term::{array::Array, Term, UnaryOp};

/// helper function to perform a Nix like update (`//` operator).
pub fn update() -> RichTerm {
op1(
UnaryOp::StaticAccess("update_all".into()),
Term::Var("compat".into()),
)
}

/// helper function to check if a record has a nested field.
pub fn has_field_path() -> RichTerm {
op1(
Expand Down
8 changes: 8 additions & 0 deletions stdlib/compat.ncl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ compat | doc "Nix compatibility layer. This library should not be used by Nickel
then a ++ b
else a + b,

# The update operator of Nix `//`. It's a "general form" of the `record.update` of Nickel.
# TODO: May be intresting to be addapted and integrated the the actual Nickel stdlib.
update_all = fun r1 r2 =>
array.fold
(fun key acc => record.update key r2."%{key}" acc)
r1
(record.fields r2),

has_field_path = fun fields record =>
%length% fields == 0 || # Because it's only used by generated code, this length will never be initialy 0. So if it's 0, it mean the end of the path.
(
Expand Down
5 changes: 5 additions & 0 deletions tests/nix/records.nix
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@
({ a.b = "ab"; }.a or "x" == { b = "ab"; })
({ a.b = "ab"; }.a.b or "x" == "ab")
({ a.b = "ab"; }.a.c or "x" == "x")

# the '//' update operator.
({ a = 1; b = 2; } // { b = 3; c = 4; } == { a = 1; b = 3; c = 4; })
(let r = { a = 1; }; in r // { } == r)
(let r = { a = 1; }; in { } // r == r)
]

0 comments on commit 3763151

Please sign in to comment.