about summary refs log tree commit diff
diff options
context:
space:
mode:
-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")]