use std::{ fmt::*, ops::{Add, Div, Mul, Sub}, }; #[derive(Debug, Copy, Clone)] pub enum LispNumber { Integer(i64), Float(f64), } impl Add for LispNumber { type Output = Self; fn add(self, rhs: Self) -> Self::Output { use LispNumber::*; match (self, rhs) { (Integer(a), Integer(b)) => Integer(a + b), (Float(a), Integer(b)) => Float(a + b as f64), (Integer(a), Float(b)) => Float(a as f64 + b), (Float(a), Float(b)) => Float(a + b), } } } impl Sub for LispNumber { type Output = Self; fn sub(self, rhs: Self) -> Self::Output { use LispNumber::*; match (self, rhs) { (Integer(a), Integer(b)) => Integer(a - b), (Float(a), Integer(b)) => Float(a - b as f64), (Integer(a), Float(b)) => Float(a as f64 - b), (Float(a), Float(b)) => Float(a - b), } } } impl Mul for LispNumber { type Output = Self; fn mul(self, rhs: Self) -> Self::Output { use LispNumber::*; match (self, rhs) { (Integer(a), Integer(b)) => Integer(a * b), (Float(a), Integer(b)) => Float(a * b as f64), (Integer(a), Float(b)) => Float(a as f64 * b), (Float(a), Float(b)) => Float(a * b), } } } impl PartialEq for LispNumber { fn eq(&self, other: &Self) -> bool { use LispNumber::*; match (self, other) { (Integer(a), Integer(b)) => *a == *b, (Float(a), Integer(b)) => *a == *b as f64, (Integer(a), Float(b)) => *a as f64 == *b, (Float(a), Float(b)) => *a == *b, } } } impl Display for LispNumber { fn fmt(&self, f: &mut Formatter<'_>) -> Result { match self { LispNumber::Integer(v) => write!(f, "{}", v), LispNumber::Float(v) => write!(f, "{}", v), } } }