/// An operation to perform on two subexpressions.
#[derive(Debug)]
enum Operation {
Add,
Sub,
Mul,
Div,
}
/// An expression, in tree form.
#[derive(Debug)]
enum Expression {
/// An operation on two subexpressions.
Op { op: Operation, left: Box<Expression>, right: Box<Expression> },
/// A literal value
Value(i64),
}
fn eval(e: Expression) -> i64 {
match e {
Expression::Op { op, left, right } => {
let left = eval(*left);
let right = eval(*right);
match op {
Operation::Add => left + right,
Operation::Sub => left - right,
Operation::Mul => left * right,
Operation::Div => left / right,
}
}
Expression::Value(v) => v,
}
}
#[test]
fn test_value() {
assert_eq!(eval(Expression::Value(19)), 19);
}
#[test]
fn test_sum() {
assert_eq!(
eval(Expression::Op {
op: Operation::Add,
left: Box::new(Expression::Value(10)),
right: Box::new(Expression::Value(20)),
}),
30
);
}
#[test]
fn test_recursion() {
let term1 = Expression::Op {
op: Operation::Mul,
left: Box::new(Expression::Value(10)),
right: Box::new(Expression::Value(9)),
};
let term2 = Expression::Op {
op: Operation::Mul,
left: Box::new(Expression::Op {
op: Operation::Sub,
left: Box::new(Expression::Value(3)),
right: Box::new(Expression::Value(4)),
}),
right: Box::new(Expression::Value(5)),
};
assert_eq!(
eval(Expression::Op {
op: Operation::Add,
left: Box::new(term1),
right: Box::new(term2),
}),
85
);
}
#[test]
fn test_zeros() {
assert_eq!(
eval(Expression::Op {
op: Operation::Add,
left: Box::new(Expression::Value(0)),
right: Box::new(Expression::Value(0))
}),
0
);
assert_eq!(
eval(Expression::Op {
op: Operation::Mul,
left: Box::new(Expression::Value(0)),
right: Box::new(Expression::Value(0))
}),
0
);
assert_eq!(
eval(Expression::Op {
op: Operation::Sub,
left: Box::new(Expression::Value(0)),
right: Box::new(Expression::Value(0))
}),
0
);
}
fn main() {
let expr = Expression::Op {
op: Operation::Sub,
left: Box::new(Expression::Value(20)),
right: Box::new(Expression::Value(10)),
};
println!("expr: {expr:?}");
println!("result: {:?}", eval(expr));
}