diff options
author | Vincent Ambo <mail@tazj.in> | 2021-03-02T20·26+0200 |
---|---|---|
committer | tazjin <mail@tazj.in> | 2021-03-03T10·51+0000 |
commit | ed3fce2b19fa0d28054382093b019967a9a16177 (patch) | |
tree | 102ade5adc95667ebedaa56e20cee387c2ff524b /users/tazjin/rlox/src/bytecode/vm.rs | |
parent | 2cd77ea26d76b20ff820f1ebe5e77f1360f5d1f5 (diff) |
feat(tazjin/rlox): Implement expression statements r/2265
These aren't particularly useful without side effects, but one step at a time. This diverges slightly from the book, in that OpPop retains the last value it "forgot" from the stack in a special field on the interpreter. This makes it possible to return values from expression statements, which helps in cases where Lox is embedded as a scripting language (please don't do this ever) or in tests. Change-Id: Ided0bc04c6e80ddb23ba4693d61ac9e08b002d58 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2584 Reviewed-by: tazjin <mail@tazj.in> Tested-by: BuildkiteCI
Diffstat (limited to 'users/tazjin/rlox/src/bytecode/vm.rs')
-rw-r--r-- | users/tazjin/rlox/src/bytecode/vm.rs | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/users/tazjin/rlox/src/bytecode/vm.rs b/users/tazjin/rlox/src/bytecode/vm.rs index c43b197279be..9161bdfe53b8 100644 --- a/users/tazjin/rlox/src/bytecode/vm.rs +++ b/users/tazjin/rlox/src/bytecode/vm.rs @@ -13,6 +13,12 @@ pub struct VM { stack: Vec<Value>, strings: Interner, + + // Operations that consume values from the stack without pushing + // anything leave their last value in this slot, which makes it + // possible to return values from interpreters that ran code which + // ended with a statement. + last_drop: Option<Value>, } impl VM { @@ -72,12 +78,15 @@ impl VM { match op { OpCode::OpReturn => { - if self.stack.is_empty() { + if !self.stack.is_empty() { + let val = self.pop(); + return Ok(self.return_value(val)); + } else if self.last_drop.is_some() { + let val = self.last_drop.take().unwrap(); + return Ok(self.return_value(val)); + } else { return Ok(Value::Nil); } - - let val = self.pop(); - return Ok(self.return_value(val)); } OpCode::OpConstant(idx) => { @@ -144,6 +153,10 @@ impl VM { let val = self.pop(); println!("{}", self.print_value(val)); } + + OpCode::OpPop => { + self.last_drop = Some(self.pop()); + } } #[cfg(feature = "disassemble")] @@ -186,6 +199,7 @@ pub fn interpret(strings: Interner, chunk: chunk::Chunk) -> LoxResult<Value> { strings, ip: 0, stack: vec![], + last_drop: None, }; vm.run() |