diff --git a/mute-interpreter/src/evaluator.rs b/mute-interpreter/src/evaluator.rs index ec2a137..5ebb6f5 100644 --- a/mute-interpreter/src/evaluator.rs +++ b/mute-interpreter/src/evaluator.rs @@ -258,7 +258,33 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result { Node::List(list) } - Node::Filter(mut body) => todo!(), + Node::Filter(mut body) => { + if body.len() != 2 { + todo!(); + } + + let list = body.pop_front().expect("arg count verified above"); + let list = match eval_node(env, list)? { + Node::List(list) => list, + _ => todo!(), + }; + + let func = match body.pop_front().expect("arg count verified above") { + node @ Node::Function(_) => node, + _ => todo!(), + }; + + let mut res = VecDeque::new(); + for node in list { + if let Node::Boolean(true) = + eval_node(env, Node::List(vec![func.clone(), node.clone()].into()))? + { + res.push_back(node); + } + } + + Node::List(res) + } Node::Reduce(mut body) => todo!(), Node::Fold(mut body) => todo!(), @@ -455,6 +481,9 @@ mod test { #[case("(pop-back (list 1 2 3))", "(1 2)")] #[case("(push-back [1 2 3] 4)", "[1 2 3 4]")] #[case("(pop-back [1 2 3 4])", "[1 2 3]")] + // Iteration + #[case("(map '(1 2 3) (fn* (x) (* x x)))", "(1 4 9)")] + #[case("(filter '(1 2 3) (fn* (x) (> x 1)))", "(2 3)")] fn test_evaluator(#[case] input: &str, #[case] expected: &str) { dbg!(input);