Skip to content

Commit 68c69e1

Browse files
committed
Merge branch 'feature/lt-gt-lte-gte' [#69]
2 parents 127b4f6 + a45852b commit 68c69e1

File tree

6 files changed

+332
-0
lines changed

6 files changed

+332
-0
lines changed

src/environment.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ impl Environment {
340340
let with_meta_fn = rust_core::WithMetaFn::new(Rc::clone(&environment));
341341
let var_fn = rust_core::special_form::VarFn::new(Rc::clone(&environment));
342342
let count_fn = rust_core::count::CountFn {};
343+
let lt_fn = rust_core::lt::LtFn {};
344+
let gt_fn = rust_core::gt::GtFn {};
345+
let lte_fn = rust_core::lte::LteFn {};
346+
let gte_fn = rust_core::gte::GteFn {};
343347
// @TODO after we merge this with all the other commits we have,
344348
// just change all the `insert`s here to use insert_in_namespace
345349
// I prefer explicity and the non-dependence-on-environmental-factors
@@ -368,6 +372,14 @@ impl Environment {
368372
count_fn.to_rc_value(),
369373
);
370374

375+
// Interop to read real clojure.core
376+
environment.insert(Symbol::intern("lt"),lt_fn.to_rc_value());
377+
378+
environment.insert(Symbol::intern("gt"),gt_fn.to_rc_value());
379+
environment.insert(Symbol::intern("lte"),lte_fn.to_rc_value());
380+
381+
environment.insert(Symbol::intern("gte"),gte_fn.to_rc_value());
382+
371383
// Thread namespace
372384
environment.insert_into_namespace(
373385
&Symbol::intern("Thread"),

src/rust_core.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,18 @@ pub use self::rand::*;
4343
pub(crate) mod rand_int;
4444
pub use self::rand_int::*;
4545

46+
pub(crate) mod lt;
47+
pub use self::lt::*;
48+
49+
pub(crate) mod lte;
50+
pub use self::lte::*;
51+
52+
pub(crate) mod gt;
53+
pub use self::gt::*;
54+
55+
pub(crate) mod gte;
56+
pub use self::gte::*;
57+
4658
// string
4759
pub(crate) mod str;
4860
pub use self::str::*;

src/rust_core/gt.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use crate::error_message;
2+
use crate::ifn::IFn;
3+
use crate::value::{ToValue, Value};
4+
use std::rc::Rc;
5+
6+
/// (gt x y)
7+
/// x > y
8+
#[derive(Debug, Clone)]
9+
pub struct GtFn {}
10+
impl ToValue for GtFn {
11+
fn to_value(&self) -> Value {
12+
Value::IFn(Rc::new(self.clone()))
13+
}
14+
}
15+
impl IFn for GtFn {
16+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
17+
if args.len() != 2 {
18+
return error_message::wrong_arg_count(2, args.len());
19+
}
20+
match args.get(0).unwrap().to_value() {
21+
Value::I32(a) => match args.get(1).unwrap().to_value() {
22+
Value::I32(b) => Value::Boolean(a > b),
23+
Value::F64(b) => Value::Boolean(a > b as i32),
24+
b_ => Value::Condition(format!(
25+
// TODO: what error message should be returned regarding using typetags?
26+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
27+
b_.type_tag()
28+
)),
29+
},
30+
Value::F64(a) => match args.get(0).unwrap().to_value() {
31+
Value::I32(b) => Value::Boolean(a > b as f64),
32+
Value::F64(b) => Value::Boolean(a > b),
33+
b_ => Value::Condition(format!(
34+
// TODO: what error message should be returned regarding using typetags?
35+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
36+
b_.type_tag()
37+
)),
38+
},
39+
a_ => Value::Condition(format!(
40+
// TODO: what error message should be returned regarding using typetags?
41+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
42+
a_.type_tag()
43+
)),
44+
}
45+
}
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
mod gt_tests {
51+
use crate::ifn::IFn;
52+
use crate::rust_core::GtFn;
53+
use crate::value::Value;
54+
use std::rc::Rc;
55+
56+
#[test]
57+
fn one_is_greater_than_zero() {
58+
let gt = GtFn {};
59+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::I32(0))];
60+
assert_eq!(Value::Boolean(true), gt.invoke(args));
61+
}
62+
63+
#[test]
64+
fn one_is_not_greater_than_one() {
65+
let gt = GtFn {};
66+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::I32(1))];
67+
assert_eq!(Value::Boolean(false), gt.invoke(args));
68+
}
69+
70+
#[test]
71+
fn one_is_not_greater_than_one_and_fractions() {
72+
let gt = GtFn {};
73+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::F64(1.00001))];
74+
assert_eq!(Value::Boolean(false), gt.invoke(args));
75+
}
76+
}
77+
}

src/rust_core/gte.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use crate::error_message;
2+
use crate::ifn::IFn;
3+
use crate::value::{ToValue, Value};
4+
use std::rc::Rc;
5+
6+
/// (gte x y)
7+
/// x >= y
8+
#[derive(Debug, Clone)]
9+
pub struct GteFn {}
10+
impl ToValue for GteFn {
11+
fn to_value(&self) -> Value {
12+
Value::IFn(Rc::new(self.clone()))
13+
}
14+
}
15+
impl IFn for GteFn {
16+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
17+
if args.len() != 2 {
18+
return error_message::wrong_arg_count(2, args.len());
19+
}
20+
match args.get(0).unwrap().to_value() {
21+
Value::I32(a) => match args.get(1).unwrap().to_value() {
22+
Value::I32(b) => Value::Boolean(a >= b),
23+
Value::F64(b) => Value::Boolean(a as f64 >= b),
24+
b_ => Value::Condition(format!(
25+
// TODO: what error message should be returned regarding using typetags?
26+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
27+
b_.type_tag()
28+
)),
29+
},
30+
Value::F64(a) => match args.get(0).unwrap().to_value() {
31+
Value::I32(b) => Value::Boolean(a >= b as f64),
32+
Value::F64(b) => Value::Boolean(a >= b),
33+
b_ => Value::Condition(format!(
34+
// TODO: what error message should be returned regarding using typetags?
35+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
36+
b_.type_tag()
37+
)),
38+
},
39+
a_ => Value::Condition(format!(
40+
// TODO: what error message should be returned regarding using typetags?
41+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
42+
a_.type_tag()
43+
)),
44+
}
45+
}
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
mod gte_tests {
51+
use crate::ifn::IFn;
52+
use crate::rust_core::GteFn;
53+
use crate::value::Value;
54+
use std::rc::Rc;
55+
56+
#[test]
57+
fn one_is_greater_than_zero() {
58+
let gte = GteFn {};
59+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::I32(0))];
60+
assert_eq!(Value::Boolean(true), gte.invoke(args));
61+
}
62+
63+
#[test]
64+
fn one_is_gte_than_one() {
65+
let gte = GteFn {};
66+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::I32(1))];
67+
assert_eq!(Value::Boolean(true), gte.invoke(args));
68+
}
69+
70+
#[test]
71+
fn one_is_not_gte_than_one_and_fractions() {
72+
let gte = GteFn {};
73+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::F64(1.00001))];
74+
assert_eq!(Value::Boolean(false), gte.invoke(args));
75+
}
76+
}
77+
}

src/rust_core/lt.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use crate::error_message;
2+
use crate::ifn::IFn;
3+
use crate::value::{ToValue, Value};
4+
use std::rc::Rc;
5+
6+
/// (lt x y)
7+
/// x < y
8+
#[derive(Debug, Clone)]
9+
pub struct LtFn {}
10+
impl ToValue for LtFn {
11+
fn to_value(&self) -> Value {
12+
Value::IFn(Rc::new(self.clone()))
13+
}
14+
}
15+
impl IFn for LtFn {
16+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
17+
if args.len() != 2 {
18+
return error_message::wrong_arg_count(2, args.len());
19+
}
20+
match args.get(0).unwrap().to_value() {
21+
Value::I32(a) => match args.get(1).unwrap().to_value() {
22+
Value::I32(b) => Value::Boolean(a < b),
23+
Value::F64(b) => Value::Boolean(a < b as i32),
24+
b_ => Value::Condition(format!(
25+
// TODO: what error message should be returned regarding using typetags?
26+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
27+
b_.type_tag()
28+
)),
29+
},
30+
Value::F64(a) => match args.get(0).unwrap().to_value() {
31+
Value::I32(b) => Value::Boolean(a < b as f64),
32+
Value::F64(b) => Value::Boolean(a < b),
33+
b_ => Value::Condition(format!(
34+
// TODO: what error message should be returned regarding using typetags?
35+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
36+
b_.type_tag()
37+
)),
38+
},
39+
a_ => Value::Condition(format!(
40+
// TODO: what error message should be returned regarding using typetags?
41+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
42+
a_.type_tag()
43+
)),
44+
}
45+
}
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
mod lt_tests {
51+
use crate::ifn::IFn;
52+
use crate::rust_core::LtFn;
53+
use crate::value::Value;
54+
use std::rc::Rc;
55+
56+
#[test]
57+
fn zero_is_less_than_one() {
58+
let lt = LtFn {};
59+
let args = vec![Rc::new(Value::I32(0)), Rc::new(Value::I32(1))];
60+
assert_eq!(Value::Boolean(true), lt.invoke(args));
61+
}
62+
63+
#[test]
64+
fn one_is_not_less_than_one() {
65+
let lt = LtFn {};
66+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::I32(1))];
67+
assert_eq!(Value::Boolean(false), lt.invoke(args));
68+
}
69+
70+
#[test]
71+
fn one_is_less_than_one_and_fractions() {
72+
let lt = LtFn {};
73+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::F64(1.00001))];
74+
assert_eq!(Value::Boolean(false), lt.invoke(args));
75+
}
76+
}
77+
}

src/rust_core/lte.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use crate::error_message;
2+
use crate::ifn::IFn;
3+
use crate::value::{ToValue, Value};
4+
use std::rc::Rc;
5+
6+
/// (lte x y)
7+
/// x <= y
8+
#[derive(Debug, Clone)]
9+
pub struct LteFn {}
10+
impl ToValue for LteFn {
11+
fn to_value(&self) -> Value {
12+
Value::IFn(Rc::new(self.clone()))
13+
}
14+
}
15+
impl IFn for LteFn {
16+
fn invoke(&self, args: Vec<Rc<Value>>) -> Value {
17+
if args.len() != 2 {
18+
return error_message::wrong_arg_count(2, args.len());
19+
}
20+
match args.get(0).unwrap().to_value() {
21+
Value::I32(a) => match args.get(1).unwrap().to_value() {
22+
Value::I32(b) => Value::Boolean(a <= b),
23+
Value::F64(b) => Value::Boolean(a <= b as i32),
24+
b_ => Value::Condition(format!(
25+
// TODO: what error message should be returned regarding using typetags?
26+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
27+
b_.type_tag()
28+
)),
29+
},
30+
Value::F64(a) => match args.get(0).unwrap().to_value() {
31+
Value::I32(b) => Value::Boolean(a <= b as f64),
32+
Value::F64(b) => Value::Boolean(a <= b),
33+
b_ => Value::Condition(format!(
34+
// TODO: what error message should be returned regarding using typetags?
35+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
36+
b_.type_tag()
37+
)),
38+
},
39+
a_ => Value::Condition(format!(
40+
// TODO: what error message should be returned regarding using typetags?
41+
"Type mismatch; Expecting: (i32 | i64 | f32 | f64), Found: {}",
42+
a_.type_tag()
43+
)),
44+
}
45+
}
46+
}
47+
48+
#[cfg(test)]
49+
mod tests {
50+
mod lte_tests {
51+
use crate::ifn::IFn;
52+
use crate::rust_core::LteFn;
53+
use crate::value::Value;
54+
use std::rc::Rc;
55+
56+
#[test]
57+
fn zero_is_lte_than_zero() {
58+
let lte = LteFn {};
59+
let args = vec![Rc::new(Value::I32(0)), Rc::new(Value::I32(1))];
60+
assert_eq!(Value::Boolean(true), lte.invoke(args));
61+
}
62+
63+
#[test]
64+
fn one_is_lte_than_one() {
65+
let lte = LteFn {};
66+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::I32(1))];
67+
assert_eq!(Value::Boolean(true), lte.invoke(args));
68+
}
69+
70+
#[test]
71+
fn one_is_lte_than_one_and_fractions() {
72+
let lte = LteFn {};
73+
let args = vec![Rc::new(Value::I32(1)), Rc::new(Value::F64(1.00001))];
74+
assert_eq!(Value::Boolean(true), lte.invoke(args));
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)