Skip to content

Commit c272638

Browse files
committed
Added equals
1 parent e72611a commit c272638

File tree

6 files changed

+84
-9
lines changed

6 files changed

+84
-9
lines changed

src/environment.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::clojure_std;
22
use crate::clojure_string;
3-
use crate::namespace::{Namespace, Namespaces};
3+
use crate::namespace::{Namespaces};
44
use crate::repl::Repl;
55
use crate::rust_core;
66
use crate::symbol::Symbol;
@@ -231,6 +231,7 @@ impl Environment {
231231
let if_macro = Value::IfMacro {};
232232
let environment = Rc::new(Environment::new_main_environment());
233233

234+
let equals_fn = rust_core::EqualsFn {};
234235
let eval_fn = rust_core::EvalFn::new(Rc::clone(&environment));
235236
let ns_macro = rust_core::NsMacro::new(Rc::clone(&environment));
236237
let load_file_fn = rust_core::LoadFileFn::new(Rc::clone(&environment));
@@ -388,6 +389,7 @@ impl Environment {
388389
);
389390
environment.insert(Symbol::intern("read-line"), read_line_fn.to_rc_value());
390391

392+
environment.insert(Symbol::intern("="),equals_fn.to_rc_value());
391393
//
392394
// Read in clojure.core
393395
//

src/rust_core.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,6 @@ pub use self::slurp::*;
6666

6767
pub(crate) mod load_file;
6868
pub use self::load_file::*;
69+
70+
pub(crate) mod equals;
71+
pub use self::equals::*;

src/rust_core/equals.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use crate::ifn::IFn;
2+
use crate::value::{ToValue, Value};
3+
use std::rc::Rc;
4+
5+
/// (assoc map key val & kvs)
6+
///
7+
// General assoc fn; however, currently just implemented
8+
// for our one map type, PersistentListMap
9+
#[derive(Debug, Clone)]
10+
pub struct EqualsFn {}
11+
impl ToValue for EqualsFn {
12+
fn to_value(&self) -> Value {
13+
Value::IFn(Rc::new(self.clone()))
14+
}
15+
}
16+
impl IFn for EqualsFn {
17+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
18+
if args.is_empty() {
19+
//@TODO use proper error function
20+
return Value::Condition(format!(
21+
"Wrong number of arguments given to function (Given: {}, Expected: > 0)",
22+
args.len()
23+
));
24+
}
25+
26+
for pair in args.windows(2) {
27+
let a = &pair[0];
28+
let b = &pair[1];
29+
if a != b {
30+
return Value::Boolean(false);
31+
}
32+
};
33+
Value::Boolean(true)
34+
35+
}
36+
}
37+
38+
mod tests {
39+
use crate::value::{Value,ToValue};
40+
use crate::rust_core::EqualsFn;
41+
use crate::keyword::Keyword;
42+
use crate::ifn::IFn;
43+
44+
// Just checks that different Values do not count as equal, and that
45+
// at least one Value of the same kind does, and that one Value of the same
46+
// kind and different Value doesn't
47+
//
48+
// Otherwise, does not test every type
49+
#[test]
50+
fn equals_basic() {
51+
let equals = EqualsFn{};
52+
let _i32 = Value::I32(1).to_rc_value();
53+
// To test that we're not getting some sort of 'memory equality'
54+
let i32_copy = Value::I32(1).to_rc_value();
55+
assert!(equals.invoke(vec![i32_copy.clone(),_i32.clone()]).is_truthy());
56+
assert!(equals.invoke(vec![_i32.clone(),_i32.clone()]).is_truthy());
57+
58+
let i32_2 = Value::I32(5).to_rc_value();
59+
assert!(!equals.invoke(vec![_i32.clone(),i32_2.clone()]).is_truthy());
60+
61+
let keyword = Keyword::intern("cat").to_rc_value();
62+
let keyword2 = Keyword::intern("cat").to_rc_value();
63+
let keyword3 = Keyword::intern("dog").to_rc_value();
64+
65+
assert!(equals.invoke(vec![keyword.clone(),keyword2.clone()]).is_truthy());
66+
assert!(!equals.invoke(vec![keyword2,keyword3]).is_truthy());
67+
assert!(!equals.invoke(vec![keyword,_i32]).is_truthy());
68+
}
69+
}

src/rust_core/flush_stdout.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use crate::ifn::IFn;
2-
use crate::value::{Value, ToValue, Evaluable};
2+
use crate::value::{Value, ToValue};
33
use std::rc::Rc;
44

55
use std::io;
66

77
use crate::error_message;
8-
use nom::lib::std::convert::TryFrom;
9-
use std::io::{Read, Write};
8+
use std::io::{Write};
109

1110
/// Read a line from stdin TODO: should be aware of *in*
1211
/// (defn read-line [])
@@ -25,4 +24,4 @@ impl IFn for FlushStdoutFn {
2524
io::stdout().flush();
2625
Value::Nil
2726
}
28-
}
27+
}

src/rust_core/read_line.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use crate::ifn::IFn;
2-
use crate::value::{Value, ToValue, Evaluable};
2+
use crate::value::{Value, ToValue};
33
use std::rc::Rc;
44

55
use std::io;
66

77
use crate::error_message;
88
use nom::lib::std::convert::TryFrom;
9-
use std::io::{Read, Write};
109

1110
/// Read a line from stdin TODO: should be aware of *in*
1211
/// (defn read-line [])
@@ -31,4 +30,4 @@ impl IFn for ReadLineFn {
3130
Err(error) => error_message::generic_err(Box::try_from(error).unwrap())
3231
}
3332
}
34-
}
33+
}

src/value.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,10 @@ impl Value {
530530
////////////////////////////////////////////////////////////////////////////////////////////////////
531531
// Eval Helper
532532
////////////////////////////////////////////////////////////////////////////////////////////////////
533-
fn is_truthy(&self) -> bool {
533+
pub fn is_truthy(&self) -> bool {
534+
if let Value::Boolean(false) = self {
535+
return false;
536+
}
534537
if let Value::Nil = self {
535538
return false;
536539
}

0 commit comments

Comments
 (0)