diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2024-05-30 20:00:08 -0700 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2024-05-30 21:09:54 -0700 |
| commit | 5e88902a161674605c6835c7be96d412d82e7dd4 (patch) | |
| tree | b14073a4270e0051dfa6dcfb0e3d4112ef5cb452 /src/expr.rs | |
| parent | 5f47e7b0613b7477ef91568f4a4ed1e10dc5f707 (diff) | |
| download | qc-5e88902a161674605c6835c7be96d412d82e7dd4.tar.zst | |
Write tests for parser.
Diffstat (limited to 'src/expr.rs')
| -rw-r--r-- | src/expr.rs | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/expr.rs b/src/expr.rs new file mode 100644 index 0000000..1022de4 --- /dev/null +++ b/src/expr.rs @@ -0,0 +1,106 @@ +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<Expr>, + }, + BinOp { + op: BinOp, + x: Box<Expr>, + y: Box<Expr>, + }, +} + +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()), + } + } +} |
