feat(tazjin/rlox): Track source lines along with bytecode
Change-Id: I272e73b9b1c9571fbfe4fa983fb4283ddee02bd4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2414 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
This commit is contained in:
parent
49c4cc6c56
commit
c26915d012
2 changed files with 40 additions and 3 deletions
|
@ -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),
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue