Implement bitwise operators as builtin functions.

Relates to #88
This commit is contained in:
Sebastian Schmidt 2021-07-30 17:06:23 +03:00
parent e0d4ef24e5
commit b3be7f600c
5 changed files with 40 additions and 0 deletions

View File

@ -6,6 +6,8 @@
### Added ### Added
* Bitwise operators as builtin functions `bitand`, `bitor`, `bitxor`, `bitnot` (#88)
### Removed ### Removed
### Changed ### Changed

View File

@ -373,6 +373,10 @@ This crate offers a set of builtin functions.
| `str::to_uppercase` | 1 | String | Returns the upper-case version of the string | | `str::to_uppercase` | 1 | String | Returns the upper-case version of the string |
| `str::trim` | 1 | String | Strips whitespace from the start and the end of the string | | `str::trim` | 1 | String | Strips whitespace from the start and the end of the string |
| `str::from` | >= 0 | Any | Returns passed value as string | | `str::from` | >= 0 | Any | Returns passed value as string |
| `bitand` | 2 | Int | Computes the bitwise and of the given integers |
| `bitor` | 2 | Int | Computes the bitwise or of the given integers |
| `bitxor` | 2 | Int | Computes the bitwise xor of the given integers |
| `bitnot` | 1 | Int | Computes the bitwise not of the given integer |
The `min` and `max` functions can deal with a mixture of integer and floating point arguments. The `min` and `max` functions can deal with a mixture of integer and floating point arguments.
If the maximum or minimum is an integer, then an integer is returned. If the maximum or minimum is an integer, then an integer is returned.

View File

@ -5,6 +5,7 @@ use crate::{
value::{FloatType, IntType}, value::{FloatType, IntType},
EvalexprError, Function, Value, ValueType, EvalexprError, Function, Value, ValueType,
}; };
use std::ops::{BitAnd, BitOr, BitXor, Not};
macro_rules! simple_math { macro_rules! simple_math {
($func:ident) => { ($func:ident) => {
@ -22,6 +23,22 @@ macro_rules! simple_math {
}; };
} }
macro_rules! int_function {
($func:ident) => {
Some(Function::new(|argument| {
let int = argument.as_int()?;
Ok(Value::Int(int.$func()))
}))
};
($func:ident, 2) => {
Some(Function::new(|argument| {
let tuple = argument.as_fixed_len_tuple(2)?;
let (a, b) = (tuple[0].as_int()?, tuple[1].as_int()?);
Ok(Value::Int(a.$func(b)))
}))
};
}
pub fn builtin_function(identifier: &str) -> Option<Function> { pub fn builtin_function(identifier: &str) -> Option<Function> {
match identifier { match identifier {
// Log // Log
@ -163,6 +180,11 @@ pub fn builtin_function(identifier: &str) -> Option<Function> {
"str::from" => Some(Function::new(|argument| { "str::from" => Some(Function::new(|argument| {
Ok(Value::String(argument.to_string())) Ok(Value::String(argument.to_string()))
})), })),
// Bitwise operators
"bitand" => int_function!(bitand, 2),
"bitor" => int_function!(bitor, 2),
"bitxor" => int_function!(bitxor, 2),
"bitnot" => int_function!(not),
_ => None, _ => None,
} }
} }

View File

@ -356,6 +356,10 @@
//! | `str::to_uppercase` | 1 | String | Returns the upper-case version of the string | //! | `str::to_uppercase` | 1 | String | Returns the upper-case version of the string |
//! | `str::trim` | 1 | String | Strips whitespace from the start and the end of the string | //! | `str::trim` | 1 | String | Strips whitespace from the start and the end of the string |
//! | `str::from` | >= 0 | Any | Returns passed value as string | //! | `str::from` | >= 0 | Any | Returns passed value as string |
//! | `bitand` | 2 | Int | Computes the bitwise and of the given integers |
//! | `bitor` | 2 | Int | Computes the bitwise or of the given integers |
//! | `bitxor` | 2 | Int | Computes the bitwise xor of the given integers |
//! | `bitnot` | 1 | Int | Computes the bitwise not of the given integer |
//! //!
//! The `min` and `max` functions can deal with a mixture of integer and floating point arguments. //! The `min` and `max` functions can deal with a mixture of integer and floating point arguments.
//! If the maximum or minimum is an integer, then an integer is returned. //! If the maximum or minimum is an integer, then an integer is returned.

View File

@ -395,6 +395,14 @@ fn test_builtin_functions() {
Ok(Value::String(String::from("(1, 2, 3)"))) Ok(Value::String(String::from("(1, 2, 3)")))
); );
assert_eq!(eval("str::from()"), Ok(Value::String(String::from("()")))); assert_eq!(eval("str::from()"), Ok(Value::String(String::from("()"))));
assert_eq!(eval("bitand(5, -1)"), Ok(Value::Int(5)));
assert_eq!(eval("bitand(6, 5)"), Ok(Value::Int(4)));
assert_eq!(eval("bitor(5, -1)"), Ok(Value::Int(-1)));
assert_eq!(eval("bitor(6, 5)"), Ok(Value::Int(7)));
assert_eq!(eval("bitxor(5, -1)"), Ok(Value::Int(-6)));
assert_eq!(eval("bitxor(6, 5)"), Ok(Value::Int(3)));
assert_eq!(eval("bitnot(5)"), Ok(Value::Int(-6)));
assert_eq!(eval("bitnot(-1)"), Ok(Value::Int(0)));
} }
#[test] #[test]