1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use std::error::Error;
use std::fmt;


/// An error that could've occurred when performing a [μOp](enum.MicroOp.html).
///
/// # Examples
///
/// ```
/// # use pir_8_emu::isa::{GeneralPurposeRegister, SpecialPurposeRegister};
/// # use pir_8_emu::micro::{MicroOpPerformError, MicroOp};
/// # use pir_8_emu::vm::{Memory, Ports};
/// # let (mut memory, mut ports, mut registers, mut pc, mut sp, mut adr, mut ins) =
/// #     (Memory::new(), Ports::new(), GeneralPurposeRegister::defaults(),
/// #      SpecialPurposeRegister::new("Program Counter", "PC"), SpecialPurposeRegister::new("Stack Pointer", "SP"),
/// #      SpecialPurposeRegister::new("Memory Address", "ADR"), SpecialPurposeRegister::new("Instruction", "INS"));
/// assert_eq!(MicroOp::StackPush.perform(&mut vec![], &mut memory, &mut ports, &mut registers,
///                                       &mut pc, &mut sp, &mut adr, &mut ins),
///            Err(MicroOpPerformError::MicrostackUnderflow));
/// ```
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum MicroOpPerformError {
    /// The microstack had too few elements for the μOp being performed
    MicrostackUnderflow,
    /// The top of the microstack had a value outside the domain of the μOp being performed
    InvalidMicrostackTop(u8, &'static [u8]),
}

impl Error for MicroOpPerformError {}

impl fmt::Display for MicroOpPerformError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            MicroOpPerformError::MicrostackUnderflow => f.write_str("μstack underflow"),
            MicroOpPerformError::InvalidMicrostackTop(actual, valid) => {
                write!(f, "Invalid top of the μstack: {:#04x}, expected any of: ", actual)?;
                write_expected(valid, f)
            }
        }
    }
}

fn write_expected(expected: &[u8], f: &mut fmt::Formatter<'_>) -> fmt::Result {
    for (i, x) in expected.iter().enumerate() {
        if i != 0 {
            f.write_str(", ")?;
        }
        write!(f, "{:#04x}", x)?;
    }
    Ok(())
}