use crate::eval::Num; use num::BigInt; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum UnOp { Neg, Sin, Cos, Tan, Asin, Acos, Atan, Sqrt, Log, Log10, Log2, Floor, Ceil, Round, Abs, } impl UnOp { fn eval(self, x: Num) -> Num { use UnOp::*; match self { Neg => Num::Int(BigInt::from(0)).sub(x), Sin => x.sin(), Cos => x.cos(), Tan => x.tan(), Asin => x.asin(), Acos => x.acos(), Atan => x.atan(), Sqrt => x.sqrt(), Log => x.log(), Log10 => x.log10(), Log2 => x.log2(), Floor => x.floor(), Ceil => x.ceil(), Round => x.round(), Abs => x.abs(), } } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum BinOp { Pow, Mul, Div, IntDiv, Mod, Add, Sub, } impl BinOp { fn eval(self, x: Num, y: Num) -> Num { match self { BinOp::Pow => x.pow(y), BinOp::Mul => x.mul(&y), BinOp::Div => x.div(y), BinOp::IntDiv => x.int_div(y), BinOp::Mod => x.modulo(y), BinOp::Add => x.add(y), BinOp::Sub => x.sub(y), } } } #[derive(Debug, PartialEq)] pub enum Op { Num(Num), Un(UnOp), Bin(BinOp), } pub fn eval(ops: impl Iterator) -> Num { let mut stack = Vec::new(); for op in ops { match op { Op::Num(n) => stack.push(n), Op::Un(op) => { let n = stack.pop().unwrap(); stack.push(op.eval(n)); } Op::Bin(op) => { let n2 = stack.pop().unwrap(); let n1 = stack.pop().unwrap(); stack.push(op.eval(n1, n2)); } } } stack.pop().unwrap() }