This adds basic addition, substraction, multiplication, and division commands as builtins. All of those operate solely on f64's. Signed-off-by: Charlotte Meyer <dev@buffet.sh>
57 lines
1.6 KiB
Rust
57 lines
1.6 KiB
Rust
use std::{
|
|
borrow::Cow,
|
|
ffi::OsStr,
|
|
io::{self, Write},
|
|
process,
|
|
};
|
|
|
|
use oyster_builtin_proc::builtin;
|
|
|
|
use crate::Shell;
|
|
|
|
macro_rules! operator {
|
|
($name:literal, $desc:literal, $funcname:ident, $operator:tt, $neutral:literal) => {
|
|
#[builtin(name = $name, description = $desc)]
|
|
pub fn $funcname(_shell: &mut Shell, args: &[Cow<OsStr>]) {
|
|
let mut errored = false;
|
|
|
|
let mut parse = |n: &Cow<OsStr>| {
|
|
n
|
|
.to_str()
|
|
.map(|n| {
|
|
n.parse::<f64>().unwrap_or_else(|_| {
|
|
writeln!(io::stderr(), "not a number: {:?}", n).unwrap();
|
|
errored = true;
|
|
$neutral
|
|
})
|
|
})
|
|
.unwrap_or_else(|| {
|
|
writeln!(io::stderr(), "not a number: {:?}", n).unwrap();
|
|
errored = true;
|
|
$neutral
|
|
})
|
|
};
|
|
|
|
let mut args = args.iter();
|
|
let mut acc = args.next().map(&mut parse).unwrap_or($neutral);
|
|
|
|
#[allow(clippy::assign_op_pattern)]
|
|
for n in args {
|
|
acc = acc $operator parse(n);
|
|
}
|
|
|
|
writeln!(io::stdout(), "{}", acc).unwrap();
|
|
|
|
process::exit(if errored {
|
|
1
|
|
} else {
|
|
0
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
operator!("+", "adds numbers", add, +, 0.0);
|
|
operator!("-", "subtracts numbers", sub, -, 0.0);
|
|
operator!("*", "multiplies numbers", mul, *, 1.0);
|
|
operator!("/", "divides numbers", div, /, 1.0);
|