diff --git a/src/clojure_std/thread.rs b/src/clojure_std/thread.rs index da4de4f..545b0d9 100644 --- a/src/clojure_std/thread.rs +++ b/src/clojure_std/thread.rs @@ -1,13 +1,9 @@ -use crate::value::{ToValue, Value}; -use std::rc::Rc; -use crate::ifn::IFn; -use std::io::Read; -use std::error::Error; use crate::error_message; -use nom::lib::std::convert::TryFrom; +use crate::ifn::IFn; use crate::type_tag::TypeTag; +use crate::value::{ToValue, Value}; +use std::rc::Rc; -use std::thread; use std::time; /// provides a sleep function to sleep for given amount of ms @@ -25,14 +21,14 @@ impl IFn for SleepFn { let arg = &**args.get(0).unwrap(); match arg { Value::I32(i) => { - std::thread::sleep(time::Duration::new(0, (*i as u32) * 1000000)); - return Value::Nil - }, - _ => error_message::type_mismatch(TypeTag::I32, args.get(0).unwrap()) + std::thread::sleep(time::Duration::new(0, (*i as u32) * 100_0000)); + Value::Nil + } + _ => error_message::type_mismatch(TypeTag::I32, args.get(0).unwrap()), } } else { error_message::wrong_arg_count(1, args.len()); - return Value::Nil + Value::Nil } } -} \ No newline at end of file +} diff --git a/src/clojure_std/time.rs b/src/clojure_std/time.rs index 022e148..0bb06eb 100644 --- a/src/clojure_std/time.rs +++ b/src/clojure_std/time.rs @@ -1,13 +1,8 @@ +use crate::error_message; +use crate::ifn::IFn; use crate::value::{ToValue, Value}; use std::rc::Rc; -use crate::ifn::IFn; -use std::io::Read; -use std::error::Error; -use crate::error_message; -use nom::lib::std::convert::TryFrom; -use crate::type_tag::TypeTag; -use std::thread; use std::time::{SystemTime, UNIX_EPOCH}; /// provides a function to return current time in nanoseconds @@ -21,12 +16,15 @@ impl ToValue for NanoTimeFn { impl IFn for NanoTimeFn { fn invoke(&self, args: Vec>) -> Value { - if args.len() == 0 { - let ns = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos(); - return Value::F64(ns as f64) + if args.is_empty() { + let ns = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_nanos(); + Value::F64(ns as f64) } else { error_message::wrong_arg_count(0, args.len()); - return Value::Nil + Value::Nil } } -} \ No newline at end of file +} diff --git a/src/environment.rs b/src/environment.rs index 897a462..ed12b0b 100644 --- a/src/environment.rs +++ b/src/environment.rs @@ -1,8 +1,7 @@ +use crate::clojure_std; use crate::namespace::{Namespace, Namespaces}; -use crate::repl; use crate::repl::Repl; use crate::rust_core; -use crate::clojure_std; use crate::symbol::Symbol; use crate::value::{ToValue, Value}; @@ -118,12 +117,15 @@ impl Environment { environment.insert(Symbol::intern("eval"), eval_fn.to_rc_value()); // Thread namespace TODO / instead of _ - environment.insert(Symbol::intern("Thread_sleep"), thread_sleep_fn.to_rc_value()); + environment.insert( + Symbol::intern("Thread_sleep"), + thread_sleep_fn.to_rc_value(), + ); environment.insert(Symbol::intern("System_nanotime"), nanotime_fn.to_rc_value()); // core.clj wraps calls to the rust implementations - // @TODO add this to clojure.rs.core namespace as clojure.rs.core/slurp + // @TODO add this to clojure.rs.core namespace as clojure.rs.core/slurp environment.insert(Symbol::intern("rust-slurp"), slurp_fn.to_rc_value()); environment.insert(Symbol::intern("+"), add_fn.to_rc_value()); @@ -141,7 +143,7 @@ impl Environment { lexical_eval_fn.to_rc_value(), ); environment.insert(Symbol::intern("nth"), nth_fn.to_rc_value()); - environment.insert(Symbol::intern("assoc"), assoc_fn.to_rc_value()); + environment.insert(Symbol::intern("assoc"), assoc_fn.to_rc_value()); environment.insert(Symbol::intern("concat"), concat_fn.to_rc_value()); environment.insert( Symbol::intern("print-string"), diff --git a/src/error_message.rs b/src/error_message.rs index f22f4eb..2a6f77d 100644 --- a/src/error_message.rs +++ b/src/error_message.rs @@ -1,36 +1,33 @@ use crate::type_tag::TypeTag; use crate::value::Value; -use nom::Err; -use nom::error::ErrorKind; use std::error::Error; pub fn type_mismatch(expected: TypeTag, got: &Value) -> Value { Value::Condition(format!( "Type mismatch; Expected instance of {}, Recieved type {}", - expected, - got + expected, got )) } pub fn wrong_arg_count(expected: usize, got: usize) -> Value { Value::Condition(format!( "Wrong number of arguments given to function (Given: {}, Expected: {})", - got, - expected + got, expected )) } pub fn wrong_varg_count(expected: &[usize], got: usize) -> Value { Value::Condition(format!( "Wrong number of arguments given to function (Given: {}, Expected: {:?})", - got, - expected + got, expected )) } pub fn zero_arg_count(got: usize) -> Value { Value::Condition(format!( - "Wrong number of arguments given to function (Given: {})", got)) + "Wrong number of arguments given to function (Given: {})", + got + )) } pub fn index_out_of_bounds(ind: usize, count: usize) -> Value { @@ -44,6 +41,6 @@ pub fn index_cannot_be_negative(ind: usize) -> Value { Value::Condition(format!("Index cannot be negative; Index ({})", ind)) } -pub fn generic_err(error: Box) -> Value { - Value::Condition(format!("{}", error.to_string())) -} \ No newline at end of file +pub fn generic_err(error: Box) -> Value { + Value::Condition(error.to_string()) +} diff --git a/src/persistent_list_map.rs b/src/persistent_list_map.rs index c58ce9d..78336b5 100644 --- a/src/persistent_list_map.rs +++ b/src/persistent_list_map.rs @@ -176,7 +176,6 @@ mod tests { #[test] fn test_persistent_list_map() { - let empty = PersistentListMap::Empty; let map1 = vec![ MapEntry { key: Symbol::intern("a").to_rc_value(), diff --git a/src/reader.rs b/src/reader.rs index a69050e..b18fba5 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -10,21 +10,19 @@ use nom::{ branch::alt, bytes::complete::tag, map, sequence::preceded, take_until, terminated, - Err::Incomplete, IResult, Needed, + Err::Incomplete, IResult, }; +use crate::keyword::Keyword; use crate::maps::MapEntry; use crate::persistent_list::ToPersistentList; use crate::persistent_list_map::ToPersistentListMap; use crate::persistent_vector::ToPersistentVector; use crate::symbol::Symbol; -use crate::keyword::Keyword; use crate::value::{ToValue, Value}; use std::rc::Rc; use std::io::BufRead; -use nom::Err::Error; -use nom::error::ErrorKind; // // Note; the difference between ours 'parsers' // identifier_parser @@ -78,7 +76,7 @@ fn cons_str(head: char, tail: &str) -> String { //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// -// +// // Predicates // //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -150,12 +148,12 @@ fn is_clojure_whitespace(c: char) -> bool { c.is_whitespace() || c == ',' } //////////////////////////////////////////////////////////////////////////////////////////////////// -// End predicates +// End predicates //////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Parsers +// +// Parsers // ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -290,11 +288,10 @@ pub fn try_read_i32(input: &str) -> IResult<&str, Value> { /// false => Value::Boolean(false) pub fn try_read_bool(input: &str) -> IResult<&str, Value> { named!(bool_parser<&str,&str>, alt!( tag!("true") | tag!("false"))); - let (rest_input,bool) = bool_parser(input)?; + let (rest_input, bool) = bool_parser(input)?; Ok((rest_input, Value::Boolean(bool.parse().unwrap()))) } - /// Tries to parse &str into Value::double /// pub fn try_read_f64(input: &str) -> IResult<&str, Value> { @@ -302,20 +299,20 @@ pub fn try_read_f64(input: &str) -> IResult<&str, Value> { } // Perhaps generalize this into reader macros -/// Tries to parse &str into Value::Keyword +/// Tries to parse &str into Value::Keyword /// Example Successes: /// :a => Value::Keyword(Keyword { sym: Symbol { name: "a" }) -/// :cat-dog => Value::Keyword(Keyword { sym: Symbol { name: "cat-dog" }) +/// :cat-dog => Value::Keyword(Keyword { sym: Symbol { name: "cat-dog" }) /// Example Failures: -/// :12 :'a +/// :12 :'a pub fn try_read_keyword(input: &str) -> IResult<&str, Value> { named!(keyword_colon<&str, &str>, preceded!(consume_clojure_whitespaces_parser, tag!(":"))); let (rest_input, _) = keyword_colon(input)?; - let (rest_input,symbol) = symbol_parser(rest_input)?; + let (rest_input, symbol) = symbol_parser(rest_input)?; let keyword_value = Keyword { sym: symbol }.to_value(); - Ok((rest_input,keyword_value)) + Ok((rest_input, keyword_value)) } /// Tries to parse &str into Value::Symbol @@ -421,28 +418,34 @@ pub fn try_read_list(input: &str) -> IResult<&str, Value> { pub fn try_read_quoted(input: &str) -> IResult<&str, Value> { named!(quote<&str, &str>, preceded!(consume_clojure_whitespaces_parser, tag!("'"))); - let (form,_) = quote(input)?; + let (form, _) = quote(input)?; - let (rest_input,quoted_form_value) = try_read(form)?; + let (rest_input, quoted_form_value) = try_read(form)?; - // (quote value) - Ok((rest_input, - vec![Symbol::intern("quote").to_rc_value(), - quoted_form_value .to_rc_value()].into_list().to_value())) + // (quote value) + Ok(( + rest_input, + vec![ + Symbol::intern("quote").to_rc_value(), + quoted_form_value.to_rc_value(), + ] + .into_list() + .to_value(), + )) } pub fn try_read(input: &str) -> IResult<&str, Value> { preceded( consume_clojure_whitespaces_parser, alt(( - try_read_quoted, + try_read_quoted, try_read_map, try_read_string, try_read_f64, try_read_i32, try_read_bool, try_read_symbol, - try_read_keyword, + try_read_keyword, try_read_list, try_read_vector, )), @@ -454,7 +457,7 @@ pub fn try_read(input: &str) -> IResult<&str, Value> { //////////////////////////////////////////////////////////////////////////////////////////////////// // -// Readers +// Readers // /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -471,7 +474,9 @@ pub fn read(reader: &mut R) -> Value { match maybe_line { Some(Err(e)) => return Value::Condition(format!("Reader error: {}", e)), Some(Ok(line)) => input_buffer.push_str(&line), - None => return Value::Condition(format!("Tried to read empty stream; unexpected EOF")), + None => { + return Value::Condition(String::from("Tried to read empty stream; unexpected EOF")) + } } let line_read = try_read(&input_buffer); @@ -594,7 +599,7 @@ mod tests { } mod integer_parser_tests { - use crate::reader::{integer_parser}; + use crate::reader::integer_parser; #[test] fn integer_parser_parses_integer_one() { @@ -623,8 +628,8 @@ mod tests { } mod try_read_bool_tests { - use crate::value::Value; use crate::reader::try_read_bool; + use crate::value::Value; #[test] fn try_read_boolean_true_test() { @@ -633,7 +638,10 @@ mod tests { #[test] fn try_read_boolean_false_test() { - assert_eq!(Value::Boolean(false), try_read_bool("false ").ok().unwrap().1); + assert_eq!( + Value::Boolean(false), + try_read_bool("false ").ok().unwrap().1 + ); } } @@ -654,7 +662,6 @@ mod tests { } mod try_read_tests { - use crate::maps::MapEntry; use crate::persistent_list; use crate::persistent_list_map; use crate::persistent_vector; @@ -662,7 +669,6 @@ mod tests { use crate::symbol::Symbol; use crate::value::Value; use crate::value::Value::{PersistentList, PersistentListMap, PersistentVector}; - use std::rc::Rc; #[test] fn try_read_empty_map_test() { @@ -743,18 +749,12 @@ mod tests { #[test] fn try_read_bool_true_test() { - assert_eq!( - Value::Boolean(true), - try_read("true ").ok().unwrap().1 - ) + assert_eq!(Value::Boolean(true), try_read("true ").ok().unwrap().1) } #[test] fn try_read_bool_false_test() { - assert_eq!( - Value::Boolean(false), - try_read("false ").ok().unwrap().1 - ) + assert_eq!(Value::Boolean(false), try_read("false ").ok().unwrap().1) } } @@ -776,7 +776,10 @@ mod tests { #[test] fn consume_whitespaces_from_input_no_whitespace() { let s = "1, 2, 3"; - assert_eq!(Some(("1, 2, 3", ())), consume_clojure_whitespaces_parser(&s).ok()); + assert_eq!( + Some(("1, 2, 3", ())), + consume_clojure_whitespaces_parser(&s).ok() + ); } } diff --git a/src/repl.rs b/src/repl.rs index b9f87c9..a7d3133 100644 --- a/src/repl.rs +++ b/src/repl.rs @@ -2,7 +2,6 @@ use std::fs::File; use std::io; use std::io::BufRead; use std::io::BufReader; -use std::io::Read; use std::io::Write; use crate::environment::Environment; @@ -39,7 +38,7 @@ impl Repl { let _ = io::stdout().flush(); // Read - let mut next = Repl::read(&mut stdin_reader); + let next = Repl::read(&mut stdin_reader); // Eval let evaled_next = self.eval(&next); // Print diff --git a/src/rust_core/_divide_.rs b/src/rust_core/_divide_.rs index 225352a..46ad8de 100644 --- a/src/rust_core/_divide_.rs +++ b/src/rust_core/_divide_.rs @@ -1,5 +1,5 @@ use crate::ifn::IFn; -use crate::value::{Value, ToValue}; +use crate::value::{ToValue, Value}; use std::rc::Rc; use crate::error_message; @@ -16,18 +16,19 @@ impl ToValue for DivideFn { impl IFn for DivideFn { fn invoke(&self, args: Vec>) -> Value { match args.len() { - 0 => { error_message::zero_arg_count(args.len()) }, + 0 => error_message::zero_arg_count(args.len()), 1 => { let val = args.get(0).unwrap().to_value(); match val { Value::I32(a_) => Value::F64(1.0 / a_ as f64), Value::F64(f_) => Value::F64(1.0 / f_), - _ => Value::Condition(format!( // TODO: what error message should be returned regarding using typetags? - "Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}", - val.type_tag() - )) + _ => Value::Condition(format!( + // TODO: what error message should be returned regarding using typetags? + "Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}", + val.type_tag() + )), } - }, + } _ => { let mut args_iterator = args.into_iter(); let first_arg = args_iterator.next().unwrap(); @@ -35,22 +36,25 @@ impl IFn for DivideFn { Value::I32(a_) => match *b { Value::I32(b_) => Value::I32(a_ / b_), Value::F64(b_) => Value::F64(a_ as f64 / b_), - _ => Value::Condition(format!( // TODO: what error message should be returned regarding using typetags? - "Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}", - b.type_tag() + _ => Value::Condition(format!( + // TODO: what error message should be returned regarding using typetags? + "Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}", + b.type_tag() )), }, Value::F64(a_) => match *b { Value::I32(b_) => Value::F64(a_ / b_ as f64), Value::F64(b_) => Value::F64(a_ / b_), - _ => Value::Condition(format!( // TODO: what error message should be returned regarding using typetags? - "Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}", - b.type_tag() + _ => Value::Condition(format!( + // TODO: what error message should be returned regarding using typetags? + "Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}", + b.type_tag() )), }, - _ => Value::Condition(format!( // TODO: what error message should be returned regarding using typetags? - "Type mismatch: Expecting: (i32 | i64 | f32 | f64), Found: {}", - a.type_tag() + _ => Value::Condition(format!( + // TODO: what error message should be returned regarding using typetags? + "Type mismatch: Expecting: (i32 | i64 | f32 | f64), Found: {}", + a.type_tag() )), }) } @@ -60,68 +64,73 @@ impl IFn for DivideFn { #[cfg(test)] mod tests { - mod Divide_tests { - use crate::rust_core::_divide_::DivideFn; + mod divide_tests { use crate::ifn::IFn; + use crate::rust_core::_divide_::DivideFn; use crate::value::Value; use std::rc::Rc; #[test] - fn Divide_without_arguments_returns_one() { - let Divide = DivideFn {}; + fn divide_without_arguments_returns_one() { + let divide = DivideFn {}; let args = vec![]; - assert_eq!(Value::Condition(String::from("Wrong number of arguments given to function (Given: 0)")), - Divide.invoke(args)); + assert_eq!( + Value::Condition(String::from( + "Wrong number of arguments given to function (Given: 0)" + )), + divide.invoke(args) + ); } #[test] - fn Divide_with_one_positive_argument_returns_reciprocal() { + fn divide_with_one_positive_argument_returns_reciprocal() { let divide = DivideFn {}; let args = vec![Rc::new(Value::I32(5))]; - assert_eq!(Value::F64(1.0/5.0), divide.invoke(args)); + assert_eq!(Value::F64(1.0 / 5.0), divide.invoke(args)); } #[test] - fn Divide_with_one_negative_argument_returns_reciprocal() { + fn divide_with_one_negative_argument_returns_reciprocal() { let divide = DivideFn {}; let args = vec![Rc::new(Value::I32(-5))]; assert_eq!(Value::F64(1.0 / -5.0), divide.invoke(args)); } #[test] - fn Divide_with_two_integer_argument_returns_quotient() { + fn divide_with_two_integer_argument_returns_quotient() { let divide = DivideFn {}; let args = vec![Rc::new(Value::I32(24)), Rc::new(Value::I32(6))]; assert_eq!(Value::I32(4), divide.invoke(args)); } #[test] - fn Divide_with_one_double_argument_returns_quotient() { + fn divide_with_one_double_argument_returns_quotient() { let divide = DivideFn {}; let args = vec![Rc::new(Value::I32(24)), Rc::new(Value::F64(1.5))]; assert_eq!(Value::F64(16.0), divide.invoke(args)); } #[test] - fn Divide_with_multiple_integer_arguments_returns_quotient() { - let Divide = DivideFn {}; + fn divide_with_multiple_integer_arguments_returns_quotient() { + let divide = DivideFn {}; let args = vec![ Rc::new(Value::I32(100)), Rc::new(Value::I32(5)), - Rc::new(Value::I32(4))]; - assert_eq!(Value::I32(5), Divide.invoke(args)); + Rc::new(Value::I32(4)), + ]; + assert_eq!(Value::I32(5), divide.invoke(args)); } #[test] - fn Divide_with_multiple_mixed_arguments_returns_quotient() { - let Divide = DivideFn {}; + fn divide_with_multiple_mixed_arguments_returns_quotient() { + let divide = DivideFn {}; let args = vec![ Rc::new(Value::I32(100)), Rc::new(Value::I32(5)), Rc::new(Value::I32(4)), - Rc::new(Value::F64(2.0))]; - assert_eq!(Value::F64(2.5), Divide.invoke(args)); + Rc::new(Value::F64(2.0)), + ]; + assert_eq!(Value::F64(2.5), divide.invoke(args)); } - } -} \ No newline at end of file +} diff --git a/src/rust_core/nth.rs b/src/rust_core/nth.rs index 79cd343..c908c11 100644 --- a/src/rust_core/nth.rs +++ b/src/rust_core/nth.rs @@ -1,10 +1,10 @@ use crate::ifn::IFn; -use crate::value::{Value, ToValue}; -use std::rc::Rc; use crate::type_tag::TypeTag; +use crate::value::{ToValue, Value}; +use std::rc::Rc; use crate::error_message; -use crate::persistent_list::PersistentList::Cons; +use crate::persistent_list::PersistentList::{Cons, Empty}; use crate::persistent_list::ToPersistentListIter; use crate::persistent_vector::PersistentVector; @@ -21,13 +21,13 @@ impl IFn for NthFn { fn invoke(&self, args: Vec>) -> Value { // @TODO generalize arity exceptions, and other exceptions if args.len() != 2 { - return error_message::wrong_varg_count(&[2,3], args.len()) + return error_message::wrong_varg_count(&[2, 3], args.len()); } // @TODO change iteration to work with Value references, or even change invoke to work on Rc<..> // as we do everything else; surely we don't want to clone just to read from a collection if let Value::I32(ind) = **args.get(1).unwrap() { if ind < 0 { - return error_message::index_cannot_be_negative(ind as usize) + return error_message::index_cannot_be_negative(ind as usize); } let ind = ind as usize; @@ -56,4 +56,4 @@ impl IFn for NthFn { error_message::type_mismatch(TypeTag::Integer, &**args.get(1).unwrap()) } } -} \ No newline at end of file +} diff --git a/src/rust_core/print_string.rs b/src/rust_core/print_string.rs index 101be6f..b6078cd 100644 --- a/src/rust_core/print_string.rs +++ b/src/rust_core/print_string.rs @@ -1,5 +1,5 @@ use crate::ifn::IFn; -use crate::value::{Value, ToValue, Evaluable}; +use crate::value::{ToValue, Value}; use std::rc::Rc; use crate::error_message; @@ -16,9 +16,9 @@ impl ToValue for PrintStringFn { impl IFn for PrintStringFn { fn invoke(&self, args: Vec>) -> Value { if args.len() != 1 { - return error_message::wrong_arg_count(1, args.len()) + return error_message::wrong_arg_count(1, args.len()); } println!("{}", args.get(0).unwrap().to_string()); Value::Nil } -} \ No newline at end of file +} diff --git a/src/rust_core/slurp.rs b/src/rust_core/slurp.rs index f855872..3875980 100644 --- a/src/rust_core/slurp.rs +++ b/src/rust_core/slurp.rs @@ -1,15 +1,14 @@ -use crate::value::{ToValue, Value}; -use std::rc::Rc; use crate::ifn::IFn; +use crate::value::{ToValue, Value}; use nom::lib::std::convert::TryFrom; +use std::rc::Rc; use std::fs::File; use std::io::Read; -use url::Url; use reqwest; +use url::Url; -use std::error::Error; use crate::error_message; /// (slurp f & opts) @@ -31,7 +30,7 @@ impl ToValue for SlurpFn { impl IFn for SlurpFn { fn invoke(&self, args: Vec>) -> Value { - if args.len() >= 1 { + if !args.is_empty() { let first_arg = &args.into_iter().next().unwrap().to_string(); let possible_url = Url::parse(first_arg); @@ -40,11 +39,11 @@ impl IFn for SlurpFn { Ok(url) => { let rslt = reqwest::blocking::get(url.as_str()); match rslt { - Ok(res) => return Value::String(res.text().unwrap()), - Err(e) => return error_message::generic_err(Box::try_from(e).unwrap()) + Ok(res) => Value::String(res.text().unwrap()), + Err(e) => error_message::generic_err(Box::try_from(e).unwrap()), } - }, - Err(e) => { + } + Err(_) => { // try to find a file, if url parsing fails let filename = first_arg; let file_descriptor = File::open(filename); @@ -56,14 +55,12 @@ impl IFn for SlurpFn { } }; let mut s = String::new(); - f.read_to_string(&mut s); - return Value::String(s) - }, - _ => return Value::Nil - }; - + f.read_to_string(&mut s).unwrap(); + Value::String(s) + } + } } else { Value::Nil } } -} \ No newline at end of file +} diff --git a/src/rust_core/string_print.rs b/src/rust_core/string_print.rs index 9094dee..ddba7b0 100644 --- a/src/rust_core/string_print.rs +++ b/src/rust_core/string_print.rs @@ -1,5 +1,5 @@ use crate::ifn::IFn; -use crate::value::{Value, ToValue, Evaluable}; +use crate::value::{ToValue, Value}; use std::rc::Rc; // Todo: dead code? no usage found diff --git a/src/value.rs b/src/value.rs index f99790b..69f88ea 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1,5 +1,6 @@ use crate::environment::Environment; use crate::ifn::IFn; +use crate::keyword::Keyword; use crate::lambda; use crate::maps::MapEntry; use crate::persistent_list::PersistentList::Cons; @@ -7,7 +8,6 @@ use crate::persistent_list::{PersistentList, ToPersistentList, ToPersistentListI use crate::persistent_list_map::{PersistentListMap, ToPersistentListMapIter}; use crate::persistent_vector::PersistentVector; use crate::symbol::Symbol; -use crate::keyword::Keyword; use crate::type_tag::TypeTag; extern crate rand; @@ -70,110 +70,29 @@ impl PartialEq for Value { // @TODO implement our generic IFns some other way? After all, again, this isn't Java fn eq(&self, other: &Value) -> bool { // - if let I32(i) = self { - if let I32(i2) = other { - return i == i2; - } - } - - if let F64(d) = self { - if let F64(d2) = other { - return d == d2; - } - } - - if let Boolean(b) = self { - if let Boolean(b2) = other { - return b == b2; - } - } - - if let Symbol(sym) = self { - if let Symbol(sym2) = other { - return sym == sym2; - } - } - - if let Keyword(kw) = self { - if let Keyword(kw2) = other { - return kw == kw2; - } - } - // Equality not defined on functions, similar to Clojure - // Change this perhaps? Diverge? - if let IFn(_) = self { - if let IFn(_) = other { - return false; - } - } - // Is it misleading for equality to sometimes work? - if let LexicalEvalFn = self { - if let LexicalEvalFn = other { - return true; - } - } - - if let PersistentList(plist) = self { - if let PersistentList(plist2) = other { - return plist == plist2; - } - } - - if let PersistentVector(pvector) = self { - if let PersistentVector(pvector2) = other { - return *pvector == *pvector2; - } + match (self, other) { + (I32(i), I32(i2)) => i == i2, + (F64(d), F64(d2)) => d == d2, + (Boolean(b), Boolean(b2)) => b == b2, + (Symbol(sym), Symbol(sym2)) => sym == sym2, + (Keyword(kw), Keyword(kw2)) => kw == kw2, + // Equality not defined on functions, similar to Clojure + // Change this perhaps? Diverge? + (IFn(_), IFn(_)) => false, + // Is it misleading for equality to sometimes work? + (LexicalEvalFn, LexicalEvalFn) => true, + (PersistentList(plist), PersistentList(plist2)) => plist == plist2, + (PersistentVector(pvector), PersistentVector(pvector2)) => *pvector == *pvector2, + (PersistentListMap(plistmap), PersistentListMap(plistmap2)) => *plistmap == *plistmap2, + (Condition(msg), Condition(msg2)) => msg == msg2, + (QuoteMacro, QuoteMacro) => true, + (DefmacroMacro, DefmacroMacro) => true, + (DefMacro, DefMacro) => true, + (LetMacro, LetMacro) => true, + (String(string), String(string2)) => string == string2, + (Nil, Nil) => true, + _ => false, } - - if let PersistentListMap(plistmap) = self { - if let PersistentListMap(plistmap2) = other { - return *plistmap == *plistmap2; - } - } - - if let Condition(msg) = self { - if let Condition(msg2) = other { - return msg == msg2; - } - } - - if let QuoteMacro = self { - if let QuoteMacro = other { - return true; - } - } - - if let DefmacroMacro = self { - if let DefmacroMacro = other { - return true; - } - } - - if let DefMacro = self { - if let DefMacro = other { - return true; - } - } - - if let LetMacro = self { - if let LetMacro = other { - return true; - } - } - - if let String(string) = self { - if let String(string2) = other { - return string == string2; - } - } - - if let Nil = self { - if let Nil = other { - return true; - } - } - - false } } @@ -197,7 +116,7 @@ impl Hash for Value { F64(d) => d.to_value().hash(state), Boolean(b) => b.hash(state), Symbol(sym) => sym.hash(state), - Keyword(kw) => kw.hash(state), + Keyword(kw) => kw.hash(state), IFn(_) => { let mut rng = rand::thread_rng(); let n2: u16 = rng.gen(); @@ -235,7 +154,7 @@ impl fmt::Display for Value { F64(val) => val.to_string(), Boolean(val) => val.to_string(), Symbol(sym) => sym.to_string(), - Keyword(kw) => kw.to_string(), + Keyword(kw) => kw.to_string(), IFn(_) => std::string::String::from("#function[]"), LexicalEvalFn => std::string::String::from("#function[lexical-eval*]"), PersistentList(plist) => plist.to_string(), @@ -275,7 +194,7 @@ impl Value { Value::F64(_) => TypeTag::F64, Value::Boolean(_) => TypeTag::Boolean, Value::Symbol(_) => TypeTag::Symbol, - Value::Keyword(_) => TypeTag::Keyword, + Value::Keyword(_) => TypeTag::Keyword, Value::IFn(_) => TypeTag::IFn, Value::LexicalEvalFn => TypeTag::IFn, Value::PersistentList(_) => TypeTag::PersistentList,