Format code

This commit is contained in:
Sebastian Schmidt 2019-05-04 13:54:19 +02:00
parent 6f533ca925
commit 502ec0adce
5 changed files with 156 additions and 177 deletions

View File

@ -9,114 +9,98 @@ use Value;
pub fn builtin_function(identifier: &str) -> Option<Function> { pub fn builtin_function(identifier: &str) -> Option<Function> {
match identifier { match identifier {
"min" => Some(Function::new( "min" => Some(Function::new(Box::new(|argument| {
Box::new(|argument| { let arguments = expect_tuple(argument)?;
let arguments = expect_tuple(argument)?; let mut min_int = IntType::max_value();
let mut min_int = IntType::max_value(); let mut min_float = 1.0f64 / 0.0f64;
let mut min_float = 1.0f64 / 0.0f64; debug_assert!(min_float.is_infinite());
debug_assert!(min_float.is_infinite());
for argument in arguments { for argument in arguments {
if let Value::Float(float) = argument { if let Value::Float(float) = argument {
min_float = min_float.min(*float); min_float = min_float.min(*float);
} else if let Value::Int(int) = argument { } else if let Value::Int(int) = argument {
min_int = min_int.min(*int); min_int = min_int.min(*int);
} else {
return Err(EvalexprError::expected_number(argument.clone()));
}
}
if (min_int as FloatType) < min_float {
Ok(Value::Int(min_int))
} else { } else {
Ok(Value::Float(min_float)) return Err(EvalexprError::expected_number(argument.clone()));
} }
}), }
)),
"max" => Some(Function::new(
Box::new(|argument| {
let arguments = expect_tuple(argument)?;
let mut max_int = IntType::min_value();
let mut max_float = -1.0f64 / 0.0f64;
debug_assert!(max_float.is_infinite());
for argument in arguments { if (min_int as FloatType) < min_float {
if let Value::Float(float) = argument { Ok(Value::Int(min_int))
max_float = max_float.max(*float); } else {
} else if let Value::Int(int) = argument { Ok(Value::Float(min_float))
max_int = max_int.max(*int); }
} else { }))),
return Err(EvalexprError::expected_number(argument.clone())); "max" => Some(Function::new(Box::new(|argument| {
} let arguments = expect_tuple(argument)?;
} let mut max_int = IntType::min_value();
let mut max_float = -1.0f64 / 0.0f64;
debug_assert!(max_float.is_infinite());
if (max_int as FloatType) > max_float { for argument in arguments {
Ok(Value::Int(max_int)) if let Value::Float(float) = argument {
max_float = max_float.max(*float);
} else if let Value::Int(int) = argument {
max_int = max_int.max(*int);
} else { } else {
Ok(Value::Float(max_float)) return Err(EvalexprError::expected_number(argument.clone()));
} }
}), }
)),
"len" => Some(Function::new( if (max_int as FloatType) > max_float {
Box::new(|argument| { Ok(Value::Int(max_int))
let subject = expect_string(argument)?; } else {
Ok(Value::from(subject.len() as i64)) Ok(Value::Float(max_float))
}), }
)), }))),
"len" => Some(Function::new(Box::new(|argument| {
let subject = expect_string(argument)?;
Ok(Value::from(subject.len() as i64))
}))),
// string functions // string functions
#[cfg(feature = "regex_support")] #[cfg(feature = "regex_support")]
"str::regex_matches" => Some(Function::new( "str::regex_matches" => Some(Function::new(Box::new(|argument| {
Box::new(|argument| { let arguments = expect_tuple(argument)?;
let arguments = expect_tuple(argument)?;
let subject = expect_string(&arguments[0])?; let subject = expect_string(&arguments[0])?;
let re_str = expect_string(&arguments[1])?; let re_str = expect_string(&arguments[1])?;
match Regex::new(re_str) { match Regex::new(re_str) {
Ok(re) => Ok(Value::Boolean(re.is_match(subject))), Ok(re) => Ok(Value::Boolean(re.is_match(subject))),
Err(err) => Err(EvalexprError::invalid_regex( Err(err) => Err(EvalexprError::invalid_regex(
re_str.to_string(), re_str.to_string(),
format!("{}", err), format!("{}", err),
)), )),
} }
}), }))),
)),
#[cfg(feature = "regex_support")] #[cfg(feature = "regex_support")]
"str::regex_replace" => Some(Function::new( "str::regex_replace" => Some(Function::new(Box::new(|argument| {
Box::new(|argument| { let arguments = expect_tuple(argument)?;
let arguments = expect_tuple(argument)?;
let subject = expect_string(&arguments[0])?; let subject = expect_string(&arguments[0])?;
let re_str = expect_string(&arguments[1])?; let re_str = expect_string(&arguments[1])?;
let repl = expect_string(&arguments[2])?; let repl = expect_string(&arguments[2])?;
match Regex::new(re_str) { match Regex::new(re_str) {
Ok(re) => Ok(Value::String(re.replace_all(subject, repl).to_string())), Ok(re) => Ok(Value::String(re.replace_all(subject, repl).to_string())),
Err(err) => Err(EvalexprError::invalid_regex( Err(err) => Err(EvalexprError::invalid_regex(
re_str.to_string(), re_str.to_string(),
format!("{}", err), format!("{}", err),
)), )),
} }
}), }))),
)), "str::to_lowercase" => Some(Function::new(Box::new(|argument| {
"str::to_lowercase" => Some(Function::new( let subject = expect_string(argument)?;
Box::new(|argument| { Ok(Value::from(subject.to_lowercase()))
let subject = expect_string(argument)?; }))),
Ok(Value::from(subject.to_lowercase())) "str::to_uppercase" => Some(Function::new(Box::new(|argument| {
}), let subject = expect_string(argument)?;
)), Ok(Value::from(subject.to_uppercase()))
"str::to_uppercase" => Some(Function::new( }))),
Box::new(|argument| { "str::trim" => Some(Function::new(Box::new(|argument| {
let subject = expect_string(argument)?; let subject = expect_string(argument)?;
Ok(Value::from(subject.to_uppercase())) Ok(Value::from(subject.trim()))
}), }))),
)),
"str::trim" => Some(Function::new(
Box::new(|argument| {
let subject = expect_string(argument)?;
Ok(Value::from(subject.trim()))
}),
)),
_ => None, _ => None,
} }
} }

View File

@ -1,6 +1,6 @@
use std::fmt; use std::fmt;
use error::{EvalexprResult}; use error::EvalexprResult;
use value::Value; use value::Value;
pub(crate) mod builtin; pub(crate) mod builtin;
@ -27,12 +27,8 @@ impl Function {
/// Creates a user-defined function. /// Creates a user-defined function.
/// ///
/// The `function` is a boxed function that takes a `Value` and returns a `EvalexprResult<Value, Error>`. /// The `function` is a boxed function that takes a `Value` and returns a `EvalexprResult<Value, Error>`.
pub fn new( pub fn new(function: Box<Fn(&Value) -> EvalexprResult<Value>>) -> Self {
function: Box<Fn(&Value) -> EvalexprResult<Value>>, Self { function }
) -> Self {
Self {
function,
}
} }
pub(crate) fn call(&self, argument: &Value) -> EvalexprResult<Value> { pub(crate) fn call(&self, argument: &Value) -> EvalexprResult<Value> {
@ -42,9 +38,6 @@ impl Function {
impl fmt::Debug for Function { impl fmt::Debug for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!( write!(f, "Function {{ [...] }}")
f,
"Function {{ [...] }}"
)
} }
} }

View File

@ -420,9 +420,7 @@ impl Operator {
Ok(Value::Boolean(false)) Ok(Value::Boolean(false))
} }
}, },
Tuple => { Tuple => Ok(Value::Tuple(arguments.into())),
Ok(Value::Tuple(arguments.into()))
},
Assign => Err(EvalexprError::ContextNotManipulable), Assign => Err(EvalexprError::ContextNotManipulable),
Chain => { Chain => {
if arguments.is_empty() { if arguments.is_empty() {

View File

@ -410,11 +410,16 @@ impl Node {
} }
} }
fn collapse_root_stack_to(root_stack: &mut Vec<Node>, mut root: Node, collapse_goal: &Node) -> EvalexprResult<Node> { fn collapse_root_stack_to(
root_stack: &mut Vec<Node>,
mut root: Node,
collapse_goal: &Node,
) -> EvalexprResult<Node> {
loop { loop {
if let Some(mut potential_higher_root) = root_stack.pop() { if let Some(mut potential_higher_root) = root_stack.pop() {
// TODO I'm not sure about this >, as I have no example for different sequence operators with the same precedence // TODO I'm not sure about this >, as I have no example for different sequence operators with the same precedence
if potential_higher_root.operator().precedence() > collapse_goal.operator().precedence() { if potential_higher_root.operator().precedence() > collapse_goal.operator().precedence()
{
potential_higher_root.children.push(root); potential_higher_root.children.push(root);
root = potential_higher_root; root = potential_higher_root;
} else { } else {
@ -569,7 +574,7 @@ pub(crate) fn tokens_to_operator_tree(tokens: Vec<Token>) -> EvalexprResult<Node
root_stack.push(node); root_stack.push(node);
} }
} }
// println!("Stack after sequence operation: {:?}", root_stack); // println!("Stack after sequence operation: {:?}", root_stack);
} else if root.operator().is_sequence() { } else if root.operator().is_sequence() {
if let Some(mut last_root_child) = root.children.pop() { if let Some(mut last_root_child) = root.children.pop() {
last_root_child.insert_back_prioritized(node, true)?; last_root_child.insert_back_prioritized(node, true)?;

View File

@ -137,17 +137,15 @@ fn test_functions() {
context context
.set_function( .set_function(
"sub2".to_string(), "sub2".to_string(),
Function::new( Function::new(Box::new(|argument| {
Box::new(|argument| { if let Value::Int(int) = argument {
if let Value::Int(int) = argument { Ok(Value::Int(int - 2))
Ok(Value::Int(int - 2)) } else if let Value::Float(float) = argument {
} else if let Value::Float(float) = argument { Ok(Value::Float(float - 2.0))
Ok(Value::Float(float - 2.0)) } else {
} else { Err(EvalexprError::expected_number(argument.clone()))
Err(EvalexprError::expected_number(argument.clone())) }
} })),
}),
),
) )
.unwrap(); .unwrap();
context context
@ -170,81 +168,76 @@ fn test_n_ary_functions() {
context context
.set_function( .set_function(
"sub2".into(), "sub2".into(),
Function::new( Function::new(Box::new(|argument| {
Box::new(|argument| { if let Value::Int(int) = argument {
if let Value::Int(int) = argument { Ok(Value::Int(int - 2))
Ok(Value::Int(int - 2)) } else if let Value::Float(float) = argument {
} else if let Value::Float(float) = argument { Ok(Value::Float(float - 2.0))
Ok(Value::Float(float - 2.0)) } else {
} else { Err(EvalexprError::expected_number(argument.clone()))
Err(EvalexprError::expected_number(argument.clone())) }
} })),
}),
),
) )
.unwrap(); .unwrap();
context context
.set_function( .set_function(
"avg".into(), "avg".into(),
Function::new( Function::new(Box::new(|argument| {
Box::new(|argument| { let arguments = expect_tuple(argument)?;
let arguments = expect_tuple(argument)?; expect_number(&arguments[0])?;
expect_number(&arguments[0])?; expect_number(&arguments[1])?;
expect_number(&arguments[1])?;
if let (Value::Int(a), Value::Int(b)) = (&arguments[0], &arguments[1]) { if let (Value::Int(a), Value::Int(b)) = (&arguments[0], &arguments[1]) {
Ok(Value::Int((a + b) / 2)) Ok(Value::Int((a + b) / 2))
} else { } else {
Ok(Value::Float( Ok(Value::Float(
(arguments[0].as_float()? + arguments[1].as_float()?) / 2.0, (arguments[0].as_float()? + arguments[1].as_float()?) / 2.0,
)) ))
} }
}), })),
),
) )
.unwrap(); .unwrap();
context context
.set_function( .set_function(
"muladd".into(), "muladd".into(),
Function::new( Function::new(Box::new(|argument| {
Box::new(|argument| { let arguments = expect_tuple(argument)?;
let arguments = expect_tuple(argument)?; expect_number(&arguments[0])?;
expect_number(&arguments[0])?; expect_number(&arguments[1])?;
expect_number(&arguments[1])?; expect_number(&arguments[2])?;
expect_number(&arguments[2])?;
if let (Value::Int(a), Value::Int(b), Value::Int(c)) = if let (Value::Int(a), Value::Int(b), Value::Int(c)) =
(&arguments[0], &arguments[1], &arguments[2]) (&arguments[0], &arguments[1], &arguments[2])
{ {
Ok(Value::Int(a * b + c)) Ok(Value::Int(a * b + c))
} else { } else {
Ok(Value::Float( Ok(Value::Float(
arguments[0].as_float()? * arguments[1].as_float()? arguments[0].as_float()? * arguments[1].as_float()?
+ arguments[2].as_float()?, + arguments[2].as_float()?,
)) ))
} }
}), })),
),
) )
.unwrap(); .unwrap();
context context
.set_function( .set_function(
"count".into(), "count".into(),
Function::new( Function::new(Box::new(|arguments| match arguments {
Box::new(|arguments| { Value::Tuple(tuple) => Ok(Value::from(tuple.len() as IntType)),
match arguments { Value::Empty => Ok(Value::from(0)),
Value::Tuple(tuple) => Ok(Value::from(tuple.len() as IntType)), _ => Ok(Value::from(1)),
Value::Empty => Ok(Value::from(0)), })),
_ => Ok(Value::from(1)),
}
}),
),
) )
.unwrap(); .unwrap();
context context
.set_value("five".to_string(), Value::Int(5)) .set_value("five".to_string(), Value::Int(5))
.unwrap(); .unwrap();
context.set_function("function_four".into(), Function::new(Box::new(|_| {Ok(Value::Int(4))}))).unwrap(); context
.set_function(
"function_four".into(),
Function::new(Box::new(|_| Ok(Value::Int(4)))),
)
.unwrap();
assert_eq!(eval_with_context("avg(7, 5)", &context), Ok(Value::Int(6))); assert_eq!(eval_with_context("avg(7, 5)", &context), Ok(Value::Int(6)));
assert_eq!( assert_eq!(
@ -264,13 +257,19 @@ fn test_n_ary_functions() {
Ok(Value::Int(14)) Ok(Value::Int(14))
); );
assert_eq!(eval_with_context("count()", &context), Ok(Value::Int(0))); assert_eq!(eval_with_context("count()", &context), Ok(Value::Int(0)));
assert_eq!(eval_with_context("count((1, 2, 3))", &context), Ok(Value::Int(3))); assert_eq!(
eval_with_context("count((1, 2, 3))", &context),
Ok(Value::Int(3))
);
assert_eq!( assert_eq!(
eval_with_context("count(3, 5.5, 2)", &context), eval_with_context("count(3, 5.5, 2)", &context),
Ok(Value::Int(3)) Ok(Value::Int(3))
); );
assert_eq!(eval_with_context("count 5", &context), Ok(Value::Int(1))); assert_eq!(eval_with_context("count 5", &context), Ok(Value::Int(1)));
assert_eq!(eval_with_context("function_four()", &context), Ok(Value::Int(4))); assert_eq!(
eval_with_context("function_four()", &context),
Ok(Value::Int(4))
);
} }
#[test] #[test]