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);
let start = self.code.current_pc();
let cmp_reg = self.compile_exp(*r#while.cond)?;
let jump_end = self.code.current_pc();
self.code
.emit(OpCode::Jump { off: 0 }, self.code.get_pos_last()); self.code.emit(
OpCode::Lit {
val: Literal::Nil,
dst_reg: cmp_reg,
},
self.code.get_pos_last(),
);
self.compile_block(*r#while.block)?;
self.scopes.mark_loop_end(self.code.current_pc());
let off = offset(self.code.current_pc(), start);
self.code
.emit(OpCode::Jump { off }, self.code.get_pos_last());
let off = offset(jump_end, self.code.current_pc());
self.code
.set_op(jump_end, OpCode::JumpIfNot { cmp_reg, off });
self.scopes.reg_free(cmp_reg);
self.scope_leave(ScopeType::Loop, r#while.pos_end)?;
Ok(())
}
}