/*! * MIR Value ID System - SSA value tracking * * Implements unique identifiers for SSA values with type safety */ use std::fmt; /// Unique identifier for SSA values within a function #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ValueId(pub u32); impl ValueId { /// Invalid/uninitialized ValueId sentinel pub const INVALID: Self = ValueId(u32::MAX); /// Create a new ValueId pub fn new(id: u32) -> Self { ValueId(id) } /// Get the raw ID value pub fn as_u32(self) -> u32 { self.0 } /// Create ValueId from usize (for array indexing) pub fn from_usize(id: usize) -> Self { ValueId(id as u32) } /// Convert to usize (for array indexing) pub fn to_usize(self) -> usize { self.0 as usize } } impl fmt::Display for ValueId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "%{}", self.0) } } /// Local variable identifier (before SSA conversion) #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct LocalId(pub u32); impl LocalId { /// Create a new LocalId pub fn new(id: u32) -> Self { LocalId(id) } /// Get the raw ID value pub fn as_u32(self) -> u32 { self.0 } } impl fmt::Display for LocalId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "local_{}", self.0) } } /// Value ID generator for unique SSA value creation #[derive(Debug, Clone)] pub struct ValueIdGenerator { next_id: u32, } impl ValueIdGenerator { /// Create a new generator starting from 0 pub fn new() -> Self { Self { next_id: 0 } } /// Generate the next unique ValueId pub fn next(&mut self) -> ValueId { let id = ValueId(self.next_id); self.next_id += 1; id } /// Peek at the next ID without consuming it pub fn peek_next(&self) -> ValueId { ValueId(self.next_id) } /// Reset the generator (for testing) pub fn reset(&mut self) { self.next_id = 0; } } impl Default for ValueIdGenerator { fn default() -> Self { Self::new() } } /// Local ID generator for variable naming #[derive(Debug, Clone)] pub struct LocalIdGenerator { next_id: u32, } impl LocalIdGenerator { /// Create a new generator starting from 0 pub fn new() -> Self { Self { next_id: 0 } } /// Generate the next unique LocalId pub fn next(&mut self) -> LocalId { let id = LocalId(self.next_id); self.next_id += 1; id } /// Reset the generator (for testing) pub fn reset(&mut self) { self.next_id = 0; } } impl Default for LocalIdGenerator { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_value_id_creation() { let id1 = ValueId::new(0); let id2 = ValueId::new(1); assert_eq!(id1.as_u32(), 0); assert_eq!(id2.as_u32(), 1); assert_ne!(id1, id2); assert_eq!(format!("{}", id1), "%0"); assert_eq!(format!("{}", id2), "%1"); } #[test] fn test_value_id_generator() { let mut gen = ValueIdGenerator::new(); let id1 = gen.next(); let id2 = gen.next(); let id3 = gen.next(); assert_eq!(id1, ValueId(0)); assert_eq!(id2, ValueId(1)); assert_eq!(id3, ValueId(2)); assert_eq!(gen.peek_next(), ValueId(3)); } #[test] fn test_local_id_creation() { let local1 = LocalId::new(0); let local2 = LocalId::new(1); assert_eq!(format!("{}", local1), "local_0"); assert_eq!(format!("{}", local2), "local_1"); } #[test] fn test_local_id_generator() { let mut gen = LocalIdGenerator::new(); let local1 = gen.next(); let local2 = gen.next(); assert_eq!(local1, LocalId(0)); assert_eq!(local2, LocalId(1)); } #[test] fn test_value_id_ordering() { let id1 = ValueId(1); let id2 = ValueId(2); let id3 = ValueId(3); assert!(id1 < id2); assert!(id2 < id3); assert!(id1 < id3); let mut ids = vec![id3, id1, id2]; ids.sort(); assert_eq!(ids, vec![id1, id2, id3]); } }