feat: reduce + fold
This commit is contained in:
parent
a2210f2db3
commit
285b93aa89
1 changed files with 60 additions and 2 deletions
|
@ -285,8 +285,62 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
|
|||
|
||||
Node::List(res)
|
||||
}
|
||||
Node::Reduce(mut body) => todo!(),
|
||||
Node::Fold(mut body) => todo!(),
|
||||
Node::Reduce(mut body) => {
|
||||
if body.len() != 2 {
|
||||
todo!();
|
||||
}
|
||||
|
||||
let list = body.pop_front().expect("arg count verified above");
|
||||
let mut 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,
|
||||
node @ Node::Symbol(_) => eval_node(env, node)?,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
let mut acc = match list.pop_front() {
|
||||
Some(node) => eval_node(env, node)?,
|
||||
None => Node::Nil,
|
||||
};
|
||||
|
||||
while let Some(node) = list.pop_front() {
|
||||
let node = eval_node(env, node)?;
|
||||
acc = eval_node(env, Node::List(vec![func.clone(), acc, node].into()))?;
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
|
||||
Node::Fold(mut body) => {
|
||||
if body.len() != 3 {
|
||||
todo!();
|
||||
}
|
||||
|
||||
let list = body.pop_front().expect("arg count verified above");
|
||||
let mut list = match eval_node(env, list)? {
|
||||
Node::List(list) => list,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
let mut acc = body.pop_front().expect("arg count verified above");
|
||||
|
||||
let func = match body.pop_front().expect("arg count verified above") {
|
||||
node @ Node::Function(_) => node,
|
||||
node @ Node::Symbol(_) => eval_node(env, node)?,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
while let Some(node) = list.pop_front() {
|
||||
let node = eval_node(env, node)?;
|
||||
acc = eval_node(env, Node::List(vec![func.clone(), acc, node].into()))?;
|
||||
}
|
||||
|
||||
acc
|
||||
}
|
||||
|
||||
Node::Symbol(sym) => env
|
||||
.get_node(&sym)
|
||||
|
@ -484,6 +538,10 @@ mod test {
|
|||
// Iteration
|
||||
#[case("(map '(1 2 3) (fn* (x) (* x x)))", "(1 4 9)")]
|
||||
#[case("(filter '(1 2 3) (fn* (x) (> x 1)))", "(2 3)")]
|
||||
#[case("(reduce '(1 2 3 4) +)", "10")]
|
||||
#[case("(reduce '(1 2 3 4) (fn* (lhs rhs) (+ lhs rhs)))", "10")]
|
||||
#[case("(fold '(1 2 3 4) 5 +)", "15")]
|
||||
#[case("(fold '(1 2 3 4) 5 (fn* (lhs rhs) (+ lhs rhs)))", "15")]
|
||||
fn test_evaluator(#[case] input: &str, #[case] expected: &str) {
|
||||
dbg!(input);
|
||||
|
||||
|
|
Loading…
Reference in a new issue