byteflow/bytecode/
disasm.rs1use std::fmt::Write as _;
2
3use super::chunk::{Chunk, ABI_VERSION};
4
5pub fn disassemble(chunk: &Chunk) -> String {
7 let mut out = String::new();
8 let _ = writeln!(
9 out,
10 "; chunk {:?} abi={} constants={} functions={} code={}",
11 chunk.name,
12 ABI_VERSION,
13 chunk.constants.len(),
14 chunk.functions.len(),
15 chunk.code.len()
16 );
17 for (i, c) in chunk.constants.iter().enumerate() {
18 let _ = writeln!(out, "; const[{i}] = {c}");
19 }
20 for (i, def) in chunk.functions.iter().enumerate() {
21 let _ = writeln!(
22 out,
23 "; fn[{i}] {} entry={} arity={} regs={}",
24 def.name, def.entry, def.arity, def.num_registers
25 );
26 }
27 for (i, instr) in chunk.code.iter().enumerate() {
28 let label = chunk
29 .functions
30 .iter()
31 .find(|f| f.entry as usize == i)
32 .map(|f| format!(" ; {}", f.name))
33 .unwrap_or_default();
34 let _ = writeln!(out, "{i:04} {instr}{label}");
35 }
36 out
37}
38
39#[cfg(test)]
40mod tests {
41 use crate::bytecode::builder::ChunkBuilder;
42
43
44 #[test]
45 fn lists_main() {
46 let mut b = ChunkBuilder::new("d");
47 b.begin_function("main", 0, 1);
48 b.emit_load_imm(0, 1);
49 b.emit_return(0);
50 let text = super::disassemble(&b.finish());
51 assert!(text.contains("LoadImm r0, 1"));
52 assert!(text.contains("main"));
53 }
54}