From e08ff38803b4dbbe820e9b8a98123bc1641d1642 Mon Sep 17 00:00:00 2001 From: luaneko Date: Mon, 23 Jun 2025 07:02:50 +1000 Subject: [PATCH] Implement variadic support in luaify --- crates/luaify/src/generate.rs | 27 +++++++++++++++++++++++---- crates/luaify/tests/test.rs | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/luaify/src/generate.rs b/crates/luaify/src/generate.rs index 0e8bb41..06591e6 100644 --- a/crates/luaify/src/generate.rs +++ b/crates/luaify/src/generate.rs @@ -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) -> 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) -> 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(()) } diff --git a/crates/luaify/tests/test.rs b/crates/luaify/tests/test.rs index 36eb7fd..7119167 100644 --- a/crates/luaify/tests/test.rs +++ b/crates/luaify/tests/test.rs @@ -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"# + ); +}