From 4c8f52de1a57ccbbdef13cd28ef08518b227a7c3 Mon Sep 17 00:00:00 2001 From: Sofia Date: Tue, 17 Mar 2026 20:04:20 +0200 Subject: [PATCH] Add assignment for deeper tables --- examples/test.lua | 28 +++++++++++++++++++++++++++- src/compile.rs | 18 ++++++++++++++++-- src/vm.rs | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/examples/test.lua b/examples/test.lua index 9af97d2..661bd90 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -1,3 +1,29 @@ +global b = 5 + +function add(x) + return function (y) + x = x + 1 + b = b + 1 + return x + y, 1, 2, b + end +end + +function min(x, y) + local m = x + if y < x then + m = y + end + return m +end global sometable = {} -sometable.hello = "there" +sometable["hello"] = {} +sometable["hello"].there = "my dude" + +print(max(11, 9)) +print(add(10)(15)) +print(add(10)(15)) +print(b) +print(min(11, 9)) +print(10 - 15) +print("hello there!") \ No newline at end of file diff --git a/src/compile.rs b/src/compile.rs index 9765389..5cb371f 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -213,7 +213,8 @@ impl Statement { None => { for (i, (name, indexes)) in names.iter().enumerate() { if indexes.len() > 0 { - let table_reg = if let Some(reg) = scope.locals.get(&name.kind) { + let mut table_reg = if let Some(reg) = scope.locals.get(&name.kind) + { *reg } else if let Some(upval_reg) = scope.upvalues.get(&name.kind) { let local = scope.register_counter.next(); @@ -228,7 +229,20 @@ impl Statement { }; if indexes.len() > 1 { - todo!() + for (_, index) in indexes + .iter() + .enumerate() + .take_while(|(i, _)| *i != indexes.len() - 1) + { + let (instr, index_reg) = + index.kind.compile(state, scope, Some(1)); + instructions.extend(instr); + instructions.push(Instruction::GetTable( + table_reg, + table_reg, + *index_reg.first().unwrap(), + )); + } } let (instr, index_reg) = diff --git a/src/vm.rs b/src/vm.rs index bc8ce22..4d5a4a5 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -51,6 +51,8 @@ pub enum Instruction { SetUpVal(u16, u16), /// R(A)[R(B)] := R(C) SetTable(u16, u16, u16), + /// R(A) := R(B)[R(C)] + GetTable(u16, u16, u16), /// R(A) := {} NewTable(u16), /// R(A) := R(B) + R(C) @@ -94,6 +96,9 @@ impl Debug for Instruction { Instruction::SetTable(arg0, arg1, arg2) => { write!(f, "SETTABLE {} {} {}", arg0, arg1, arg2) } + Instruction::GetTable(arg0, arg1, arg2) => { + write!(f, "GETTABLE {} {} {}", arg0, arg1, arg2) + } Instruction::NewTable(arg0) => write!(f, "NEWTABLE {}", arg0), Instruction::Jmp(arg0) => write!(f, "JMP {}", arg0), Instruction::Test(arg0, arg1, arg2) => write!(f, "TEST {} {} {}", arg0, arg1, arg2), @@ -614,6 +619,34 @@ impl ClosureRunner { None => todo!(), } } + Instruction::GetTable(res, tablereg, indexreg) => { + let value = match self.stack.get(tablereg).cloned() { + Some(value) => { + let table = value.borrow(); + if let Value::Table(table) = &*table { + let table = table.borrow(); + let index_value = self + .stack + .get(indexreg) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil) + .as_indexable()?; + let value = table.get(&index_value); + match value { + Some(value) => StackValue::Value(value.clone()), + None => StackValue::Value(Value::Nil), + } + } else { + return Err(RuntimeError::NotTable(table.clone())); + } + } + None => { + return Err(RuntimeError::NotTable(Value::Nil)); + } + }; + + self.set_stack(*res, value); + } Instruction::NewTable(reg) => { self.set_stack( *reg,