Fix varargs for single value returns

This commit is contained in:
Sofia 2026-03-18 19:47:47 +02:00
parent a0108b4fd4
commit 28e1b43b81
3 changed files with 75 additions and 20 deletions

View File

@ -1,7 +1,39 @@
global b = 5
function f(x, ...) function add(x)
local b, c = ... return function (y)
return x + 5, b, c x = x + 1
b = b + 1
return x + y, 1, 2, b
end
end end
function min(x, y)
local m = x
if y < x then
m = y
end
return m
end
function f(x, ...)
local b = {10, ..., add(10)(15)}
return x + 5, b
end
global sometable = {}
sometable["hello"] = { 100, 150, add(10)(15) }
print(#sometable["hello"])
sometable["hello"].there = "my dude"
print(sometable.hello.there)
print(max(11.12345, 9))
print(add(10)(15))
print(add(10)(15))
print(b)
print(min(11, 9))
print(10 - 15)
print("hello there!")
print(true or 0)
print(123, f(10, 11, 12)) print(123, f(10, 11, 12))

View File

@ -750,8 +750,13 @@ impl Expression {
} }
let mut instructions = Vec::new(); let mut instructions = Vec::new();
let new_reg = scope.register_counter.new(); let new_reg = scope.register_counter.new();
instructions.push(Instruction::Vararg(new_reg)); if expected_values == None {
instructions.push(Instruction::Vararg(new_reg, 0));
(instructions, Vec::new()) (instructions, Vec::new())
} else {
instructions.push(Instruction::Vararg(new_reg, 3));
(instructions, vec![new_reg])
}
} }
} }
} }

View File

@ -161,8 +161,8 @@ pub enum Instruction {
Close(u16), Close(u16),
/// R(A) := closure(KPROTO[Bx], R(A), ..., R(A+n)) /// R(A) := closure(KPROTO[Bx], R(A), ..., R(A+n))
Closure(u16, u32), Closure(u16, u32),
/// R(A), ... := varargs /// R(A), ... , R(A+B-2) := varargs
Vararg(u16), Vararg(u16, u16),
} }
impl Debug for Instruction { impl Debug for Instruction {
@ -200,7 +200,7 @@ impl Debug for Instruction {
Instruction::Len(arg0, arg1) => write!(f, "LEN {} {}", arg0, arg1), Instruction::Len(arg0, arg1) => write!(f, "LEN {} {}", arg0, arg1),
Instruction::Or(arg0, arg1, arg2) => write!(f, "OR {} {} {}", arg0, arg1, arg2), Instruction::Or(arg0, arg1, arg2) => write!(f, "OR {} {} {}", arg0, arg1, arg2),
Instruction::And(arg0, arg1, arg2) => write!(f, "AND {} {} {}", arg0, arg1, arg2), Instruction::And(arg0, arg1, arg2) => write!(f, "AND {} {} {}", arg0, arg1, arg2),
Instruction::Vararg(arg0) => write!(f, "VARARG {}", arg0), Instruction::Vararg(arg0, arg1) => write!(f, "VARARG {} {}", arg0, arg1),
} }
} }
} }
@ -1097,8 +1097,9 @@ impl ClosureRunner {
.unwrap_or(Value::Nil); .unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.and(&rhs)?)); self.set_stack(*res, StackValue::Value(lhs.and(&rhs)?));
} }
Instruction::Vararg(reg) => { Instruction::Vararg(reg, len) => {
self.function_register = reg - 1; self.function_register = reg - 1;
if *len == 0 {
self.top = self.function_register + self.parameters.len() as u16 self.top = self.function_register + self.parameters.len() as u16
- prototype.parameters as u16; - prototype.parameters as u16;
@ -1111,6 +1112,23 @@ impl ClosureRunner {
{ {
self.set_stack(*reg + i as u16, StackValue::Value(param.clone())); self.set_stack(*reg + i as u16, StackValue::Value(param.clone()));
} }
} else {
let len = len - 2;
self.top = self.function_register + len + 1;
for i in 0..len {
self.set_stack(
*reg + i as u16,
StackValue::Value(
self.parameters
.iter()
.skip(prototype.parameters)
.next()
.unwrap_or(&Value::Nil)
.clone(),
),
);
}
}
} }
}; };