diff options
author | Vincent Ambo <mail@tazj.in> | 2021-10-21T09·18+0200 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-10-22T09·42+0000 |
commit | 33e71ba97fd3df598daa217ec36a48334136dcfc (patch) | |
tree | 1c792910f3c3d65517a592dce9eb8d8d2b199f2d | |
parent | 670662a360447509940dac417195cf419d7f42c5 (diff) |
feat(tazjin/rlox): Implement else clauses r/2987
Change-Id: I0bc2333c0b4dd3e2e584a90d0d15b28c48130f03 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3740 Tested-by: BuildkiteCI Reviewed-by: tazjin <mail@tazj.in>
-rw-r--r-- | users/tazjin/rlox/examples/if.lox | 4 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/compiler.rs | 14 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/opcode.rs | 1 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/vm.rs | 4 |
4 files changed, 22 insertions, 1 deletions
diff --git a/users/tazjin/rlox/examples/if.lox b/users/tazjin/rlox/examples/if.lox index b59f00b20161..5f335c0e8b29 100644 --- a/users/tazjin/rlox/examples/if.lox +++ b/users/tazjin/rlox/examples/if.lox @@ -1,5 +1,7 @@ -if (true) { +if (false) { print "yes"; +} else { + print "no"; } print "afterwards"; diff --git a/users/tazjin/rlox/src/bytecode/compiler.rs b/users/tazjin/rlox/src/bytecode/compiler.rs index 1b87e94a5512..3e8a80653f91 100644 --- a/users/tazjin/rlox/src/bytecode/compiler.rs +++ b/users/tazjin/rlox/src/bytecode/compiler.rs @@ -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; diff --git a/users/tazjin/rlox/src/bytecode/opcode.rs b/users/tazjin/rlox/src/bytecode/opcode.rs index accc6b3bac10..8a106f96917d 100644 --- a/users/tazjin/rlox/src/bytecode/opcode.rs +++ b/users/tazjin/rlox/src/bytecode/opcode.rs @@ -51,5 +51,6 @@ pub enum OpCode { // Control flow OpJumpPlaceholder(bool), + OpJump(CodeOffset), OpJumpIfFalse(CodeOffset), } diff --git a/users/tazjin/rlox/src/bytecode/vm.rs b/users/tazjin/rlox/src/bytecode/vm.rs index e0db97abe5a2..d287ec7cb8c5 100644 --- a/users/tazjin/rlox/src/bytecode/vm.rs +++ b/users/tazjin/rlox/src/bytecode/vm.rs @@ -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 |