stack-assembly 1.0.0

minimalist, stack-based, assembly-like programming language
Documentation
use std::fmt;

/// # A unit of data
///
/// StackAssembly is an _untyped_ languages. All of its values, both on the
/// [`OperandStack`] and in [`Memory`], are 32 bits wide. Depending on the
/// situation, they may be interpreted as unsigned or signed.
///
/// You can create an instance of `Value` through its `From` implementations.
///
/// ```
/// use stack_assembly::Value;
///
/// Value::from(3i32);
/// Value::from(5u32);
/// ```
///
/// [`OperandStack`]: crate::OperandStack
/// [`Memory`]: crate::Memory
#[derive(Clone, Copy, Eq, PartialEq, bytemuck::Pod, bytemuck::Zeroable)]
#[repr(transparent)]
pub struct Value {
    inner: u32,
}

impl Value {
    /// # Convert the value to an `i32`
    ///
    /// Since all values are 32 bits wide, this is always possible. Interprets
    /// the bits of the value as a signed (two's complement) integer.
    pub fn to_i32(self) -> i32 {
        i32::from_le_bytes(self.inner.to_le_bytes())
    }

    /// # Convert the value to a `u32`
    ///
    /// Since all values are 32 bits wide, this is always possible. Interprets
    /// the bits of the value as an unsigned integer.
    pub fn to_u32(self) -> u32 {
        self.inner
    }

    /// # Convert to a `bool`
    ///
    /// A zero value is considered `false`, while any other value is considered
    /// `true`.
    pub fn to_bool(self) -> bool {
        self.inner != 0
    }
}

impl From<bool> for Value {
    fn from(value: bool) -> Self {
        let inner = if value { 1 } else { 0 };
        Self { inner }
    }
}

impl From<i32> for Value {
    fn from(value: i32) -> Self {
        let inner = u32::from_le_bytes(value.to_le_bytes());
        Self { inner }
    }
}

impl From<u32> for Value {
    fn from(inner: u32) -> Self {
        Self { inner }
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Let's bypass this type and format the inner value. This is just a
        // wrapper anyway, and showing it in debug output is unnecessary noise.
        self.inner.fmt(f)
    }
}