14.challenges.1

main
Alpha Chen 2 years ago
parent e9b4e8cbfd
commit d6577e5c4d

@ -1,2 +1,3 @@
test-watch: 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

@ -10,24 +10,58 @@ pub enum OpCode {
type Value = f32; type Value = f32;
#[derive(Default)]
pub struct Chunk { pub struct Chunk {
code: Vec<u8>, code: Vec<u8>,
constants: Vec<Value>, constants: Vec<Value>,
lines: Vec<usize>, lines: Lines,
} }
impl Chunk { // Lines are stored using run-length encoding, where the first element is the line and the second
pub fn new() -> Self { // element the number of instructions that are associated with that line
Chunk { #[derive(Default, Debug)]
code: Vec::new(), struct Lines(std::vec::Vec<(usize, usize)>);
constants: Vec::new(),
lines: Vec::new(), 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) { pub fn write(&mut self, byte: u8, line: usize) {
self.code.push(byte); self.code.push(byte);
self.lines.push(line); self.lines.add(line);
} }
pub fn add_constant(&mut self, value: Value) -> u8 { pub fn add_constant(&mut self, value: Value) -> u8 {
@ -50,10 +84,11 @@ impl Chunk {
fn disassemble_instruction(&self, offset: usize) -> usize { fn disassemble_instruction(&self, offset: usize) -> usize {
print!("{:04} ", offset); print!("{:04} ", offset);
if offset > 0 && self.lines[offset] == self.lines[offset - 1] { let (line, is_first) = self.lines.get(offset);
print!(" | "); if is_first {
print!("{:>4} ", line);
} else { } else {
print!("{:>4} ", self.lines[offset]); print!(" | ");
} }
match self.code[offset] { match self.code[offset] {
@ -75,9 +110,3 @@ impl Chunk {
offset + 2 offset + 2
} }
} }
impl Default for Chunk {
fn default() -> Self {
Self::new()
}
}

Loading…
Cancel
Save