about summary refs log tree commit diff
path: root/users/tazjin/rlox/src/bytecode/chunk.rs
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2021-01-17T18·05+0300
committertazjin <mail@tazj.in>2021-01-17T21·17+0000
commitc26915d0120e8577cd684eb9c4f2694e1727cb4a (patch)
tree4c1dc612c126e06a2cfca9cb4f22345fe3315a51 /users/tazjin/rlox/src/bytecode/chunk.rs
parent49c4cc6c56048dbf35dbe5d87837d47b80d90f82 (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
Diffstat (limited to 'users/tazjin/rlox/src/bytecode/chunk.rs')
-rw-r--r--users/tazjin/rlox/src/bytecode/chunk.rs39
1 files changed, 38 insertions, 1 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),