diff options
| -rw-r--r-- | lcode.c | 57 | ||||
| -rw-r--r-- | ljumptab.h | 3 | ||||
| -rw-r--r-- | lopcodes.c | 1 | ||||
| -rw-r--r-- | lopcodes.h | 2 | ||||
| -rw-r--r-- | lopnames.h | 1 | ||||
| -rw-r--r-- | lparser.c | 10 | ||||
| -rw-r--r-- | lparser.h | 2 | ||||
| -rw-r--r-- | ltm.c | 22 | ||||
| -rw-r--r-- | ltm.h | 1 | ||||
| -rw-r--r-- | lvm.c | 6 | ||||
| -rw-r--r-- | manual/manual.of | 91 | ||||
| -rw-r--r-- | testes/locals.lua | 6 | ||||
| -rw-r--r-- | testes/vararg.lua | 47 |
13 files changed, 186 insertions, 63 deletions
| @@ -842,6 +842,12 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 842 | e->k = VRELOC; | 842 | e->k = VRELOC; |
| 843 | break; | 843 | break; |
| 844 | } | 844 | } |
| 845 | case VVARGIND: { | ||
| 846 | freeregs(fs, e->u.ind.t, e->u.ind.idx); | ||
| 847 | e->u.info = luaK_codeABC(fs, OP_GETVARG, 0, e->u.ind.t, e->u.ind.idx); | ||
| 848 | e->k = VRELOC; | ||
| 849 | break; | ||
| 850 | } | ||
| 845 | case VVARARG: case VCALL: { | 851 | case VVARARG: case VCALL: { |
| 846 | luaK_setoneret(fs, e); | 852 | luaK_setoneret(fs, e); |
| 847 | break; | 853 | break; |
| @@ -1004,11 +1010,11 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | |||
| 1004 | 1010 | ||
| 1005 | 1011 | ||
| 1006 | /* | 1012 | /* |
| 1007 | ** Ensures final expression result is either in a register | 1013 | ** Ensures final expression result is either in a register, |
| 1008 | ** or in an upvalue. | 1014 | ** in an upvalue, or it is the vararg parameter. |
| 1009 | */ | 1015 | */ |
| 1010 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { | 1016 | void luaK_exp2anyregup (FuncState *fs, expdesc *e) { |
| 1011 | if (e->k != VUPVAL || hasjumps(e)) | 1017 | if ((e->k != VUPVAL && e->k != VVARGVAR) || hasjumps(e)) |
| 1012 | luaK_exp2anyreg(fs, e); | 1018 | luaK_exp2anyreg(fs, e); |
| 1013 | } | 1019 | } |
| 1014 | 1020 | ||
| @@ -1314,6 +1320,13 @@ void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { | |||
| 1314 | } | 1320 | } |
| 1315 | 1321 | ||
| 1316 | 1322 | ||
| 1323 | /* auxiliary function to define indexing expressions */ | ||
| 1324 | static void fillidxk (expdesc *t, int idx, expkind k) { | ||
| 1325 | t->u.ind.idx = cast_byte(idx); | ||
| 1326 | t->k = k; | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | |||
| 1317 | /* | 1330 | /* |
| 1318 | ** Create expression 't[k]'. 't' must have its final result already in a | 1331 | ** Create expression 't[k]'. 't' must have its final result already in a |
| 1319 | ** register or upvalue. Upvalues can only be indexed by literal strings. | 1332 | ** register or upvalue. Upvalues can only be indexed by literal strings. |
| @@ -1325,31 +1338,30 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | |||
| 1325 | if (k->k == VKSTR) | 1338 | if (k->k == VKSTR) |
| 1326 | keystr = str2K(fs, k); | 1339 | keystr = str2K(fs, k); |
| 1327 | lua_assert(!hasjumps(t) && | 1340 | lua_assert(!hasjumps(t) && |
| 1328 | (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); | 1341 | (t->k == VLOCAL || t->k == VVARGVAR || |
| 1342 | t->k == VNONRELOC || t->k == VUPVAL)); | ||
| 1329 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ | 1343 | if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ |
| 1330 | luaK_exp2anyreg(fs, t); /* put it in a register */ | 1344 | luaK_exp2anyreg(fs, t); /* put it in a register */ |
| 1331 | if (t->k == VUPVAL) { | 1345 | if (t->k == VUPVAL) { |
| 1332 | lu_byte temp = cast_byte(t->u.info); /* upvalue index */ | 1346 | lu_byte temp = cast_byte(t->u.info); /* upvalue index */ |
| 1333 | t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */ | 1347 | t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */ |
| 1334 | lua_assert(isKstr(fs, k)); | 1348 | lua_assert(isKstr(fs, k)); |
| 1335 | t->u.ind.idx = cast_short(k->u.info); /* literal short string */ | 1349 | fillidxk(t, k->u.info, VINDEXUP); /* literal short string */ |
| 1336 | t->k = VINDEXUP; | 1350 | } |
| 1351 | else if (t->k == VVARGVAR) { /* indexing the vararg parameter? */ | ||
| 1352 | lua_assert(t->u.ind.t == fs->f->numparams); | ||
| 1353 | t->u.ind.t = cast_byte(t->u.var.ridx); | ||
| 1354 | fillidxk(t, luaK_exp2anyreg(fs, k), VVARGIND); /* register */ | ||
| 1337 | } | 1355 | } |
| 1338 | else { | 1356 | else { |
| 1339 | /* register index of the table */ | 1357 | /* register index of the table */ |
| 1340 | t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info); | 1358 | t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info); |
| 1341 | if (isKstr(fs, k)) { | 1359 | if (isKstr(fs, k)) |
| 1342 | t->u.ind.idx = cast_short(k->u.info); /* literal short string */ | 1360 | fillidxk(t, k->u.info, VINDEXSTR); /* literal short string */ |
| 1343 | t->k = VINDEXSTR; | 1361 | else if (isCint(k)) /* int. constant in proper range? */ |
| 1344 | } | 1362 | fillidxk(t, cast_int(k->u.ival), VINDEXI); |
| 1345 | else if (isCint(k)) { /* int. constant in proper range? */ | 1363 | else |
| 1346 | t->u.ind.idx = cast_short(k->u.ival); | 1364 | fillidxk(t, luaK_exp2anyreg(fs, k), VINDEXED); /* register */ |
| 1347 | t->k = VINDEXI; | ||
| 1348 | } | ||
| 1349 | else { | ||
| 1350 | t->u.ind.idx = cast_short(luaK_exp2anyreg(fs, k)); /* register */ | ||
| 1351 | t->k = VINDEXED; | ||
| 1352 | } | ||
| 1353 | } | 1365 | } |
| 1354 | t->u.ind.keystr = keystr; /* string index in 'k' */ | 1366 | t->u.ind.keystr = keystr; /* string index in 'k' */ |
| 1355 | t->u.ind.ro = 0; /* by default, not read-only */ | 1367 | t->u.ind.ro = 0; /* by default, not read-only */ |
| @@ -1913,9 +1925,14 @@ void luaK_finish (FuncState *fs) { | |||
| 1913 | SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ | 1925 | SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ |
| 1914 | break; | 1926 | break; |
| 1915 | } | 1927 | } |
| 1916 | case OP_JMP: { | 1928 | case OP_GETVARG: { |
| 1929 | if (p->flag & PF_VATAB) /* function has a vararg table? */ | ||
| 1930 | SET_OPCODE(*pc, OP_GETTABLE); /* must get vararg there */ | ||
| 1931 | break; | ||
| 1932 | } | ||
| 1933 | case OP_JMP: { /* to optimize jumps to jumps */ | ||
| 1917 | int target = finaltarget(p->code, i); | 1934 | int target = finaltarget(p->code, i); |
| 1918 | fixjump(fs, i, target); | 1935 | fixjump(fs, i, target); /* jump directly to final target */ |
| 1919 | break; | 1936 | break; |
| 1920 | } | 1937 | } |
| 1921 | default: break; | 1938 | default: break; |
| @@ -21,7 +21,7 @@ static const void *const disptab[NUM_OPCODES] = { | |||
| 21 | #if 0 | 21 | #if 0 |
| 22 | ** you can update the following list with this command: | 22 | ** you can update the following list with this command: |
| 23 | ** | 23 | ** |
| 24 | ** sed -n '/^OP_/\!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h | 24 | ** sed -n '/^OP_/!d; s/OP_/\&\&L_OP_/ ; s/,.*/,/ ; s/\/.*// ; p' lopcodes.h |
| 25 | ** | 25 | ** |
| 26 | #endif | 26 | #endif |
| 27 | 27 | ||
| @@ -106,6 +106,7 @@ static const void *const disptab[NUM_OPCODES] = { | |||
| 106 | &&L_OP_SETLIST, | 106 | &&L_OP_SETLIST, |
| 107 | &&L_OP_CLOSURE, | 107 | &&L_OP_CLOSURE, |
| 108 | &&L_OP_VARARG, | 108 | &&L_OP_VARARG, |
| 109 | &&L_OP_GETVARG, | ||
| 109 | &&L_OP_VARARGPREP, | 110 | &&L_OP_VARARGPREP, |
| 110 | &&L_OP_EXTRAARG | 111 | &&L_OP_EXTRAARG |
| 111 | 112 | ||
| @@ -102,6 +102,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
| 102 | ,opmode(0, 0, 1, 0, 0, ivABC) /* OP_SETLIST */ | 102 | ,opmode(0, 0, 1, 0, 0, ivABC) /* OP_SETLIST */ |
| 103 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ | 103 | ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ |
| 104 | ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ | 104 | ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ |
| 105 | ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETVARG */ | ||
| 105 | ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ | 106 | ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ |
| 106 | ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */ | 107 | ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */ |
| 107 | }; | 108 | }; |
| @@ -338,6 +338,8 @@ OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ | |||
| 338 | 338 | ||
| 339 | OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */ | 339 | OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */ |
| 340 | 340 | ||
| 341 | OP_GETVARG, /* A B C R[A] := R[B][R[C]], R[B] is vararg parameter */ | ||
| 342 | |||
| 341 | OP_VARARGPREP,/* (adjust vararg parameters) */ | 343 | OP_VARARGPREP,/* (adjust vararg parameters) */ |
| 342 | 344 | ||
| 343 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | 345 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ |
| @@ -94,6 +94,7 @@ static const char *const opnames[] = { | |||
| 94 | "SETLIST", | 94 | "SETLIST", |
| 95 | "CLOSURE", | 95 | "CLOSURE", |
| 96 | "VARARG", | 96 | "VARARG", |
| 97 | "GETVARG", | ||
| 97 | "VARARGPREP", | 98 | "VARARGPREP", |
| 98 | "EXTRAARG", | 99 | "EXTRAARG", |
| 99 | NULL | 100 | NULL |
| @@ -279,7 +279,9 @@ static void init_var (FuncState *fs, expdesc *e, int vidx) { | |||
| 279 | 279 | ||
| 280 | 280 | ||
| 281 | /* | 281 | /* |
| 282 | ** Raises an error if variable described by 'e' is read only | 282 | ** Raises an error if variable described by 'e' is read only; moreover, |
| 283 | ** if 'e' is t[exp] where t is the vararg parameter, change it to index | ||
| 284 | ** a real table. (Virtual vararg tables cannot be changed.) | ||
| 283 | */ | 285 | */ |
| 284 | static void check_readonly (LexState *ls, expdesc *e) { | 286 | static void check_readonly (LexState *ls, expdesc *e) { |
| 285 | FuncState *fs = ls->fs; | 287 | FuncState *fs = ls->fs; |
| @@ -301,6 +303,10 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
| 301 | varname = up->name; | 303 | varname = up->name; |
| 302 | break; | 304 | break; |
| 303 | } | 305 | } |
| 306 | case VVARGIND: { | ||
| 307 | fs->f->flag |= PF_VATAB; /* function will need a vararg table */ | ||
| 308 | e->k = VINDEXED; | ||
| 309 | } /* FALLTHROUGH */ | ||
| 304 | case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ | 310 | case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ |
| 305 | if (e->u.ind.ro) /* read-only? */ | 311 | if (e->u.ind.ro) /* read-only? */ |
| 306 | varname = tsvalue(&fs->f->k[e->u.ind.keystr]); | 312 | varname = tsvalue(&fs->f->k[e->u.ind.keystr]); |
| @@ -1073,7 +1079,7 @@ static void parlist (LexState *ls) { | |||
| 1073 | case TK_DOTS: { | 1079 | case TK_DOTS: { |
| 1074 | varargk |= PF_ISVARARG; | 1080 | varargk |= PF_ISVARARG; |
| 1075 | luaX_next(ls); | 1081 | luaX_next(ls); |
| 1076 | if (testnext(ls, '=')) { | 1082 | if (testnext(ls, '|')) { |
| 1077 | new_varkind(ls, str_checkname(ls), RDKVAVAR); | 1083 | new_varkind(ls, str_checkname(ls), RDKVAVAR); |
| 1078 | varargk |= PF_VAVAR; | 1084 | varargk |= PF_VAVAR; |
| 1079 | } | 1085 | } |
| @@ -51,6 +51,8 @@ typedef enum { | |||
| 51 | ind.ro = true if it represents a read-only global; | 51 | ind.ro = true if it represents a read-only global; |
| 52 | ind.keystr = if key is a string, index in 'k' of that string; | 52 | ind.keystr = if key is a string, index in 'k' of that string; |
| 53 | -1 if key is not a string */ | 53 | -1 if key is not a string */ |
| 54 | VVARGIND, /* indexed vararg parameter; | ||
| 55 | ind.* as in VINDEXED */ | ||
| 54 | VINDEXUP, /* indexed upvalue; | 56 | VINDEXUP, /* indexed upvalue; |
| 55 | ind.idx = key's K index; | 57 | ind.idx = key's K index; |
| 56 | ind.* as in VINDEXED */ | 58 | ind.* as in VINDEXED */ |
| @@ -277,6 +277,28 @@ void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) { | |||
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | 279 | ||
| 280 | void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc) { | ||
| 281 | int nextra = ci->u.l.nextraargs; | ||
| 282 | lua_Integer n; | ||
| 283 | if (tointegerns(rc, &n)) { /* integral value? */ | ||
| 284 | if (l_castS2U(n) - 1 < cast_uint(nextra)) { | ||
| 285 | StkId slot = ci->func.p - nextra + cast_int(n) - 1; | ||
| 286 | setobjs2s(((lua_State*)NULL), ra, slot); | ||
| 287 | return; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | else if (ttisshrstring(rc)) { /* short-string value? */ | ||
| 291 | size_t len; | ||
| 292 | const char *s = getlstr(tsvalue(rc), len); | ||
| 293 | if (len == 1 && s[0] == 'n') { /* key is "n"? */ | ||
| 294 | setivalue(s2v(ra), nextra); | ||
| 295 | return; | ||
| 296 | } | ||
| 297 | } | ||
| 298 | setnilvalue(s2v(ra)); /* else produce nil */ | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 280 | void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { | 302 | void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { |
| 281 | int i; | 303 | int i; |
| 282 | int nextra = ci->u.l.nextraargs; | 304 | int nextra = ci->u.l.nextraargs; |
| @@ -97,6 +97,7 @@ LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, | |||
| 97 | 97 | ||
| 98 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, struct CallInfo *ci, | 98 | LUAI_FUNC void luaT_adjustvarargs (lua_State *L, struct CallInfo *ci, |
| 99 | const Proto *p); | 99 | const Proto *p); |
| 100 | LUAI_FUNC void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc); | ||
| 100 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, | 101 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, |
| 101 | StkId where, int wanted); | 102 | StkId where, int wanted); |
| 102 | 103 | ||
| @@ -1926,6 +1926,12 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1926 | Protect(luaT_getvarargs(L, ci, ra, n)); | 1926 | Protect(luaT_getvarargs(L, ci, ra, n)); |
| 1927 | vmbreak; | 1927 | vmbreak; |
| 1928 | } | 1928 | } |
| 1929 | vmcase(OP_GETVARG) { | ||
| 1930 | StkId ra = RA(i); | ||
| 1931 | TValue *rc = vRC(i); | ||
| 1932 | luaT_getvararg(ci, ra, rc); | ||
| 1933 | vmbreak; | ||
| 1934 | } | ||
| 1929 | vmcase(OP_VARARGPREP) { | 1935 | vmcase(OP_VARARGPREP) { |
| 1930 | ProtectNT(luaT_adjustvarargs(L, ci, cl->p)); | 1936 | ProtectNT(luaT_adjustvarargs(L, ci, cl->p)); |
| 1931 | if (l_unlikely(trap)) { /* previous "Protect" updated trap */ | 1937 | if (l_unlikely(trap)) { /* previous "Protect" updated trap */ |
diff --git a/manual/manual.of b/manual/manual.of index 3c704118..beea41f9 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -2262,7 +2262,7 @@ return x or f(x) -- results adjusted to 1 | |||
| 2262 | 2262 | ||
| 2263 | @sect3{func-def| @title{Function Definitions} | 2263 | @sect3{func-def| @title{Function Definitions} |
| 2264 | 2264 | ||
| 2265 | The syntax for function definition is | 2265 | The syntax for a function definition is |
| 2266 | @Produc{ | 2266 | @Produc{ |
| 2267 | @producname{functiondef}@producbody{@Rw{function} funcbody} | 2267 | @producname{functiondef}@producbody{@Rw{function} funcbody} |
| 2268 | @producname{funcbody}@producbody{@bnfter{(} @bnfopt{parlist} @bnfter{)} block @Rw{end}} | 2268 | @producname{funcbody}@producbody{@bnfter{(} @bnfopt{parlist} @bnfter{)} block @Rw{end}} |
| @@ -2315,6 +2315,18 @@ translates to | |||
| 2315 | global f; f = function () @rep{body} end | 2315 | global f; f = function () @rep{body} end |
| 2316 | } | 2316 | } |
| 2317 | 2317 | ||
| 2318 | The @emphx{colon} syntax | ||
| 2319 | is used to emulate @def{methods}, | ||
| 2320 | adding an implicit extra parameter @idx{self} to the function. | ||
| 2321 | Thus, the statement | ||
| 2322 | @verbatim{ | ||
| 2323 | function t.a.b.c:f (@rep{params}) @rep{body} end | ||
| 2324 | } | ||
| 2325 | is syntactic sugar for | ||
| 2326 | @verbatim{ | ||
| 2327 | t.a.b.c.f = function (self, @rep{params}) @rep{body} end | ||
| 2328 | } | ||
| 2329 | |||
| 2318 | A function definition is an executable expression, | 2330 | A function definition is an executable expression, |
| 2319 | whose value has type @emph{function}. | 2331 | whose value has type @emph{function}. |
| 2320 | When Lua precompiles a chunk, | 2332 | When Lua precompiles a chunk, |
| @@ -2325,11 +2337,25 @@ the function is @emph{instantiated} (or @emph{closed}). | |||
| 2325 | This function instance, or @emphx{closure}, | 2337 | This function instance, or @emphx{closure}, |
| 2326 | is the final value of the expression. | 2338 | is the final value of the expression. |
| 2327 | 2339 | ||
| 2340 | Results are returned using the @Rw{return} statement @see{control}. | ||
| 2341 | If control reaches the end of a function | ||
| 2342 | without encountering a @Rw{return} statement, | ||
| 2343 | then the function returns with no results. | ||
| 2344 | |||
| 2345 | @index{multiple return} | ||
| 2346 | There is a system-dependent limit on the number of values | ||
| 2347 | that a function may return. | ||
| 2348 | This limit is guaranteed to be at least 1000. | ||
| 2349 | |||
| 2350 | @sect4{@title{Parameters} | ||
| 2351 | |||
| 2328 | Parameters act as local variables that are | 2352 | Parameters act as local variables that are |
| 2329 | initialized with the argument values: | 2353 | initialized with the argument values: |
| 2330 | @Produc{ | 2354 | @Produc{ |
| 2331 | @producname{parlist}@producbody{namelist @bnfopt{@bnfter{,} @bnfter{...}} @Or | 2355 | @producname{parlist}@producbody{namelist @bnfopt{@bnfter{,} varargparam} @Or |
| 2332 | @bnfter{...}} | 2356 | varargparam} |
| 2357 | @producname{varargparam}@producbody{@bnfter{...} | ||
| 2358 | @bnfopt{@bnfter{|} @bnfNter{Name}}} | ||
| 2333 | } | 2359 | } |
| 2334 | When a Lua function is called, | 2360 | When a Lua function is called, |
| 2335 | it adjusts its list of @x{arguments} to | 2361 | it adjusts its list of @x{arguments} to |
| @@ -2339,11 +2365,12 @@ which is indicated by three dots (@Char{...}) | |||
| 2339 | at the end of its parameter list. | 2365 | at the end of its parameter list. |
| 2340 | A variadic function does not adjust its argument list; | 2366 | A variadic function does not adjust its argument list; |
| 2341 | instead, it collects all extra arguments and supplies them | 2367 | instead, it collects all extra arguments and supplies them |
| 2342 | to the function through a @def{vararg expression}, | 2368 | to the function through a @def{vararg expression} and, |
| 2343 | which is also written as three dots. | 2369 | if present, a @def{vararg table}. |
| 2344 | The value of this expression is a list of all actual extra arguments, | ||
| 2345 | similar to a function with multiple results @see{multires}. | ||
| 2346 | 2370 | ||
| 2371 | A vararg expression is also written as three dots, | ||
| 2372 | and its value is a list of all actual extra arguments, | ||
| 2373 | similar to a function with multiple results @see{multires}. | ||
| 2347 | 2374 | ||
| 2348 | As an example, consider the following definitions: | 2375 | As an example, consider the following definitions: |
| 2349 | @verbatim{ | 2376 | @verbatim{ |
| @@ -2368,26 +2395,27 @@ g(3, 4, 5, 8) a=3, b=4, ... -> 5 8 | |||
| 2368 | g(5, r()) a=5, b=1, ... -> 2 3 | 2395 | g(5, r()) a=5, b=1, ... -> 2 3 |
| 2369 | } | 2396 | } |
| 2370 | 2397 | ||
| 2371 | Results are returned using the @Rw{return} statement @see{control}. | 2398 | The presence of a varag table in a variadic function is indicated |
| 2372 | If control reaches the end of a function | 2399 | by the @T{|name} syntax after the three dots. |
| 2373 | without encountering a @Rw{return} statement, | 2400 | When present, |
| 2374 | then the function returns with no results. | 2401 | a vararg table behaves like a read-only local variable |
| 2375 | 2402 | with the given name that is initialized with a table. | |
| 2376 | @index{multiple return} | 2403 | In that table, |
| 2377 | There is a system-dependent limit on the number of values | 2404 | the values at indices 1, 2, etc. are the extra arguments, |
| 2378 | that a function may return. | 2405 | and the value at index @St{n} is the number of extra arguments. |
| 2379 | This limit is guaranteed to be at least 1000. | 2406 | In other words, the code behaves as if the function started with |
| 2380 | 2407 | the following statement, | |
| 2381 | The @emphx{colon} syntax | 2408 | assuming the standard behavior of @Lid{table.pack}: |
| 2382 | is used to emulate @def{methods}, | ||
| 2383 | adding an implicit extra parameter @idx{self} to the function. | ||
| 2384 | Thus, the statement | ||
| 2385 | @verbatim{ | 2409 | @verbatim{ |
| 2386 | function t.a.b.c:f (@rep{params}) @rep{body} end | 2410 | local <const> name = table.pack(...) |
| 2387 | } | 2411 | } |
| 2388 | is syntactic sugar for | 2412 | |
| 2389 | @verbatim{ | 2413 | As an optimization, |
| 2390 | t.a.b.c.f = function (self, @rep{params}) @rep{body} end | 2414 | if the vararg table is used only as a base in indexing expressions |
| 2415 | (the @T{t} in @T{t[exp]} or @T{t.id}) and it is not an upvalue, | ||
| 2416 | the code does not create an actual table and instead translates | ||
| 2417 | the indexing expressions into accesses to the internal vararg data. | ||
| 2418 | |||
| 2391 | } | 2419 | } |
| 2392 | 2420 | ||
| 2393 | } | 2421 | } |
| @@ -2422,7 +2450,7 @@ for instance @T{foo(e1, e2, e3)} @see{functioncall}.} | |||
| 2422 | for instance @T{a , b, c = e1, e2, e3} @see{assignment}.} | 2450 | for instance @T{a , b, c = e1, e2, e3} @see{assignment}.} |
| 2423 | 2451 | ||
| 2424 | @item{A local or global declaration, | 2452 | @item{A local or global declaration, |
| 2425 | which is a special case of multiple assignment.} | 2453 | which is similar to a multiple assignment.} |
| 2426 | 2454 | ||
| 2427 | @item{The initial values in a generic @rw{for} loop, | 2455 | @item{The initial values in a generic @rw{for} loop, |
| 2428 | for instance @T{for k in e1, e2, e3 do ... end} @see{for}.} | 2456 | for instance @T{for k in e1, e2, e3 do ... end} @see{for}.} |
| @@ -3016,7 +3044,7 @@ typedef void * (*lua_Alloc) (void *ud, | |||
| 3016 | size_t osize, | 3044 | size_t osize, |
| 3017 | size_t nsize);| | 3045 | size_t nsize);| |
| 3018 | 3046 | ||
| 3019 | The type of the @x{memory-allocation function} used by Lua states. | 3047 | The type of the @x{memory-allocator function} used by Lua states. |
| 3020 | The allocator function must provide a | 3048 | The allocator function must provide a |
| 3021 | functionality similar to @id{realloc}, | 3049 | functionality similar to @id{realloc}, |
| 3022 | but not exactly the same. | 3050 | but not exactly the same. |
| @@ -3482,7 +3510,7 @@ This function should not be called by a finalizer. | |||
| 3482 | @APIEntry{lua_Alloc lua_getallocf (lua_State *L, void **ud);| | 3510 | @APIEntry{lua_Alloc lua_getallocf (lua_State *L, void **ud);| |
| 3483 | @apii{0,0,-} | 3511 | @apii{0,0,-} |
| 3484 | 3512 | ||
| 3485 | Returns the @x{memory-allocation function} of a given state. | 3513 | Returns the @x{memory-allocator function} of a given state. |
| 3486 | If @id{ud} is not @id{NULL}, Lua stores in @T{*ud} the | 3514 | If @id{ud} is not @id{NULL}, Lua stores in @T{*ud} the |
| 3487 | opaque pointer given when the memory-allocator function was set. | 3515 | opaque pointer given when the memory-allocator function was set. |
| 3488 | 3516 | ||
| @@ -9732,8 +9760,11 @@ and @bnfNter{LiteralString}, see @See{lexical}.) | |||
| 9732 | 9760 | ||
| 9733 | @producname{funcbody}@producbody{@bnfter{(} @bnfopt{parlist} @bnfter{)} block @Rw{end}} | 9761 | @producname{funcbody}@producbody{@bnfter{(} @bnfopt{parlist} @bnfter{)} block @Rw{end}} |
| 9734 | 9762 | ||
| 9735 | @producname{parlist}@producbody{namelist @bnfopt{@bnfter{,} @bnfter{...}} | 9763 | @producname{parlist}@producbody{namelist @bnfopt{@bnfter{,} varargparam} @Or |
| 9736 | @Or @bnfter{...}} | 9764 | varargparam} |
| 9765 | |||
| 9766 | @producname{varargparam}@producbody{@bnfter{...} | ||
| 9767 | @bnfopt{@bnfter{|} @bnfNter{Name}}} | ||
| 9737 | 9768 | ||
| 9738 | @producname{tableconstructor}@producbody{@bnfter{@Open} @bnfopt{fieldlist} @bnfter{@Close}} | 9769 | @producname{tableconstructor}@producbody{@bnfter{@Open} @bnfopt{fieldlist} @bnfter{@Close}} |
| 9739 | 9770 | ||
diff --git a/testes/locals.lua b/testes/locals.lua index 02f41980..5222802f 100644 --- a/testes/locals.lua +++ b/testes/locals.lua | |||
| @@ -310,8 +310,7 @@ do -- testing presence of second argument | |||
| 310 | local function foo (howtoclose, obj, n) | 310 | local function foo (howtoclose, obj, n) |
| 311 | local ca -- copy of 'a' visible inside its close metamethod | 311 | local ca -- copy of 'a' visible inside its close metamethod |
| 312 | do | 312 | do |
| 313 | local a <close> = func2close(function (...) | 313 | local a <close> = func2close(function (... | t) |
| 314 | local t = table.pack(...) | ||
| 315 | assert(select("#", ...) == n) | 314 | assert(select("#", ...) == n) |
| 316 | assert(t.n == n and t[1] == ca and (t.n < 2 or t[2] == obj)) | 315 | assert(t.n == n and t[1] == ca and (t.n < 2 or t[2] == obj)) |
| 317 | ca = 15 -- final value to be returned if howtoclose=="scope" | 316 | ca = 15 -- final value to be returned if howtoclose=="scope" |
| @@ -911,8 +910,7 @@ do | |||
| 911 | 910 | ||
| 912 | local extrares -- result from extra yield (if any) | 911 | local extrares -- result from extra yield (if any) |
| 913 | 912 | ||
| 914 | local function check (body, extra, ...) | 913 | local function check (body, extra, ...|t) |
| 915 | local t = table.pack(...) -- expected returns | ||
| 916 | local co = coroutine.wrap(body) | 914 | local co = coroutine.wrap(body) |
| 917 | if extra then | 915 | if extra then |
| 918 | extrares = co() -- runs until first (extra) yield | 916 | extrares = co() -- runs until first (extra) yield |
diff --git a/testes/vararg.lua b/testes/vararg.lua index 92f720cb..5711f78b 100644 --- a/testes/vararg.lua +++ b/testes/vararg.lua | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | print('testing vararg') | 4 | print('testing vararg') |
| 5 | 5 | ||
| 6 | local function f (a, ...=t) | 6 | local function f (a, ...|t) |
| 7 | local x = {n = select('#', ...), ...} | 7 | local x = {n = select('#', ...), ...} |
| 8 | assert(x.n == t.n) | 8 | assert(x.n == t.n) |
| 9 | for i = 1, x.n do | 9 | for i = 1, x.n do |
| @@ -20,7 +20,7 @@ local function c12 (...) | |||
| 20 | return res, 2 | 20 | return res, 2 |
| 21 | end | 21 | end |
| 22 | 22 | ||
| 23 | local function vararg (...=t) return t end | 23 | local function vararg (... | t) return t end |
| 24 | 24 | ||
| 25 | local call = function (f, args) return f(table.unpack(args, 1, args.n)) end | 25 | local call = function (f, args) return f(table.unpack(args, 1, args.n)) end |
| 26 | 26 | ||
| @@ -153,8 +153,8 @@ end | |||
| 153 | 153 | ||
| 154 | 154 | ||
| 155 | do -- vararg parameter used in nested functions | 155 | do -- vararg parameter used in nested functions |
| 156 | local function foo (... = tab1) | 156 | local function foo (... | tab1) |
| 157 | return function (... = tab2) | 157 | return function (... | tab2) |
| 158 | return {tab1, tab2} | 158 | return {tab1, tab2} |
| 159 | end | 159 | end |
| 160 | end | 160 | end |
| @@ -165,16 +165,51 @@ do -- vararg parameter used in nested functions | |||
| 165 | end | 165 | end |
| 166 | 166 | ||
| 167 | do -- vararg parameter is read-only | 167 | do -- vararg parameter is read-only |
| 168 | local st, msg = load("return function (... = t) t = 10 end") | 168 | local st, msg = load("return function (... | t) t = 10 end") |
| 169 | assert(string.find(msg, "const variable 't'")) | 169 | assert(string.find(msg, "const variable 't'")) |
| 170 | 170 | ||
| 171 | local st, msg = load[[ | 171 | local st, msg = load[[ |
| 172 | local function foo (... = extra) | 172 | local function foo (... | extra) |
| 173 | return function (...) extra = nil end | 173 | return function (...) extra = nil end |
| 174 | end | 174 | end |
| 175 | ]] | 175 | ]] |
| 176 | assert(string.find(msg, "const variable 'extra'")) | 176 | assert(string.find(msg, "const variable 'extra'")) |
| 177 | end | 177 | end |
| 178 | 178 | ||
| 179 | |||
| 180 | do -- _ENV as vararg parameter | ||
| 181 | local st, msg = load[[ | ||
| 182 | local function aux (... | _ENV) | ||
| 183 | global <const> a | ||
| 184 | a = 10 | ||
| 185 | end ]] | ||
| 186 | assert(string.find(msg, "const variable 'a'")) | ||
| 187 | end | ||
| 188 | |||
| 189 | |||
| 190 | do -- access to vararg parameter | ||
| 191 | local function notab (keys, t, ... | v) | ||
| 192 | for _, k in pairs(keys) do | ||
| 193 | assert(t[k] == v[k]) | ||
| 194 | end | ||
| 195 | assert(t.n == v.n) | ||
| 196 | end | ||
| 197 | |||
| 198 | local t = table.pack(10, 20, 30) | ||
| 199 | local keys = {-1, 0, 1, t.n, t.n + 1, 1.0, 1.1, "n", print, "k", "1"} | ||
| 200 | notab(keys, t, 10, 20, 30) -- ensure stack space | ||
| 201 | local m = collectgarbage"count" | ||
| 202 | notab(keys, t, 10, 20, 30) | ||
| 203 | -- 'notab' does not create any table/object | ||
| 204 | assert(m == collectgarbage"count") | ||
| 205 | |||
| 206 | -- writing to the vararg table | ||
| 207 | local function foo (... | t) | ||
| 208 | t[1] = t[1] + 10 | ||
| 209 | return t[1] | ||
| 210 | end | ||
| 211 | assert(foo(10, 30) == 20) | ||
| 212 | end | ||
| 213 | |||
| 179 | print('OK') | 214 | print('OK') |
| 180 | 215 | ||
