From 1eb62b078e63d3034f5a44d72b1e64bb8925ca43 Mon Sep 17 00:00:00 2001 From: Sofia Date: Mon, 16 Mar 2026 15:56:57 +0200 Subject: [PATCH] Fix upvalues and stack values being different references --- examples/test.lua | 3 + src/vm.rs | 145 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 103 insertions(+), 45 deletions(-) diff --git a/examples/test.lua b/examples/test.lua index f587b69..aa8896b 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -3,6 +3,7 @@ local b = 5 function add(x) return function (y) x = x + 1 + b = b + 1 return x + y, 1, 2, b end end @@ -17,4 +18,6 @@ end print(max(11, 9)) print(add(10)(15)) +print(add(10)(15)) +print(b) print(min(11, 9)) \ No newline at end of file diff --git a/src/vm.rs b/src/vm.rs index edb2b3c..bded6e1 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -162,7 +162,7 @@ impl Closure { pub fn run(&self, params: Vec) -> ClosureRunner { let mut stack = HashMap::new(); for (i, param) in params.iter().enumerate() { - stack.insert(i as u16, param.clone()); + stack.insert(i as u16, Rc::new(RefCell::new(param.clone()))); } ClosureRunner { closure: self.clone(), @@ -179,7 +179,7 @@ impl Closure { pub struct ClosureRunner { pub closure: Closure, pub program_counter: usize, - pub stack: HashMap, + pub stack: HashMap>>, pub inner: Option>, pub function_register: u16, pub return_registers: Vec, @@ -187,20 +187,34 @@ pub struct ClosureRunner { } impl ClosureRunner { + pub fn set_stack(&mut self, idx: u16, value: Value) { + if let Some(stack_slot) = self.stack.get(&idx) { + *stack_slot.borrow_mut() = value; + } else { + self.stack.insert(idx, Rc::new(RefCell::new(value))); + } + } + pub fn next(&mut self) -> Option> { if let Some(inner) = &mut self.inner { if let Some(ret_values) = inner.next() { self.inner = None; if self.return_registers.len() == 0 { for (i, value) in ret_values.iter().enumerate() { - self.stack - .insert(self.function_register + i as u16 + 1, value.clone()); + self.stack.insert( + self.function_register + i as u16 + 1, + Rc::new(RefCell::new(value.clone())), + ); } self.top = self.function_register + ret_values.len() as u16; } for (i, reg) in self.return_registers.iter().enumerate() { - self.stack - .insert(*reg, ret_values.get(i).cloned().unwrap_or(Value::Nil)); + self.stack.insert( + *reg, + Rc::new(RefCell::new( + ret_values.get(i).cloned().unwrap_or(Value::Nil), + )), + ); } } else { return None; @@ -212,17 +226,24 @@ impl ClosureRunner { .vm .prototypes .get(&self.closure.prototype) - .unwrap(); + .unwrap() + .clone(); let constants = &self.closure.vm.constants; if let Some(instr) = instructions.get(self.program_counter) { match instr { Instruction::Move(a, b) => { - self.stack - .insert(*a, self.stack.get(b).unwrap_or(&Value::Nil).clone()); + self.set_stack( + *a, + self.stack + .get(b) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil) + .clone(), + ); } Instruction::LoadK(reg, constant) => { - self.stack.insert( + self.set_stack( *reg, match constants.get(*constant as usize).unwrap() { Constant::String(_) => todo!(), @@ -232,13 +253,17 @@ impl ClosureRunner { } Instruction::LoadNil(from_reg, to_reg) => { for i in *from_reg..=*to_reg { - self.stack.insert(i, Value::Nil); + self.stack.insert(i, Rc::new(RefCell::new(Value::Nil))); } } Instruction::SetGlobal(reg, global) => { self.closure.environment.borrow_mut().globals.insert( constants.get(*global as usize).unwrap().clone(), - self.stack.get(reg).unwrap_or(&Value::Nil).clone(), + self.stack + .get(reg) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil) + .clone(), ); } Instruction::GetGlobal(reg, global) => { @@ -249,37 +274,44 @@ impl ClosureRunner { .globals .get(constants.get(*global as usize).unwrap()) { - self.stack.insert(*reg, global.clone()); + self.stack + .insert(*reg, Rc::new(RefCell::new(global.clone()))); } else { todo!("Global not found: {:?}", constants.get(*global as usize)) } } Instruction::GetUpVal(reg, upvalreg) => { - self.stack.insert( - *reg, - self.closure - .upvalues - .get(upvalreg) - .unwrap() - .borrow() - .clone(), - ); + self.stack + .insert(*reg, self.closure.upvalues.get(upvalreg).unwrap().clone()); } Instruction::SetUpVal(upvalreg, reg) => { - *self.closure.upvalues.get(upvalreg).unwrap().borrow_mut() = - self.stack.get(reg).cloned().unwrap_or(Value::Nil); + *self.closure.upvalues.get(upvalreg).unwrap().borrow_mut() = self + .stack + .get(reg) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil); } Instruction::Jmp(b) => { self.program_counter = (self.program_counter as i32 + *b) as usize } Instruction::Test(a, b, c) => { - let is_true = match self.stack.get(b).unwrap_or(&Value::Nil) { - Value::Number(val) => (LuaNumber::from_bits(*val) as u16) == *c, + let is_true = match self + .stack + .get(b) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil) + { + Value::Number(val) => (LuaNumber::from_bits(val) as u16) == *c, _ => false, }; if is_true { - self.stack - .insert(*a, self.stack.get(b).cloned().unwrap_or(Value::Nil)); + self.set_stack( + *a, + self.stack + .get(b) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil), + ); } else { self.program_counter += 1; } @@ -303,25 +335,30 @@ impl ClosureRunner { params.push( self.stack .get(&(param_start_func_reg + i + 1)) - .unwrap_or(&Value::Nil) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil) .clone(), ); } - let value = self.stack.get(func_reg).unwrap_or(&Value::Nil); + let value = self + .stack + .get(func_reg) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil); match value { Value::RustFunction(func) => { let ret_values = func.borrow_mut().execute(params); if *ret_len != 0 { for i in 0..=(*ret_len - 2) { - self.stack.insert( + self.set_stack( *func_reg + i, ret_values.get(i as usize).cloned().unwrap_or(Value::Nil), ); } } else { for (i, value) in ret_values.iter().enumerate() { - self.stack.insert(*func_reg + i as u16 + 1, value.clone()); + self.set_stack(*func_reg + i as u16 + 1, value.clone()); } self.top = *func_reg + ret_values.len() as u16; } @@ -339,7 +376,7 @@ impl ClosureRunner { dbg!(&value); if *ret_len > 0 { for i in 0..=(*ret_len - 2) { - self.stack.insert(*func_reg + i, Value::Nil); + self.set_stack(*func_reg + i, Value::Nil); } } } @@ -358,14 +395,11 @@ impl ClosureRunner { dbg!(&self.stack); let mut upvalues = self.closure.upvalues.clone(); for (reg, value) in &self.stack { - upvalues.insert( - reg + highest_upvalue + 1, - Rc::new(RefCell::new(value.clone())), - ); + upvalues.insert(reg + highest_upvalue + 1, value.clone()); } dbg!(&upvalues); - self.stack.insert( + self.set_stack( *reg, Value::Function(Closure { vm: self.closure.vm.clone(), @@ -388,19 +422,40 @@ impl ClosureRunner { (*reg_start, *reg_end) }; for i in reg_start..=reg_end { - ret_values.push(self.stack.get(&i).cloned().unwrap_or(Value::Nil)); + ret_values.push( + self.stack + .get(&i) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil), + ); } return Some(ret_values); } Instruction::Add(res, lhs, rhs) => { - let lhs = self.stack.get(lhs).unwrap_or(&Value::Nil); - let rhs = self.stack.get(rhs).unwrap_or(&Value::Nil); - self.stack.insert(*res, lhs.add(rhs)); + let lhs = self + .stack + .get(lhs) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil); + let rhs = self + .stack + .get(rhs) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil); + self.set_stack(*res, lhs.add(&rhs)); } Instruction::LessThan(res, lhs, rhs) => { - let lhs = self.stack.get(lhs).unwrap_or(&Value::Nil); - let rhs = self.stack.get(rhs).unwrap_or(&Value::Nil); - self.stack.insert(*res, lhs.lt(rhs)); + let lhs = self + .stack + .get(lhs) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil); + let rhs = self + .stack + .get(rhs) + .map(|v| v.borrow().clone()) + .unwrap_or(Value::Nil); + self.set_stack(*res, lhs.lt(&rhs)); } };