42 lines
1.3 KiB
Rust
Raw Normal View History

// © 2023 John Breaux
//! A [`JumpTarget`] contains the [pc-relative offset](Number) or [label](Identifier)
//! for a [Jump](Encoding::Jump) [instruction]
use super::*;
/// Contains the [pc-relative offset](Number) or [label](Identifier)
2023-08-23 02:25:43 -05:00
/// for a [Jump](Encoding::Jump) [Instruction]
// TODO: Allow identifiers in JumpTarget
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct JumpTarget(Number);
impl JumpTarget {
pub fn word(&self) -> u16 { u16::from(self.0) & 0x3ff }
}
impl Parsable for JumpTarget {
/// - Identifier
/// - Number
/// - Negative
/// - Number
fn parse<'text, T>(p: &Parser, stream: &mut T) -> Result<Self, Error>
where T: crate::TokenStream<'text> {
// Try to parse a number
let target = Number::parse(p, stream)?;
match target.into() {
i if i % 2 != 0 => Err(Error::JumpedOdd(i).context(stream.context()))?,
i if (-1024..=1022).contains(&(i - 2)) => Ok(Self((target - 2) >> 1)),
i => Err(Error::JumpedTooFar(i).context(stream.context()))?,
}
}
}
impl From<JumpTarget> for u16 {
fn from(value: JumpTarget) -> Self { value.0.into() }
}
impl Display for JumpTarget {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", (1 + isize::from(self.0)) << 1)
}
}