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)
|
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
145
src/vm.rs
@ -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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user