From c5be1088c5bcb58592e3de23347cdb31be1ee644 Mon Sep 17 00:00:00 2001 From: Reuh Date: Fri, 26 Dec 2025 15:12:33 +0100 Subject: [PATCH] feat: add named varargs from Lua 5.5 --- candran/can-parser/parser.lua | 6 ++-- candran/can-parser/validator.lua | 4 +-- compiler/lua55.can | 48 ++++++++++++++++++-------------- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/candran/can-parser/parser.lua b/candran/can-parser/parser.lua index 615e006..baf92f7 100644 --- a/candran/can-parser/parser.lua +++ b/candran/can-parser/parser.lua @@ -34,7 +34,7 @@ expr: | `Boolean{ } | `Number{ } -- we don't use convert to number to avoid losing precision when tostring()-ing it later | `String{ } - | `Function{ { ( `ParPair{ Id expr } | `Id{ } )* `Dots? } block } + | `Function{ { ( `ParPair{ Id expr } | `Id{ } )* `ParDots? } block } | `Table{ ( `Pair{ expr expr } | expr )* } | `Op{ opid expr expr? } | `Paren{ expr } -- significant to cut multiple values returns @@ -573,8 +573,8 @@ local G = { V"Lua", * (sym(":") * expect(V"StrId", "NameFunc2"))^-1 / markMethod; FuncBody = tagC("Function", V"FuncParams" * expectBlockWithEnd("EndFunc")); FuncParams = expect(sym("("), "OParenPList") * V"ParList" * expect(sym(")"), "CParenPList"); - ParList = V"NamedParList" * (sym(",") * expect(tagC("Dots", sym("...")), "ParList"))^-1 / addDots - + Ct(tagC("Dots", sym("..."))) + ParList = V"NamedParList" * (sym(",") * expect(tagC("ParDots", sym("...") * V"Id"^-1), "ParList"))^-1 / addDots + + Ct(tagC("ParDots", sym("...") * V"Id"^-1)) + Ct(Cc()); -- Cc({}) generates a bug since the {} would be shared across parses ShortFuncDef = tagC("Function", V"ShortFuncParams" * maybeBlockWithEnd()) / fixShortFunc; diff --git a/candran/can-parser/validator.lua b/candran/can-parser/validator.lua index 6e7bd8d..c722003 100644 --- a/candran/can-parser/validator.lua +++ b/candran/can-parser/validator.lua @@ -71,7 +71,7 @@ local traverse_block, traverse_explist, traverse_varlist, traverse_parlist function traverse_parlist (env, parlist) local len = #parlist local is_vararg = false - if len > 0 and parlist[len].tag == "Dots" then + if len > 0 and parlist[len].tag == "ParDots" then is_vararg = true end set_vararg(env, is_vararg) @@ -348,7 +348,7 @@ function traverse_exp (env, exp) return true elseif tag == "Dots" then return traverse_vararg(env, exp) - elseif tag == "Function" then -- `Function{ { `Id{ }* `Dots? } block } + elseif tag == "Function" then -- `Function{ { `Id{ }* `ParDots? } block } return traverse_function(env, exp) elseif tag == "Table" then -- `Table{ ( `Pair{ expr expr } | expr )* } return traverse_table(env, exp) diff --git a/compiler/lua55.can b/compiler/lua55.can index 08c87c8..add25c5 100644 --- a/compiler/lua55.can +++ b/compiler/lua55.can @@ -587,33 +587,35 @@ return function(code, ast, options, macros={functions={}, variables={}}) String = (t) return "%q":format(t[1]) end, - -- Function{ { ( `ParPair{ Id expr } | `Id{ } )* `Dots? } block } + -- Function{ { ( `ParPair{ Id expr } | `Id{ } )* `ParDots? } block } + _functionParameter = { + ParPair = (t, decl) + local id = lua(t[1]) + indentLevel += 1 + table.insert(decl, "if "..id.." == nil then "..id.." = "..lua(t[2]).." end") + indentLevel -= 1 + return id + end, + ParDots = (t, decl) + if #t == 1 then + return "..." .. lua(t[1]) + else + return "..." + end + end, + }, _functionWithoutKeyword = (t) local r = "(" local decl = {} - if t[1][1] then - if t[1][1].tag == "ParPair" then - local id = lua(t[1][1][1]) - indentLevel += 1 - table.insert(decl, "if "..id.." == nil then "..id.." = "..lua(t[1][1][2]).." end") - indentLevel -= 1 - r ..= id + local pars = {} + for i=1, #t[1], 1 do + if tags._functionParameter[t[1][i].tag] then + table.insert(pars, tags._functionParameter[t[1][i].tag](t[1][i], decl)) else - r ..= lua(t[1][1]) - end - for i=2, #t[1], 1 do - if t[1][i].tag == "ParPair" then - local id = lua(t[1][i][1]) - indentLevel += 1 - table.insert(decl, "if "..id.." == nil then "..id.." = "..lua(t[1][i][2]).." end") - indentLevel -= 1 - r ..= ", " ..id - else - r ..= ", "..lua(t[1][i]) - end + table.insert(pars, lua(t[1][i])) end end - r ..= ")"..indent() + r ..= table.concat(pars, ", ")..")"..indent() for _, d in ipairs(decl) do r ..= d..newline() end @@ -851,6 +853,10 @@ return function(code, ast, options, macros={functions={}, variables={}}) AttributeNameList = (t) return lua(t, "_lhs") end, + -- NameList{ {Id+} } + NameList = (t) + return lua(t, "_lhs") + end, -- AttributeId{ ? } AttributeId = (t) if t[2] then