about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2021-10-02T12·55+0300
committertazjin <mail@tazj.in>2021-10-19T12·58+0000
commitad7e591c8046d6e179476192ef9928d5fae78422 (patch)
tree52347fd8cdd8f7d888746abbd6f66a3a2946de83
parent6a38600ce88bbf2d9fa9a3821d7df3ebd8e0d4f3 (diff)
feat(tazjin/rlox): Global variable assignment r/2977
Needed for example code compatibility.

Change-Id: Id83210eaaad7dcfef5aa238dd3a7ec159f6935e9
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3684
Tested-by: BuildkiteCI
Reviewed-by: tazjin <mail@tazj.in>
-rw-r--r--users/tazjin/rlox/src/bytecode/compiler.rs12
-rw-r--r--users/tazjin/rlox/src/bytecode/opcode.rs1
-rw-r--r--users/tazjin/rlox/src/bytecode/tests.rs15
-rw-r--r--users/tazjin/rlox/src/bytecode/vm.rs13
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")]