phoenix_lang/
debug.rs

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}