diff options
-rw-r--r-- | tvix/eval/src/builtins/mod.rs | 18 | ||||
-rw-r--r-- | tvix/eval/src/errors.rs | 9 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp | 1 | ||||
-rw-r--r-- | tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix | 16 |
4 files changed, 43 insertions, 1 deletions
diff --git a/tvix/eval/src/builtins/mod.rs b/tvix/eval/src/builtins/mod.rs index dfc1986141a0..598c8aa08ece 100644 --- a/tvix/eval/src/builtins/mod.rs +++ b/tvix/eval/src/builtins/mod.rs @@ -12,7 +12,8 @@ use std::{ use crate::{ errors::ErrorKind, - value::{Builtin, CoercionKind, NixAttrs, NixList, NixString, Value}, + upvalues::UpvalueCarrier, + value::{Builtin, Closure, CoercionKind, NixAttrs, NixList, NixString, Value}, vm::VM, }; @@ -144,6 +145,21 @@ fn pure_builtins() -> Vec<Builtin> { Builtin::new("length", &[true], |args, _| { Ok(Value::Integer(args[0].to_list()?.len() as i64)) }), + Builtin::new("map", &[true, true], |args, vm| { + let list: NixList = args[1].to_list()?; + let func: Closure = args[0].to_closure()?; + + list.into_iter() + .map(|val| { + // Leave the argument on the stack before calling the + // function. + vm.push(val); + vm.call(func.lambda(), func.upvalues().clone(), 1) + }) + .collect::<Result<Vec<Value>, _>>() + .map(|list| Value::List(NixList::from(list))) + .map_err(Into::into) + }), Builtin::new("hasAttr", &[true, true], |args, _| { let k = args[0].to_str()?; let xs = args[1].to_attrs()?; diff --git a/tvix/eval/src/errors.rs b/tvix/eval/src/errors.rs index 10bc9276adde..17b236d0385f 100644 --- a/tvix/eval/src/errors.rs +++ b/tvix/eval/src/errors.rs @@ -100,6 +100,15 @@ impl From<ParseIntError> for ErrorKind { } } +/// Implementation used if errors occur while forcing thunks (which +/// can potentially be threaded through a few contexts, i.e. nested +/// thunks). +impl From<Error> for ErrorKind { + fn from(e: Error) -> Self { + Self::ThunkForce(Box::new(e)) + } +} + #[derive(Clone, Debug)] pub struct Error { pub kind: ErrorKind, diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp new file mode 100644 index 000000000000..e1ff70800245 --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.exp @@ -0,0 +1 @@ +[ [ 1 2 3 4 5 ] [ 2 4 6 8 10 ] [ 2 4 6 8 10 ] [ 1 2 3 4 5 ] ] diff --git a/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix new file mode 100644 index 000000000000..6ff42d0891dc --- /dev/null +++ b/tvix/eval/src/tests/tvix_tests/eval-okay-builtins-map.nix @@ -0,0 +1,16 @@ +[ + # identity function + (builtins.map (x: x) [ 1 2 3 4 5 ]) + + # double stuff + (builtins.map (x: x * 2) [ 1 2 3 4 5 ]) + + # same but with a closure this time + ( + let n = 2; + in builtins.map (x: x * n) [ 1 2 3 4 5 ] + ) + + # from global scope + (map (x: x) [ 1 2 3 4 5 ]) +] |