Implement variadic support in luaify

This commit is contained in:
lumi 2025-06-23 07:02:50 +10:00
parent 40478fb7de
commit e08ff38803
Signed by: luaneko
GPG Key ID: 406809B8763FF07A
2 changed files with 41 additions and 4 deletions

View File

@ -569,9 +569,10 @@ fn generate_expr_while(f: &mut Formatter, whil: &ExprWhile, cx: Context) -> Resu
}
fn generate_punctuated_expr(f: &mut Formatter, exprs: &Punctuated<Expr, Token![,]>) -> Result<()> {
let len = exprs.len();
for (i, expr) in exprs.iter().enumerate() {
(i != 0).then(|| f.write(","));
generate_expr(f, expr, Context::expr(false))?;
generate_expr(f, expr, Context::expr(i == len - 1))?;
}
Ok(())
}
@ -795,6 +796,7 @@ fn generate_receiver(f: &mut Formatter, recv: &Receiver) -> Result<()> {
fn generate_macro(f: &mut Formatter, mac: &Macro, cx: Context) -> Result<()> {
match format!("{}", mac.path.require_ident()?).as_str() {
"concat" => generate_macro_concat(f, mac, cx),
"variadic" => generate_macro_variadic(f, mac, cx),
"embed" => generate_macro_embed(f, mac, cx),
"raw" => generate_macro_raw(f, mac, cx),
name => syn_error!(mac.path, "unknown macro '{name}'"),
@ -813,6 +815,17 @@ fn generate_macro_concat(f: &mut Formatter, mac: &Macro, cx: Context) -> Result<
Ok(())
}
fn generate_macro_variadic(f: &mut Formatter, mac: &Macro, cx: Context) -> Result<()> {
syn_assert!(
cx.is_multi_expr(),
mac,
"variadic! must be in multi-value expression position"
);
cx.is_ret().then(|| f.write("return"));
f.write("...");
Ok(())
}
fn generate_macro_embed(f: &mut Formatter, mac: &Macro, cx: Context) -> Result<()> {
syn_assert!(cx.is_value(), mac, "embed! must be in expression position");
cx.is_ret().then(|| f.write("return"));
@ -871,9 +884,9 @@ fn generate_pat_ident(f: &mut Formatter, ident: &PatIdent, _cx: PatContext) -> R
generate_ident(f, &ident.ident)
}
fn generate_pat_macro(f: &mut Formatter, mac: &PatMacro, _cx: PatContext) -> Result<()> {
fn generate_pat_macro(f: &mut Formatter, mac: &PatMacro, cx: PatContext) -> Result<()> {
assert_no_attrs!(mac);
generate_macro(f, &mac.mac, Context::expr(false))
generate_macro(f, &mac.mac, Context::expr(cx.is_multi()))
}
fn generate_pat_tuple(f: &mut Formatter, tuple: &PatTuple, cx: PatContext) -> Result<()> {
@ -900,9 +913,15 @@ fn generate_pat_wild(f: &mut Formatter, wild: &PatWild, _cx: PatContext) -> Resu
}
fn generate_punctuated_pat(f: &mut Formatter, pats: &Punctuated<Pat, Token![,]>) -> Result<()> {
let len = pats.len();
for (i, pat) in pats.iter().enumerate() {
(i != 0).then(|| f.write(","));
generate_pat(f, pat, PatContext::Single)?;
let cx = if i == len - 1 {
PatContext::Multi
} else {
PatContext::Single
};
generate_pat(f, pat, cx)?;
}
Ok(())
}

View File

@ -373,3 +373,21 @@ fn ifs() {
r#"function()if a==b then c();elseif b==c then return a();else d();end;end"#
);
}
#[test]
fn variadic() {
assert_eq!(luaify!(|a, b, variadic!()| {}), r#"function(a,b,...)end"#);
assert_eq!(
luaify!(|variadic!()| {
let (a, b) = variadic!();
}),
r#"function(...)local a,b=...;end"#
);
assert_eq!(
luaify!(|a, variadic!()| {
let (a, b) = (a, b, c, variadic!());
func(a, b, (c, (d, variadic!())))
}),
r#"function(a,...)local a,b=a,b,c,...;return func(a,b,c,d,...);end"#
);
}