I already reported all the problems I found in the new features and they
are already fixed.
Personally, I like the new `...name` syntax to name varargs.
However, I would have liked to see a `varargtable...` operator as the
reverse of the named vararg `...varargtable`.
This should behave like `table.unpack(varargtable, 1, varargtable.n)`
and should not have parsing problems since constructs such as
`...(funcarg)` or `...[1]=1` are not valid.
In my opinion this would make the use of `...` cleaner in case the
function uses a named vararg parameter as in:
local function test(...args)
return ...
end
vs
local function test(...args)
return args...
end
and could allow for constructs such as
local function test(...args)
return functon() return args... end
end
I tried to implement this myself by using OP_VARARG and the unused K and
RB parameters to encode if this is the `a...` version and what the slot
of `a` is.
The following is the patch in case someone is interested:
index 95ef900c..fe9e4454 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1951,6 +1951,11 @@ void luaK_finish (FuncState *fs) {
SET_OPCODE(*pc, OP_GETTABLE); /* must get vararg there */
break;
}
+ case OP_VARARG: {
+ if ((p->flag & (PF_VATAB | PF_ISVARARG)) == PF_ISVARARG &&
GETARG_B(*pc) == fs->f->numparams)
+ SETARG_k(*pc, 0); /* Don't use the spread function in case
the vararg table is not created */
+ break;
+ }
case OP_JMP: { /* to optimize jumps to jumps */
int target = finaltarget(p->code, i);
fixjump(fs, i, target); /* jump directly to final target */
diff --git a/lparser.c b/lparser.c
index 77141e79..4ecaa670 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1247,6 +1247,21 @@ static void suffixedexp (LexState *ls, expdesc *v) {
funcargs(ls, v);
break;
}
+ case TK_DOTS: {
+ if (v->k == VVARGVAR && v->t == v->f) {
+ init_exp(v, VVARARG, luaK_codeABCk(fs, OP_VARARG, 0,
v->u.var.ridx, 1, 1));
+ } else {
+ luaK_exp2anyreg(fs, v);
+ if (v->k == VNONRELOC && v->
u.info >= luaY_nvarstack(fs)) {
+ fs->freereg--;
+ lua_assert(v->
u.info == fs->freereg);
+ }
+ init_exp(v, VVARARG, luaK_codeABCk(fs, OP_VARARG, 0,
v->
u.info, 1, 1));
+ }
+ luaK_checkstack(fs, 2);
+ luaX_next(ls);
+ return;
+ }
default: return;
}
}
diff --git a/ltablib.c b/ltablib.c
index 46ecb5e0..0c0aefac 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -424,3 +424,13 @@ LUAMOD_API int luaopen_table (lua_State *L) {
return 1;
}
+LUAI_FUNC int luaT_spread(lua_State *L);
+int luaT_spread(lua_State *L) {
+ int isnum;
+ lua_settop(L, 1);
+ lua_pushinteger(L, 1);
+ lua_getfield(L, 1, "n");
+ lua_tointegerx(L, -1, &isnum);
+ if (l_unlikely(!isnum)) return luaL_error(L, "'n' not an integer");
+ return tunpack(L);
+}
\ No newline at end of file
diff --git a/lvm.c b/lvm.c
index 2c868c21..77ad8e2e 100644
--- a/lvm.c
+++ b/lvm.c
@@ -31,6 +31,7 @@
#include "ltm.h"
#include "lvm.h"
+LUAI_FUNC int luaT_spread(lua_State *L);
/*
** By default, use jump tables in the main interpreter loop on gcc
@@ -1936,6 +1937,13 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmcase(OP_VARARG) {
StkId ra = RA(i);
int n = GETARG_C(i) - 1; /* required results */
+ if (TESTARG_k(i)) {
+ StkId rb = RB(i);
+ setobjs2s(L, ra+1, rb);
+ setfvalue(s2v(ra), luaT_spread);
+ L->top.p = ra + 2;
+ ProtectNT(luaD_call(L, ra, n));
+ } else
Protect(luaT_getvarargs(L, ci, ra, n));
vmbreak;
}
Regards,
Xmilia