aboutsummaryrefslogtreecommitdiffstats
path: root/src/op.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/op.rs')
-rw-r--r--src/op.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/op.rs b/src/op.rs
new file mode 100644
index 0000000..6a2d00f
--- /dev/null
+++ b/src/op.rs
@@ -0,0 +1,93 @@
+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]
+}