looklook 0.9.0

Descriptive signal synthesiser.
// Copyright 2026 Gabriel Bjørnager Jensen.
//
// This file is part of LOOKLOOK.
//
// LOOKLOOK is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later ver-
// sion.
//
// LOOKLOOK is distributed in the hope that it will be useful, but WITHOUT ANY WAR-
// RANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License along
// with LOOKLOOK. If not, see <https://www.gnu.org/licenses/>.

//! The [`An`] enumeration.

use std::fmt::{self, Display, Formatter};

/// An address register name.
#[repr(u8)]
#[derive(Copy, Debug)]
#[derive_const(
	Clone,
	Eq,
	Ord,
	PartialEq,
	PartialOrd,
)]
pub enum An {
	/// The `A0` register.
	A0 = 0,

	/// The `A1` register.
	A1 = 1,

	/// The `A2` register.
	A2 = 2,

	/// The `A3` register.
	A3 = 3,

	/// The `A4` register.
	A4 = 4,

	/// The `A5` register.
	A5 = 5,

	/// The frame pointer (`A6`) register.
	Fp = 6,

	/// The stack pointer (`A7`) register.
	Sp = 7,
}

impl An {
	/// The minimum address register index (i.e. `A0`.)
	pub const MIN: Self = Self::A0;

	/// The maximum address register index (i.e. `A7` or `SP`.)
	pub const MAX: Self = Self::Sp;

	/// Reinterprets a [`u16`] value as an address register.
	#[inline]
	#[must_use]
	pub const fn from_u16(mut index: u16) -> Self {
		// Mask to `3` bits.
		index &= 0b111;

		match index {
			0 => Self::A0,
			1 => Self::A1,
			2 => Self::A2,
			3 => Self::A3,
			4 => Self::A4,
			5 => Self::A5,
			6 => Self::Fp,
			7 => Self::Sp,

			_ => {
				unreachable!();
			}
		}
	}

	/// Reinterprets the register index as a [`u16`] scalar index.
	#[inline(always)]
	#[must_use]
	pub const fn as_u16(self) -> u16 {
		self as u16
	}

	/// Retrieves the data index as a [`usize`] value.
	#[inline]
	#[must_use]
	pub const fn as_usize(self) -> usize {
		self.as_u16().into()
	}

	/// Retrieves a textual representation of the register.
	#[inline]
	#[must_use]
	pub const fn as_str(self) -> &'static str {
		match self {
			Self::A0 => "A0",
			Self::A1 => "A1",
			Self::A2 => "A2",
			Self::A3 => "A3",
			Self::A4 => "A4",
			Self::A5 => "A5",
			Self::Fp => "FP",
			Self::Sp => "SP",
		}
	}
}

impl Display for An {
	#[inline]
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		f.write_str(self.as_str())
	}
}