diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-05-13 10:04:33 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-05-13 10:04:33 -0300 |
| commit | 5c8770f8969a73cf4ca503f54c2217f76de62e04 (patch) | |
| tree | d5dac87490011d117277d94c81f6f2fd47b1b094 | |
| parent | 7647d5d13d016f114dac4be0b9da62d502eab400 (diff) | |
| download | lua-5c8770f8969a73cf4ca503f54c2217f76de62e04.tar.gz lua-5c8770f8969a73cf4ca503f54c2217f76de62e04.tar.bz2 lua-5c8770f8969a73cf4ca503f54c2217f76de62e04.zip | |
back to old-style vararg system (with vararg table collecting extra
arguments)
| -rw-r--r-- | ldebug.c | 21 | ||||
| -rw-r--r-- | ldo.c | 41 | ||||
| -rw-r--r-- | ldo.h | 10 | ||||
| -rw-r--r-- | lparser.c | 11 | ||||
| -rw-r--r-- | ltm.c | 40 | ||||
| -rw-r--r-- | ltm.h | 5 | ||||
| -rw-r--r-- | lvm.c | 18 |
7 files changed, 74 insertions, 72 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.c,v 2.123 2017/04/28 20:57:45 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.124 2017/04/29 15:28:38 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 | */ |
| @@ -131,28 +131,13 @@ static const char *upvalname (Proto *p, int uv) { | |||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | 133 | ||
| 134 | static const char *findvararg (CallInfo *ci, int n, StkId *pos) { | ||
| 135 | int nparams = clLvalue(ci->func)->p->numparams; | ||
| 136 | if (n >= cast_int(ci->u.l.base - ci->func) - nparams) | ||
| 137 | return NULL; /* no such vararg */ | ||
| 138 | else { | ||
| 139 | *pos = ci->func + nparams + n; | ||
| 140 | return "(*vararg)"; /* generic name for any vararg */ | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | static const char *findlocal (lua_State *L, CallInfo *ci, int n, | 134 | static const char *findlocal (lua_State *L, CallInfo *ci, int n, |
| 146 | StkId *pos) { | 135 | StkId *pos) { |
| 147 | const char *name = NULL; | 136 | const char *name = NULL; |
| 148 | StkId base; | 137 | StkId base; |
| 149 | if (isLua(ci)) { | 138 | if (isLua(ci)) { |
| 150 | if (n < 0) /* access to vararg values? */ | 139 | base = ci->u.l.base; |
| 151 | return findvararg(ci, -n, pos); | 140 | name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); |
| 152 | else { | ||
| 153 | base = ci->u.l.base; | ||
| 154 | name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); | ||
| 155 | } | ||
| 156 | } | 141 | } |
| 157 | else | 142 | else |
| 158 | base = ci->func + 1; | 143 | base = ci->func + 1; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.156 2016/09/20 16:37:45 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.157 2016/12/13 15:52:21 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 | */ |
| @@ -290,23 +290,6 @@ static void callhook (lua_State *L, CallInfo *ci) { | |||
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | 292 | ||
| 293 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { | ||
| 294 | int i; | ||
| 295 | int nfixargs = p->numparams; | ||
| 296 | StkId base, fixed; | ||
| 297 | /* move fixed parameters to final position */ | ||
| 298 | fixed = L->top - actual; /* first fixed argument */ | ||
| 299 | base = L->top; /* final position of first argument */ | ||
| 300 | for (i = 0; i < nfixargs && i < actual; i++) { | ||
| 301 | setobjs2s(L, L->top++, fixed + i); | ||
| 302 | setnilvalue(fixed + i); /* erase original copy (for GC) */ | ||
| 303 | } | ||
| 304 | for (; i < nfixargs; i++) | ||
| 305 | setnilvalue(L->top++); /* complete missing arguments */ | ||
| 306 | return base; | ||
| 307 | } | ||
| 308 | |||
| 309 | |||
| 310 | /* | 293 | /* |
| 311 | ** Check whether __call metafield of 'func' is a function. If so, put | 294 | ** Check whether __call metafield of 'func' is a function. If so, put |
| 312 | ** it in stack below original 'func' so that 'luaD_precall' can call | 295 | ** it in stack below original 'func' so that 'luaD_precall' can call |
| @@ -395,14 +378,6 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { | |||
| 395 | #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) | 378 | #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) |
| 396 | 379 | ||
| 397 | 380 | ||
| 398 | /* macro to check stack size, preserving 'p' */ | ||
| 399 | #define checkstackp(L,n,p) \ | ||
| 400 | luaD_checkstackaux(L, n, \ | ||
| 401 | ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ | ||
| 402 | luaC_checkGC(L), /* stack grow uses memory */ \ | ||
| 403 | p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ | ||
| 404 | |||
| 405 | |||
| 406 | /* | 381 | /* |
| 407 | ** Prepares a function call: checks the stack, creates a new CallInfo | 382 | ** Prepares a function call: checks the stack, creates a new CallInfo |
| 408 | ** entry, fills in the relevant information, calls hook if needed. | 383 | ** entry, fills in the relevant information, calls hook if needed. |
| @@ -438,23 +413,19 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 438 | return 1; | 413 | return 1; |
| 439 | } | 414 | } |
| 440 | case LUA_TLCL: { /* Lua function: prepare its call */ | 415 | case LUA_TLCL: { /* Lua function: prepare its call */ |
| 441 | StkId base; | ||
| 442 | Proto *p = clLvalue(func)->p; | 416 | Proto *p = clLvalue(func)->p; |
| 443 | int n = cast_int(L->top - func) - 1; /* number of real arguments */ | 417 | int n = cast_int(L->top - func) - 1; /* number of real arguments */ |
| 444 | int fsize = p->maxstacksize; /* frame size */ | 418 | int fsize = p->maxstacksize; /* frame size */ |
| 445 | checkstackp(L, fsize, func); | 419 | checkstackp(L, fsize, func); |
| 420 | for (; n < p->numparams - p->is_vararg; n++) | ||
| 421 | setnilvalue(L->top++); /* complete missing arguments */ | ||
| 446 | if (p->is_vararg) | 422 | if (p->is_vararg) |
| 447 | base = adjust_varargs(L, p, n); | 423 | luaT_adjustvarargs(L, p, n); |
| 448 | else { /* non vararg function */ | ||
| 449 | for (; n < p->numparams; n++) | ||
| 450 | setnilvalue(L->top++); /* complete missing arguments */ | ||
| 451 | base = func + 1; | ||
| 452 | } | ||
| 453 | ci = next_ci(L); /* now 'enter' new function */ | 424 | ci = next_ci(L); /* now 'enter' new function */ |
| 454 | ci->nresults = nresults; | 425 | ci->nresults = nresults; |
| 455 | ci->func = func; | 426 | ci->func = func; |
| 456 | ci->u.l.base = base; | 427 | ci->u.l.base = func + 1; |
| 457 | L->top = ci->top = base + fsize; | 428 | L->top = ci->top = func + 1 + fsize; |
| 458 | lua_assert(ci->top <= L->stack_last); | 429 | lua_assert(ci->top <= L->stack_last); |
| 459 | ci->u.l.savedpc = p->code; /* starting point */ | 430 | ci->u.l.savedpc = p->code; /* starting point */ |
| 460 | ci->callstatus = CIST_LUA; | 431 | ci->callstatus = CIST_LUA; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp roberto $ | 2 | ** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 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 | */ |
| @@ -33,6 +33,14 @@ | |||
| 33 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) | 33 | #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) |
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | /* macro to check stack size, preserving 'p' */ | ||
| 37 | #define checkstackp(L,n,p) \ | ||
| 38 | luaD_checkstackaux(L, n, \ | ||
| 39 | ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ | ||
| 40 | luaC_checkGC(L), /* stack grow uses memory */ \ | ||
| 41 | p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ | ||
| 42 | |||
| 43 | |||
| 36 | /* type of protected functions, to be ran by 'runprotected' */ | 44 | /* type of protected functions, to be ran by 'runprotected' */ |
| 37 | typedef void (*Pfunc) (lua_State *L, void *ud); | 45 | typedef void (*Pfunc) (lua_State *L, void *ud); |
| 38 | 46 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 2.157 2017/04/28 20:57:45 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.158 2017/04/29 18:09:17 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 | */ |
| @@ -766,7 +766,12 @@ static void parlist (LexState *ls) { | |||
| 766 | } | 766 | } |
| 767 | case TK_DOTS: { /* param -> '...' */ | 767 | case TK_DOTS: { /* param -> '...' */ |
| 768 | luaX_next(ls); | 768 | luaX_next(ls); |
| 769 | if (testnext(ls, '=')) | ||
| 770 | new_localvar(ls, str_checkname(ls)); | ||
| 771 | else | ||
| 772 | new_localvarliteral(ls, "_ARG"); | ||
| 769 | f->is_vararg = 1; /* declared vararg */ | 773 | f->is_vararg = 1; /* declared vararg */ |
| 774 | nparams++; | ||
| 770 | break; | 775 | break; |
| 771 | } | 776 | } |
| 772 | default: luaX_syntaxerror(ls, "<name> or '...' expected"); | 777 | default: luaX_syntaxerror(ls, "<name> or '...' expected"); |
| @@ -1622,6 +1627,10 @@ static void mainfunc (LexState *ls, FuncState *fs) { | |||
| 1622 | expdesc v; | 1627 | expdesc v; |
| 1623 | open_func(ls, fs, &bl); | 1628 | open_func(ls, fs, &bl); |
| 1624 | fs->f->is_vararg = 1; /* main function is always declared vararg */ | 1629 | fs->f->is_vararg = 1; /* main function is always declared vararg */ |
| 1630 | fs->f->numparams = 1; | ||
| 1631 | new_localvarliteral(ls, "_ARG"); | ||
| 1632 | adjustlocalvars(ls, 1); | ||
| 1633 | luaK_reserveregs(fs, 1); /* reserve register for vararg */ | ||
| 1625 | init_exp(&v, VLOCAL, 0); /* create and... */ | 1634 | init_exp(&v, VLOCAL, 0); /* create and... */ |
| 1626 | newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ | 1635 | newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ |
| 1627 | luaX_next(ls); /* read first token */ | 1636 | luaX_next(ls); /* read first token */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltm.c,v 2.39 2017/04/11 18:41:09 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 2.40 2017/05/08 15:57:23 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 | */ |
| @@ -163,3 +163,41 @@ int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, | |||
| 163 | return !l_isfalse(L->top); | 163 | return !l_isfalse(L->top); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | |||
| 167 | void luaT_adjustvarargs (lua_State *L, Proto *p, int actual) { | ||
| 168 | int i; | ||
| 169 | Table *vtab; | ||
| 170 | TValue nname; | ||
| 171 | int nfixparams = p->numparams - 1; /* number of fixed parameters */ | ||
| 172 | actual -= nfixparams; /* number of extra arguments */ | ||
| 173 | vtab = luaH_new(L); /* create vararg table */ | ||
| 174 | sethvalue(L, L->top, vtab); /* anchor it for resizing */ | ||
| 175 | L->top++; /* space ensured by caller */ | ||
| 176 | luaH_resize(L, vtab, actual, 1); | ||
| 177 | for (i = 0; i < actual; i++) /* put extra arguments into vararg table */ | ||
| 178 | setobj2n(L, &vtab->array[i], L->top - actual + i - 1); | ||
| 179 | setsvalue(L, &nname, luaS_newliteral(L, "n")); /* get field 'n' */ | ||
| 180 | setivalue(luaH_set(L, vtab, &nname), actual); /* store counter there */ | ||
| 181 | L->top -= actual; /* remove extra elements from the stack */ | ||
| 182 | sethvalue(L, L->top - 1, vtab); /* move table to new top */ | ||
| 183 | } | ||
| 184 | |||
| 185 | |||
| 186 | void luaT_getvarargs (lua_State *L, StkId t, StkId where, int wanted) { | ||
| 187 | if (!ttistable(t)) | ||
| 188 | luaG_runerror(L, "'vararg' parameter is not a table"); | ||
| 189 | else { | ||
| 190 | int i; | ||
| 191 | Table *h = hvalue(t); | ||
| 192 | if (wanted < 0) { /* get all? */ | ||
| 193 | const TValue *ns = luaH_getstr(h, luaS_newliteral(L, "n")); | ||
| 194 | int n = (ttisinteger(ns)) ? ivalue(ns) : 0; | ||
| 195 | wanted = n; | ||
| 196 | checkstackp(L, n, where); | ||
| 197 | L->top = where + n; | ||
| 198 | } | ||
| 199 | for (i = 0; i < wanted; i++) /* get what is available */ | ||
| 200 | setobj2s(L, where + i, luaH_getint(h, i + 1)); | ||
| 201 | return; | ||
| 202 | } | ||
| 203 | } | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp roberto $ | 2 | ** $Id: ltm.h,v 2.23 2017/05/08 15:57:23 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 | */ |
| @@ -69,6 +69,9 @@ LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, | |||
| 69 | LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, | 69 | LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, |
| 70 | const TValue *p2, TMS event); | 70 | const TValue *p2, TMS event); |
| 71 | 71 | ||
| 72 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, Proto *p, int actual); | ||
| 73 | LUAI_FUNC void luaT_getvarargs (lua_State *L, StkId t, StkId where, | ||
| 74 | int wanted); | ||
| 72 | 75 | ||
| 73 | 76 | ||
| 74 | #endif | 77 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.279 2017/05/10 17:32:19 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.280 2017/05/11 18:57:46 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 | */ |
| @@ -1433,20 +1433,8 @@ void luaV_execute (lua_State *L) { | |||
| 1433 | } | 1433 | } |
| 1434 | vmcase(OP_VARARG) { | 1434 | vmcase(OP_VARARG) { |
| 1435 | int b = GETARG_B(i) - 1; /* required results */ | 1435 | int b = GETARG_B(i) - 1; /* required results */ |
| 1436 | int j; | 1436 | StkId vtab = base + cl->p->numparams - 1; /* vararg table */ |
| 1437 | int n = cast_int(base - ci->func) - cl->p->numparams - 1; | 1437 | Protect(luaT_getvarargs(L, vtab, ra, b)); |
| 1438 | if (n < 0) /* less arguments than parameters? */ | ||
| 1439 | n = 0; /* no vararg arguments */ | ||
| 1440 | if (b < 0) { /* B == 0? */ | ||
| 1441 | b = n; /* get all var. arguments */ | ||
| 1442 | Protect(luaD_checkstack(L, n)); | ||
| 1443 | ra = RA(i); /* previous call may change the stack */ | ||
| 1444 | L->top = ra + n; | ||
| 1445 | } | ||
| 1446 | for (j = 0; j < b && j < n; j++) | ||
| 1447 | setobjs2s(L, ra + j, base - n + j); | ||
| 1448 | for (; j < b; j++) /* complete required results with nil */ | ||
| 1449 | setnilvalue(ra + j); | ||
| 1450 | vmbreak; | 1438 | vmbreak; |
| 1451 | } | 1439 | } |
| 1452 | vmcase(OP_EXTRAARG) { | 1440 | vmcase(OP_EXTRAARG) { |
