1use crate::chunk::{Chunk, ClassChunk, FunctionChunk, Instr, OpCode};
2use crate::value::Value;
3
4pub fn disassemble_class_chunk(
5 class_chunk: &ClassChunk,
6 function_defs: &[FunctionChunk],
7 class_defs: &[ClassChunk],
8 constants: &[Value],
9 identifiers: &[String],
10) {
11 match class_chunk.superclass {
12 Some(i) => eprintln!(
13 "== <class {} | subclass of {}> ===============",
14 &class_chunk.name, &class_defs[i].name
15 ),
16 None => eprintln!("== <class {}> ===============", &class_chunk.name),
17 }
18 for (name, fn_index) in class_chunk.methods.iter() {
19 eprintln!(
20 "== <method {} | #{}> ============",
21 identifiers.get(*name).unwrap(),
22 fn_index
23 );
24 disassemble_chunk(&function_defs[*fn_index].chunk, constants, identifiers);
25 }
26}
27
28pub fn disassemble_fn_chunk(
29 file_name: String,
30 index: usize,
31 fn_chunk: &FunctionChunk,
32 constants: &[Value],
33 identifiers: &[String],
34) {
35 match &fn_chunk.name {
36 Some(name) => eprintln!("== <fn {} | #{}> ==============", name, index),
37 None => eprintln!("== <{}> ==============", file_name),
38 }
39 disassemble_chunk(&fn_chunk.chunk, constants, identifiers);
40}
41
42fn disassemble_chunk(chunk: &Chunk, constants: &[Value], identifiers: &[String]) {
43 eprintln!("---");
44 eprintln!("byte\tline\tOpCode");
45 let mut last_line_num = 0;
46 for (i, instr) in chunk.code.iter().enumerate() {
47 let line_marker = if last_line_num == instr.line_num {
48 "|".to_string()
49 } else {
50 instr.line_num.to_string()
51 };
52 last_line_num = instr.line_num;
53 eprint!("{}\t{}", i, line_marker);
54 disassemble_instruction(instr, i, constants, identifiers)
55 }
56
57 eprintln!("======================\n");
58}
59
60pub fn disassemble_instruction(
61 instr: &Instr,
62 instr_offset: usize,
63 constants: &[Value],
64 identifiers: &[String],
65) {
66 match instr.op_code {
67 OpCode::OpConstant(index) => eprintln!(
68 "\t{:?} => {:?}",
69 instr.op_code,
70 constants.get(index).unwrap()
71 ),
72 OpCode::OpDefineGlobal(index)
73 | OpCode::OpGetSuper(index)
74 | OpCode::OpSetGlobal(index)
75 | OpCode::OpGetGlobal(index)
76 | OpCode::OpCallGlobal(_, index, _)
77 | OpCode::OpGetProperty(index)
78 | OpCode::OpSetProperty(index) => eprintln!(
79 "\t{:?} => name: {:?}",
80 instr.op_code,
81 identifiers.get(index).unwrap()
82 ),
83 OpCode::OpJump(jump_offset) | OpCode::OpJumpIfFalse(jump_offset) => eprintln!(
84 "\t{:?} | jump -> {}",
85 instr.op_code,
86 instr_offset + jump_offset
87 ),
88 OpCode::OpLoop(neg_offset) => eprintln!(
89 "\t{:?} | loop back -> {}",
90 instr.op_code,
91 instr_offset - neg_offset
92 ),
93 _ => eprintln!("\t{:?}", instr.op_code),
94 }
95}