oysh/crates/oyster_runtime/src/builtins/math.rs
Charlotte Meyer 5e18e89af4 feat(builtins): add basic math builtins
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>
2022-11-05 13:22:33 +00:00

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);