From ce3dba470af263218e986acf3d82503ad8bf8762 Mon Sep 17 00:00:00 2001 From: Ava Hahn Date: Thu, 9 Mar 2023 17:28:17 -0800 Subject: [PATCH] add boolean cast function --- Readme.org | 2 - src/stl.rs | 11 +++++ src/stl/boolean.rs | 26 +++++++++++ tests/test_lib_bools.rs | 96 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 2 deletions(-) diff --git a/Readme.org b/Readme.org index c6f5a2e..a0479f2 100644 --- a/Readme.org +++ b/Readme.org @@ -301,8 +301,6 @@ This contains any executable target of this project. Notably the main shell file Note: this section will not show the status of each item unless you are viewing it with a proper orgmode viewer. Note: this section only tracks the state of incomplete TODO items. Having everything on here would be cluttered. -*** TODO append -> cons -*** TODO bool cast *** TODO Quote function *** TODO Eval function *** TODO lambda diff --git a/src/stl.rs b/src/stl.rs index b8713a1..39bd96e 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -162,6 +162,17 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> { }, ); + syms.insert( + "bool".to_string(), + Symbol { + name: String::from("bool"), + args: Args::Infinite, + conditional_branches: false, + docs: boolean::BOOLCAST_DOCSTRING.to_string(), + value: ValueType::Internal(Rc::new(boolean::boolcast_callback)), + }, + ); + syms.insert( "or".to_string(), Symbol { diff --git a/src/stl/boolean.rs b/src/stl/boolean.rs index 1b2a99e..25d7c4e 100644 --- a/src/stl/boolean.rs +++ b/src/stl/boolean.rs @@ -117,3 +117,29 @@ pub fn toggle_callback(ast: &Seg, syms: &mut SymTable) -> Result { syms.insert(var_name, sym); Ok(Ctr::None) } + + +pub const BOOLCAST_DOCSTRING: &str = "takes one argument of any type. +attempts to cast argument to a bool. +Strings will cast to a bool if they are 'true' or 'false'. +Integers and Floats will cast to true if they are 0 and false otherwise."; + +pub fn boolcast_callback(ast: &Seg, _syms: &mut SymTable) -> Result { + match &*ast.car { + Ctr::Bool(_) => Ok(*ast.car.clone()), + Ctr::Symbol(_) => Err("not clear how to cast a symbol to a bool".to_string()), + Ctr::String(s) => { + if s == "true" { + Ok(Ctr::Bool(true)) + } else if s == "false" { + Ok(Ctr::Bool(false)) + } else { + Err("string cannot be parsed as a bool".to_string()) + } + }, + Ctr::Integer(i) => Ok(Ctr::Bool(*i == 0)), + Ctr::Float(f) => Ok(Ctr::Bool(*f == 0.0)), + Ctr::Seg(_) => Err("cannot convert list to a boolean".to_string()), + Ctr::None => Err("Impossible task: cannot convert none to bool".to_string()), + } +} diff --git a/tests/test_lib_bools.rs b/tests/test_lib_bools.rs index 87b9ea8..7c15761 100644 --- a/tests/test_lib_bools.rs +++ b/tests/test_lib_bools.rs @@ -321,4 +321,100 @@ mod bool_lib_tests { panic!() } } + + #[test] + fn test_boolcast_str_t() { + let document = "(bool 'true')"; + let test = lex(&document.to_string()).unwrap(); + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + + if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() { + assert!(b) + } else { + panic!() + } + } + + #[test] + fn test_boolcast_str_f() { + let document = "(bool 'false')"; + let test = lex(&document.to_string()).unwrap(); + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + + if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() { + assert!(!b) + } else { + panic!() + } + } + + #[test] + fn test_boolcast_int_t() { + let document = "(bool 0)"; + let test = lex(&document.to_string()).unwrap(); + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + + if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() { + assert!(b) + } else { + panic!() + } + } + + #[test] + fn test_boolcast_int_f() { + let document = "(bool 12)"; + let test = lex(&document.to_string()).unwrap(); + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + + if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() { + assert!(!b) + } else { + panic!() + } + } + + #[test] + fn test_boolcast_float_t() { + let document = "(bool 0.0)"; + let test = lex(&document.to_string()).unwrap(); + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + + if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() { + assert!(b) + } else { + panic!() + } + } + + #[test] + fn test_boolcast_float_f() { + let document = "(bool 1.2)"; + let test = lex(&document.to_string()).unwrap(); + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(&mut syms).unwrap(); + + if let Ctr::Bool(b) = *eval(&test, &mut syms).unwrap() { + assert!(!b) + } else { + panic!() + } + } }