phoenix-lang 1.5.3

A simple, fast programming language
Documentation
use crate::chunk::{Chunk, ClassChunk, FunctionChunk, Instr, OpCode};
use crate::value::Value;

pub fn disassemble_class_chunk(
    class_chunk: &ClassChunk,
    function_defs: &[FunctionChunk],
    class_defs: &[ClassChunk],
    constants: &[Value],
    identifiers: &[String],
) {
    match class_chunk.superclass {
        Some(i) => eprintln!(
            "== <class {} | subclass of {}> ===============",
            &class_chunk.name, &class_defs[i].name
        ),
        None => eprintln!("== <class {}> ===============", &class_chunk.name),
    }
    for (name, fn_index) in class_chunk.methods.iter() {
        eprintln!(
            "== <method {} | #{}> ============",
            identifiers.get(*name).unwrap(),
            fn_index
        );
        disassemble_chunk(&function_defs[*fn_index].chunk, constants, identifiers);
    }
}

pub fn disassemble_fn_chunk(
    file_name: String,
    index: usize,
    fn_chunk: &FunctionChunk,
    constants: &[Value],
    identifiers: &[String],
) {
    match &fn_chunk.name {
        Some(name) => eprintln!("== <fn {} | #{}> ==============", name, index),
        None => eprintln!("== <{}> ==============", file_name),
    }
    disassemble_chunk(&fn_chunk.chunk, constants, identifiers);
}

fn disassemble_chunk(chunk: &Chunk, constants: &[Value], identifiers: &[String]) {
    eprintln!("---");
    eprintln!("byte\tline\tOpCode");
    let mut last_line_num = 0;
    for (i, instr) in chunk.code.iter().enumerate() {
        let line_marker = if last_line_num == instr.line_num {
            "|".to_string()
        } else {
            instr.line_num.to_string()
        };
        last_line_num = instr.line_num;
        eprint!("{}\t{}", i, line_marker);
        disassemble_instruction(instr, i, constants, identifiers)
    }

    eprintln!("======================\n");
}

pub fn disassemble_instruction(
    instr: &Instr,
    instr_offset: usize,
    constants: &[Value],
    identifiers: &[String],
) {
    match instr.op_code {
        OpCode::OpConstant(index) => eprintln!(
            "\t{:?} => {:?}",
            instr.op_code,
            constants.get(index).unwrap()
        ),
        OpCode::OpDefineGlobal(index)
        | OpCode::OpGetSuper(index)
        | OpCode::OpSetGlobal(index)
        | OpCode::OpGetGlobal(index)
        | OpCode::OpCallGlobal(_, index, _)
        | OpCode::OpGetProperty(index)
        | OpCode::OpSetProperty(index) => eprintln!(
            "\t{:?} => name: {:?}",
            instr.op_code,
            identifiers.get(index).unwrap()
        ),
        OpCode::OpJump(jump_offset) | OpCode::OpJumpIfFalse(jump_offset) => eprintln!(
            "\t{:?} | jump -> {}",
            instr.op_code,
            instr_offset + jump_offset
        ),
        OpCode::OpLoop(neg_offset) => eprintln!(
            "\t{:?} | loop back -> {}",
            instr.op_code,
            instr_offset - neg_offset
        ),
        _ => eprintln!("\t{:?}", instr.op_code),
    }
}