use crate::ast::Local;
use crate::compiler::Compiler;
use crate::error::Result;
use crate::vm::OpCode;
impl Compiler {
pub(super) fn compile_local(&mut self, local: Local) -> Result<()> {
let mut end = Vec::new();
let mut to_free = Vec::new();
let exp_regs: Vec<usize> = local
.exps
.into_iter()
.map(|exp| self.compile_exp(exp))
.collect::<Result<_>>()?;
for (ind, (name, attr, pos)) in local.vars.into_iter().enumerate() {
let dst_loc = self.declare_local(name, attr, pos);
if !exp_regs.is_empty() {
let src_reg = if ind + 1 < exp_regs.len() {
exp_regs[ind]
} else {
let dst_reg = self.scopes.reg_reserve();
self.code.emit(
OpCode::MovMult {
src_reg: *exp_regs.last().unwrap(),
ind: ind + 1 - exp_regs.len(),
dst_reg,
},
pos,
);
to_free.push(dst_reg);
dst_reg
};
end.push(OpCode::LocalSet { src_reg, dst_loc });
}
}
self.code.emit_all(end, self.code.get_pos_last());
for reg in exp_regs {
self.scopes.reg_free(reg);
}
for reg in to_free {
self.scopes.reg_free(reg);
}
Ok(())
}
}