Implementation of the UM-32 "Universal Machine" as described by the Cult of the Bound Variable

add support for `smallvec`

tjh dcf39087 9a425502

Changed files
+38 -5
src
+9
Cargo.lock
··· 3 3 version = 3 4 4 5 5 [[package]] 6 + name = "smallvec" 7 + version = "1.13.2" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 10 + 11 + [[package]] 6 12 name = "um" 7 13 version = "0.1.0" 14 + dependencies = [ 15 + "smallvec", 16 + ]
+4
Cargo.toml
··· 3 3 version = "0.1.0" 4 4 edition = "2021" 5 5 6 + [dependencies] 7 + smallvec = { version = "1.13.2", optional = true } 8 + 6 9 [features] 7 10 default = ["reclaim-memory"] 8 11 reclaim-memory = [] 12 + smallvec = ["dep:smallvec"]
+25 -5
src/main.rs
··· 1 + #[cfg(feature = "smallvec")] 2 + use smallvec::SmallVec; 3 + use std::time::Instant; 4 + 5 + #[cfg(feature = "smallvec")] 6 + const SMALLVEC_SIZE: usize = 24; 7 + 1 8 fn main() { 2 9 let mut program = Vec::new(); 3 10 for arg in std::env::args().skip(1) { ··· 114 121 pub struct Um { 115 122 program_counter: Platter, 116 123 registers: [Platter; 8], 124 + #[cfg(feature = "smallvec")] 125 + memory: Vec<SmallVec<[Platter; SMALLVEC_SIZE]>>, 126 + #[cfg(not(feature = "smallvec"))] 117 127 memory: Vec<Vec<Platter>>, 118 128 #[cfg(feature = "reclaim-memory")] 119 129 free_blocks: Vec<Platter>, ··· 127 137 pub fn new(program: Vec<Platter>) -> Self { 128 138 let ops = decode_ops(&program); 129 139 Self { 130 - memory: vec![program], 140 + memory: vec![program.into()], 131 141 ops, 132 142 ..Default::default() 133 143 } ··· 381 391 382 392 #[cfg(not(feature = "reclaim-memory"))] 383 393 fn allocate_memory(&mut self, length: Platter) -> Platter { 384 - self.memory.push(vec![0; length as usize]); 394 + self.memory.push(Self::new_block(length as usize)); 385 395 (self.memory.len() - 1) as Platter 386 396 } 387 397 388 398 #[cfg(feature = "reclaim-memory")] 389 399 fn allocate_memory(&mut self, length: Platter) -> Platter { 390 400 if let Some(index) = self.free_blocks.pop() { 391 - self.memory[index as usize] = vec![0; length as usize]; 401 + self.memory[index as usize] = Self::new_block(length as usize); 392 402 index as Platter 393 403 } else { 394 - self.memory.push(vec![0; length as usize]); 404 + self.memory.push(Self::new_block(length as usize)); 395 405 (self.memory.len() - 1) as Platter 396 406 } 397 407 } ··· 401 411 #[cfg(feature = "reclaim-memory")] 402 412 { 403 413 self.free_blocks.push(block); 404 - self.memory[block as usize] = vec![]; 414 + self.memory[block as usize] = Self::new_block(0); 405 415 } 406 416 } 407 417 ··· 411 421 "universal machine failure: instruction: {:08x}, program_counter: {:08x}, registers: {:08x?}", 412 422 self.memory[0][self.program_counter as usize], self.program_counter, self.registers 413 423 ) 424 + } 425 + 426 + #[cfg(feature = "smallvec")] 427 + fn new_block(len: usize) -> SmallVec<[Platter; SMALLVEC_SIZE]> { 428 + smallvec::smallvec![0; len] 429 + } 430 + 431 + #[cfg(not(feature = "smallvec"))] 432 + fn new_block(len: usize) -> Vec<Platter> { 433 + vec![0; len] 414 434 } 415 435 }