kaon 0.1.4

A little scripting language written in rust
Documentation
use crate::common::{Chunk, Opcode};

pub struct Disassembler<'a> {
    name: &'a str,
    chunk: &'a Chunk,
}

impl<'a> Disassembler<'a> {
    pub fn new(name: &'a str, chunk: &'a Chunk) -> Self {
        Disassembler { name, chunk }
    }

    pub fn disassemble(&self) {
        println!("Disassembling {}", self.name);
        let mut offset = 0;

        println!("Code");
        while offset < self.chunk.opcodes.len() {
            offset = self.disassemble_instruction(offset);
        }

        println!("Constants");
        for con in &self.chunk.constants {
            print!("[ {} ]", con);
        }

        println!();
    }

    fn disassemble_instruction(&self, offset: usize) -> usize {
        let byte = self.chunk.opcodes[offset];
        match Opcode::from(byte) {
            Opcode::Const => self.byte_instruction("Const", offset),
            Opcode::True => self.simple_instruction("True", offset),
            Opcode::False => self.simple_instruction("False", offset),
            Opcode::Nil => self.simple_instruction("Nil", offset),
            Opcode::Add => self.simple_instruction("Add", offset),
            Opcode::Sub => self.simple_instruction("Subtract", offset),
            Opcode::Mul => self.simple_instruction("Multiply", offset),
            Opcode::Div => self.simple_instruction("Divide", offset),
            Opcode::Mod => self.simple_instruction("Modulo", offset),
            Opcode::Negate => self.simple_instruction("Negate", offset),
            Opcode::Equal => self.simple_instruction("EqualsTo", offset),
            Opcode::NotEqual => self.simple_instruction("NotEqual", offset),
            Opcode::Gte => self.simple_instruction("GreaterThanEquals", offset),
            Opcode::Lte => self.simple_instruction("LessThanEquals", offset),
            Opcode::Gt => self.simple_instruction("GreaterThan", offset),
            Opcode::Lt => self.simple_instruction("LessThan", offset),
            Opcode::Not => self.simple_instruction("Not", offset),
            Opcode::DefGlobal => self.byte_instruction("DefGlobal", offset),
            Opcode::SetGlobal => self.byte_instruction("SetGlobal", offset),
            Opcode::GetGlobal => self.byte_instruction("GetGlobal", offset),
            Opcode::LoadLocal => self.byte_instruction("LoadLocal", offset),
            Opcode::SaveLocal => self.byte_instruction("SaveLocal", offset),
            Opcode::LoadUpValue => self.byte_instruction("LoadUpValue", offset),
            Opcode::SaveUpValue => self.byte_instruction("SaveUpValue", offset),
            Opcode::CloseUpValue => self.simple_instruction("CloseUpValue", offset),
            Opcode::Jump => self.short_instruction("Jump", offset),
            Opcode::JumpIfFalse => self.short_instruction("JumpIfFalse", offset),
            Opcode::JumpIfTrue => self.short_instruction("JumpIfTrue", offset),
            Opcode::Call => self.simple_instruction("Call", offset),
            Opcode::Closure => self.closure(offset),
            Opcode::Return => self.simple_instruction("Return", offset),
            Opcode::Pop => self.simple_instruction("Del", offset),
            Opcode::Class => self.byte_instruction("Class", offset),
            Opcode::List => self.byte_instruction("List", offset),
            Opcode::Tuple => self.byte_instruction("Tuple", offset),
            Opcode::Map => self.byte_instruction("Map", offset),
            Opcode::GetIndex => self.byte_instruction("GetIndex", offset),
            Opcode::Get => self.byte_instruction("Get", offset),
            Opcode::Set => self.byte_instruction("Set", offset),
            Opcode::Loop => self.short_instruction("Loop", offset),
            Opcode::Halt => self.simple_instruction("Halt", offset),
            _ => unimplemented!()
        }
    }

    fn simple_instruction(&self, name: &str, offset: usize) -> usize {
        self.write_instruction(name, offset);
        println!();
        offset + 1
    }

    fn byte_instruction(&self, name: &str, offset: usize) -> usize {
        self.write_instruction(name, offset);
        let index = &self.chunk.opcodes[offset + 1];
        let i_padding =
            " ".repeat(self.chunk.constants.len().to_string().len() - index.to_string().len());
        print!("{}{}", i_padding, index);

        self.write_value(*index as usize);

        offset + 2
    }

    fn short_instruction(&self, name: &str, offset: usize) -> usize {
        self.write_instruction(name, offset);
        let index = &self.chunk.opcodes[offset + 1];
        let i_padding =
            " ".repeat(self.chunk.constants.len().to_string().len() - index.to_string().len());
        print!("{}{}", i_padding, index);

        self.write_value(*index as usize);

        offset + 3
    }

    fn closure(&self, offset: usize) -> usize {
        let constant = self.chunk.opcodes[offset + 2];
        println!("{}", constant);

        self.write_value(constant as usize);

        offset + 2
    }

    fn write_instruction(&self, name: &str, offset: usize) {
        let padding =
            " ".repeat(self.chunk.opcodes.len().to_string().len() - offset.to_string().len());
        print!("{}{}: {:<14}", padding, offset, name);
    }

    fn write_value(&self, index: usize) {
        println!(" ; {}", self.chunk.constants[index]);
    }
}