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 = match chunk.functions.iter().find(|f| f.entry as usize == i) {
29 Some(f) => format!(" ; {}", f.name),
30 None => String::new(),
31 };
32 let _ = writeln!(out, "{i:04} {instr}{label}");
33 }
34 out
35}
36
37#[cfg(test)]
38mod tests {
39 use crate::bytecode::builder::ChunkBuilder;
40
41
42 #[test]
43 fn lists_main() {
44 let mut b = ChunkBuilder::new("d");
45 b.begin_function("main", 0, 1);
46 b.emit_load_imm(0, 1);
47 b.emit_return(0);
48 let text = super::disassemble(&b.finish());
49 assert!(text.contains("LoadImm r0, 1"));
50 assert!(text.contains("main"));
51 }
52}