summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lcode.c26
-rw-r--r--ldebug.c26
-rw-r--r--ldo.c37
-rw-r--r--ldo.h10
-rw-r--r--lopcodes.c4
-rw-r--r--lopcodes.h10
-rw-r--r--lparser.c22
-rw-r--r--lstate.h3
-rw-r--r--ltm.c55
-rw-r--r--ltm.h10
-rw-r--r--lvm.c40
11 files changed, 133 insertions, 110 deletions
diff --git a/lcode.c b/lcode.c
index 7f240580..25fb0770 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.151 2018/01/27 16:56:33 roberto Exp roberto $ 2** $Id: lcode.c,v 2.152 2018/01/28 15:13:26 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -31,7 +31,7 @@
31 31
32 32
33/* Maximum number of registers in a Lua function (must fit in 8 bits) */ 33/* Maximum number of registers in a Lua function (must fit in 8 bits) */
34#define MAXREGS 255 34#define MAXREGS 254
35 35
36 36
37#define hasjumps(e) ((e)->t != (e)->f) 37#define hasjumps(e) ((e)->t != (e)->f)
@@ -157,17 +157,17 @@ int luaK_jump (FuncState *fs) {
157** Code a 'return' instruction 157** Code a 'return' instruction
158*/ 158*/
159void luaK_ret (FuncState *fs, int first, int nret) { 159void luaK_ret (FuncState *fs, int first, int nret) {
160 switch (nret) { 160 OpCode op;
161 case 0: 161 if (fs->f->is_vararg)
162 luaK_codeABC(fs, OP_RETURN0, 0, 0, 0); 162 op = OP_RETVARARG;
163 break; 163 else {
164 case 1: 164 switch (nret) {
165 luaK_codeABC(fs, OP_RETURN1, first, 0, 0); 165 case 0: op = OP_RETURN0; break;
166 break; 166 case 1: op = OP_RETURN1; break;
167 default: 167 default: op = OP_RETURN; break;
168 luaK_codeABC(fs, OP_RETURN, first, nret + 1, 0); 168 }
169 break;
170 } 169 }
170 luaK_codeABC(fs, op, first, nret + 1, fs->f->numparams);
171} 171}
172 172
173 173
@@ -1647,7 +1647,7 @@ void luaK_finish (FuncState *fs) {
1647 lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); 1647 lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc));
1648 switch (GET_OPCODE(*pc)) { 1648 switch (GET_OPCODE(*pc)) {
1649 case OP_RETURN: case OP_RETURN0: case OP_RETURN1: 1649 case OP_RETURN: case OP_RETURN0: case OP_RETURN1:
1650 case OP_TAILCALL: { 1650 case OP_RETVARARG: case OP_TAILCALL: {
1651 if (p->sizep > 0) 1651 if (p->sizep > 0)
1652 SETARG_k(*pc, 1); /* signal that they must close upvalues */ 1652 SETARG_k(*pc, 1); /* signal that they must close upvalues */
1653 break; 1653 break;
diff --git a/ldebug.c b/ldebug.c
index 93a935a5..3ddac547 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.152 2018/01/10 12:02:35 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.153 2018/02/06 19:16:56 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -187,12 +187,28 @@ static const char *upvalname (Proto *p, int uv) {
187} 187}
188 188
189 189
190static const char *findvararg (CallInfo *ci, int n, StkId *pos) {
191 if (clLvalue(s2v(ci->func))->p->is_vararg) {
192 int nextra = ci->u.l.nextraargs;
193 if (n <= nextra) {
194 *pos = ci->func - nextra + (n - 1);
195 return "(*vararg)"; /* generic name for any vararg */
196 }
197 }
198 return NULL; /* no such vararg */
199}
200
201
190static const char *findlocal (lua_State *L, CallInfo *ci, int n, 202static const char *findlocal (lua_State *L, CallInfo *ci, int n,
191 StkId *pos) { 203 StkId *pos) {
192 StkId base = ci->func + 1; 204 StkId base = ci->func + 1;
193 const char *name = (isLua(ci)) 205 const char *name = NULL;
194 ? luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)) 206 if (isLua(ci)) {
195 : NULL; 207 if (n < 0) /* access to vararg values? */
208 return findvararg(ci, -n, pos);
209 else
210 name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci));
211 }
196 if (name == NULL) { /* no 'standard' name? */ 212 if (name == NULL) { /* no 'standard' name? */
197 StkId limit = (ci == L->ci) ? L->top : ci->next->func; 213 StkId limit = (ci == L->ci) ? L->top : ci->next->func;
198 if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ 214 if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */
@@ -324,7 +340,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
324 } 340 }
325 else { 341 else {
326 ar->isvararg = f->l.p->is_vararg; 342 ar->isvararg = f->l.p->is_vararg;
327 ar->nparams = f->l.p->numparams + f->l.p->is_vararg; 343 ar->nparams = f->l.p->numparams;
328 } 344 }
329 break; 345 break;
330 } 346 }
diff --git a/ldo.c b/ldo.c
index 402b3703..64512487 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 2.191 2018/02/07 15:18:04 roberto Exp roberto $ 2** $Id: ldo.c,v 2.192 2018/02/07 15:55:18 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -310,7 +310,7 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) {
310} 310}
311 311
312 312
313static void rethook (lua_State *L, CallInfo *ci) { 313void luaD_rethook (lua_State *L, CallInfo *ci) {
314 if (isLuacode(ci)) 314 if (isLuacode(ci))
315 L->top = ci->top; /* prepare top */ 315 L->top = ci->top; /* prepare top */
316 if (L->hookmask & LUA_MASKRET) /* is return hook on? */ 316 if (L->hookmask & LUA_MASKRET) /* is return hook on? */
@@ -343,8 +343,8 @@ void luaD_tryfuncTM (lua_State *L, StkId func) {
343** expressions, multiple results for tail calls/single parameters) 343** expressions, multiple results for tail calls/single parameters)
344** separated. 344** separated.
345*/ 345*/
346static void moveresults (lua_State *L, StkId firstResult, StkId res, 346void luaD_moveresults (lua_State *L, StkId firstResult, StkId res,
347 int nres, int wanted) { 347 int nres, int wanted) {
348 switch (wanted) { /* handle typical cases separately */ 348 switch (wanted) { /* handle typical cases separately */
349 case 0: break; /* nothing to move */ 349 case 0: break; /* nothing to move */
350 case 1: { /* one result needed */ 350 case 1: { /* one result needed */
@@ -382,27 +382,22 @@ static void moveresults (lua_State *L, StkId firstResult, StkId res,
382 382
383/* 383/*
384** Finishes a function call: calls hook if necessary, removes CallInfo, 384** Finishes a function call: calls hook if necessary, removes CallInfo,
385** moves current number of results to proper place; returns 0 iff call 385** moves current number of results to proper place.
386** wanted multiple (variable number of) results.
387*/ 386*/
388void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { 387void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
389 if (L->hookmask) { 388 if (L->hookmask) {
390 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ 389 ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */
391 rethook(L, ci); 390 luaD_rethook(L, ci);
392 firstResult = restorestack(L, fr); 391 firstResult = restorestack(L, fr);
393 } 392 }
394 L->ci = ci->previous; /* back to caller */ 393 L->ci = ci->previous; /* back to caller */
395 /* move results to proper place */ 394 /* move results to proper place */
396 moveresults(L, firstResult, ci->func, nres, ci->nresults); 395 luaD_moveresults(L, firstResult, ci->func, nres, ci->nresults);
397} 396}
398 397
399 398
400 399
401#define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) 400#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L)))
402
403
404#define checkstackGC(L,fsize) \
405 luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L))
406 401
407 402
408/* 403/*
@@ -438,8 +433,6 @@ void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) {
438void luaD_call (lua_State *L, StkId func, int nresults) { 433void luaD_call (lua_State *L, StkId func, int nresults) {
439 lua_CFunction f; 434 lua_CFunction f;
440 TValue *funcv = s2v(func); 435 TValue *funcv = s2v(func);
441 CallInfo *ci = next_ci(L);
442 ci->nresults = nresults;
443 switch (ttype(funcv)) { 436 switch (ttype(funcv)) {
444 case LUA_TCCL: /* C closure */ 437 case LUA_TCCL: /* C closure */
445 f = clCvalue(funcv)->f; 438 f = clCvalue(funcv)->f;
@@ -448,12 +441,14 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
448 f = fvalue(funcv); 441 f = fvalue(funcv);
449 Cfunc: { 442 Cfunc: {
450 int n; /* number of returns */ 443 int n; /* number of returns */
444 CallInfo *ci;
451 checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ 445 checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */
446 ci = next_ci(L);
447 ci->nresults = nresults;
452 ci->callstatus = CIST_C; 448 ci->callstatus = CIST_C;
453 ci->top = L->top + LUA_MINSTACK; 449 ci->top = L->top + LUA_MINSTACK;
454 ci->func = func; 450 ci->func = func;
455 lua_assert(ci->top <= L->stack_last); 451 lua_assert(ci->top <= L->stack_last);
456 L->ci = ci; /* now 'enter' new function */
457 if (L->hookmask & LUA_MASKCALL) 452 if (L->hookmask & LUA_MASKCALL)
458 luaD_hook(L, LUA_HOOKCALL, -1); 453 luaD_hook(L, LUA_HOOKCALL, -1);
459 lua_unlock(L); 454 lua_unlock(L);
@@ -464,18 +459,20 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
464 break; 459 break;
465 } 460 }
466 case LUA_TLCL: { /* Lua function */ 461 case LUA_TLCL: { /* Lua function */
462 CallInfo *ci;
467 Proto *p = clLvalue(funcv)->p; 463 Proto *p = clLvalue(funcv)->p;
468 int narg = cast_int(L->top - func) - 1; /* number of real arguments */ 464 int narg = cast_int(L->top - func) - 1; /* number of real arguments */
469 int nfixparams = p->numparams; 465 int nfixparams = p->numparams;
470 int fsize = p->maxstacksize; /* frame size */ 466 int fsize = p->maxstacksize; /* frame size */
471 ci->u.l.savedpc = p->code; /* starting point */
472 checkstackp(L, fsize, func); 467 checkstackp(L, fsize, func);
473 for (; narg < nfixparams; narg++) 468 ci = next_ci(L);
474 setnilvalue(s2v(L->top++)); /* complete missing arguments */ 469 ci->nresults = nresults;
470 ci->u.l.savedpc = p->code; /* starting point */
475 ci->callstatus = 0; 471 ci->callstatus = 0;
476 ci->top = func + 1 + fsize; 472 ci->top = func + 1 + fsize;
477 ci->func = func; 473 ci->func = func;
478 L->ci = ci; /* now 'enter' new function */ 474 for (; narg < nfixparams; narg++)
475 setnilvalue(s2v(L->top++)); /* complete missing arguments */
479 lua_assert(ci->top <= L->stack_last); 476 lua_assert(ci->top <= L->stack_last);
480 luaV_execute(L, ci); /* run the function */ 477 luaV_execute(L, ci); /* run the function */
481 break; 478 break;
diff --git a/ldo.h b/ldo.h
index 44e3af20..864cf3e6 100644
--- a/ldo.h
+++ b/ldo.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.h,v 2.39 2018/01/10 19:19:27 roberto Exp roberto $ 2** $Id: ldo.h,v 2.40 2018/02/06 19:16:56 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -42,6 +42,11 @@
42 p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ 42 p = restorestack(L, t__)) /* 'pos' part: restore 'p' */
43 43
44 44
45/* macro to check stack size and GC */
46#define checkstackGC(L,fsize) \
47 luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L))
48
49
45/* type of protected functions, to be ran by 'runprotected' */ 50/* type of protected functions, to be ran by 'runprotected' */
46typedef void (*Pfunc) (lua_State *L, void *ud); 51typedef void (*Pfunc) (lua_State *L, void *ud);
47 52
@@ -57,7 +62,10 @@ LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
57 ptrdiff_t oldtop, ptrdiff_t ef); 62 ptrdiff_t oldtop, ptrdiff_t ef);
58LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, 63LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
59 int nres); 64 int nres);
65LUAI_FUNC void luaD_rethook (lua_State *L, CallInfo *ci);
60LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); 66LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
67LUAI_FUNC void luaD_moveresults (lua_State *L, StkId firstResult, StkId res,
68 int nres, int wanted);
61LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); 69LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
62LUAI_FUNC void luaD_shrinkstack (lua_State *L); 70LUAI_FUNC void luaD_shrinkstack (lua_State *L);
63LUAI_FUNC void luaD_inctop (lua_State *L); 71LUAI_FUNC void luaD_inctop (lua_State *L);
diff --git a/lopcodes.c b/lopcodes.c
index cd85f1a9..d04e707f 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.c,v 1.75 2017/12/22 14:16:46 roberto Exp roberto $ 2** $Id: lopcodes.c,v 1.76 2018/02/07 15:18:04 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -80,6 +80,7 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
80 "CALL", 80 "CALL",
81 "TAILCALL", 81 "TAILCALL",
82 "RETURN", 82 "RETURN",
83 "RETVARARG",
83 "RETURN0", 84 "RETURN0",
84 "RETURN1", 85 "RETURN1",
85 "FORLOOP1", 86 "FORLOOP1",
@@ -161,6 +162,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
161 ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */ 162 ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */
162 ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */ 163 ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */
163 ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */ 164 ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */
165 ,opmode(0, 1, 0, 0, iABC) /* OP_RETVARARG */
164 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */ 166 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */
165 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */ 167 ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */
166 ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */ 168 ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP1 */
diff --git a/lopcodes.h b/lopcodes.h
index 47c72c69..3c7a9573 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lopcodes.h,v 1.184 2018/01/28 15:13:26 roberto Exp roberto $ 2** $Id: lopcodes.h,v 1.186 2018/02/07 15:18:04 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -268,6 +268,7 @@ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
268OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ 268OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
269 269
270OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ 270OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
271OP_RETVARARG,/* A B return R(A), ... ,R(A+B-2) (see note) */
271OP_RETURN0,/* return */ 272OP_RETURN0,/* return */
272OP_RETURN1,/* A return R(A) */ 273OP_RETURN1,/* A return R(A) */
273 274
@@ -286,7 +287,7 @@ OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
286 287
287OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ 288OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */
288 289
289OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */ 290OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg */
290 291
291OP_PREPVARARG,/*A (adjust vararg parameters) */ 292OP_PREPVARARG,/*A (adjust vararg parameters) */
292 293
@@ -305,9 +306,10 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
305 OP_SETLIST) may use 'top'. 306 OP_SETLIST) may use 'top'.
306 307
307 (*) In OP_VARARG, if (C == 0) then use actual number of varargs and 308 (*) In OP_VARARG, if (C == 0) then use actual number of varargs and
308 set top (like in OP_CALL with C == 0). B is the vararg parameter. 309 set top (like in OP_CALL with C == 0).
309 310
310 (*) In OP_RETURN, if (B == 0) then return up to 'top'. 311 (*) In OP_RETURN/OP_RETVARARG, if (B == 0) then return up to 'top'.
312 (OP_RETVARARG is the return instruction for vararg functions.)
311 313
312 (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then 314 (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then
313 next 'instruction' is EXTRAARG(real C). 315 next 'instruction' is EXTRAARG(real C).
diff --git a/lparser.c b/lparser.c
index aab03dc8..802c64bd 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.175 2017/12/22 14:16:46 roberto Exp roberto $ 2** $Id: lparser.c,v 2.176 2018/02/07 15:18:04 roberto Exp roberto $
3** Lua Parser 3** Lua Parser
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -568,6 +568,7 @@ static void close_func (LexState *ls) {
568 Proto *f = fs->f; 568 Proto *f = fs->f;
569 luaK_ret(fs, 0, 0); /* final return */ 569 luaK_ret(fs, 0, 0); /* final return */
570 leaveblock(fs); 570 leaveblock(fs);
571 lua_assert(fs->bl == NULL);
571 luaK_finish(fs); 572 luaK_finish(fs);
572 luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction); 573 luaM_shrinkvector(L, f->code, f->sizecode, fs->pc, Instruction);
573 luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); 574 luaM_shrinkvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte);
@@ -577,7 +578,8 @@ static void close_func (LexState *ls) {
577 luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *); 578 luaM_shrinkvector(L, f->p, f->sizep, fs->np, Proto *);
578 luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); 579 luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
579 luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); 580 luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
580 lua_assert(fs->bl == NULL); 581 if (f->is_vararg)
582 f->maxstacksize++; /* ensure space to copy the function */
581 ls->fs = fs->prev; 583 ls->fs = fs->prev;
582 luaC_checkGC(L); 584 luaC_checkGC(L);
583} 585}
@@ -781,11 +783,6 @@ static void parlist (LexState *ls) {
781 } 783 }
782 case TK_DOTS: { /* param -> '...' */ 784 case TK_DOTS: { /* param -> '...' */
783 luaX_next(ls); 785 luaX_next(ls);
784 if (testnext(ls, '='))
785 new_localvar(ls, str_checkname(ls));
786 else
787 new_localvarliteral(ls, "_ARG");
788 nparams++;
789 isvararg = 1; 786 isvararg = 1;
790 break; 787 break;
791 } 788 }
@@ -795,10 +792,8 @@ static void parlist (LexState *ls) {
795 } 792 }
796 adjustlocalvars(ls, nparams); 793 adjustlocalvars(ls, nparams);
797 f->numparams = cast_byte(fs->nactvar); 794 f->numparams = cast_byte(fs->nactvar);
798 if (isvararg) { 795 if (isvararg)
799 f->numparams--; /* exclude vararg parameter */
800 setvararg(fs, f->numparams); /* declared vararg */ 796 setvararg(fs, f->numparams); /* declared vararg */
801 }
802 luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */ 797 luaK_reserveregs(fs, fs->nactvar); /* reserve registers for parameters */
803} 798}
804 799
@@ -984,10 +979,9 @@ static void simpleexp (LexState *ls, expdesc *v) {
984 } 979 }
985 case TK_DOTS: { /* vararg */ 980 case TK_DOTS: { /* vararg */
986 FuncState *fs = ls->fs; 981 FuncState *fs = ls->fs;
987 int lastparam = fs->f->numparams;
988 check_condition(ls, fs->f->is_vararg, 982 check_condition(ls, fs->f->is_vararg,
989 "cannot use '...' outside a vararg function"); 983 "cannot use '...' outside a vararg function");
990 init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, lastparam, 1)); 984 init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1));
991 break; 985 break;
992 } 986 }
993 case '{': { /* constructor */ 987 case '{': { /* constructor */
@@ -1703,10 +1697,6 @@ static void mainfunc (LexState *ls, FuncState *fs) {
1703 expdesc v; 1697 expdesc v;
1704 open_func(ls, fs, &bl); 1698 open_func(ls, fs, &bl);
1705 setvararg(fs, 0); /* main function is always declared vararg */ 1699 setvararg(fs, 0); /* main function is always declared vararg */
1706 fs->f->numparams = 0;
1707 new_localvarliteral(ls, "_ARG");
1708 adjustlocalvars(ls, 1);
1709 luaK_reserveregs(fs, 1); /* reserve register for vararg */
1710 init_exp(&v, VLOCAL, 0); /* create and... */ 1700 init_exp(&v, VLOCAL, 0); /* create and... */
1711 newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ 1701 newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */
1712 luaX_next(ls); /* read first token */ 1702 luaX_next(ls); /* read first token */
diff --git a/lstate.h b/lstate.h
index bc4df4e5..2cce8e4f 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.152 2017/11/23 16:35:54 roberto Exp roberto $ 2** $Id: lstate.h,v 2.153 2017/12/19 16:40:17 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -92,6 +92,7 @@ typedef struct CallInfo {
92 struct { /* only for Lua functions */ 92 struct { /* only for Lua functions */
93 const Instruction *savedpc; 93 const Instruction *savedpc;
94 l_signalT trap; 94 l_signalT trap;
95 int nextraargs; /* # of extra arguments in vararg functions */
95 } l; 96 } l;
96 struct { /* only for C functions */ 97 struct { /* only for C functions */
97 lua_KFunction k; /* continuation in case of yields */ 98 lua_KFunction k; /* continuation in case of yields */
diff --git a/ltm.c b/ltm.c
index f36f4625..d88b636b 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 2.58 2018/01/28 13:39:52 roberto Exp roberto $ 2** $Id: ltm.c,v 2.59 2018/02/07 15:18:04 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -216,41 +216,32 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
216} 216}
217 217
218 218
219void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base) { 219void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci) {
220 int i; 220 int i;
221 Table *vtab; 221 int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */
222 TValue nname;
223 int actual = cast_int(L->top - base); /* number of arguments */
224 int nextra = actual - nfixparams; /* number of extra arguments */ 222 int nextra = actual - nfixparams; /* number of extra arguments */
225 vtab = luaH_new(L); /* create vararg table */ 223 ci->u.l.nextraargs = nextra;
226 sethvalue2s(L, L->top, vtab); /* anchor it for resizing */ 224 checkstackGC(L, nfixparams + 1);
227 L->top++; /* space ensured by caller */ 225 /* copy function and fixed parameters to the top of the stack */
228 luaH_resize(L, vtab, nextra, 1); 226 for (i = 0; i <= nfixparams; i++) {
229 for (i = 0; i < nextra; i++) /* put extra arguments into vararg table */ 227 setobjs2s(L, L->top++, ci->func + i);
230 setobj2n(L, &vtab->array[i], s2v(L->top - nextra + i - 1)); 228 setnilvalue(s2v(ci->func + i)); /* erase original copy (for GC) */
231 setsvalue(L, &nname, G(L)->nfield); /* get field 'n' */ 229 }
232 setivalue(luaH_set(L, vtab, &nname), nextra); /* store counter there */ 230 ci->func += actual + 1;
233 L->top -= nextra; /* remove extra elements from the stack */ 231 ci->top += actual + 1;
234 sethvalue2s(L, L->top - 1, vtab); /* move table to new top */
235 luaC_checkGC(L);
236} 232}
237 233
238 234
239void luaT_getvarargs (lua_State *L, TValue *t, StkId where, int wanted) { 235void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) {
240 if (!ttistable(t)) 236 int i;
241 luaG_runerror(L, "'vararg' parameter is not a table"); 237 int nextra = ci->u.l.nextraargs;
242 else { 238 if (wanted < 0) {
243 int i; 239 wanted = nextra; /* get all extra arguments available */
244 Table *h = hvalue(t); 240 checkstackp(L, nextra, where); /* ensure stack space */
245 if (wanted < 0) { /* get all? */ 241 L->top = where + nextra; /* next instruction will need top */
246 const TValue *ns = luaH_getstr(h, G(L)->nfield);
247 int n = (ttisinteger(ns)) ? cast_int(ivalue(ns)) : 0;
248 wanted = n;
249 checkstackp(L, n, where);
250 L->top = where + n;
251 }
252 for (i = 0; i < wanted; i++) /* get what is available */
253 setobj2s(L, where + i, luaH_getint(h, i + 1));
254 return;
255 } 242 }
243 for (i = 0; i < wanted && i < nextra; i++)
244 setobjs2s(L, where + i, ci->func - nextra + i);
245 for (; i < wanted; i++) /* complete required results with nil */
246 setnilvalue(s2v(where + i));
256} 247}
diff --git a/ltm.h b/ltm.h
index a0f4f92e..54cece9e 100644
--- a/ltm.h
+++ b/ltm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.h,v 2.29 2018/01/28 13:39:52 roberto Exp roberto $ 2** $Id: ltm.h,v 2.30 2018/02/07 15:18:04 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -9,6 +9,7 @@
9 9
10 10
11#include "lobject.h" 11#include "lobject.h"
12#include "lstate.h"
12 13
13 14
14/* 15/*
@@ -77,9 +78,10 @@ LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1,
77LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, 78LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2,
78 int inv, TMS event); 79 int inv, TMS event);
79 80
80LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base); 81LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
81LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where, 82 struct CallInfo *ci);
82 int wanted); 83LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
84 StkId where, int wanted);
83 85
84 86
85#endif 87#endif
diff --git a/lvm.c b/lvm.c
index 7f2e2492..2d01e4c1 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.337 2018/02/06 19:16:56 roberto Exp roberto $ 2** $Id: lvm.c,v 2.338 2018/02/07 15:18:04 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -1506,14 +1506,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1506 luaF_close(L, base); /* close upvalues from current call */ 1506 luaF_close(L, base); /* close upvalues from current call */
1507 if (!ttisLclosure(vra)) { /* C function? */ 1507 if (!ttisLclosure(vra)) { /* C function? */
1508 ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */ 1508 ProtectNT(luaD_call(L, ra, LUA_MULTRET)); /* call it */
1509 if (trap) {
1510 updatebase(ci);
1511 ra = RA(i);
1512 }
1513 luaD_poscall(L, ci, ra, cast_int(L->top - ra));
1514 return;
1515 } 1509 }
1516 else { /* Lua tail call */ 1510 else { /* Lua tail call */
1511 if (cl->p->is_vararg)
1512 ci->func -= cl->p->numparams + ci->u.l.nextraargs + 1;
1517 luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ 1513 luaD_pretailcall(L, ci, ra, b); /* prepare call frame */
1518 goto tailcall; 1514 goto tailcall;
1519 } 1515 }
@@ -1521,11 +1517,30 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1521 } 1517 }
1522 vmcase(OP_RETURN) { 1518 vmcase(OP_RETURN) {
1523 int b = GETARG_B(i); 1519 int b = GETARG_B(i);
1520 int n = (b != 0 ? b - 1 : cast_int(L->top - ra));
1521 if (TESTARG_k(i))
1522 luaF_close(L, base);
1523 halfProtect(luaD_poscall(L, ci, ra, n));
1524 return;
1525 }
1526 vmcase(OP_RETVARARG) {
1527 int b = GETARG_B(i);
1528 int nparams = GETARG_C(i);
1529 int nres = (b != 0 ? b - 1 : cast_int(L->top - ra));
1530 int delta = ci->u.l.nextraargs + nparams + 2;
1524 if (TESTARG_k(i)) 1531 if (TESTARG_k(i))
1525 luaF_close(L, base); 1532 luaF_close(L, base);
1526 halfProtect( 1533 savepc(L);
1527 luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))) 1534 /* code similar to 'luaD_poscall', but with a delta */
1528 ); 1535 if (L->hookmask) {
1536 luaD_rethook(L, ci);
1537 if (ci->u.l.trap) {
1538 updatebase(ci);
1539 ra = RA(i);
1540 }
1541 }
1542 L->ci = ci->previous; /* back to caller */
1543 luaD_moveresults(L, ra, base - delta, nres, ci->nresults);
1529 return; 1544 return;
1530 } 1545 }
1531 vmcase(OP_RETURN0) { 1546 vmcase(OP_RETURN0) {
@@ -1702,12 +1717,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1702 } 1717 }
1703 vmcase(OP_VARARG) { 1718 vmcase(OP_VARARG) {
1704 int n = GETARG_C(i) - 1; /* required results */ 1719 int n = GETARG_C(i) - 1; /* required results */
1705 TValue *vtab = vRB(i); /* vararg table */ 1720 ProtectNT(luaT_getvarargs(L, ci, ra, n));
1706 Protect(luaT_getvarargs(L, vtab, ra, n));
1707 vmbreak; 1721 vmbreak;
1708 } 1722 }
1709 vmcase(OP_PREPVARARG) { 1723 vmcase(OP_PREPVARARG) {
1710 luaT_adjustvarargs(L, GETARG_A(i), base); 1724 luaT_adjustvarargs(L, GETARG_A(i), ci);
1711 updatetrap(ci); 1725 updatetrap(ci);
1712 if (trap) { 1726 if (trap) {
1713 luaD_hookcall(L, ci); 1727 luaD_hookcall(L, ci);