use crate::eval::Num; #[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 { match self { UnOp::Neg => Num::Int(0).sub(x), UnOp::Sin => x.sin(), UnOp::Cos => x.cos(), UnOp::Tan => x.tan(), UnOp::Asin => x.asin(), UnOp::Acos => x.acos(), UnOp::Atan => x.atan(), UnOp::Sqrt => x.sqrt(), UnOp::Log => x.log(), UnOp::Log10 => x.log10(), UnOp::Log2 => x.log2(), UnOp::Floor => x.floor(), UnOp::Ceil => x.ceil(), UnOp::Round => x.round(), UnOp::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(Clone, Copy, Debug, PartialEq)] pub enum Op { Num(Num), Un(UnOp), Bin(BinOp), } pub fn eval(ops: &[Op]) -> 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[0] }