feat(tazjin/rlox): Implement else clauses

Change-Id: I0bc2333c0b4dd3e2e584a90d0d15b28c48130f03
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3740
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
This commit is contained in:
Vincent Ambo 2021-10-21 11:18:49 +02:00 committed by tazjin
parent 670662a360
commit 33e71ba97f
4 changed files with 22 additions and 1 deletions

View file

@ -1,5 +1,7 @@
if (true) {
if (false) {
print "yes";
} else {
print "no";
}
print "afterwards";

View file

@ -343,8 +343,17 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
);
let then_jump = self.emit_op(OpCode::OpJumpPlaceholder(false));
self.emit_op(OpCode::OpPop);
self.statement()?;
let else_jump = self.emit_op(OpCode::OpJumpPlaceholder(true));
self.patch_jump(then_jump);
self.emit_op(OpCode::OpPop);
if self.match_token(&TokenKind::Else) {
self.statement()?;
}
self.patch_jump(else_jump);
Ok(())
}
@ -620,6 +629,11 @@ impl<T: Iterator<Item = Token>> Compiler<T> {
fn patch_jump(&mut self, idx: CodeIdx) {
let offset = CodeOffset(self.chunk.code.len() - idx.0 - 1);
if let OpCode::OpJumpPlaceholder(true) = self.chunk.code[idx.0] {
self.chunk.code[idx.0] = OpCode::OpJump(offset);
return;
}
if let OpCode::OpJumpPlaceholder(false) = self.chunk.code[idx.0] {
self.chunk.code[idx.0] = OpCode::OpJumpIfFalse(offset);
return;

View file

@ -51,5 +51,6 @@ pub enum OpCode {
// Control flow
OpJumpPlaceholder(bool),
OpJump(CodeOffset),
OpJumpIfFalse(CodeOffset),
}

View file

@ -213,6 +213,10 @@ impl VM {
panic!("unpatched jump detected - this is a fatal compiler error!");
}
OpCode::OpJump(offset) => {
self.ip += offset.0;
}
OpCode::OpJumpIfFalse(offset) => {
if self
.stack