use super::Stack; use crate::{Byte, Short, Trap}; pub trait Pop { fn pop(stack: &mut Stack) -> Result where Self: Sized; } impl Pop for () { fn pop(_stack: &mut Stack) -> Result { Ok(()) } } impl Pop for Byte { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 1 { return Err(Trap::StackUnderflow); } let a = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; Ok(a) } } impl Pop for bool { fn pop(stack: &mut Stack) -> Result { let a = ::pop(stack)?; Ok(bool::from(a)) } } impl Pop for (Byte, Byte) { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 2 { return Err(Trap::StackUnderflow); } let b = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; let a = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; Ok((a, b)) } } impl Pop for (bool, Byte) { fn pop(stack: &mut Stack) -> Result { let (a, b) = <(Byte, Byte)>::pop(stack)?; Ok((bool::from(a), b)) } } impl Pop for (Byte, Byte, Byte) { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 3 { return Err(Trap::StackUnderflow); } let c = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; let b = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; let a = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; Ok((a, b, c)) } } impl Pop for Short { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 2 { return Err(Trap::StackUnderflow); } let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; Ok(a) } } impl Pop for (Byte, Short) { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 3 { return Err(Trap::StackUnderflow); } let b = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; let a = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; Ok((a, b)) } } impl Pop for (bool, Short) { fn pop(stack: &mut Stack) -> Result { let (a, b) = <(Byte, Short)>::pop(stack)?; Ok((bool::from(a), b)) } } impl Pop for (Short, Byte) { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 3 { return Err(Trap::StackUnderflow); } let b = { let val = stack.data[stack.ptr as usize - 1]; stack.ptr -= 1; Byte::from(val) }; let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; Ok((a, b)) } } impl Pop for (Short, Short) { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 4 { return Err(Trap::StackUnderflow); } let b = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; Ok((a, b)) } } impl Pop for (Short, Short, Short) { fn pop(stack: &mut Stack) -> Result { if stack.ptr < 6 { return Err(Trap::StackUnderflow); } let c = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; let b = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; let a = { let val = u16::from_be_bytes([ stack.data[stack.ptr as usize - 2], stack.data[stack.ptr as usize - 1], ]); stack.ptr -= 2; Short::from(val) }; Ok((a, b, c)) } }