diff options
author | Vincent Ambo <mail@tazj.in> | 2021-01-17T18·05+0300 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-01-17T21·17+0000 |
commit | c26915d0120e8577cd684eb9c4f2694e1727cb4a (patch) | |
tree | 4c1dc612c126e06a2cfca9cb4f22345fe3315a51 | |
parent | 49c4cc6c56048dbf35dbe5d87837d47b80d90f82 (diff) |
feat(tazjin/rlox): Track source lines along with bytecode r/2125
Change-Id: I272e73b9b1c9571fbfe4fa983fb4283ddee02bd4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2414 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
-rw-r--r-- | users/tazjin/rlox/src/bytecode/chunk.rs | 39 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/mod.rs | 4 |
2 files changed, 40 insertions, 3 deletions
diff --git a/users/tazjin/rlox/src/bytecode/chunk.rs b/users/tazjin/rlox/src/bytecode/chunk.rs index f5c0a2bb85d0..fa3909f038cd 100644 --- a/users/tazjin/rlox/src/bytecode/chunk.rs +++ b/users/tazjin/rlox/src/bytecode/chunk.rs @@ -11,13 +11,24 @@ use super::value; #[derive(Debug, Default)] pub struct Chunk { code: Vec<OpCode>, + lines: Vec<Span>, constants: Vec<value::Value>, } +#[derive(Debug)] +struct Span { + /// Source code line + line: usize, + + /// Number of instructions derived from this line + count: usize, +} + impl Chunk { - pub fn add_op(&mut self, data: OpCode) -> usize { + pub fn add_op(&mut self, data: OpCode, line: usize) -> usize { let idx = self.code.len(); self.code.push(data); + self.add_line(line); idx } @@ -26,6 +37,25 @@ impl Chunk { self.constants.push(data); idx } + + fn add_line(&mut self, line: usize) { + match self.lines.last_mut() { + Some(span) if span.line == line => span.count += 1, + _ => self.lines.push(Span { line, count: 1 }), + } + } + + fn get_line(&self, offset: usize) -> usize { + let mut pos = 0; + for span in &self.lines { + pos += span.count; + if pos > offset { + return span.line; + } + } + + panic!("invalid chunk state: line missing for offset {}", offset); + } } impl Index<usize> for Chunk { @@ -50,6 +80,13 @@ pub fn disassemble(chunk: &Chunk, name: &str) { fn disassemble_instruction(chunk: &Chunk, offset: usize) { print!("{:04} ", offset); + let line = chunk.get_line(offset); + if offset > 0 && line == chunk.get_line(offset - 1) { + print!(" | "); + } else { + print!("{:4} ", line); + } + match &chunk[offset] { OpCode::OpConstant(idx) => println!("OpConstant idx '{:?}'", chunk.constants[*idx]), op => println!("{:?}", op), diff --git a/users/tazjin/rlox/src/bytecode/mod.rs b/users/tazjin/rlox/src/bytecode/mod.rs index a58f610417fd..922b3bef4484 100644 --- a/users/tazjin/rlox/src/bytecode/mod.rs +++ b/users/tazjin/rlox/src/bytecode/mod.rs @@ -13,8 +13,8 @@ pub fn main() { let mut chunk: Chunk = Default::default(); let constant = chunk.add_constant(1.2); - chunk.add_op(OpCode::OpConstant(constant)); - chunk.add_op(OpCode::OpReturn); + chunk.add_op(OpCode::OpConstant(constant), 1); + chunk.add_op(OpCode::OpReturn, 1); chunk::disassemble(&chunk, "test chunk"); } |