From ad7e591c8046d6e179476192ef9928d5fae78422 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sat, 2 Oct 2021 15:55:58 +0300 Subject: feat(tazjin/rlox): Global variable assignment Needed for example code compatibility. Change-Id: Id83210eaaad7dcfef5aa238dd3a7ec159f6935e9 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3684 Tested-by: BuildkiteCI Reviewed-by: tazjin --- users/tazjin/rlox/src/bytecode/compiler.rs | 12 ++++++++++-- users/tazjin/rlox/src/bytecode/opcode.rs | 1 + users/tazjin/rlox/src/bytecode/tests.rs | 15 ++++++++++++++- users/tazjin/rlox/src/bytecode/vm.rs | 13 +++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) (limited to 'users/tazjin') diff --git a/users/tazjin/rlox/src/bytecode/compiler.rs b/users/tazjin/rlox/src/bytecode/compiler.rs index b8b91667d3fa..a6675d1c20b6 100644 --- a/users/tazjin/rlox/src/bytecode/compiler.rs +++ b/users/tazjin/rlox/src/bytecode/compiler.rs @@ -236,7 +236,8 @@ impl> Compiler { fn expression_statement(&mut self) -> LoxResult<()> { self.expression()?; self.expect_semicolon("expect ';' after expression")?; - self.emit_op(OpCode::OpPop); + // TODO(tazjin): Why did I add this originally? + // self.emit_op(OpCode::OpPop); Ok(()) } @@ -343,7 +344,14 @@ impl> Compiler { let ident = self.identifier_str(Self::previous)?; let constant_id = self.emit_constant(Value::String(ident.into()), false); - self.emit_op(OpCode::OpGetGlobal(constant_id)); + + if self.match_token(&TokenKind::Equal) { + self.expression()?; + self.emit_op(OpCode::OpSetGlobal(constant_id)); + } else { + self.emit_op(OpCode::OpGetGlobal(constant_id)); + } + Ok(()) } diff --git a/users/tazjin/rlox/src/bytecode/opcode.rs b/users/tazjin/rlox/src/bytecode/opcode.rs index 1c23449e76b3..c7ccdd89e85f 100644 --- a/users/tazjin/rlox/src/bytecode/opcode.rs +++ b/users/tazjin/rlox/src/bytecode/opcode.rs @@ -33,4 +33,5 @@ pub enum OpCode { // Variable management OpDefineGlobal(usize), OpGetGlobal(usize), + OpSetGlobal(usize), } diff --git a/users/tazjin/rlox/src/bytecode/tests.rs b/users/tazjin/rlox/src/bytecode/tests.rs index d5b6ab020389..13e64400ade5 100644 --- a/users/tazjin/rlox/src/bytecode/tests.rs +++ b/users/tazjin/rlox/src/bytecode/tests.rs @@ -110,7 +110,7 @@ fn strings() { } #[test] -fn variables() { +fn global_variables() { expect_num("var a = 5; a;", 5.0); expect_num("var a = 5; var b = 2; a * b;", 10.0); expect_str( @@ -118,3 +118,16 @@ fn variables() { "hello Zubnog", ); } + +#[test] +fn global_assignment() { + expect_str( + r#" + var breakfast = "beignets"; + var beverage = "cafe au lait"; + breakfast = "beignets with " + beverage; + breakfast; + "#, + "beignets with cafe au lait" + ); +} diff --git a/users/tazjin/rlox/src/bytecode/vm.rs b/users/tazjin/rlox/src/bytecode/vm.rs index 0cd0853764e0..4432473ee649 100644 --- a/users/tazjin/rlox/src/bytecode/vm.rs +++ b/users/tazjin/rlox/src/bytecode/vm.rs @@ -181,6 +181,19 @@ impl VM { self.push(val) }); } + + OpCode::OpSetGlobal(name_idx) => { + let name = self.chunk.constant(*name_idx).clone(); + let new_val = self.pop(); + with_type!(self, name, Value::String(name), { + match self.globals.get_mut(&name) { + None => unimplemented!("variable not found error"), + Some(val) => { + *val = new_val; + } + } + }); + } } #[cfg(feature = "disassemble")] -- cgit 1.4.1