diff options
| -rw-r--r-- | lcode.c | 5 | ||||
| -rw-r--r-- | lobject.h | 5 | ||||
| -rw-r--r-- | lopcodes.h | 2 | ||||
| -rw-r--r-- | lparser.c | 24 | ||||
| -rw-r--r-- | ltm.c | 64 | ||||
| -rw-r--r-- | ltm.h | 4 | ||||
| -rw-r--r-- | lvm.c | 5 | ||||
| -rw-r--r-- | manual/manual.of | 68 | ||||
| -rw-r--r-- | testes/coroutine.lua | 4 | ||||
| -rw-r--r-- | testes/db.lua | 9 | ||||
| -rw-r--r-- | testes/vararg.lua | 33 |
11 files changed, 154 insertions, 69 deletions
| @@ -1951,6 +1951,11 @@ void luaK_finish (FuncState *fs) { | |||
| 1951 | SET_OPCODE(*pc, OP_GETTABLE); /* must get vararg there */ | 1951 | SET_OPCODE(*pc, OP_GETTABLE); /* must get vararg there */ |
| 1952 | break; | 1952 | break; |
| 1953 | } | 1953 | } |
| 1954 | case OP_VARARG: { | ||
| 1955 | if (p->flag & PF_VATAB) /* function has a vararg table? */ | ||
| 1956 | SETARG_k(*pc, 1); /* must get vararg there */ | ||
| 1957 | break; | ||
| 1958 | } | ||
| 1954 | case OP_JMP: { /* to optimize jumps to jumps */ | 1959 | case OP_JMP: { /* to optimize jumps to jumps */ |
| 1955 | int target = finaltarget(p->code, i); | 1960 | int target = finaltarget(p->code, i); |
| 1956 | fixjump(fs, i, target); /* jump directly to final target */ | 1961 | fixjump(fs, i, target); /* jump directly to final target */ |
| @@ -584,9 +584,8 @@ typedef struct AbsLineInfo { | |||
| 584 | ** Flags in Prototypes | 584 | ** Flags in Prototypes |
| 585 | */ | 585 | */ |
| 586 | #define PF_ISVARARG 1 /* function is vararg */ | 586 | #define PF_ISVARARG 1 /* function is vararg */ |
| 587 | #define PF_VAVAR 2 /* function has vararg parameter */ | 587 | #define PF_VATAB 2 /* function has vararg table */ |
| 588 | #define PF_VATAB 4 /* function has vararg table */ | 588 | #define PF_FIXED 4 /* prototype has parts in fixed memory */ |
| 589 | #define PF_FIXED 8 /* prototype has parts in fixed memory */ | ||
| 590 | 589 | ||
| 591 | 590 | ||
| 592 | /* | 591 | /* |
| @@ -336,7 +336,7 @@ OP_SETLIST,/* A vB vC k R[A][vC+i] := R[A+i], 1 <= i <= vB */ | |||
| 336 | 336 | ||
| 337 | OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */ | 337 | 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+C-2] = vararg, R[B] is vararg param. */ |
| 340 | 340 | ||
| 341 | OP_GETVARG, /* A B C R[A] := R[B][R[C]], R[B] is vararg parameter */ | 341 | OP_GETVARG, /* A B C R[A] := R[B][R[C]], R[B] is vararg parameter */ |
| 342 | 342 | ||
| @@ -1056,9 +1056,8 @@ static void constructor (LexState *ls, expdesc *t) { | |||
| 1056 | /* }====================================================================== */ | 1056 | /* }====================================================================== */ |
| 1057 | 1057 | ||
| 1058 | 1058 | ||
| 1059 | static void setvararg (FuncState *fs, int kind) { | 1059 | static void setvararg (FuncState *fs) { |
| 1060 | lua_assert(kind & PF_ISVARARG); | 1060 | fs->f->flag |= PF_ISVARARG; |
| 1061 | fs->f->flag |= cast_byte(kind); | ||
| 1062 | luaK_codeABC(fs, OP_VARARGPREP, 0, 0, 0); | 1061 | luaK_codeABC(fs, OP_VARARGPREP, 0, 0, 0); |
| 1063 | } | 1062 | } |
| 1064 | 1063 | ||
| @@ -1078,12 +1077,12 @@ static void parlist (LexState *ls) { | |||
| 1078 | break; | 1077 | break; |
| 1079 | } | 1078 | } |
| 1080 | case TK_DOTS: { | 1079 | case TK_DOTS: { |
| 1081 | varargk |= PF_ISVARARG; | 1080 | varargk = 1; |
| 1082 | luaX_next(ls); /* skip '...' */ | 1081 | luaX_next(ls); /* skip '...' */ |
| 1083 | if (ls->t.token == TK_NAME) { | 1082 | if (ls->t.token == TK_NAME) |
| 1084 | new_varkind(ls, str_checkname(ls), RDKVAVAR); | 1083 | new_varkind(ls, str_checkname(ls), RDKVAVAR); |
| 1085 | varargk |= PF_VAVAR; | 1084 | else |
| 1086 | } | 1085 | new_localvarliteral(ls, "(vararg table)"); |
| 1087 | break; | 1086 | break; |
| 1088 | } | 1087 | } |
| 1089 | default: luaX_syntaxerror(ls, "<name> or '...' expected"); | 1088 | default: luaX_syntaxerror(ls, "<name> or '...' expected"); |
| @@ -1092,10 +1091,9 @@ static void parlist (LexState *ls) { | |||
| 1092 | } | 1091 | } |
| 1093 | adjustlocalvars(ls, nparams); | 1092 | adjustlocalvars(ls, nparams); |
| 1094 | f->numparams = cast_byte(fs->nactvar); | 1093 | f->numparams = cast_byte(fs->nactvar); |
| 1095 | if (varargk != 0) { | 1094 | if (varargk) { |
| 1096 | setvararg(fs, varargk); /* declared vararg */ | 1095 | setvararg(fs); /* declared vararg */ |
| 1097 | if (varargk & PF_VAVAR) | 1096 | adjustlocalvars(ls, 1); /* vararg parameter */ |
| 1098 | adjustlocalvars(ls, 1); /* vararg parameter */ | ||
| 1099 | } | 1097 | } |
| 1100 | /* reserve registers for parameters (plus vararg parameter, if present) */ | 1098 | /* reserve registers for parameters (plus vararg parameter, if present) */ |
| 1101 | luaK_reserveregs(fs, fs->nactvar); | 1099 | luaK_reserveregs(fs, fs->nactvar); |
| @@ -1287,7 +1285,7 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
| 1287 | FuncState *fs = ls->fs; | 1285 | FuncState *fs = ls->fs; |
| 1288 | check_condition(ls, fs->f->flag & PF_ISVARARG, | 1286 | check_condition(ls, fs->f->flag & PF_ISVARARG, |
| 1289 | "cannot use '...' outside a vararg function"); | 1287 | "cannot use '...' outside a vararg function"); |
| 1290 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1)); | 1288 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, fs->f->numparams, 1)); |
| 1291 | break; | 1289 | break; |
| 1292 | } | 1290 | } |
| 1293 | case '{' /*}*/: { /* constructor */ | 1291 | case '{' /*}*/: { /* constructor */ |
| @@ -2153,7 +2151,7 @@ static void mainfunc (LexState *ls, FuncState *fs) { | |||
| 2153 | BlockCnt bl; | 2151 | BlockCnt bl; |
| 2154 | Upvaldesc *env; | 2152 | Upvaldesc *env; |
| 2155 | open_func(ls, fs, &bl); | 2153 | open_func(ls, fs, &bl); |
| 2156 | setvararg(fs, PF_ISVARARG); /* main function is always vararg */ | 2154 | setvararg(fs); /* main function is always vararg */ |
| 2157 | env = allocupvalue(fs); /* ...set environment upvalue */ | 2155 | env = allocupvalue(fs); /* ...set environment upvalue */ |
| 2158 | env->instack = 1; | 2156 | env->instack = 1; |
| 2159 | env->idx = 0; | 2157 | env->idx = 0; |
| @@ -242,6 +242,7 @@ static void createvarargtab (lua_State *L, StkId f, int n) { | |||
| 242 | luaH_set(L, t, &key, &value); /* t.n = n */ | 242 | luaH_set(L, t, &key, &value); /* t.n = n */ |
| 243 | for (i = 0; i < n; i++) | 243 | for (i = 0; i < n; i++) |
| 244 | luaH_setint(L, t, i + 1, s2v(f + i)); | 244 | luaH_setint(L, t, i + 1, s2v(f + i)); |
| 245 | luaC_checkGC(L); | ||
| 245 | } | 246 | } |
| 246 | 247 | ||
| 247 | 248 | ||
| @@ -265,11 +266,11 @@ void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) { | |||
| 265 | setobjs2s(L, L->top.p++, ci->func.p + i); | 266 | setobjs2s(L, L->top.p++, ci->func.p + i); |
| 266 | setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ | 267 | setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ |
| 267 | } | 268 | } |
| 268 | if (p->flag & PF_VAVAR) { /* is there a vararg parameter? */ | 269 | if (p->flag & PF_VATAB) /* does it need a vararg table? */ |
| 269 | if (p->flag & PF_VATAB) /* does it need a vararg table? */ | 270 | createvarargtab(L, ci->func.p + nfixparams + 1, nextra); |
| 270 | createvarargtab(L, ci->func.p + nfixparams + 1, nextra); | 271 | else { /* no table; set parameter to nil */ |
| 271 | else /* no table; set parameter to nil */ | 272 | setnilvalue(s2v(L->top.p)); |
| 272 | setnilvalue(s2v(L->top.p)); | 273 | L->top.p++; |
| 273 | } | 274 | } |
| 274 | ci->func.p += totalargs + 1; | 275 | ci->func.p += totalargs + 1; |
| 275 | ci->top.p += totalargs + 1; | 276 | ci->top.p += totalargs + 1; |
| @@ -299,16 +300,53 @@ void luaT_getvararg (CallInfo *ci, StkId ra, TValue *rc) { | |||
| 299 | } | 300 | } |
| 300 | 301 | ||
| 301 | 302 | ||
| 302 | void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { | 303 | /* |
| 303 | int i; | 304 | ** Get the number of extra arguments in a vararg function. If vararg |
| 304 | int nextra = ci->u.l.nextraargs; | 305 | ** table has been optimized away, that number is in the call info. |
| 306 | ** Otherwise, get the field 'n' from the vararg table and check that it | ||
| 307 | ** has a proper value (non-negative integer not larger than the stack | ||
| 308 | ** limit). | ||
| 309 | */ | ||
| 310 | static int getnumargs (lua_State *L, CallInfo *ci, Table *h) { | ||
| 311 | if (h == NULL) /* no vararg table? */ | ||
| 312 | return ci->u.l.nextraargs; | ||
| 313 | else { | ||
| 314 | TValue res; | ||
| 315 | if (luaH_getshortstr(h, luaS_new(L, "n"), &res) != LUA_VNUMINT || | ||
| 316 | l_castS2U(ivalue(&res)) > cast_uint(INT_MAX/2)) | ||
| 317 | luaG_runerror(L, "vararg table has no proper 'n'"); | ||
| 318 | return cast_int(ivalue(&res)); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | |||
| 323 | /* | ||
| 324 | ** Get 'wanted' vararg arguments and put them in 'where'. 'vatab' is | ||
| 325 | ** the register of the vararg table or -1 if there is no vararg table. | ||
| 326 | */ | ||
| 327 | void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted, | ||
| 328 | int vatab) { | ||
| 329 | Table *h = (vatab < 0) ? NULL : hvalue(s2v(ci->func.p + vatab + 1)); | ||
| 330 | int nargs = getnumargs(L, ci, h); /* number of available vararg args. */ | ||
| 331 | int i, touse; /* 'touse' is minimum between 'wanted' and 'nargs' */ | ||
| 305 | if (wanted < 0) { | 332 | if (wanted < 0) { |
| 306 | wanted = nextra; /* get all extra arguments available */ | 333 | touse = wanted = nargs; /* get all extra arguments available */ |
| 307 | checkstackp(L, nextra, where); /* ensure stack space */ | 334 | checkstackp(L, nargs, where); /* ensure stack space */ |
| 308 | L->top.p = where + nextra; /* next instruction will need top */ | 335 | L->top.p = where + nargs; /* next instruction will need top */ |
| 336 | } | ||
| 337 | else | ||
| 338 | touse = (nargs > wanted) ? wanted : nargs; | ||
| 339 | if (h == NULL) { /* no vararg table? */ | ||
| 340 | for (i = 0; i < touse; i++) /* get vararg values from the stack */ | ||
| 341 | setobjs2s(L, where + i, ci->func.p - nargs + i); | ||
| 342 | } | ||
| 343 | else { /* get vararg values from vararg table */ | ||
| 344 | for (i = 0; i < touse; i++) { | ||
| 345 | lu_byte tag = luaH_getint(h, i + 1, s2v(where + i)); | ||
| 346 | if (tagisempty(tag)) | ||
| 347 | setnilvalue(s2v(where + i)); | ||
| 348 | } | ||
| 309 | } | 349 | } |
| 310 | for (i = 0; i < wanted && i < nextra; i++) | ||
| 311 | setobjs2s(L, where + i, ci->func.p - nextra + i); | ||
| 312 | for (; i < wanted; i++) /* complete required results with nil */ | 350 | for (; i < wanted; i++) /* complete required results with nil */ |
| 313 | setnilvalue(s2v(where + i)); | 351 | setnilvalue(s2v(where + i)); |
| 314 | } | 352 | } |
| @@ -98,8 +98,8 @@ LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, | |||
| 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_getvararg (CallInfo *ci, StkId ra, TValue *rc); |
| 101 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, | 101 | LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, StkId where, |
| 102 | StkId where, int wanted); | 102 | int wanted, int vatab); |
| 103 | 103 | ||
| 104 | 104 | ||
| 105 | #endif | 105 | #endif |
| @@ -1935,8 +1935,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
| 1935 | } | 1935 | } |
| 1936 | vmcase(OP_VARARG) { | 1936 | vmcase(OP_VARARG) { |
| 1937 | StkId ra = RA(i); | 1937 | StkId ra = RA(i); |
| 1938 | int n = GETARG_C(i) - 1; /* required results */ | 1938 | int n = GETARG_C(i) - 1; /* required results (-1 means all) */ |
| 1939 | Protect(luaT_getvarargs(L, ci, ra, n)); | 1939 | int vatab = GETARG_k(i) ? GETARG_B(i) : -1; |
| 1940 | Protect(luaT_getvarargs(L, ci, ra, n, vatab)); | ||
| 1940 | vmbreak; | 1941 | vmbreak; |
| 1941 | } | 1942 | } |
| 1942 | vmcase(OP_GETVARG) { | 1943 | vmcase(OP_GETVARG) { |
diff --git a/manual/manual.of b/manual/manual.of index 96203d7f..9b8e144d 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -2221,7 +2221,7 @@ The form | |||
| 2221 | } | 2221 | } |
| 2222 | can be used to emulate methods. | 2222 | can be used to emulate methods. |
| 2223 | A call @T{v:name(@rep{args})} | 2223 | A call @T{v:name(@rep{args})} |
| 2224 | is syntactic sugar for @T{v.name(v,@rep{args})}, | 2224 | is syntactic sugar for @T{v.name(v, @rep{args})}, |
| 2225 | except that @id{v} is evaluated only once. | 2225 | except that @id{v} is evaluated only once. |
| 2226 | 2226 | ||
| 2227 | Arguments have the following syntax: | 2227 | Arguments have the following syntax: |
| @@ -2372,12 +2372,10 @@ which is indicated by three dots (@Char{...}) | |||
| 2372 | at the end of its parameter list. | 2372 | at the end of its parameter list. |
| 2373 | A variadic function does not adjust its argument list; | 2373 | A variadic function does not adjust its argument list; |
| 2374 | instead, it collects all extra arguments and supplies them | 2374 | instead, it collects all extra arguments and supplies them |
| 2375 | to the function through a @def{vararg expression} and, | 2375 | to the function through a @def{vararg table}. |
| 2376 | if present, a @def{vararg table}. | 2376 | In that table, |
| 2377 | 2377 | the values at indices 1, 2, etc. are the extra arguments, | |
| 2378 | A vararg expression is also written as three dots, | 2378 | and the value at index @St{n} is the number of extra arguments. |
| 2379 | and its value is a list of all actual extra arguments, | ||
| 2380 | similar to a function with multiple results @see{multires}. | ||
| 2381 | 2379 | ||
| 2382 | As an example, consider the following definitions: | 2380 | As an example, consider the following definitions: |
| 2383 | @verbatim{ | 2381 | @verbatim{ |
| @@ -2386,7 +2384,7 @@ function g(a, b, ...) end | |||
| 2386 | function r() return 1,2,3 end | 2384 | function r() return 1,2,3 end |
| 2387 | } | 2385 | } |
| 2388 | Then, we have the following mapping from arguments to parameters and | 2386 | Then, we have the following mapping from arguments to parameters and |
| 2389 | to the vararg expression: | 2387 | to the vararg table: |
| 2390 | @verbatim{ | 2388 | @verbatim{ |
| 2391 | CALL PARAMETERS | 2389 | CALL PARAMETERS |
| 2392 | 2390 | ||
| @@ -2396,33 +2394,39 @@ f(3, 4, 5) a=3, b=4 | |||
| 2396 | f(r(), 10) a=1, b=10 | 2394 | f(r(), 10) a=1, b=10 |
| 2397 | f(r()) a=1, b=2 | 2395 | f(r()) a=1, b=2 |
| 2398 | 2396 | ||
| 2399 | g(3) a=3, b=nil, ... -> (nothing) | 2397 | g(3) a=3, b=nil, va. table -> {n = 0} |
| 2400 | g(3, 4) a=3, b=4, ... -> (nothing) | 2398 | g(3, 4) a=3, b=4, va. table -> {n = 0} |
| 2401 | g(3, 4, 5, 8) a=3, b=4, ... -> 5 8 | 2399 | g(3, 4, 5, 8) a=3, b=4, va. table -> {5, 8, n = 2} |
| 2402 | g(5, r()) a=5, b=1, ... -> 2 3 | 2400 | g(5, r()) a=5, b=1, va. table -> {2, 3, n = 2} |
| 2403 | } | 2401 | } |
| 2404 | 2402 | ||
| 2405 | The presence of a vararg table in a variadic function is indicated | 2403 | A vararg table in a variadic function can have an optional name, |
| 2406 | by a name after the three dots. | 2404 | given after the three dots. |
| 2407 | When present, | 2405 | When present, |
| 2408 | a vararg table behaves like a read-only local variable | 2406 | that name denotes a read-only local variable that |
| 2409 | with the given name that is initialized with a table. | 2407 | refers to the vararg table. |
| 2410 | In that table, | 2408 | If the vararg table does not have a name, |
| 2411 | the values at indices 1, 2, etc. are the extra arguments, | 2409 | it can only be accessed through a vararg expression. |
| 2412 | and the value at index @St{n} is the number of extra arguments. | 2410 | |
| 2413 | In other words, the code behaves as if the function started with | 2411 | A vararg expression is also written as three dots, |
| 2414 | the following statement, | 2412 | and its value is a list of the values in the vararg table, |
| 2415 | assuming the standard behavior of @Lid{table.pack}: | 2413 | from 1 to the integer value at index @St{n}. |
| 2416 | @verbatim{ | 2414 | (Therefore, if the code does not modify the vararg table, |
| 2417 | local <const> name = table.pack(...) | 2415 | this list corresponds to the extra arguments in the function call.) |
| 2418 | } | 2416 | This list behaves like the results from a |
| 2417 | function with multiple results @see{multires}. | ||
| 2419 | 2418 | ||
| 2420 | As an optimization, | 2419 | As an optimization, |
| 2421 | if the vararg table is used only as the base table | 2420 | if the vararg table satisfies some conditions, |
| 2422 | in the syntactic constructions @T{t[exp]} or @T{t.id}) | ||
| 2423 | and it is not an upvalue, | ||
| 2424 | the code does not create an actual table and instead translates | 2421 | the code does not create an actual table and instead translates |
| 2425 | the indexing expressions into accesses to the internal vararg data. | 2422 | the indexing expressions and the vararg expressions |
| 2423 | into accesses to the internal vararg data. | ||
| 2424 | The conditions are as follows: | ||
| 2425 | If the vararg table has a name, | ||
| 2426 | that name is not an upvalue in a nested function | ||
| 2427 | and it is used only as the base table | ||
| 2428 | in the syntactic constructions @T{t[exp]} or @T{t.id}). | ||
| 2429 | Note that an anonymous vararg table always satisfy these conditions. | ||
| 2426 | 2430 | ||
| 2427 | } | 2431 | } |
| 2428 | 2432 | ||
| @@ -3103,7 +3107,7 @@ void *luaL_alloc (void *ud, void *ptr, size_t osize, | |||
| 3103 | } | 3107 | } |
| 3104 | Note that @N{ISO C} ensures | 3108 | Note that @N{ISO C} ensures |
| 3105 | that @T{free(NULL)} has no effect and that | 3109 | that @T{free(NULL)} has no effect and that |
| 3106 | @T{realloc(NULL,size)} is equivalent to @T{malloc(size)}. | 3110 | @T{realloc(NULL, size)} is equivalent to @T{malloc(size)}. |
| 3107 | 3111 | ||
| 3108 | } | 3112 | } |
| 3109 | 3113 | ||
| @@ -9197,6 +9201,10 @@ Compile-time constants may not appear in this listing, | |||
| 9197 | if they were optimized away by the compiler. | 9201 | if they were optimized away by the compiler. |
| 9198 | Negative indices refer to vararg arguments; | 9202 | Negative indices refer to vararg arguments; |
| 9199 | @num{-1} is the first vararg argument. | 9203 | @num{-1} is the first vararg argument. |
| 9204 | These negative indices are only available when the vararg table | ||
| 9205 | has been optimized away; | ||
| 9206 | otherwise, the vararg arguments are available in the vararg table. | ||
| 9207 | |||
| 9200 | The function returns @fail | 9208 | The function returns @fail |
| 9201 | if there is no variable with the given index, | 9209 | if there is no variable with the given index, |
| 9202 | and raises an error when called with a level out of range. | 9210 | and raises an error when called with a level out of range. |
diff --git a/testes/coroutine.lua b/testes/coroutine.lua index 4881d964..ba394e0c 100644 --- a/testes/coroutine.lua +++ b/testes/coroutine.lua | |||
| @@ -702,7 +702,9 @@ else | |||
| 702 | assert(t.currentline == t.linedefined + 2) | 702 | assert(t.currentline == t.linedefined + 2) |
| 703 | assert(not debug.getinfo(c, 1)) -- no other level | 703 | assert(not debug.getinfo(c, 1)) -- no other level |
| 704 | assert(coroutine.resume(c)) -- run next line | 704 | assert(coroutine.resume(c)) -- run next line |
| 705 | local n,v = debug.getlocal(c, 0, 2) -- check next local | 705 | local n,v = debug.getlocal(c, 0, 2) -- check vararg table |
| 706 | assert(n == "(vararg table)" and v == nil) | ||
| 707 | local n,v = debug.getlocal(c, 0, 3) -- check next local | ||
| 706 | assert(n == "b" and v == 10) | 708 | assert(n == "b" and v == 10) |
| 707 | v = {coroutine.resume(c)} -- finish coroutine | 709 | v = {coroutine.resume(c)} -- finish coroutine |
| 708 | assert(v[1] == true and v[2] == 2 and v[3] == 3 and v[4] == undef) | 710 | assert(v[1] == true and v[2] == 2 and v[3] == 3 and v[4] == undef) |
diff --git a/testes/db.lua b/testes/db.lua index 0f174f17..4220b68b 100644 --- a/testes/db.lua +++ b/testes/db.lua | |||
| @@ -356,8 +356,8 @@ function f(a,b) | |||
| 356 | global assert, g, string | 356 | global assert, g, string |
| 357 | local _, y = debug.getlocal(1, 2) | 357 | local _, y = debug.getlocal(1, 2) |
| 358 | assert(x == a and y == b) | 358 | assert(x == a and y == b) |
| 359 | assert(debug.setlocal(2, 3, "pera") == "AA".."AA") | 359 | assert(debug.setlocal(2, 4, "pera") == "AA".."AA") |
| 360 | assert(debug.setlocal(2, 4, "manga") == "B") | 360 | assert(debug.setlocal(2, 5, "manga") == "B") |
| 361 | x = debug.getinfo(2) | 361 | x = debug.getinfo(2) |
| 362 | assert(x.func == g and x.what == "Lua" and x.name == 'g' and | 362 | assert(x.func == g and x.what == "Lua" and x.name == 'g' and |
| 363 | x.nups == 2 and string.find(x.source, "^@.*db%.lua$")) | 363 | x.nups == 2 and string.find(x.source, "^@.*db%.lua$")) |
| @@ -392,7 +392,7 @@ function g (...) | |||
| 392 | global * | 392 | global * |
| 393 | local B = 13 | 393 | local B = 13 |
| 394 | global<const> assert | 394 | global<const> assert |
| 395 | local x,y = debug.getlocal(1,5) | 395 | local x,y = debug.getlocal(1,6) |
| 396 | assert(x == 'B' and y == 13) | 396 | assert(x == 'B' and y == 13) |
| 397 | end | 397 | end |
| 398 | end | 398 | end |
| @@ -458,7 +458,8 @@ local function collectlocals (level) | |||
| 458 | local tab = {} | 458 | local tab = {} |
| 459 | for i = 1, math.huge do | 459 | for i = 1, math.huge do |
| 460 | local n, v = debug.getlocal(level + 1, i) | 460 | local n, v = debug.getlocal(level + 1, i) |
| 461 | if not (n and string.find(n, "^[a-zA-Z0-9_]+$")) then | 461 | if not (n and string.find(n, "^[a-zA-Z0-9_]+$") or |
| 462 | n == "(vararg table)") then | ||
| 462 | break -- consider only real variables | 463 | break -- consider only real variables |
| 463 | end | 464 | end |
| 464 | tab[n] = v | 465 | tab[n] = v |
diff --git a/testes/vararg.lua b/testes/vararg.lua index a01598ff..043fa7d4 100644 --- a/testes/vararg.lua +++ b/testes/vararg.lua | |||
| @@ -101,6 +101,38 @@ a,b,c,d,e = f(4) | |||
| 101 | assert(a==nil and b==nil and c==nil and d==nil and e==nil) | 101 | assert(a==nil and b==nil and c==nil and d==nil and e==nil) |
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | do -- vararg expressions using unpack | ||
| 105 | local function aux (a, v, ...t) | ||
| 106 | for k, val in pairs(v) do t[k] = val end | ||
| 107 | return ... | ||
| 108 | end | ||
| 109 | |||
| 110 | local t = table.pack(aux(10, {11, [5] = 24}, 1, 2, 3, nil, 4)) | ||
| 111 | assert(t.n == 5 and t[1] == 11 and t[2] == 2 and t[3] == 3 | ||
| 112 | and t[4] == nil and t[5] == 24) | ||
| 113 | |||
| 114 | local t = table.pack(aux(nil, {1, [20] = "a", [30] = "b", n = 30})) | ||
| 115 | assert(t.n == 30 and t[1] == 1 and t[20] == "a" and t[30] == "b") | ||
| 116 | -- table has only those four elements | ||
| 117 | assert(next(t, next(t, next(t, next(t, next(t, nil))))) == nil) | ||
| 118 | |||
| 119 | local a, b, c, d = aux(nil, {}, 10, 20, 30) | ||
| 120 | assert(a == 10 and b == 20 and c == 30 and d == nil) | ||
| 121 | |||
| 122 | local function aux (a, b, n, ...t) t.n = n; return b, ... end | ||
| 123 | local t = table.pack(aux(10, 1, 10000)) | ||
| 124 | assert(t.n == 10001 and t[1] == 1 and #t == 1) | ||
| 125 | |||
| 126 | local function checkerr (emsg, f, ...) | ||
| 127 | local st, msg = pcall(f, ...) | ||
| 128 | assert(not st and string.find(msg, emsg)) | ||
| 129 | end | ||
| 130 | checkerr("no proper 'n'", aux, 1, 1, -1) | ||
| 131 | checkerr("no proper 'n'", aux, 1, 1, math.maxinteger) | ||
| 132 | checkerr("no proper 'n'", aux, 1, 1, math.mininteger) | ||
| 133 | checkerr("no proper 'n'", aux, 1, 1, 1.0) | ||
| 134 | end | ||
| 135 | |||
| 104 | -- varargs for main chunks | 136 | -- varargs for main chunks |
| 105 | local f = assert(load[[ return {...} ]]) | 137 | local f = assert(load[[ return {...} ]]) |
| 106 | local x = f(2,3) | 138 | local x = f(2,3) |
| @@ -205,6 +237,7 @@ do -- access to vararg parameter | |||
| 205 | assert(t[k] == v[k]) | 237 | assert(t[k] == v[k]) |
| 206 | end | 238 | end |
| 207 | assert(t.n == v.n) | 239 | assert(t.n == v.n) |
| 240 | return ... | ||
| 208 | end | 241 | end |
| 209 | 242 | ||
| 210 | local t = table.pack(10, 20, 30) | 243 | local t = table.pack(10, 20, 30) |
