Added LT, GT, LTE, and GTE functions, and big test coverage
This commit is contained in:
parent
5d89c6b684
commit
c74d6f5ddf
6 changed files with 468 additions and 11 deletions
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Add, Sub, Mul, Div, Index};
|
||||
use std::ops::{Add, Div, Index, Mul, Sub};
|
||||
|
||||
// Container
|
||||
#[derive(Debug, Default)]
|
||||
|
|
@ -321,7 +321,6 @@ impl Sub<Ctr> for Ctr {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl Mul<Ctr> for Ctr {
|
||||
type Output = Ctr;
|
||||
|
||||
|
|
|
|||
48
src/stl.rs
48
src/stl.rs
|
|
@ -291,7 +291,7 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> {
|
|||
conditional_branches: false,
|
||||
docs: math::EXP_DOCSTRING.to_string(),
|
||||
value: ValueType::Internal(Rc::new(math::exp_callback)),
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
|
|
@ -302,7 +302,51 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> {
|
|||
conditional_branches: false,
|
||||
docs: math::MOD_DOCSTRING.to_string(),
|
||||
value: ValueType::Internal(Rc::new(math::mod_callback)),
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"gt?".to_string(),
|
||||
Symbol {
|
||||
name: String::from("gt?"),
|
||||
args: Args::Lazy(2),
|
||||
conditional_branches: false,
|
||||
docs: math::ISGT_DOCSTRING.to_string(),
|
||||
value: ValueType::Internal(Rc::new(math::isgt_callback)),
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"lt?".to_string(),
|
||||
Symbol {
|
||||
name: String::from("lt?"),
|
||||
args: Args::Lazy(2),
|
||||
conditional_branches: false,
|
||||
docs: math::ISLT_DOCSTRING.to_string(),
|
||||
value: ValueType::Internal(Rc::new(math::islt_callback)),
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"gte?".to_string(),
|
||||
Symbol {
|
||||
name: String::from("gt?"),
|
||||
args: Args::Lazy(2),
|
||||
conditional_branches: false,
|
||||
docs: math::ISGTE_DOCSTRING.to_string(),
|
||||
value: ValueType::Internal(Rc::new(math::isgte_callback)),
|
||||
},
|
||||
);
|
||||
|
||||
syms.insert(
|
||||
"lte?".to_string(),
|
||||
Symbol {
|
||||
name: String::from("lt?"),
|
||||
args: Args::Lazy(2),
|
||||
conditional_branches: false,
|
||||
docs: math::ISLTE_DOCSTRING.to_string(),
|
||||
value: ValueType::Internal(Rc::new(math::islte_callback)),
|
||||
},
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -264,3 +264,97 @@ pub fn mod_callback(ast: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
|||
|
||||
Ok(Ctr::Seg(ret))
|
||||
}
|
||||
|
||||
pub const ISGT_DOCSTRING: &str = "takes two args, which must both evaluate to an Integer or Float.
|
||||
Returns true or false according to whether the first argument is bigger than the second argument.
|
||||
May panic if an integer larger than a max f64 is compared to a float.";
|
||||
|
||||
pub fn isgt_callback(ast: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
let first = *ast.car.clone();
|
||||
if !isnumeric(&first) {
|
||||
return Err("first argument must be numeric".to_string());
|
||||
}
|
||||
let second: Ctr;
|
||||
if let Ctr::Seg(ref s) = *ast.cdr {
|
||||
second = *s.car.clone();
|
||||
} else {
|
||||
return Err("impossible error: needs two arguments".to_string());
|
||||
}
|
||||
if !isnumeric(&second) {
|
||||
return Err("second argument must be numeric".to_string());
|
||||
}
|
||||
|
||||
match first {
|
||||
Ctr::Float(lf) => match second {
|
||||
Ctr::Float(rf) => Ok(Ctr::Bool(lf > rf)),
|
||||
Ctr::Integer(ri) => Ok(Ctr::Bool(lf > ri as f64)),
|
||||
_ => Err("gt? not implemented for these arguments".to_string()),
|
||||
},
|
||||
Ctr::Integer(li) => match second {
|
||||
Ctr::Float(rf) => Ok(Ctr::Bool(li as f64 > rf)),
|
||||
Ctr::Integer(ri) => Ok(Ctr::Bool(li > ri)),
|
||||
_ => Err("gt? not implemented for these arguments".to_string()),
|
||||
},
|
||||
|
||||
_ => Err("gt? not implemented for these arguments".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub const ISLT_DOCSTRING: &str = "takes two args, which must both evaluate to an Integer or Float.
|
||||
Returns true or false according to whether the first argument is smaller than the second argument.
|
||||
May panic if an integer larger than a max f64 is compared to a float.";
|
||||
|
||||
pub fn islt_callback(ast: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
|
||||
let first = *ast.car.clone();
|
||||
if !isnumeric(&first) {
|
||||
return Err("first argument must be numeric".to_string());
|
||||
}
|
||||
let second: Ctr;
|
||||
if let Ctr::Seg(ref s) = *ast.cdr {
|
||||
second = *s.car.clone();
|
||||
} else {
|
||||
return Err("impossible error: needs two arguments".to_string());
|
||||
}
|
||||
if !isnumeric(&second) {
|
||||
return Err("second argument must be numeric".to_string());
|
||||
}
|
||||
|
||||
match first {
|
||||
Ctr::Float(lf) => match second {
|
||||
Ctr::Float(rf) => Ok(Ctr::Bool(lf < rf)),
|
||||
Ctr::Integer(ri) => Ok(Ctr::Bool(lf < ri as f64)),
|
||||
_ => Err("gt? not implemented for these arguments".to_string()),
|
||||
},
|
||||
Ctr::Integer(li) => match second {
|
||||
Ctr::Float(rf) => Ok(Ctr::Bool((li as f64) < rf)),
|
||||
Ctr::Integer(ri) => Ok(Ctr::Bool(li < ri)),
|
||||
_ => Err("gt? not implemented for these arguments".to_string()),
|
||||
},
|
||||
|
||||
_ => Err("gt? not implemented for these arguments".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
pub const ISGTE_DOCSTRING: &str = "takes two args, which must both evaluate to an Integer or Float.
|
||||
Returns true or false according to whether the first argument is greater than or equal to the second argument.
|
||||
May panic if an integer larger than a max f64 is compared to a float.";
|
||||
|
||||
pub fn isgte_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
if let Ctr::Bool(b) = islt_callback(ast, syms)? {
|
||||
Ok(Ctr::Bool(!b))
|
||||
} else {
|
||||
Err("impossible state: islt returned non-bool".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub const ISLTE_DOCSTRING: &str = "takes two args, which must both evaluate to an Integer or Float.
|
||||
Returns true or false according to whether the first argument is less than or equal to the second argument.
|
||||
May panic if an integer larger than a max f64 is compared to a float.";
|
||||
|
||||
pub fn islte_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||
if let Ctr::Bool(b) = isgt_callback(ast, syms)? {
|
||||
Ok(Ctr::Bool(!b))
|
||||
} else {
|
||||
Err("impossible state: islt returned non-bool".to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ impl Args {
|
|||
} else {
|
||||
return Err("expected no args".to_string());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Args::Infinite => {
|
||||
if !args.is_empty() {
|
||||
|
|
@ -153,7 +153,7 @@ impl Args {
|
|||
} else {
|
||||
return Err("expected args but none were provided".to_string());
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Args::Lazy(ref num) => {
|
||||
let called_arg_count = args.len();
|
||||
|
|
@ -168,7 +168,7 @@ impl Args {
|
|||
} else if let Ctr::None = *args.car {
|
||||
return Err(format!("expected {} args. Got 0.", num,));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Args::Strict(ref arg_types) => {
|
||||
let mut idx: usize = 0;
|
||||
|
|
@ -203,7 +203,7 @@ impl Args {
|
|||
return Err("too few arguments".to_string());
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue