This commit is contained in:
nora 2022-01-07 20:44:19 +01:00
parent 06dd53525a
commit 628899dde7
9 changed files with 145 additions and 8 deletions

View file

@ -56,6 +56,11 @@ struct Compiler<'bc, 'gc> {
/// the current local variables that are in scope, only needed for compiling
env: Rc<RefCell<Env>>,
rt: &'gc mut RtAlloc,
/// How nested the current loop is, required for break offsets
loop_nesting: usize,
/// All break instructions currently in need of an offset. K=loop_nesting, V=break_indices
breaks: HashMap<usize, std::vec::Vec<usize>>,
}
pub fn compile<'ast, 'bc, 'gc>(
@ -69,6 +74,8 @@ pub fn compile<'ast, 'bc, 'gc>(
bump: bytecode_bump,
env: Rc::new(RefCell::new(Env::default())),
rt,
loop_nesting: 0,
breaks: HashMap::default(),
};
compiler.compile(ast)?;
@ -200,12 +207,17 @@ impl<'bc, 'gc> Compiler<'bc, 'gc> {
*/
let first_stmt_idx = self.code_len();
self.loop_nesting += 1;
self.compile_block(ast_block)?;
let jmp_offset = self.back_jmp_offset(first_stmt_idx);
self.push_instr(Instr::Jmp(jmp_offset), StackChange::None, span);
self.end_loop();
Ok(())
}
@ -219,6 +231,9 @@ impl<'bc, 'gc> Compiler<'bc, 'gc> {
*/
let cond_index = self.code_len();
self.loop_nesting += 1;
self.compile_expr(&while_stmt.cond)?;
let jmp_false_idx =
@ -232,11 +247,18 @@ impl<'bc, 'gc> Compiler<'bc, 'gc> {
let jmp_offset = self.forward_jmp_offset(jmp_false_idx as isize);
self.change_instr(jmp_false_idx, Instr::JmpFalse(jmp_offset));
self.end_loop();
Ok(())
}
fn compile_break(&mut self, _: Span) -> CResult {
todo!()
fn compile_break(&mut self, span: Span) -> CResult {
let break_idx = self.push_instr(Instr::Jmp(0), StackChange::None, span);
self.breaks
.entry(self.loop_nesting)
.or_default()
.push(break_idx);
Ok(())
}
fn compile_return(&mut self, _: &Option<Expr>, _: Span) -> CResult {
@ -337,6 +359,17 @@ impl<'bc, 'gc> Compiler<'bc, 'gc> {
todo!()
}
fn end_loop(&mut self) {
let breaks = self.breaks.remove(&self.loop_nesting);
if let Some(breaks) = breaks {
for brk in breaks {
let offset = self.forward_jmp_offset(brk as isize);
self.change_instr(brk, Instr::Jmp(offset));
}
}
self.loop_nesting -= 1;
}
fn current_stack_top(&self) -> usize {
let block = &self.blocks[self.current_block];
// we want the stack position, not the size, so the `- 1`

View file

@ -65,7 +65,7 @@ impl<'bc> Vm<'bc, '_> {
}
self.pc += 1;
// debug stack size assertion
todo!()
// todo!()
}
}