diff options
| -rw-r--r-- | lcode.c | 26 | ||||
| -rw-r--r-- | ldebug.c | 26 | ||||
| -rw-r--r-- | ldo.c | 37 | ||||
| -rw-r--r-- | ldo.h | 10 | ||||
| -rw-r--r-- | lopcodes.c | 4 | ||||
| -rw-r--r-- | lopcodes.h | 10 | ||||
| -rw-r--r-- | lparser.c | 22 | ||||
| -rw-r--r-- | lstate.h | 3 | ||||
| -rw-r--r-- | ltm.c | 55 | ||||
| -rw-r--r-- | ltm.h | 10 | ||||
| -rw-r--r-- | lvm.c | 40 |
11 files changed, 133 insertions, 110 deletions
| @@ -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 | */ |
| 159 | void luaK_ret (FuncState *fs, int first, int nret) { | 159 | void 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; |
| @@ -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 | ||
| 190 | static 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 | |||
| 190 | static const char *findlocal (lua_State *L, CallInfo *ci, int n, | 202 | static 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 | } |
| @@ -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 | ||
| 313 | static void rethook (lua_State *L, CallInfo *ci) { | 313 | void 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 | */ |
| 346 | static void moveresults (lua_State *L, StkId firstResult, StkId res, | 346 | void 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 | */ |
| 388 | void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { | 387 | void 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) { | |||
| 438 | void luaD_call (lua_State *L, StkId func, int nresults) { | 433 | void 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; |
| @@ -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' */ |
| 46 | typedef void (*Pfunc) (lua_State *L, void *ud); | 51 | typedef 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); |
| 58 | LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, | 63 | LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, |
| 59 | int nres); | 64 | int nres); |
| 65 | LUAI_FUNC void luaD_rethook (lua_State *L, CallInfo *ci); | ||
| 60 | LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); | 66 | LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); |
| 67 | LUAI_FUNC void luaD_moveresults (lua_State *L, StkId firstResult, StkId res, | ||
| 68 | int nres, int wanted); | ||
| 61 | LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); | 69 | LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); |
| 62 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); | 70 | LUAI_FUNC void luaD_shrinkstack (lua_State *L); |
| 63 | LUAI_FUNC void luaD_inctop (lua_State *L); | 71 | LUAI_FUNC void luaD_inctop (lua_State *L); |
| @@ -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 */ |
| @@ -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)) */ | |||
| 268 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ | 268 | OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ |
| 269 | 269 | ||
| 270 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ | 270 | OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ |
| 271 | OP_RETVARARG,/* A B return R(A), ... ,R(A+B-2) (see note) */ | ||
| 271 | OP_RETURN0,/* return */ | 272 | OP_RETURN0,/* return */ |
| 272 | OP_RETURN1,/* A return R(A) */ | 273 | OP_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 | ||
| 287 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ | 288 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ |
| 288 | 289 | ||
| 289 | OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg(B) */ | 290 | OP_VARARG,/* A B C R(A), R(A+1), ..., R(A+C-2) = vararg */ |
| 290 | 291 | ||
| 291 | OP_PREPVARARG,/*A (adjust vararg parameters) */ | 292 | OP_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). |
| @@ -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 */ |
| @@ -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 */ |
| @@ -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 | ||
| 219 | void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base) { | 219 | void 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 | ||
| 239 | void luaT_getvarargs (lua_State *L, TValue *t, StkId where, int wanted) { | 235 | void 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 | } |
| @@ -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, | |||
| 77 | LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, | 78 | LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, |
| 78 | int inv, TMS event); | 79 | int inv, TMS event); |
| 79 | 80 | ||
| 80 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, StkId base); | 81 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, |
| 81 | LUAI_FUNC void luaT_getvarargs (lua_State *L, TValue *t, StkId where, | 82 | struct CallInfo *ci); |
| 82 | int wanted); | 83 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, |
| 84 | StkId where, int wanted); | ||
| 83 | 85 | ||
| 84 | 86 | ||
| 85 | #endif | 87 | #endif |
| @@ -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); |
