Fix upvalues and stack values being different references
This commit is contained in:
parent
c9a0a5560d
commit
1eb62b078e
@ -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))
|
||||
145
src/vm.rs
145
src/vm.rs
@ -162,7 +162,7 @@ impl Closure {
|
||||
pub fn run(&self, params: Vec<Value>) -> 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<u16, Value>,
|
||||
pub stack: HashMap<u16, Rc<RefCell<Value>>>,
|
||||
pub inner: Option<Box<ClosureRunner>>,
|
||||
pub function_register: u16,
|
||||
pub return_registers: Vec<u16>,
|
||||
@ -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<Vec<Value>> {
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user