bitcalc 0.3.0

A calculator with bit operations
use std::fmt::Display;

#[derive(Debug)]
pub enum Expr {
    Op(Op),
    Val(Val),
}

#[derive(Debug)]
pub enum Op {
    Mul(Box<Expr>, Box<Expr>),
    Div(Box<Expr>, Box<Expr>),
    Mod(Box<Expr>, Box<Expr>),
    Add(Box<Expr>, Box<Expr>),
    Sub(Box<Expr>, Box<Expr>),
    Pow(Box<Expr>, Box<Expr>),
    ShiftLeft(Box<Expr>, Box<Expr>),
    ShiftRight(Box<Expr>, Box<Expr>),
    RotLeft(Box<Expr>, Box<Expr>),
    RotRight(Box<Expr>, Box<Expr>),
    BitXor(Box<Expr>, Box<Expr>),
    BitOr(Box<Expr>, Box<Expr>),
    BitAnd(Box<Expr>, Box<Expr>),
}

#[derive(Debug)]
pub enum Val {
    Hex(u64),
    Int(u64),
    Bin(u64),
    LastAnswer,
    History(usize),
}

impl Display for Expr {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Expr::Op(op) => op.fmt(f),
            Expr::Val(val) => val.fmt(f),
        }
    }
}

impl Display for Op {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Op::Mul(a, b) => write!(f, "( {a} * {b} )"),
            Op::Div(a, b) => write!(f, "( {a} / {b} )"),
            Op::Mod(a, b) => write!(f, "( {a} % {b} )"),
            Op::Add(a, b) => write!(f, "( {a} + {b} )"),
            Op::Sub(a, b) => write!(f, "( {a} - {b} )"),
            Op::Pow(a, b) => write!(f, "( {a} ** {b} )"),
            Op::ShiftLeft(a, b) => write!(f, "( {a} << {b} )"),
            Op::ShiftRight(a, b) => write!(f, "( {a} >> {b} )"),
            Op::RotLeft(a, b) => write!(f, "( {a} rotl {b} )"),
            Op::RotRight(a, b) => write!(f, "( {a} rotr {b} )"),
            Op::BitXor(a, b) => write!(f, "( {a} ^ {b} )"),
            Op::BitOr(a, b) => write!(f, "( {a} | {b} )"),
            Op::BitAnd(a, b) => write!(f, "( {a} & {b} )"),
        }
    }
}

impl Display for Val {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Val::Hex(a) => write!(f, "{a:#x}"),
            Val::Int(a) => write!(f, "{a}"),
            Val::Bin(a) => write!(f, "{a:#b}"),
            Val::LastAnswer => write!(f, "_"),
            Val::History(x) => write!(f, "${x}"),
        }
    }
}