Add returning varargs

This commit is contained in:
Sofia 2026-03-18 19:23:14 +02:00
parent 17c7432b7b
commit b0fc0a1dce
3 changed files with 28 additions and 4 deletions

View File

@ -1,6 +1,6 @@
function f(x, ...) function f(x, ...)
return x + 5 return x + 5, ...
end end
print(123, f(10, 12, 13)) print(123, f(10, 11, 12))

View File

@ -31,6 +31,7 @@ pub struct Scope {
pub register_counter: LocalCounter, pub register_counter: LocalCounter,
pub highest_upvalue: u16, pub highest_upvalue: u16,
pub upvalues: HashMap<String, u16>, pub upvalues: HashMap<String, u16>,
pub is_vararg: bool,
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
@ -543,7 +544,9 @@ impl Expression {
.locals .locals
.insert(name.clone(), inner_scope.register_counter.next()); .insert(name.clone(), inner_scope.register_counter.next());
} }
IdentOrEllipsis::Ellipsis => todo!(), IdentOrEllipsis::Ellipsis => {
inner_scope.is_vararg = true;
}
} }
} }
@ -726,7 +729,15 @@ impl Expression {
(instructions, vec![local]) (instructions, vec![local])
} }
Expression::Ellipsis => todo!(), Expression::Ellipsis => {
if !scope.is_vararg {
panic!("Function is not vararg!");
}
let mut instructions = Vec::new();
let new_reg = scope.register_counter.new();
instructions.push(Instruction::Vararg(new_reg));
(instructions, Vec::new())
}
} }
} }
} }

View File

@ -161,6 +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
Vararg(u16),
} }
impl Debug for Instruction { impl Debug for Instruction {
@ -198,6 +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),
} }
} }
} }
@ -574,6 +577,7 @@ impl Closure {
function_register: 0, function_register: 0,
return_registers: Vec::new(), return_registers: Vec::new(),
top: 0, top: 0,
parameters: params,
} }
} }
@ -597,6 +601,7 @@ pub struct ClosureRunner {
function_register: u16, function_register: u16,
return_registers: Vec<u16>, return_registers: Vec<u16>,
top: u16, top: u16,
parameters: Vec<Value>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -1083,6 +1088,14 @@ 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) => {
self.function_register = reg - 1;
self.top = self.function_register + self.parameters.len() as u16;
for (i, param) in self.parameters.clone().iter().enumerate() {
self.set_stack(*reg + i as u16, StackValue::Value(param.clone()));
}
}
}; };
self.program_counter += 1; self.program_counter += 1;