commit 5c8770f8969a73cf4ca503f54c2217f76de62e04
parent 7647d5d13d016f114dac4be0b9da62d502eab400
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Sat, 13 May 2017 10:04:06 -0300
back to old-style vararg system (with vararg table collecting extra
arguments)
Diffstat:
M | ldebug.c | | | 21 | +++------------------ |
M | ldo.c | | | 41 | ++++++----------------------------------- |
M | ldo.h | | | 10 | +++++++++- |
M | lparser.c | | | 11 | ++++++++++- |
M | ltm.c | | | 40 | +++++++++++++++++++++++++++++++++++++++- |
M | ltm.h | | | 5 | ++++- |
M | lvm.c | | | 18 | +++--------------- |
7 files changed, 74 insertions(+), 72 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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, "<name> 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
@@ -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
@@ -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
@@ -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) {