Add MoveRetValues instruction
This commit is contained in:
parent
38e5b41644
commit
b55c5eb070
@ -17,7 +17,7 @@ function min(x, y)
|
||||
end
|
||||
|
||||
function f(x)
|
||||
return x + 5
|
||||
return x + 5, add(10)(15)
|
||||
end
|
||||
|
||||
global sometable = {}
|
||||
@ -33,4 +33,5 @@ print(b)
|
||||
print(min(11, 9))
|
||||
print(10 - 15)
|
||||
print("hello there!")
|
||||
print(true or 0)
|
||||
print(true or 0)
|
||||
print(f(10))
|
||||
@ -566,18 +566,23 @@ impl Expression {
|
||||
|
||||
let mut param_scope = scope.clone();
|
||||
let mut original_param_regs = Vec::new();
|
||||
for param in params.kind.0.iter() {
|
||||
let mut vararg = false;
|
||||
for (i, param) in params.kind.0.iter().enumerate() {
|
||||
let (instr, registers) = param.kind.compile(
|
||||
state,
|
||||
&mut param_scope,
|
||||
if params.kind.0.len() == 1 {
|
||||
if i == params.kind.0.len() - 1 {
|
||||
None
|
||||
} else {
|
||||
Some(1)
|
||||
},
|
||||
);
|
||||
instructions.extend(instr);
|
||||
original_param_regs.extend(registers);
|
||||
if registers.len() > 0 {
|
||||
original_param_regs.push(*registers.first().unwrap());
|
||||
} else {
|
||||
vararg = true;
|
||||
}
|
||||
}
|
||||
|
||||
let mut registers = scope
|
||||
@ -600,6 +605,11 @@ impl Expression {
|
||||
instructions.push(Instruction::Move(function_reg, *old_function_reg));
|
||||
}
|
||||
|
||||
if vararg {
|
||||
let last_reg = param_regs.last().unwrap_or(&function_reg) + 1;
|
||||
instructions.push(Instruction::MoveRetValues(last_reg));
|
||||
}
|
||||
|
||||
let last_param_reg = param_regs.last().unwrap_or(&function_reg);
|
||||
|
||||
let mut return_regs = Vec::new();
|
||||
@ -616,7 +626,7 @@ impl Expression {
|
||||
|
||||
instructions.push(Instruction::Call(
|
||||
*&function_reg,
|
||||
param_regs.len() as u16,
|
||||
if vararg { 0 } else { param_regs.len() as u16 },
|
||||
if return_regs.len() == 0 {
|
||||
0
|
||||
} else {
|
||||
|
||||
25
src/vm.rs
25
src/vm.rs
@ -110,6 +110,8 @@ impl Debug for Constant {
|
||||
pub enum Instruction {
|
||||
/// R(A) := R(B)
|
||||
Move(u16, u16),
|
||||
/// R(A) ... R(A + func_register - top) := previous function return values
|
||||
MoveRetValues(u16),
|
||||
/// R(A) := K(Bx)
|
||||
LoadK(u16, u32),
|
||||
/// R(A), ..., R(B) := nil
|
||||
@ -165,6 +167,7 @@ impl Debug for Instruction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Instruction::Move(arg0, arg1) => write!(f, "MOVE {} {}", arg0, arg1),
|
||||
Instruction::MoveRetValues(arg0) => write!(f, "MOVERETVALS {}", arg0),
|
||||
Instruction::LoadK(arg0, arg1) => write!(f, "LOADK {} {}", arg0, arg1),
|
||||
Instruction::SetGlobal(arg0, arg1) => write!(f, "SETGLOBAL {} {}", arg0, arg1),
|
||||
Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1),
|
||||
@ -708,6 +711,20 @@ impl ClosureRunner {
|
||||
let b = self.get_stack(*b);
|
||||
self.set_stack(*a, b);
|
||||
}
|
||||
Instruction::MoveRetValues(res) => {
|
||||
let length = self.top - self.function_register;
|
||||
|
||||
let mut values = Vec::new();
|
||||
for i in 0..length {
|
||||
let b = self.get_stack(self.function_register + i + 1);
|
||||
values.push(b);
|
||||
}
|
||||
for (i, val) in values.into_iter().enumerate() {
|
||||
self.set_stack(*res + i as u16, val);
|
||||
}
|
||||
|
||||
self.top = *res + length;
|
||||
}
|
||||
Instruction::LoadK(reg, constant) => {
|
||||
self.set_stack(
|
||||
*reg,
|
||||
@ -868,14 +885,10 @@ impl ClosureRunner {
|
||||
}
|
||||
}
|
||||
Instruction::Call(func_reg, param_len, ret_len) => {
|
||||
let param_start_func_reg = if *param_len == 0 {
|
||||
self.function_register
|
||||
} else {
|
||||
*func_reg
|
||||
};
|
||||
let param_start_func_reg = *func_reg;
|
||||
|
||||
let param_len = if *param_len == 0 {
|
||||
self.top - self.top.min(param_start_func_reg)
|
||||
self.top - self.top.min(param_start_func_reg + 1)
|
||||
} else {
|
||||
*param_len
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user