diff --git a/src/lib/environ.rs b/src/lib/environ.rs index 8b414fd..c1b1f60 100644 --- a/src/lib/environ.rs +++ b/src/lib/environ.rs @@ -63,6 +63,32 @@ pub fn default_env<'a>() -> Environ<'a> { }), ); + data.insert( + "+".to_string(), + Expr::Func(|args: &[Expr]| -> Result { + let sum = parse_list_of_floats(args)? + .iter() + .fold(0.0, |sum, a| sum + a); + + Ok(Expr::Number(sum)) + }), + ); + + data.insert( + "*".to_string(), + Expr::Func(|args: &[Expr]| -> Result { + let floats = parse_list_of_floats(args)?; + let first = *floats.first().ok_or(RispError::Reason( + "expected at least one number".to_string(), + ))?; + let sum_of_rest = floats[1..].iter().fold(0.0, |sum, a| sum + a); + + Ok(Expr::Number(first * sum_of_rest)) + }), + ); + + + data.insert("=".to_string(), Expr::Func(ensure_tonicity!(|a, b| a == b))); data.insert(">".to_string(), Expr::Func(ensure_tonicity!(|a, b| a > b))); data.insert( diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 448289b..7270440 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -1,4 +1,4 @@ -use core::fmt; +use std::fmt; use core::num::ParseFloatError; pub use std::collections::HashMap; @@ -21,7 +21,7 @@ mod evaluate; pub enum RispError { Reason(String), } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Expr { Bool(bool), Symbol(String), @@ -31,7 +31,7 @@ pub enum Expr { Func(fn(&[Expr]) -> Result), Lambda(RLambda), } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct RLambda { params_exp: Rc, body_exp: Rc, @@ -47,10 +47,14 @@ impl fmt::Display for Expr { Str(s) => format!("\"{}\"", s), List(list) => { let xs: Vec = list.iter().map(|x| x.to_string()).collect(); - format!("({})", xs.join(",")) + format!("({})", xs.join(" ")) + } + Func(func) => { + format!("({:?})", func) + } + Lambda(lambda) => { + format!("(fn {} {})", lambda.params_exp, lambda.body_exp) } - Func(_) => "Function {}".to_string(), - Lambda(_) => "Lambda {}".to_string(), }; write!(f, "{}", str) diff --git a/src/lib/parser.rs b/src/lib/parser.rs index d889d9a..35df025 100644 --- a/src/lib/parser.rs +++ b/src/lib/parser.rs @@ -44,7 +44,7 @@ fn parse_atom(token: &str) -> Expr { let potential_float: Result = token.parse(); match potential_float { Ok(v) => Number(v), - Err(er) => { + Err(_er) => { if token.to_string().starts_with("\"") && token.to_string().ends_with("\""){ let mut stri = token.to_string().clone(); stri.remove(0); diff --git a/src/main.rs b/src/main.rs index 2f645e7..937cf17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,4 @@ -use std::collections::HashMap; -use std::fmt; +#![allow(special_module_name)] use std::io; use std::io::Write; @@ -20,29 +19,44 @@ fn slurp_expr() -> String { fn extend_environ<'a>(mut env: Environ<'a>) -> Environ<'a> { env.data.insert( "quit".to_string(), - Expr::Func(|args: &[Expr]| -> Result { + Expr::Func(|_args: &[Expr]| -> Result { // TODO: let this function take in arguments println!("Exiting."); std::process::exit(0); + #[allow(unreachable_code)] Err(RispError::Reason("Cannot exit process".to_string())) }), ); env.data.insert( "prompt".to_string(), - Expr::Symbol("risp => ".to_string()), + Expr::Symbol("rlisp => ".to_string()), ); -env + + env.data.insert( + "print".to_string(), + Expr::Func(|args: &[Expr]| -> Result { + let mut stri = String::new(); + for arg in args { + let fmted = format!("{}", arg); + stri.push_str(&fmted); + stri.push_str(" ") + } + + Ok(Expr::Symbol(stri.to_string())) + }), + ); + env } fn main() { - let mut env = &mut default_env(); - let mut env = &mut extend_environ(env.clone()); + let env = &mut default_env(); + let env = &mut extend_environ(env.clone()); loop { - let prompt = env_get("prompt", env).unwrap_or(lib::Expr::Symbol("risp => ".to_string())); + let prompt = env_get("prompt", env).unwrap_or(lib::Expr::Symbol("rlisp => ".to_string())); print!("{}", prompt); let _ = std::io::stdout().flush(); let expr = slurp_expr();