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