From d6577e5c4d1be7eb064e55a9b8c7b3c4bc5b6fd7 Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sun, 21 Aug 2022 08:47:04 -0700 Subject: [PATCH] 14.challenges.1 --- rust/justfile | 3 ++- rust/src/chunk.rs | 63 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/rust/justfile b/rust/justfile index cdac729..7868a1a 100644 --- a/rust/justfile +++ b/rust/justfile @@ -1,2 +1,3 @@ test-watch: - while true; do fd .*.rs | entr -d cargo test; done + # while true; do fd .*.rs | entr -d cargo test; done + fd .*.rs | entr -d cargo test diff --git a/rust/src/chunk.rs b/rust/src/chunk.rs index 881c768..41ddbe5 100644 --- a/rust/src/chunk.rs +++ b/rust/src/chunk.rs @@ -10,24 +10,58 @@ pub enum OpCode { type Value = f32; +#[derive(Default)] pub struct Chunk { code: Vec, constants: Vec, - lines: Vec, + lines: Lines, } -impl Chunk { - pub fn new() -> Self { - Chunk { - code: Vec::new(), - constants: Vec::new(), - lines: Vec::new(), +// Lines are stored using run-length encoding, where the first element is the line and the second +// element the number of instructions that are associated with that line +#[derive(Default, Debug)] +struct Lines(std::vec::Vec<(usize, usize)>); + +impl Lines { + fn add(&mut self, line: usize) { + if let Some(last) = self.0.last_mut() { + last.1 += 1; + } else { + self.0.push((line, 1)); } } + fn get(&self, offset: usize) -> (usize, bool) { + let mut offset = offset; + for (line, run) in self.0.iter() { + if offset == 0 { + return (*line, true); + } + + if offset < *run { + return (*line, false); + } + + offset -= run; + } + + unreachable!() + } +} + +#[test] +fn test_get_line() { + let lines = Lines(vec![(1_usize, 2_usize), (2_usize, 2_usize)]); + assert_eq!(lines.get(0), (1, true)); + assert_eq!(lines.get(1), (1, false)); + assert_eq!(lines.get(2), (2, true)); + assert_eq!(lines.get(3), (2, false)); +} + +impl Chunk { pub fn write(&mut self, byte: u8, line: usize) { self.code.push(byte); - self.lines.push(line); + self.lines.add(line); } pub fn add_constant(&mut self, value: Value) -> u8 { @@ -50,10 +84,11 @@ impl Chunk { fn disassemble_instruction(&self, offset: usize) -> usize { print!("{:04} ", offset); - if offset > 0 && self.lines[offset] == self.lines[offset - 1] { - print!(" | "); + let (line, is_first) = self.lines.get(offset); + if is_first { + print!("{:>4} ", line); } else { - print!("{:>4} ", self.lines[offset]); + print!(" | "); } match self.code[offset] { @@ -75,9 +110,3 @@ impl Chunk { offset + 2 } } - -impl Default for Chunk { - fn default() -> Self { - Self::new() - } -}