From 2403cdb7ee077c1762a4d3dff2f7c128fbe5e694 Mon Sep 17 00:00:00 2001 From: XFFXFF <1247714429@qq.com> Date: Tue, 19 Sep 2023 08:55:00 +0800 Subject: [PATCH] add a step_inspect to vm.interpret for debugging --- components/lox-execute/src/execute.rs | 6 ++--- components/lox-execute/src/lib.rs | 1 + components/lox-execute/src/vm.rs | 10 ++++++-- lox_tests/arithmetic.output | 36 +++++++++++++++++++++++++-- lox_tests/boolean.output | 11 ++++++-- src/main.rs | 13 +++++++--- 6 files changed, 65 insertions(+), 12 deletions(-) diff --git a/components/lox-execute/src/execute.rs b/components/lox-execute/src/execute.rs index 15411e1..a526dd7 100644 --- a/components/lox-execute/src/execute.rs +++ b/components/lox-execute/src/execute.rs @@ -1,10 +1,10 @@ use lox_compile::compile; -use lox_ir::input_file::InputFile; +use lox_ir::{input_file::InputFile, bytecode}; use crate::vm::{VM, Value}; -pub fn execute_file(db: &impl crate::Db, input_file: InputFile) -> Value { +pub fn execute_file(db: &impl crate::Db, input_file: InputFile, step_inspect: Option) -> Value { let chunk = compile::compile_file(db, input_file); let mut vm = VM::new(chunk); - vm.interpret() + vm.interpret(step_inspect) } diff --git a/components/lox-execute/src/lib.rs b/components/lox-execute/src/lib.rs index 4395c78..85b3838 100644 --- a/components/lox-execute/src/lib.rs +++ b/components/lox-execute/src/lib.rs @@ -4,6 +4,7 @@ pub mod execute; pub mod vm; pub use execute::execute_file; +pub use vm::VM; #[salsa::jar(db = Db)] pub struct Jar(); diff --git a/components/lox-execute/src/vm.rs b/components/lox-execute/src/vm.rs index 6021d0b..f9beccf 100644 --- a/components/lox-execute/src/vm.rs +++ b/components/lox-execute/src/vm.rs @@ -67,7 +67,7 @@ pub struct VM { chunk: bytecode::Chunk, ip: usize, - stack: Vec, + pub stack: Vec, } impl VM { @@ -79,7 +79,10 @@ impl VM { } } - pub fn interpret(&mut self) -> Value { + // `step_inspect` is a callback that is called after each instruction is executed. + // It is useful for debugging. + pub fn interpret(&mut self, mut step_inspect: Option) -> Value + where F: FnMut(bytecode::Code, &VM) { loop { if self.chunk.len() <= self.ip { break; @@ -117,6 +120,9 @@ impl VM { self.push(false); }, } + if let Some(step_inspect) = &mut step_inspect { + step_inspect(instruction, self); + } } self.stack.pop().unwrap() } diff --git a/lox_tests/arithmetic.output b/lox_tests/arithmetic.output index 06980d6..5ebcd5d 100644 --- a/lox_tests/arithmetic.output +++ b/lox_tests/arithmetic.output @@ -1,3 +1,35 @@ -Number( +execute: Constant( + F64( + 1.0, + ), +) +stack: [ + Number( + 1.0, + ), +] + +execute: Constant( + F64( + 2.0, + ), +) +stack: [ + Number( + 1.0, + ), + Number( + 2.0, + ), +] + +execute: Add +stack: [ + Number( + 3.0, + ), +] + +output: Number( 3.0, -) \ No newline at end of file +) diff --git a/lox_tests/boolean.output b/lox_tests/boolean.output index 3da3958..7011a24 100644 --- a/lox_tests/boolean.output +++ b/lox_tests/boolean.output @@ -1,3 +1,10 @@ -Boolean( +execute: True +stack: [ + Boolean( + true, + ), +] + +output: Boolean( true, -) \ No newline at end of file +) diff --git a/src/main.rs b/src/main.rs index 0beb03c..09640da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,7 +48,7 @@ impl TestCase { } use expect_test::expect_file; -use lox_ir::{diagnostic::Diagnostics, input_file::InputFile, word::Word}; +use lox_ir::{diagnostic::Diagnostics, input_file::InputFile, word::Word, bytecode}; #[salsa::db( lox_parse::Jar, @@ -113,7 +113,14 @@ fn main() { expect_file![case.bytecode].assert_eq(&format!("{:#?}", chunk)); // test execute - let output = lox_execute::execute_file(&db, input_file); - expect_file![case.output].assert_eq(&format!("{:#?}", output)); + let mut buf = String::new(); + let step_inspect = |code: bytecode::Code, vm: &lox_execute::VM| { + buf.push_str(&format!("execute: {:#?}\n", code)); + buf.push_str(&format!("stack: {:#?}\n", vm.stack)); + buf.push('\n'); + }; + let output = lox_execute::execute_file(&db, input_file, Some(step_inspect)); + buf.push_str(&format!("output: {:#?}\n", output)); + expect_file![case.output].assert_eq(&buf); } }