From 5c8770f8969a73cf4ca503f54c2217f76de62e04 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Sat, 13 May 2017 10:04:33 -0300 Subject: [PATCH] back to old-style vararg system (with vararg table collecting extra arguments) --- ldebug.c | 21 +++------------------ ldo.c | 41 ++++++----------------------------------- ldo.h | 10 +++++++++- lparser.c | 11 ++++++++++- ltm.c | 40 +++++++++++++++++++++++++++++++++++++++- ltm.h | 5 ++++- lvm.c | 18 +++--------------- 7 files changed, 74 insertions(+), 72 deletions(-) diff --git a/ldebug.c b/ldebug.c index ead16794..776b05eb 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.123 2017/04/28 20:57:45 roberto Exp roberto $ +** $Id: ldebug.c,v 2.124 2017/04/29 15:28:38 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -131,28 +131,13 @@ static const char *upvalname (Proto *p, int uv) { } -static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - int nparams = clLvalue(ci->func)->p->numparams; - if (n >= cast_int(ci->u.l.base - ci->func) - nparams) - return NULL; /* no such vararg */ - else { - *pos = ci->func + nparams + n; - return "(*vararg)"; /* generic name for any vararg */ - } -} - - static const char *findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { const char *name = NULL; StkId base; if (isLua(ci)) { - if (n < 0) /* access to vararg values? */ - return findvararg(ci, -n, pos); - else { - base = ci->u.l.base; - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); - } + base = ci->u.l.base; + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); } else base = ci->func + 1; diff --git a/ldo.c b/ldo.c index 13387516..14d1adc6 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.156 2016/09/20 16:37:45 roberto Exp roberto $ +** $Id: ldo.c,v 2.157 2016/12/13 15:52:21 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -290,23 +290,6 @@ static void callhook (lua_State *L, CallInfo *ci) { } -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { - int i; - int nfixargs = p->numparams; - StkId base, fixed; - /* move fixed parameters to final position */ - fixed = L->top - actual; /* first fixed argument */ - base = L->top; /* final position of first argument */ - for (i = 0; i < nfixargs && i < actual; i++) { - setobjs2s(L, L->top++, fixed + i); - setnilvalue(fixed + i); /* erase original copy (for GC) */ - } - for (; i < nfixargs; i++) - setnilvalue(L->top++); /* complete missing arguments */ - return base; -} - - /* ** Check whether __call metafield of 'func' is a function. If so, put ** 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) { #define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) -/* macro to check stack size, preserving 'p' */ -#define checkstackp(L,n,p) \ - luaD_checkstackaux(L, n, \ - ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ - luaC_checkGC(L), /* stack grow uses memory */ \ - p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ - - /* ** Prepares a function call: checks the stack, creates a new CallInfo ** entry, fills in the relevant information, calls hook if needed. @@ -438,23 +413,19 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { return 1; } case LUA_TLCL: { /* Lua function: prepare its call */ - StkId base; Proto *p = clLvalue(func)->p; int n = cast_int(L->top - func) - 1; /* number of real arguments */ int fsize = p->maxstacksize; /* frame size */ checkstackp(L, fsize, func); + for (; n < p->numparams - p->is_vararg; n++) + setnilvalue(L->top++); /* complete missing arguments */ if (p->is_vararg) - base = adjust_varargs(L, p, n); - else { /* non vararg function */ - for (; n < p->numparams; n++) - setnilvalue(L->top++); /* complete missing arguments */ - base = func + 1; - } + luaT_adjustvarargs(L, p, n); ci = next_ci(L); /* now 'enter' new function */ ci->nresults = nresults; ci->func = func; - ci->u.l.base = base; - L->top = ci->top = base + fsize; + ci->u.l.base = func + 1; + L->top = ci->top = func + 1 + fsize; lua_assert(ci->top <= L->stack_last); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus = CIST_LUA; diff --git a/ldo.h b/ldo.h index b2065cfa..4717620f 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.28 2015/11/23 11:29:43 roberto Exp roberto $ +** $Id: ldo.h,v 2.29 2015/12/21 13:02:14 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -33,6 +33,14 @@ #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) +/* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ + luaC_checkGC(L), /* stack grow uses memory */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + /* type of protected functions, to be ran by 'runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); diff --git a/lparser.c b/lparser.c index af5891c2..37f84cce 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.157 2017/04/28 20:57:45 roberto Exp roberto $ +** $Id: lparser.c,v 2.158 2017/04/29 18:09:17 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -766,7 +766,12 @@ static void parlist (LexState *ls) { } case TK_DOTS: { /* param -> '...' */ luaX_next(ls); + if (testnext(ls, '=')) + new_localvar(ls, str_checkname(ls)); + else + new_localvarliteral(ls, "_ARG"); f->is_vararg = 1; /* declared vararg */ + nparams++; break; } default: luaX_syntaxerror(ls, " or '...' expected"); @@ -1622,6 +1627,10 @@ static void mainfunc (LexState *ls, FuncState *fs) { expdesc v; open_func(ls, fs, &bl); fs->f->is_vararg = 1; /* main function is always declared vararg */ + fs->f->numparams = 1; + new_localvarliteral(ls, "_ARG"); + adjustlocalvars(ls, 1); + luaK_reserveregs(fs, 1); /* reserve register for vararg */ init_exp(&v, VLOCAL, 0); /* create and... */ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ luaX_next(ls); /* read first token */ diff --git a/ltm.c b/ltm.c index 0ef76313..9da191f6 100644 --- a/ltm.c +++ b/ltm.c @@ -1,5 +1,5 @@ /* -** $Id: ltm.c,v 2.39 2017/04/11 18:41:09 roberto Exp roberto $ +** $Id: ltm.c,v 2.40 2017/05/08 15:57:23 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -163,3 +163,41 @@ int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, return !l_isfalse(L->top); } + +void luaT_adjustvarargs (lua_State *L, Proto *p, int actual) { + int i; + Table *vtab; + TValue nname; + int nfixparams = p->numparams - 1; /* number of fixed parameters */ + actual -= nfixparams; /* number of extra arguments */ + vtab = luaH_new(L); /* create vararg table */ + sethvalue(L, L->top, vtab); /* anchor it for resizing */ + L->top++; /* space ensured by caller */ + luaH_resize(L, vtab, actual, 1); + for (i = 0; i < actual; i++) /* put extra arguments into vararg table */ + setobj2n(L, &vtab->array[i], L->top - actual + i - 1); + setsvalue(L, &nname, luaS_newliteral(L, "n")); /* get field 'n' */ + setivalue(luaH_set(L, vtab, &nname), actual); /* store counter there */ + L->top -= actual; /* remove extra elements from the stack */ + sethvalue(L, L->top - 1, vtab); /* move table to new top */ +} + + +void luaT_getvarargs (lua_State *L, StkId t, StkId where, int wanted) { + if (!ttistable(t)) + luaG_runerror(L, "'vararg' parameter is not a table"); + else { + int i; + Table *h = hvalue(t); + if (wanted < 0) { /* get all? */ + const TValue *ns = luaH_getstr(h, luaS_newliteral(L, "n")); + int n = (ttisinteger(ns)) ? ivalue(ns) : 0; + wanted = n; + checkstackp(L, n, where); + L->top = where + n; + } + for (i = 0; i < wanted; i++) /* get what is available */ + setobj2s(L, where + i, luaH_getint(h, i + 1)); + return; + } +} diff --git a/ltm.h b/ltm.h index 535e1885..2dfb46c1 100644 --- a/ltm.h +++ b/ltm.h @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.22 2016/02/26 19:20:15 roberto Exp roberto $ +** $Id: ltm.h,v 2.23 2017/05/08 15:57:23 roberto Exp roberto $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -69,6 +69,9 @@ LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, TMS event); +LUAI_FUNC void luaT_adjustvarargs (lua_State *L, Proto *p, int actual); +LUAI_FUNC void luaT_getvarargs (lua_State *L, StkId t, StkId where, + int wanted); #endif diff --git a/lvm.c b/lvm.c index 9a60bb5b..3053d929 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.279 2017/05/10 17:32:19 roberto Exp roberto $ +** $Id: lvm.c,v 2.280 2017/05/11 18:57:46 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -1433,20 +1433,8 @@ void luaV_execute (lua_State *L) { } vmcase(OP_VARARG) { int b = GETARG_B(i) - 1; /* required results */ - int j; - int n = cast_int(base - ci->func) - cl->p->numparams - 1; - if (n < 0) /* less arguments than parameters? */ - n = 0; /* no vararg arguments */ - if (b < 0) { /* B == 0? */ - b = n; /* get all var. arguments */ - Protect(luaD_checkstack(L, n)); - ra = RA(i); /* previous call may change the stack */ - L->top = ra + n; - } - for (j = 0; j < b && j < n; j++) - setobjs2s(L, ra + j, base - n + j); - for (; j < b; j++) /* complete required results with nil */ - setnilvalue(ra + j); + StkId vtab = base + cl->p->numparams - 1; /* vararg table */ + Protect(luaT_getvarargs(L, vtab, ra, b)); vmbreak; } vmcase(OP_EXTRAARG) {