use crate::elementary_functions::*;
use crate::types::*;
#[macro_export]
macro_rules! list {
( $head:expr ) =>{{
use $crate::elementary_functions::*;
use $crate::types::*;
let head: SExpression = $head.into();
cons(head, NIL)
}};
( $head:expr, $tail:expr ) => {{
use $crate::elementary_functions::*;
use $crate::types::*;
let head: SExpression = $head.into();
let tail: SExpression = $tail.into();
cons(head, cons(tail, NIL))
}};
( $head:expr, $($tail:expr),* ) => {{
use $crate::elementary_functions::*;
use $crate::types::*;
let head: SExpression = $head.into();
let tail: List = list!($($tail),*);
cons(head, tail)
}};
}
pub use list;
#[test]
fn test_list_macro() {
assert_eq!(list![T], cons(T, NIL));
assert_eq!(list![T, T], cons(T, cons(T, NIL)));
assert_eq!(list![1, 2, 3], cons(1, cons(2, cons(3, NIL))));
let macro_list = list![1, list![2, 3], 4];
let cons_list = cons(1, cons(cons(2, cons(3, NIL)), cons(4, NIL)));
assert_eq!(macro_list, cons_list);
}
pub fn compose_car_cdr(car_cdr_composition: &str, list: &List) -> Option<SExpression> {
if car_cdr_composition.to_lowercase() == "car" {
return Some(car(list.clone()));
} else if car_cdr_composition.to_lowercase() == "cdr" {
return Some(cdr(list.clone()));
}
let next_composition = format!(
"{}r",
&car_cdr_composition
.get(0..(car_cdr_composition.len() - 2))
.or_else(|| {
log::error!("Tried to apply {} to: {}", car_cdr_composition, list);
None
})?
);
let next_list = if car_cdr_composition.to_lowercase().ends_with("ar") {
car(list.clone())
} else if car_cdr_composition.to_lowercase().ends_with("dr") {
cdr(list.clone())
} else {
log::error!("Tried to apply {} to: {}", car_cdr_composition, list);
return None;
};
if let SExpression::List(l) = next_list {
compose_car_cdr(&next_composition, &l)
} else {
None
}
}