use std::any; use std::fmt::{Debug, Error, Formatter}; use std::marker::PhantomData; use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Id { inner: usize, _phantom: PhantomData, } impl Id { /// Creates a new `Id`. /// /// Using a distinct type like `Id` instead of `usize` helps us avoid mixing plain integers /// with identifiers. #[inline] pub const fn new(inner: usize) -> Self { Self { inner, _phantom: PhantomData, } } /// Returns the inner `usize` value. /// /// This requires an explicit call, ensuring we only use the raw value when intended. #[inline] pub const fn get(self) -> usize { self.inner } } impl Debug for Id { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { let marker = any::type_name::().split("::").last().expect("not empty"); write!(f, "{marker}Id({})", self.inner) } } impl Serialize for Id { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { self.inner.serialize(serializer) } } impl<'de, T> Deserialize<'de> for Id { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { let inner = usize::deserialize(deserializer)?; Ok(Self { inner, _phantom: PhantomData, }) } } pub mod marker { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Var; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Decl; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Block; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Module; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Overlay; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct File; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct VirtualPath; } pub type VarId = Id; pub type DeclId = Id; pub type BlockId = Id; pub type ModuleId = Id; pub type OverlayId = Id; pub type FileId = Id; pub type VirtualPathId = Id; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct SpanId(pub usize); // more robust ID style used in the new parser /// An ID for an [IR](crate::ir) register. `%n` is a common shorthand for `RegId(n)`. /// /// Note: `%0` is allocated with the block input at the beginning of a compiled block. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] #[repr(transparent)] pub struct RegId(pub u32); impl std::fmt::Display for RegId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "%{}", self.0) } }