diff --git a/src/stl/control.rs b/src/stl/control.rs index 4a4c801..d20befc 100644 --- a/src/stl/control.rs +++ b/src/stl/control.rs @@ -20,43 +20,79 @@ use crate::eval::eval; use crate::sym::SymTable; pub fn if_callback (ast: &Seg, syms: &mut SymTable) -> Result { - if let Ctr::Seg(ref cond_form) = *ast.car { - if let Ctr::Bool(cond) = *eval(cond_form, syms)? { - if let Ctr::Seg(ref first_form) = *ast.cdr { - if cond { - match *first_form.car { - Ctr::Seg(ref first_arg) => Ok(*eval(first_arg, syms)?), - _ => Ok(*eval(&Seg::from_mono(first_form.car.clone()), syms)?), - } - } else { - if let Ctr::Seg(ref second_form) = *first_form.cdr { - match *second_form.car { - Ctr::Seg(ref second_arg) => Ok(*eval(second_arg, syms)?), - _ => Ok(*eval(&Seg::from_mono(second_form.car.clone()), syms)?), - } - } else { - Err("impossible condition: args not in standard form".to_string()) - } - } + let cond: bool; + match *ast.car { + Ctr::Seg(ref cond_form) => { + if let Ctr::Bool(cond_from_eval) = *eval(cond_form, syms)? { + cond = cond_from_eval; } else { - Err("impossible condition: not 3 args to if".to_string()) + return Err("first argument to if must evaluate to be a boolean".to_string()) + } + } + + Ctr::Bool(cond_from_car) => cond = cond_from_car, + _ => { + return Err("first argument to if must evaluate to be a boolean".to_string()) + } + } + + let then_form: &Seg; + if let Ctr::Seg(ref s) = *ast.cdr { + then_form = s; + } else { + return Err("impossible condition: not enough args to if".to_string()) + } + + if cond { + // then + match *then_form.car { + Ctr::Seg(ref first_arg) => Ok(*eval(first_arg, syms)?), + _ => { + //Ok(*eval(&Seg::from_mono(then_form.car.clone()), syms)?)}, + let eval_tree = &Seg::from_mono(then_form.car.clone()); + let eval_res = *eval(eval_tree, syms)?; + if let Ctr::Seg(ref s) = eval_res { + Ok(*s.car.clone()) + } else { + Err("impossible condition: list evals to non list".to_string()) + } + }, + } + + } else { + // else + if let Ctr::Seg(ref else_form) = *then_form.cdr { + match *else_form.car { + Ctr::Seg(ref second_arg) => Ok(*eval(second_arg, syms)?), + _ => { + //Ok(*eval(&Seg::from_mono(then_form.car.clone()), syms)?)}, + let eval_tree = &Seg::from_mono(else_form.car.clone()); + let eval_res = *eval(eval_tree, syms)?; + if let Ctr::Seg(ref s) = eval_res { + Ok(*s.car.clone()) + } else { + Err("impossible condition: list evals to non list".to_string()) + } + }, } } else { - Err("first argument to if must evaluate to be a boolean".to_string()) + Err("impossible condition: args not in standard form".to_string()) } - } else { - Err("impossible condition: not 3 args to if".to_string()) } } -fn let_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { +pub fn let_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { todo!() } -fn while_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { +pub fn while_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { todo!() } -fn map_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { +pub fn map_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { + todo!() +} + +pub fn circuit_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { todo!() } diff --git a/tests/test_lib_control.rs b/tests/test_lib_control.rs index b6d5bb4..7a1a4c1 100644 --- a/tests/test_lib_control.rs +++ b/tests/test_lib_control.rs @@ -35,6 +35,7 @@ mod control_lib_tests { if let Ctr::Integer(i) = *eval(&tree, &mut syms).unwrap() { assert_eq!(i, result); } else { + eprintln!("{}", *eval(&tree, &mut syms).unwrap()); assert!(false); } } else {