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!()
}
}

View file

@ -1,7 +1,5 @@
let i = 0;
while i < 100000 {
i = i + 1;
loop {
break;
}
print "done";
print "hi";

View file

@ -140,3 +140,74 @@ while i < 100 {
}
"#
);
run_test!(
break_out_loop,
r#"
print "Start";
loop {
break;
print "WRONG";
}
print "Good end";
"#
);
run_test!(
break_out_while,
r#"
print "Start";
while true {
break;
print "WRONG";
}
print "Good end";
"#
);
run_test!(
fizzbuzz_with_loop,
r#"
let i = 1;
loop {
if i % 15 == 0 {
print "FizzBuzz";
} else if i % 5 == 0 {
print "Buzz";
} else if i % 3 == 0 {
print "Fizz";
} else {
print i;
}
i = i + 1;
if i >= 100 {
break;
}
}
"#
);
run_test!(
nested_loop_break,
r#"
print "Start";
loop {
print "Start inner";
loop {
print "inside inner";
break;
print "WRONG";
}
print "Outside inner";
break;
print "WRONG";
}
print "End";
"#
);

View file

@ -0,0 +1,7 @@
---
source: tests/control_flow.rs
assertion_line: 144
expression: output
---
"Start\nGood end\n"

View file

@ -0,0 +1,7 @@
---
source: tests/control_flow.rs
assertion_line: 144
expression: output
---
"Start\nGood end\n"

View file

@ -0,0 +1,7 @@
---
source: tests/control_flow.rs
assertion_line: 158
expression: output
---
"Start\nGood end\n"

View file

@ -0,0 +1,7 @@
---
source: tests/control_flow.rs
assertion_line: 158
expression: output
---
"1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n16\n17\nFizz\n19\nBuzz\nFizz\n22\n23\nFizz\nBuzz\n26\nFizz\n28\n29\nFizzBuzz\n31\n32\nFizz\n34\nBuzz\nFizz\n37\n38\nFizz\nBuzz\n41\nFizz\n43\n44\nFizzBuzz\n46\n47\nFizz\n49\nBuzz\nFizz\n52\n53\nFizz\nBuzz\n56\nFizz\n58\n59\nFizzBuzz\n61\n62\nFizz\n64\nBuzz\nFizz\n67\n68\nFizz\nBuzz\n71\nFizz\n73\n74\nFizzBuzz\n76\n77\nFizz\n79\nBuzz\nFizz\n82\n83\nFizz\nBuzz\n86\nFizz\n88\n89\nFizzBuzz\n91\n92\nFizz\n94\nBuzz\nFizz\n97\n98\nFizz\n"

View file

@ -0,0 +1,7 @@
---
source: tests/control_flow.rs
assertion_line: 196
expression: output
---
"Start\nStart inner\ninside inner\nOutside inner\nEnd\n"