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) { |