use crate::eval::Num; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum BinOp { Pow, Mul, Div, IntDiv, Mod, Add, Sub, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum UnOp { Neg, Sin, Cos, Tan, Asin, Acos, Atan, Sqrt, Log, Log10, Log2, Floor, Ceil, Round, Abs, } #[derive(Debug, PartialEq)] pub enum Expr { Num(Num), UnOp { op: UnOp, x: Box, }, BinOp { op: BinOp, x: Box, y: Box, }, } impl BinOp { pub fn expr(self, x: Expr, y: Expr) -> Expr { Expr::BinOp { op: self, x: Box::new(x), y: Box::new(y), } } 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), } } } impl UnOp { pub fn expr(self, x: Expr) -> Expr { Expr::UnOp { op: self, x: Box::new(x), } } 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(), } } } impl Expr { pub fn eval(&self) -> Num { match self { Expr::Num(n) => *n, Expr::UnOp { op, x } => op.eval(x.eval()), Expr::BinOp { op, x, y } => op.eval(x.eval(), y.eval()), } } }