use std::{collections::HashMap, fmt}; use crate::PreLispValue; pub struct LispState { table: HashMap, } fn add_function + Clone>(table: &mut HashMap, name: T, func: fn(Vec) -> Vec) { table.insert(name.clone().into(), LispValue::RustFunction(name.into(), func)); } #[derive(Debug, Clone)] pub enum LispValue { Nil, String(String), Integer(i32), Float(f32), List(Vec, bool), LispFunction(String, Vec), RustFunction(String, fn(Vec) -> Vec), } impl fmt::Display for LispValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { LispValue::Nil => write!(f, "nil"), LispValue::String(str) => write!(f, "{}", str), LispValue::LispFunction(name, _) => write!(f, "<'{}': Lisp Function>", name), LispValue::RustFunction(name, _) => write!(f, "<'{}': Rust Function>", name), LispValue::Integer(num) => write!(f, "{}", num), LispValue::Float(num) => write!(f, "{}", num), val => { write!(f, "{}", format!("{:?}", val)) } } } } impl From<&str> for LispValue { fn from(value: &str) -> Self { LispValue::String(value.to_string()) } } impl From for LispValue { fn from(value: String) -> Self { LispValue::String(value) } } impl From for LispValue { fn from(value: i32) -> Self { LispValue::Integer(value) } } impl From for LispValue { fn from(value: f32) -> Self { LispValue::Float(value) } } impl LispState { pub fn new() -> LispState { let mut table = HashMap::new(); add_function(&mut table, "print", |x| { let mut strings = Vec::new(); for val in x { strings.push(val.to_string()); } let str = strings.join(" "); println!("{}", str); vec![LispValue::Nil] }); add_function(&mut table, "concat", |x| { let mut strings = Vec::new(); for val in x { strings.push(val.to_string()); } let str = strings.concat(); vec![LispValue::String(str)] }); add_function(&mut table, "add", |x| { if x.len() < 1 { return vec![LispValue::Nil] } else if x.len() == 1 { return vec![x[0].clone()]; } let mut t = "int"; for v in &x { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), _ => return vec![LispValue::Nil] } } match t { "int" => { let mut sum = 0; for v in &x { if let LispValue::Integer(n) = v { sum += n; } else { unreachable!() } } return vec![LispValue::Integer(sum)]; }, "float" => { let mut sum = 0.0 as f32; for v in &x { if let LispValue::Float(n) = v { sum += n; } else if let LispValue::Integer(n) = v{ sum += *n as f32; } else { unreachable!() } } return vec![LispValue::Float(sum)]; }, _ => unreachable!() } }); add_function(&mut table, "sub", |x| { if x.len() < 1 { return vec![LispValue::Nil] } else if x.len() == 1 { return vec![x[0].clone()]; } let mut t = "int"; for v in &x { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), _ => return vec![LispValue::Nil] } } match t { "int" => { if let LispValue::Integer(n) = x[0] { let mut sum = n; for i in 1..x.len() { if let LispValue::Integer(n) = &x[i] { sum -= n; } else { unreachable!() } } return vec![LispValue::Integer(sum)]; } else { unreachable!() } }, "float" => { if let LispValue::Float(n) = x[0] { let mut sum = n; for i in 1..x.len() { if let LispValue::Float(n) = &x[i] { sum -= *n; } else if let LispValue::Integer(n) = &x[i] { sum -= *n as f32; } else { unreachable!() } } return vec![LispValue::Float(sum)]; } else if let LispValue::Integer(n) = x[0] { let mut sum = n as f32; for i in 1..x.len() { if let LispValue::Float(n) = &x[i] { sum -= *n; } else if let LispValue::Integer(n) = &x[i] { sum -= *n as f32; } else { unreachable!() } } return vec![LispValue::Float(sum)]; } { unreachable!() } }, _ => unreachable!() } }); add_function(&mut table, "mul", |x| { if x.len() < 1 { return vec![LispValue::Nil] } else if x.len() == 1 { return vec![x[0].clone()]; } let mut t = "int"; for v in &x { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), _ => return vec![LispValue::Nil] } } match t { "int" => { if let LispValue::Integer(n) = x[0] { let mut sum = n; for i in 1..x.len() { if let LispValue::Integer(n) = &x[i] { sum *= n; } else { unreachable!() } } return vec![LispValue::Integer(sum)]; } else { unreachable!() } }, "float" => { if let LispValue::Float(n) = x[0] { let mut product = n; for i in 1..x.len() { if let LispValue::Float(n) = &x[i] { product *= *n; } else if let LispValue::Integer(n) = &x[i] { product *= *n as f32; } else { unreachable!() } } return vec![LispValue::Float(product)]; } else if let LispValue::Integer(n) = x[0] { let mut product = n as f32; for i in 1..x.len() { if let LispValue::Float(n) = &x[i] { product *= *n; } else if let LispValue::Integer(n) = &x[i] { product *= *n as f32; } else { unreachable!() } } return vec![LispValue::Float(product)]; } { unreachable!() } }, _ => unreachable!() } }); add_function(&mut table, "div", |x| { if x.len() < 1 { return vec![LispValue::Nil] } else if x.len() == 1 { return vec![x[0].clone()]; } let mut t = "int"; for v in &x { match v { LispValue::Float(_) => t = "float", LispValue::Integer(_) => (), _ => return vec![LispValue::Nil] } } match t { "int" => { if let LispValue::Integer(n) = x[0] { let mut sum = n; for i in 1..x.len() { if let LispValue::Integer(n) = &x[i] { sum /= n; } else { unreachable!() } } return vec![LispValue::Integer(sum)]; } else { unreachable!() } }, "float" => { if let LispValue::Float(n) = x[0] { let mut product = n; for i in 1..x.len() { if let LispValue::Float(n) = &x[i] { product /= *n; } else if let LispValue::Integer(n) = &x[i] { product /= *n as f32; } else { unreachable!() } } return vec![LispValue::Float(product)]; } else if let LispValue::Integer(n) = x[0] { let mut product = n as f32; for i in 1..x.len() { if let LispValue::Float(n) = &x[i] { product /= *n; } else if let LispValue::Integer(n) = &x[i] { product /= *n as f32; } else { unreachable!() } } return vec![LispValue::Float(product)]; } { unreachable!() } }, _ => unreachable!() } }); LispState { table } } fn handle_prevalues(&self, input: Vec) -> Vec { let mut out = Vec::new(); for v in input { out.push(match v { PreLispValue::Nil => LispValue::Nil, PreLispValue::String(str) => LispValue::String(str), PreLispValue::Integer(num) => LispValue::Integer(num), PreLispValue::Float(num) => LispValue::Float(num), PreLispValue::List(list, quoted) => { LispValue::List(Self::handle_prevalues(self, list), quoted) }, PreLispValue::LispFunction(name, instructions) => { LispValue::LispFunction(name, Self::handle_prevalues(self, instructions)) }, PreLispValue::Var(name) => { self.table.get(&name).unwrap_or(&LispValue::Nil).to_owned() } }) } out } fn eval_list(list: &Vec, quoted: bool) -> (Vec, bool) { if list.len() < 1 { return (vec![LispValue::List(Vec::new(), quoted)], false); } let list = &mut list.clone(); for i in 0..list.len() { if let LispValue::List(elements, quoted) = &list[i] { let (elems, astuple) = Self::eval_list(elements, *quoted); if astuple { list[i] = elems.get(0).unwrap_or(&LispValue::Nil).to_owned(); for j in 1..elems.len() { list.insert(i, elems[j].to_owned()); } } else { list[i] = LispValue::List(elems, *quoted); } } } if quoted { return (list.to_vec(), false); } if let LispValue::RustFunction(_name, f) = &list[0] { (f(list[1..].to_vec()), true) } else if let LispValue::LispFunction(_name, ins) = &list[0] { (Self::call_lisp_func(&list[0], list[1..].to_vec()), true) } else { (list.to_vec(), false) } } fn call_lisp_func(f: &LispValue, args: Vec) -> Vec { todo!() } pub fn execute(&self, instructions: Vec) { let instructions = Self::handle_prevalues(self, instructions); for val in instructions { if let LispValue::List(elements, quoted) = val { Self::eval_list(&elements, quoted); } } } }