diff options
-rw-r--r-- | users/tazjin/rlox/src/bytecode/compiler.rs | 12 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/opcode.rs | 1 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/tests.rs | 15 | ||||
-rw-r--r-- | users/tazjin/rlox/src/bytecode/vm.rs | 13 |
4 files changed, 38 insertions, 3 deletions
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<T: Iterator<Item = Token>> Compiler<T> { 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<T: Iterator<Item = Token>> Compiler<T> { 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")] |