Fix upvalues and stack values being different references

This commit is contained in:
Sofia 2026-03-16 15:56:57 +02:00
parent c9a0a5560d
commit 1eb62b078e
2 changed files with 103 additions and 45 deletions

View File

@ -3,6 +3,7 @@ local b = 5
function add(x) function add(x)
return function (y) return function (y)
x = x + 1 x = x + 1
b = b + 1
return x + y, 1, 2, b return x + y, 1, 2, b
end end
end end
@ -17,4 +18,6 @@ end
print(max(11, 9)) print(max(11, 9))
print(add(10)(15)) print(add(10)(15))
print(add(10)(15))
print(b)
print(min(11, 9)) print(min(11, 9))

145
src/vm.rs
View File

@ -162,7 +162,7 @@ impl Closure {
pub fn run(&self, params: Vec<Value>) -> ClosureRunner { pub fn run(&self, params: Vec<Value>) -> ClosureRunner {
let mut stack = HashMap::new(); let mut stack = HashMap::new();
for (i, param) in params.iter().enumerate() { 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 { ClosureRunner {
closure: self.clone(), closure: self.clone(),
@ -179,7 +179,7 @@ impl Closure {
pub struct ClosureRunner { pub struct ClosureRunner {
pub closure: Closure, pub closure: Closure,
pub program_counter: usize, pub program_counter: usize,
pub stack: HashMap<u16, Value>, pub stack: HashMap<u16, Rc<RefCell<Value>>>,
pub inner: Option<Box<ClosureRunner>>, pub inner: Option<Box<ClosureRunner>>,
pub function_register: u16, pub function_register: u16,
pub return_registers: Vec<u16>, pub return_registers: Vec<u16>,
@ -187,20 +187,34 @@ pub struct ClosureRunner {
} }
impl 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<Vec<Value>> { pub fn next(&mut self) -> Option<Vec<Value>> {
if let Some(inner) = &mut self.inner { if let Some(inner) = &mut self.inner {
if let Some(ret_values) = inner.next() { if let Some(ret_values) = inner.next() {
self.inner = None; self.inner = None;
if self.return_registers.len() == 0 { if self.return_registers.len() == 0 {
for (i, value) in ret_values.iter().enumerate() { for (i, value) in ret_values.iter().enumerate() {
self.stack self.stack.insert(
.insert(self.function_register + i as u16 + 1, value.clone()); self.function_register + i as u16 + 1,
Rc::new(RefCell::new(value.clone())),
);
} }
self.top = self.function_register + ret_values.len() as u16; self.top = self.function_register + ret_values.len() as u16;
} }
for (i, reg) in self.return_registers.iter().enumerate() { for (i, reg) in self.return_registers.iter().enumerate() {
self.stack self.stack.insert(
.insert(*reg, ret_values.get(i).cloned().unwrap_or(Value::Nil)); *reg,
Rc::new(RefCell::new(
ret_values.get(i).cloned().unwrap_or(Value::Nil),
)),
);
} }
} else { } else {
return None; return None;
@ -212,17 +226,24 @@ impl ClosureRunner {
.vm .vm
.prototypes .prototypes
.get(&self.closure.prototype) .get(&self.closure.prototype)
.unwrap(); .unwrap()
.clone();
let constants = &self.closure.vm.constants; let constants = &self.closure.vm.constants;
if let Some(instr) = instructions.get(self.program_counter) { if let Some(instr) = instructions.get(self.program_counter) {
match instr { match instr {
Instruction::Move(a, b) => { Instruction::Move(a, b) => {
self.stack self.set_stack(
.insert(*a, self.stack.get(b).unwrap_or(&Value::Nil).clone()); *a,
self.stack
.get(b)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil)
.clone(),
);
} }
Instruction::LoadK(reg, constant) => { Instruction::LoadK(reg, constant) => {
self.stack.insert( self.set_stack(
*reg, *reg,
match constants.get(*constant as usize).unwrap() { match constants.get(*constant as usize).unwrap() {
Constant::String(_) => todo!(), Constant::String(_) => todo!(),
@ -232,13 +253,17 @@ impl ClosureRunner {
} }
Instruction::LoadNil(from_reg, to_reg) => { Instruction::LoadNil(from_reg, to_reg) => {
for i in *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) => { Instruction::SetGlobal(reg, global) => {
self.closure.environment.borrow_mut().globals.insert( self.closure.environment.borrow_mut().globals.insert(
constants.get(*global as usize).unwrap().clone(), 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) => { Instruction::GetGlobal(reg, global) => {
@ -249,37 +274,44 @@ impl ClosureRunner {
.globals .globals
.get(constants.get(*global as usize).unwrap()) .get(constants.get(*global as usize).unwrap())
{ {
self.stack.insert(*reg, global.clone()); self.stack
.insert(*reg, Rc::new(RefCell::new(global.clone())));
} else { } else {
todo!("Global not found: {:?}", constants.get(*global as usize)) todo!("Global not found: {:?}", constants.get(*global as usize))
} }
} }
Instruction::GetUpVal(reg, upvalreg) => { Instruction::GetUpVal(reg, upvalreg) => {
self.stack.insert( self.stack
*reg, .insert(*reg, self.closure.upvalues.get(upvalreg).unwrap().clone());
self.closure
.upvalues
.get(upvalreg)
.unwrap()
.borrow()
.clone(),
);
} }
Instruction::SetUpVal(upvalreg, reg) => { Instruction::SetUpVal(upvalreg, reg) => {
*self.closure.upvalues.get(upvalreg).unwrap().borrow_mut() = *self.closure.upvalues.get(upvalreg).unwrap().borrow_mut() = self
self.stack.get(reg).cloned().unwrap_or(Value::Nil); .stack
.get(reg)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil);
} }
Instruction::Jmp(b) => { Instruction::Jmp(b) => {
self.program_counter = (self.program_counter as i32 + *b) as usize self.program_counter = (self.program_counter as i32 + *b) as usize
} }
Instruction::Test(a, b, c) => { Instruction::Test(a, b, c) => {
let is_true = match self.stack.get(b).unwrap_or(&Value::Nil) { let is_true = match self
Value::Number(val) => (LuaNumber::from_bits(*val) as u16) == *c, .stack
.get(b)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil)
{
Value::Number(val) => (LuaNumber::from_bits(val) as u16) == *c,
_ => false, _ => false,
}; };
if is_true { if is_true {
self.stack self.set_stack(
.insert(*a, self.stack.get(b).cloned().unwrap_or(Value::Nil)); *a,
self.stack
.get(b)
.map(|v| v.borrow().clone())
.unwrap_or(Value::Nil),
);
} else { } else {
self.program_counter += 1; self.program_counter += 1;
} }
@ -303,25 +335,30 @@ impl ClosureRunner {
params.push( params.push(
self.stack self.stack
.get(&(param_start_func_reg + i + 1)) .get(&(param_start_func_reg + i + 1))
.unwrap_or(&Value::Nil) .map(|v| v.borrow().clone())
.unwrap_or(Value::Nil)
.clone(), .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 { match value {
Value::RustFunction(func) => { Value::RustFunction(func) => {
let ret_values = func.borrow_mut().execute(params); let ret_values = func.borrow_mut().execute(params);
if *ret_len != 0 { if *ret_len != 0 {
for i in 0..=(*ret_len - 2) { for i in 0..=(*ret_len - 2) {
self.stack.insert( self.set_stack(
*func_reg + i, *func_reg + i,
ret_values.get(i as usize).cloned().unwrap_or(Value::Nil), ret_values.get(i as usize).cloned().unwrap_or(Value::Nil),
); );
} }
} else { } else {
for (i, value) in ret_values.iter().enumerate() { 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; self.top = *func_reg + ret_values.len() as u16;
} }
@ -339,7 +376,7 @@ impl ClosureRunner {
dbg!(&value); dbg!(&value);
if *ret_len > 0 { if *ret_len > 0 {
for i in 0..=(*ret_len - 2) { 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); dbg!(&self.stack);
let mut upvalues = self.closure.upvalues.clone(); let mut upvalues = self.closure.upvalues.clone();
for (reg, value) in &self.stack { for (reg, value) in &self.stack {
upvalues.insert( upvalues.insert(reg + highest_upvalue + 1, value.clone());
reg + highest_upvalue + 1,
Rc::new(RefCell::new(value.clone())),
);
} }
dbg!(&upvalues); dbg!(&upvalues);
self.stack.insert( self.set_stack(
*reg, *reg,
Value::Function(Closure { Value::Function(Closure {
vm: self.closure.vm.clone(), vm: self.closure.vm.clone(),
@ -388,19 +422,40 @@ impl ClosureRunner {
(*reg_start, *reg_end) (*reg_start, *reg_end)
}; };
for i in 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); return Some(ret_values);
} }
Instruction::Add(res, lhs, rhs) => { Instruction::Add(res, lhs, rhs) => {
let lhs = self.stack.get(lhs).unwrap_or(&Value::Nil); let lhs = self
let rhs = self.stack.get(rhs).unwrap_or(&Value::Nil); .stack
self.stack.insert(*res, lhs.add(rhs)); .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) => { Instruction::LessThan(res, lhs, rhs) => {
let lhs = self.stack.get(lhs).unwrap_or(&Value::Nil); let lhs = self
let rhs = self.stack.get(rhs).unwrap_or(&Value::Nil); .stack
self.stack.insert(*res, lhs.lt(rhs)); .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));
} }
}; };