From c26915d0120e8577cd684eb9c4f2694e1727cb4a Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 17 Jan 2021 21:05:05 +0300 Subject: feat(tazjin/rlox): Track source lines along with bytecode Change-Id: I272e73b9b1c9571fbfe4fa983fb4283ddee02bd4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2414 Reviewed-by: tazjin Tested-by: BuildkiteCI --- users/tazjin/rlox/src/bytecode/chunk.rs | 39 ++++++++++++++++++++++++++++++++- users/tazjin/rlox/src/bytecode/mod.rs | 4 ++-- 2 files changed, 40 insertions(+), 3 deletions(-) (limited to 'users/tazjin/rlox') 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, + lines: Vec, constants: Vec, } +#[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 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"); } -- cgit 1.4.1