use crate::interpreter::has_tag; use crate::interpreter::is_true; use crate::parser::make_symbol; use crate::parser::Datum; use crate::parser::Datum::*; use std::io; use std::io::prelude::*; use std::mem; pub fn add(mut args: Vec) -> Datum { let mut r = 0; for i in 1..args.len() { let datum = mem::take(&mut args[i]); if let Number(n) = datum { r += n; } else { panic!("ADD -- not-all-args-are-numbers {:?}", args) } } Number(r) } pub fn mul(mut args: Vec) -> Datum { let mut r = 1; for i in 1..args.len() { let datum = mem::take(&mut args[i]); if let Number(n) = datum { r *= n; } else { panic!("MUL -- not-all-args-are-numbers {:?}", args) } } Number(r) } pub fn sub(mut args: Vec) -> Datum { if args.len() == 2 { let datum = mem::take(&mut args[1]); if let Number(n) = datum { return Number(-n); } else { panic!("SUB -- not-all-args-are-numbers {:?}", args) } } let mut r; let datum = mem::take(&mut args[1]); if let Number(n) = datum { r = n; } else { panic!("SUB -- not-all-args-are-numbers {:?}", args) } for i in 2..args.len() { let datum = mem::take(&mut args[i]); if let Number(n) = datum { r -= n; } else { panic!("SUB -- not-all-args-are-numbers {:?}", args) } } Number(r) } pub fn eq(args: Vec) -> Datum { if args.len() == 1 { Boolean(true) } else { let first = &args[1]; for i in 2..args.len() { let current = &args[i]; if first != current { return Boolean(false); } } Boolean(true) } } pub fn lt(args: Vec) -> Datum { if args.len() == 1 { Boolean(true) } else { for i in 1..(args.len() - 1) { if &args[i] >= &args[i + 1] { return Boolean(false); } } Boolean(true) } } pub fn or(args: Vec) -> Datum { if args.len() == 1 { Boolean(false) } else { for i in 1..args.len() { if is_true(&args[i]) { return args[i].clone(); } } Boolean(false) } } pub fn and(args: Vec) -> Datum { if args.len() == 1 { Boolean(true) } else { for i in 1..args.len() { if !is_true(&args[i]) { return Boolean(false); } } args[args.len() - 1].clone() } } pub fn not(args: Vec) -> Datum { if args.len() != 2 { panic!("NOT -- takes one argument"); } else { if is_true(&args[1]) { Boolean(false) } else { Boolean(true) } } } pub fn display(args: Vec) -> Datum { for i in 1..args.len() { print!("{}", args[i]); } io::stdout().flush().ok().expect("Could not flush stdout"); Unspecified } pub fn list(mut args: Vec) -> Datum { args[0] = make_symbol("list"); Datum::List(args) } pub fn cons(mut args: Vec) -> Datum { if args.len() != 3 { panic!("CONS -- two args expected {:?}", args); } let a = std::mem::take(&mut args[1]); let b = std::mem::take(&mut args[2]); match b { List(b_vec) if has_tag(&b_vec, "list") => { let mut r_vec = vec![make_symbol("list"), a]; r_vec.append(&mut b_vec[1..].to_vec()); Datum::List(r_vec) } _ => Datum::Pair(Box::new((a, b))), } } pub fn car(mut args: Vec) -> Datum { if args.len() != 2 { panic!("CAR -- expected a single arg {:?}", args); } let a = std::mem::take(&mut args[1]); match a { List(mut v) if has_tag(&v, "list") => std::mem::take(&mut v[1]), Pair(p) => p.0, _ => panic!("CAR -- could not get car {:?}", a), } } pub fn cdr(mut args: Vec) -> Datum { if args.len() != 2 { panic!("CDR -- expected a single arg {:?}", args); } let a = std::mem::take(&mut args[1]); match a { List(v) if has_tag(&v, "list") => { let mut v_cdr = v[1..].to_vec(); v_cdr[0] = make_symbol("list"); List(v_cdr) } Pair(p) => p.1, _ => panic!("CAR -- could not get car {:?}", a), } } pub fn pair(args: Vec) -> Datum { if args.len() != 2 { panic!("PAIR? -- expected a single arg {:?}", args); } match &args[1] { List(v) if has_tag(&v, "list") => { if v.len() == 1 { Boolean(false) } else { Boolean(true) } } Pair(_) => Boolean(true), _ => Boolean(false), } } pub fn null(args: Vec) -> Datum { if args.len() != 2 { panic!("PAIR? -- expected a single arg {:?}", args); } match &args[1] { List(v) if has_tag(&v, "list") => { if v.len() == 1 { Boolean(true) } else { Boolean(false) } } Pair(_) => Boolean(false), _ => Boolean(false), } }