use std::rc::Rc;
use crate::ast::Chunk;
use crate::compiler::{Compiler, ScopeType};
use crate::error::Result;
use crate::vm::{FuncObject, Literal, OpCode};
impl Compiler {
pub(super) fn compile_chunk(&mut self, chunk: Chunk) -> Result<FuncObject> {
self.scope_enter(ScopeType::Func);
self.code_push();
if !self.compile_block(chunk.block)? {
let ret_reg = self.scopes.reg_reserve();
self.code.emit(
OpCode::Lit {
val: Literal::Empty,
dst_reg: ret_reg,
},
self.code.get_pos_last(),
);
self.code
.emit(OpCode::Return { ret_reg }, self.code.get_pos_last());
self.scopes.reg_free(ret_reg);
}
let scope = self
.scope_leave(ScopeType::Func, self.code.get_pos_last())?
.unwrap();
let code = self.code_pop();
assert!(scope.locals.is_empty());
assert!(scope.ups.len() == 1);
assert!(self.code_stack.is_empty());
Ok(FuncObject {
regs: scope.regs.count(),
locals_cap: scope.locals_cap,
params: Vec::new(),
ups: scope.ups.into_iter().map(|up| up.upper).collect(),
varargs: true,
code: Rc::new(code),
linedefined: 0,
lastlinedefined: 0,
})
}
}