fe-lang / sonatina

Apache License 2.0
47 stars 6 forks source link

Flexible inst cast #68

Closed Y-Nak closed 2 months ago

Y-Nak commented 2 months ago

The new implementation of BranchInfo would be a nice example of this change.

pub trait InstDowncast: Sized {
    fn downcast(isb: &dyn InstSetBase, inst: &dyn Inst) -> Option<Self>;

    fn map<F, R>(isb: &dyn InstSetBase, inst: &dyn Inst, f: F) -> Option<R>
    where
        F: Fn(Self) -> R,
    {
        let data = Self::downcast(isb, inst)?;
        Some(f(data))
    }
}

#[derive(Clone, Copy)]
pub enum BranchInfo<'i> {
    Jump(&'i Jump),
    Br(&'i Br),
    BrTable(&'i BrTable),
}

impl<'i> InstDowncast for BranchInfo<'i> {
    fn downcast(isb: &dyn crate::InstSetBase, inst: &dyn super::Inst) -> Option<Self> {
        InstDowncast::map(isb, inst, BranchInfo::Jump)
            .or_else(|| InstDowncast::map(isb, inst, BranchInfo::Br))
            .or_else(|| InstDowncast::map(isb, inst, BranchInfo::BrTable))
    }
}

NOTE: Inst derive macro automatically implements InstDowncast for &YourInst and InstDowncastMut for &mut YourInst.