parent
8e898044c0
commit
fd3243e555
18
README.md
18
README.md
@ -45,7 +45,7 @@ use evalexpr::error::expect_number;
|
|||||||
let mut configuration = HashMapConfiguration::new();
|
let mut configuration = HashMapConfiguration::new();
|
||||||
configuration.insert_variable("five", 5);
|
configuration.insert_variable("five", 5);
|
||||||
configuration.insert_variable("twelve", 12);
|
configuration.insert_variable("twelve", 12);
|
||||||
configuration.insert_function("f", Function::new(1 /* argument amount */, Box::new(|arguments| {
|
configuration.insert_function("f", Function::new(Some(1) /* argument amount */, Box::new(|arguments| {
|
||||||
if let Value::Int(int) = arguments[0] {
|
if let Value::Int(int) = arguments[0] {
|
||||||
Ok(Value::Int(int / 2))
|
Ok(Value::Int(int / 2))
|
||||||
} else if let Value::Float(float) = arguments[0] {
|
} else if let Value::Float(float) = arguments[0] {
|
||||||
@ -54,7 +54,7 @@ configuration.insert_function("f", Function::new(1 /* argument amount */, Box::n
|
|||||||
Err(Error::expected_number(arguments[0].clone()))
|
Err(Error::expected_number(arguments[0].clone()))
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
configuration.insert_function("avg", Function::new(2 /* argument amount */, Box::new(|arguments| {
|
configuration.insert_function("avg", Function::new(Some(2) /* argument amount */, Box::new(|arguments| {
|
||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
|
||||||
@ -115,6 +115,18 @@ Supported unary operators:
|
|||||||
| - | 110 | Negation |
|
| - | 110 | Negation |
|
||||||
| ! | 110 | Logical not |
|
| ! | 110 | Logical not |
|
||||||
|
|
||||||
|
#### The Aggregation Operator
|
||||||
|
|
||||||
|
The aggregation operator aggregates two values into a tuple.
|
||||||
|
If one of the values is a tuple already, the resulting tuple will be flattened.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use evalexpr::*;
|
||||||
|
|
||||||
|
assert_eq!(eval("1, 2, 3"), Ok(Value::from(vec![Value::from(1), Value::from(2), Value::from(3)])));
|
||||||
|
```
|
||||||
|
|
||||||
### Values
|
### Values
|
||||||
|
|
||||||
Operators take values as arguments and produce values as results.
|
Operators take values as arguments and produce values as results.
|
||||||
@ -157,7 +169,7 @@ This crate also allows to define arbitrary functions to be used in parsed expres
|
|||||||
A function is defined as a `Function` instance.
|
A function is defined as a `Function` instance.
|
||||||
It contains two properties, the `argument_amount` and the `function`.
|
It contains two properties, the `argument_amount` and the `function`.
|
||||||
The `function` is a boxed `Fn(&[Value]) -> Result<Value, Error>`.
|
The `function` is a boxed `Fn(&[Value]) -> Result<Value, Error>`.
|
||||||
The `argument_amount` determines the length of the slice that is passed to `function`.
|
The `argument_amount` determines the length of the slice that is passed to `function` if it is `Some(_)`, otherwise the function is defined to take an arbitrary amount of arguments.
|
||||||
It is verified on execution by the crate and does not need to be verified by the `function`.
|
It is verified on execution by the crate and does not need to be verified by the `function`.
|
||||||
|
|
||||||
Be aware that functions need to verify the types of values that are passed to them.
|
Be aware that functions need to verify the types of values that are passed to them.
|
||||||
|
@ -2,13 +2,13 @@ use error::{self, Error};
|
|||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
argument_amount: usize,
|
argument_amount: Option<usize>,
|
||||||
function: Box<Fn(&[Value]) -> Result<Value, Error>>,
|
function: Box<Fn(&[Value]) -> Result<Value, Error>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
argument_amount: usize,
|
argument_amount: Option<usize>,
|
||||||
function: Box<Fn(&[Value]) -> Result<Value, Error>>,
|
function: Box<Fn(&[Value]) -> Result<Value, Error>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -18,7 +18,10 @@ impl Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&self, arguments: &[Value]) -> Result<Value, Error> {
|
pub fn call(&self, arguments: &[Value]) -> Result<Value, Error> {
|
||||||
error::expect_function_argument_amount(arguments.len(), self.argument_amount)?;
|
if let Some(argument_amount) = self.argument_amount {
|
||||||
|
error::expect_function_argument_amount(arguments.len(), argument_amount)?;
|
||||||
|
}
|
||||||
|
|
||||||
(self.function)(arguments)
|
(self.function)(arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
src/lib.rs
14
src/lib.rs
@ -34,7 +34,7 @@
|
|||||||
//! let mut configuration = HashMapConfiguration::new();
|
//! let mut configuration = HashMapConfiguration::new();
|
||||||
//! configuration.insert_variable("five", 5);
|
//! configuration.insert_variable("five", 5);
|
||||||
//! configuration.insert_variable("twelve", 12);
|
//! configuration.insert_variable("twelve", 12);
|
||||||
//! configuration.insert_function("f", Function::new(1 /* argument amount */, Box::new(|arguments| {
|
//! configuration.insert_function("f", Function::new(Some(1) /* argument amount */, Box::new(|arguments| {
|
||||||
//! if let Value::Int(int) = arguments[0] {
|
//! if let Value::Int(int) = arguments[0] {
|
||||||
//! Ok(Value::Int(int / 2))
|
//! Ok(Value::Int(int / 2))
|
||||||
//! } else if let Value::Float(float) = arguments[0] {
|
//! } else if let Value::Float(float) = arguments[0] {
|
||||||
@ -43,7 +43,7 @@
|
|||||||
//! Err(Error::expected_number(arguments[0].clone()))
|
//! Err(Error::expected_number(arguments[0].clone()))
|
||||||
//! }
|
//! }
|
||||||
//! })));
|
//! })));
|
||||||
//! configuration.insert_function("avg", Function::new(2 /* argument amount */, Box::new(|arguments| {
|
//! configuration.insert_function("avg", Function::new(Some(2) /* argument amount */, Box::new(|arguments| {
|
||||||
//! expect_number(&arguments[0])?;
|
//! expect_number(&arguments[0])?;
|
||||||
//! expect_number(&arguments[1])?;
|
//! expect_number(&arguments[1])?;
|
||||||
//!
|
//!
|
||||||
@ -158,7 +158,7 @@
|
|||||||
//! A function is defined as a `Function` instance.
|
//! A function is defined as a `Function` instance.
|
||||||
//! It contains two properties, the `argument_amount` and the `function`.
|
//! It contains two properties, the `argument_amount` and the `function`.
|
||||||
//! The `function` is a boxed `Fn(&[Value]) -> Result<Value, Error>`.
|
//! The `function` is a boxed `Fn(&[Value]) -> Result<Value, Error>`.
|
||||||
//! The `argument_amount` determines the length of the slice that is passed to `function`.
|
//! The `argument_amount` determines the length of the slice that is passed to `function` if it is `Some(_)`, otherwise the function is defined to take an arbitrary amount of arguments.
|
||||||
//! It is verified on execution by the crate and does not need to be verified by the `function`.
|
//! It is verified on execution by the crate and does not need to be verified by the `function`.
|
||||||
//!
|
//!
|
||||||
//! Be aware that functions need to verify the types of values that are passed to them.
|
//! Be aware that functions need to verify the types of values that are passed to them.
|
||||||
@ -365,7 +365,7 @@ mod test {
|
|||||||
configuration.insert_function(
|
configuration.insert_function(
|
||||||
"sub2".to_string(),
|
"sub2".to_string(),
|
||||||
Function::new(
|
Function::new(
|
||||||
1,
|
Some(1),
|
||||||
Box::new(|arguments| {
|
Box::new(|arguments| {
|
||||||
if let Value::Int(int) = arguments[0] {
|
if let Value::Int(int) = arguments[0] {
|
||||||
Ok(Value::Int(int - 2))
|
Ok(Value::Int(int - 2))
|
||||||
@ -407,7 +407,7 @@ mod test {
|
|||||||
configuration.insert_function(
|
configuration.insert_function(
|
||||||
"sub2",
|
"sub2",
|
||||||
Function::new(
|
Function::new(
|
||||||
1,
|
Some(1),
|
||||||
Box::new(|arguments| {
|
Box::new(|arguments| {
|
||||||
if let Value::Int(int) = arguments[0] {
|
if let Value::Int(int) = arguments[0] {
|
||||||
Ok(Value::Int(int - 2))
|
Ok(Value::Int(int - 2))
|
||||||
@ -422,7 +422,7 @@ mod test {
|
|||||||
configuration.insert_function(
|
configuration.insert_function(
|
||||||
"avg",
|
"avg",
|
||||||
Function::new(
|
Function::new(
|
||||||
2,
|
Some(2),
|
||||||
Box::new(|arguments| {
|
Box::new(|arguments| {
|
||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
@ -440,7 +440,7 @@ mod test {
|
|||||||
configuration.insert_function(
|
configuration.insert_function(
|
||||||
"muladd",
|
"muladd",
|
||||||
Function::new(
|
Function::new(
|
||||||
3,
|
Some(3),
|
||||||
Box::new(|arguments| {
|
Box::new(|arguments| {
|
||||||
expect_number(&arguments[0])?;
|
expect_number(&arguments[0])?;
|
||||||
expect_number(&arguments[1])?;
|
expect_number(&arguments[1])?;
|
||||||
|
Loading…
Reference in New Issue
Block a user