about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/eval/src/chunk.rs2
-rw-r--r--tvix/eval/src/disassembler.rs31
-rw-r--r--tvix/eval/src/eval.rs4
3 files changed, 35 insertions, 2 deletions
diff --git a/tvix/eval/src/chunk.rs b/tvix/eval/src/chunk.rs
index e0b584fb1f98..03071b3008de 100644
--- a/tvix/eval/src/chunk.rs
+++ b/tvix/eval/src/chunk.rs
@@ -4,7 +4,7 @@ use crate::value::Value;
 #[derive(Debug, Default)]
 pub struct Chunk {
     pub code: Vec<OpCode>,
-    constants: Vec<Value>,
+    pub constants: Vec<Value>,
 }
 
 impl Chunk {
diff --git a/tvix/eval/src/disassembler.rs b/tvix/eval/src/disassembler.rs
index 98a6dac9afc4..e5f6df525ad4 100644
--- a/tvix/eval/src/disassembler.rs
+++ b/tvix/eval/src/disassembler.rs
@@ -4,6 +4,7 @@
 use std::io::{Stderr, Write};
 use tabwriter::TabWriter;
 
+use crate::chunk::Chunk;
 use crate::opcode::OpCode;
 use crate::value::Value;
 
@@ -35,3 +36,33 @@ impl Drop for Tracer {
         self.0.flush().ok();
     }
 }
+
+fn disassemble_op(tw: &mut TabWriter<Stderr>, chunk: &Chunk, offset: usize) {
+    let code_width = format!("{}", chunk.code.len()).len();
+    write!(tw, "{:0width$}\t ", width = code_width).ok();
+
+    match chunk.code[offset] {
+        OpCode::OpConstant(idx) => write!(tw, "OpConstant({})\n", chunk.constant(idx)).ok(),
+
+        op => write!(tw, "{:?}\n", op).ok(),
+    };
+}
+
+/// Disassemble a chunk of code, printing out the operations in a
+/// reasonable, human-readable format.
+pub fn disassemble_chunk(chunk: &Chunk) {
+    let mut tw = TabWriter::new(std::io::stderr());
+
+    write!(
+        &mut tw,
+        "=== compiled bytecode ({} operations) ===\n",
+        chunk.code.len()
+    )
+    .ok();
+
+    for (idx, _) in chunk.code.iter().enumerate() {
+        disassemble_op(&mut tw, chunk, idx);
+    }
+
+    tw.flush().ok();
+}
diff --git a/tvix/eval/src/eval.rs b/tvix/eval/src/eval.rs
index 903708f108b3..456f2575cab7 100644
--- a/tvix/eval/src/eval.rs
+++ b/tvix/eval/src/eval.rs
@@ -17,7 +17,9 @@ pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> {
     }
 
     let result = crate::compiler::compile(ast, location)?;
-    println!("code: {:?}", result.chunk);
+
+    #[cfg(feature = "disassembler")]
+    crate::disassembler::disassemble_chunk(&result.chunk);
 
     for warning in result.warnings {
         eprintln!(