luallaby 0.1.0

**Work in progress** A pure-Rust Lua interpreter/compiler
Documentation
use crate::ast::While;
use crate::compiler::{offset, Compiler, ScopeType};
use crate::error::Result;
use crate::vm::{Literal, OpCode};

impl Compiler {
    pub(super) fn compile_while(&mut self, r#while: While) -> Result<()> {
        self.scope_enter(ScopeType::Loop);

        // Start
        let start = self.code.current_pc();
        let cmp_reg = self.compile_exp(*r#while.cond)?;

        // Jump to end if condition is false, placeholder
        let jump_end = self.code.current_pc();
        self.code
            .emit(OpCode::Jump { off: 0 }, self.code.get_pos_last()); // Placeholder
        self.code.emit(
            OpCode::Lit {
                val: Literal::Nil,
                dst_reg: cmp_reg,
            },
            self.code.get_pos_last(),
        ); // Clear cmp_reg

        self.compile_block(*r#while.block)?;
        self.scopes.mark_loop_end(self.code.current_pc());

        // Jump to start
        let off = offset(self.code.current_pc(), start);
        self.code
            .emit(OpCode::Jump { off }, self.code.get_pos_last());

        // Fill in jump to end
        let off = offset(jump_end, self.code.current_pc());
        self.code
            .set_op(jump_end, OpCode::JumpIfNot { cmp_reg, off }); // In position where jump inserted, cmp_reg is valid

        self.scopes.reg_free(cmp_reg);

        self.scope_leave(ScopeType::Loop, r#while.pos_end)?;

        Ok(())
    }
}