feat(tvix/eval): implement builtins.map
As we already have a VM passed to the builtins, we can simply execute the provided closure/lambda in it for each value. The primary annoyance with this is that we have to clone the upvalues for each element, but we can try making this cheaper in the future (it's also a general problem in the VM itself). Change-Id: I5bcf56d58c509c0eb081e7cf52f6093216451ce4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6714 Tested-by: BuildkiteCI Reviewed-by: sterni <sternenseemann@systemli.org>
This commit is contained in:
parent
8207977648
commit
876c477256
4 changed files with 43 additions and 1 deletions
|
|
@ -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()?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue