`map(fn, iter)`, eager; returns a list. Re-enters `exec_call` per item so closures with captures see the caller's chunk/slots. */
(&mut self, argc: u16, chunk: &crate::modules::parser::SSAChunk, slots: &mut [Val])
| 443 | |
| 444 | /* `map(fn, iter)`, eager; returns a list. Re-enters `exec_call` per item so closures with captures see the caller's chunk/slots. */ |
| 445 | pub fn call_map(&mut self, argc: u16, chunk: &crate::modules::parser::SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { |
| 446 | if argc < 2 { return Err(cold_type("map() must have at least two arguments")); } |
| 447 | let mut args = self.pop_n(argc as usize)?; |
| 448 | let fn_val = args.remove(0); |
| 449 | // Materialise each iterable; the parallel walk stops at the shortest, like zip. |
| 450 | let mut lists: Vec<Vec<Val>> = Vec::with_capacity(args.len()); |
| 451 | for it in args { lists.push(self.iter_to_vec_general(it)?); } |
| 452 | let n = lists.iter().map(|l| l.len()).min().unwrap_or(0); |
| 453 | let arity = lists.len() as u16; |
| 454 | let mut out: Vec<Val> = Vec::with_capacity(n); |
| 455 | for i in 0..n { |
| 456 | self.push(fn_val); |
| 457 | for l in &lists { self.push(l[i]); } |
| 458 | self.exec_call(arity, chunk, slots)?; |
| 459 | out.push(self.pop()?); |
| 460 | } |
| 461 | self.alloc_and_push_list(out) |
| 462 | } |
| 463 | |
| 464 | /* `filter(pred, iter)`, eager; keeps truthy `pred(item)`. Same call-shape as `map`. `pred=None` falls back to Python's identity-truthy filter. */ |
| 465 | pub fn call_filter(&mut self, chunk: &crate::modules::parser::SSAChunk, slots: &mut [Val]) -> Result<(), VmErr> { |
no test coverage detected