diff options
| -rw-r--r-- | lcode.c | 12 | ||||
| -rw-r--r-- | ldebug.c | 8 | ||||
| -rw-r--r-- | ldo.c | 2 | ||||
| -rw-r--r-- | lobject.h | 10 | ||||
| -rw-r--r-- | lopcodes.h | 31 | ||||
| -rw-r--r-- | lparser.c | 6 | ||||
| -rw-r--r-- | ltm.c | 39 | ||||
| -rw-r--r-- | manual/manual.of | 2 | ||||
| -rw-r--r-- | testes/db.lua | 3 |
9 files changed, 70 insertions, 43 deletions
| @@ -806,7 +806,7 @@ void luaK_setoneret (FuncState *fs, expdesc *e) { | |||
| 806 | ** Change a vararg parameter into a regular local variable | 806 | ** Change a vararg parameter into a regular local variable |
| 807 | */ | 807 | */ |
| 808 | void luaK_vapar2local (FuncState *fs, expdesc *var) { | 808 | void luaK_vapar2local (FuncState *fs, expdesc *var) { |
| 809 | fs->f->flag |= PF_VATAB; /* function will need a vararg table */ | 809 | needvatab(fs->f); /* function will need a vararg table */ |
| 810 | /* now a vararg parameter is equivalent to a regular local variable */ | 810 | /* now a vararg parameter is equivalent to a regular local variable */ |
| 811 | var->k = VLOCAL; | 811 | var->k = VLOCAL; |
| 812 | } | 812 | } |
| @@ -1127,7 +1127,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
| 1127 | break; | 1127 | break; |
| 1128 | } | 1128 | } |
| 1129 | case VVARGIND: { | 1129 | case VVARGIND: { |
| 1130 | fs->f->flag |= PF_VATAB; /* function will need a vararg table */ | 1130 | needvatab(fs->f); /* function will need a vararg table */ |
| 1131 | /* now, assignment is to a regular table */ | 1131 | /* now, assignment is to a regular table */ |
| 1132 | } /* FALLTHROUGH */ | 1132 | } /* FALLTHROUGH */ |
| 1133 | case VINDEXED: { | 1133 | case VINDEXED: { |
| @@ -1927,6 +1927,8 @@ static int finaltarget (Instruction *code, int i) { | |||
| 1927 | void luaK_finish (FuncState *fs) { | 1927 | void luaK_finish (FuncState *fs) { |
| 1928 | int i; | 1928 | int i; |
| 1929 | Proto *p = fs->f; | 1929 | Proto *p = fs->f; |
| 1930 | if (p->flag & PF_VATAB) /* will it use a vararg table? */ | ||
| 1931 | p->flag &= cast_byte(~PF_VAHID); /* then it will not use hidden args. */ | ||
| 1930 | for (i = 0; i < fs->pc; i++) { | 1932 | for (i = 0; i < fs->pc; i++) { |
| 1931 | Instruction *pc = &p->code[i]; | 1933 | Instruction *pc = &p->code[i]; |
| 1932 | /* avoid "not used" warnings when assert is off (for 'onelua.c') */ | 1934 | /* avoid "not used" warnings when assert is off (for 'onelua.c') */ |
| @@ -1934,7 +1936,7 @@ void luaK_finish (FuncState *fs) { | |||
| 1934 | lua_assert(i == 0 || luaP_isOT(*(pc - 1)) == luaP_isIT(*pc)); | 1936 | lua_assert(i == 0 || luaP_isOT(*(pc - 1)) == luaP_isIT(*pc)); |
| 1935 | switch (GET_OPCODE(*pc)) { | 1937 | switch (GET_OPCODE(*pc)) { |
| 1936 | case OP_RETURN0: case OP_RETURN1: { | 1938 | case OP_RETURN0: case OP_RETURN1: { |
| 1937 | if (!(fs->needclose || (p->flag & PF_ISVARARG))) | 1939 | if (!(fs->needclose || (p->flag & PF_VAHID))) |
| 1938 | break; /* no extra work */ | 1940 | break; /* no extra work */ |
| 1939 | /* else use OP_RETURN to do the extra work */ | 1941 | /* else use OP_RETURN to do the extra work */ |
| 1940 | SET_OPCODE(*pc, OP_RETURN); | 1942 | SET_OPCODE(*pc, OP_RETURN); |
| @@ -1942,8 +1944,8 @@ void luaK_finish (FuncState *fs) { | |||
| 1942 | case OP_RETURN: case OP_TAILCALL: { | 1944 | case OP_RETURN: case OP_TAILCALL: { |
| 1943 | if (fs->needclose) | 1945 | if (fs->needclose) |
| 1944 | SETARG_k(*pc, 1); /* signal that it needs to close */ | 1946 | SETARG_k(*pc, 1); /* signal that it needs to close */ |
| 1945 | if (p->flag & PF_ISVARARG) | 1947 | if (p->flag & PF_VAHID) /* does it use hidden arguments? */ |
| 1946 | SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ | 1948 | SETARG_C(*pc, p->numparams + 1); /* signal that */ |
| 1947 | break; | 1949 | break; |
| 1948 | } | 1950 | } |
| 1949 | case OP_GETVARG: { | 1951 | case OP_GETVARG: { |
| @@ -184,7 +184,7 @@ static const char *upvalname (const Proto *p, int uv) { | |||
| 184 | 184 | ||
| 185 | 185 | ||
| 186 | static const char *findvararg (CallInfo *ci, int n, StkId *pos) { | 186 | static const char *findvararg (CallInfo *ci, int n, StkId *pos) { |
| 187 | if (clLvalue(s2v(ci->func.p))->p->flag & PF_ISVARARG) { | 187 | if (clLvalue(s2v(ci->func.p))->p->flag & PF_VAHID) { |
| 188 | int nextra = ci->u.l.nextraargs; | 188 | int nextra = ci->u.l.nextraargs; |
| 189 | if (n >= -nextra) { /* 'n' is negative */ | 189 | if (n >= -nextra) { /* 'n' is negative */ |
| 190 | *pos = ci->func.p - nextra - (n + 1); | 190 | *pos = ci->func.p - nextra - (n + 1); |
| @@ -304,7 +304,7 @@ static void collectvalidlines (lua_State *L, Closure *f) { | |||
| 304 | int i; | 304 | int i; |
| 305 | TValue v; | 305 | TValue v; |
| 306 | setbtvalue(&v); /* boolean 'true' to be the value of all indices */ | 306 | setbtvalue(&v); /* boolean 'true' to be the value of all indices */ |
| 307 | if (!(p->flag & PF_ISVARARG)) /* regular function? */ | 307 | if (!(isvararg(p))) /* regular function? */ |
| 308 | i = 0; /* consider all instructions */ | 308 | i = 0; /* consider all instructions */ |
| 309 | else { /* vararg function */ | 309 | else { /* vararg function */ |
| 310 | lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); | 310 | lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); |
| @@ -348,7 +348,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
| 348 | ar->nparams = 0; | 348 | ar->nparams = 0; |
| 349 | } | 349 | } |
| 350 | else { | 350 | else { |
| 351 | ar->isvararg = (f->l.p->flag & PF_ISVARARG) ? 1 : 0; | 351 | ar->isvararg = (isvararg(f->l.p)) ? 1 : 0; |
| 352 | ar->nparams = f->l.p->numparams; | 352 | ar->nparams = f->l.p->numparams; |
| 353 | } | 353 | } |
| 354 | break; | 354 | break; |
| @@ -912,7 +912,7 @@ int luaG_tracecall (lua_State *L) { | |||
| 912 | Proto *p = ci_func(ci)->p; | 912 | Proto *p = ci_func(ci)->p; |
| 913 | ci->u.l.trap = 1; /* ensure hooks will be checked */ | 913 | ci->u.l.trap = 1; /* ensure hooks will be checked */ |
| 914 | if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */ | 914 | if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */ |
| 915 | if (p->flag & PF_ISVARARG) | 915 | if (isvararg(p)) |
| 916 | return 0; /* hooks will start at VARARGPREP instruction */ | 916 | return 0; /* hooks will start at VARARGPREP instruction */ |
| 917 | else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yielded? */ | 917 | else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yielded? */ |
| 918 | luaD_hookcall(L, ci); /* check 'call' hook */ | 918 | luaD_hookcall(L, ci); /* check 'call' hook */ |
| @@ -487,7 +487,7 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { | |||
| 487 | int ftransfer; | 487 | int ftransfer; |
| 488 | if (isLua(ci)) { | 488 | if (isLua(ci)) { |
| 489 | Proto *p = ci_func(ci)->p; | 489 | Proto *p = ci_func(ci)->p; |
| 490 | if (p->flag & PF_ISVARARG) | 490 | if (p->flag & PF_VAHID) |
| 491 | delta = ci->u.l.nextraargs + p->numparams + 1; | 491 | delta = ci->u.l.nextraargs + p->numparams + 1; |
| 492 | } | 492 | } |
| 493 | ci->func.p += delta; /* if vararg, back to virtual 'func' */ | 493 | ci->func.p += delta; /* if vararg, back to virtual 'func' */ |
| @@ -583,10 +583,18 @@ typedef struct AbsLineInfo { | |||
| 583 | /* | 583 | /* |
| 584 | ** Flags in Prototypes | 584 | ** Flags in Prototypes |
| 585 | */ | 585 | */ |
| 586 | #define PF_ISVARARG 1 /* function is vararg */ | 586 | #define PF_VAHID 1 /* function has hidden vararg arguments */ |
| 587 | #define PF_VATAB 2 /* function has vararg table */ | 587 | #define PF_VATAB 2 /* function has vararg table */ |
| 588 | #define PF_FIXED 4 /* prototype has parts in fixed memory */ | 588 | #define PF_FIXED 4 /* prototype has parts in fixed memory */ |
| 589 | 589 | ||
| 590 | /* a vararg function either has hidden args. or a vararg table */ | ||
| 591 | #define isvararg(p) ((p)->flag & (PF_VAHID | PF_VATAB)) | ||
| 592 | |||
| 593 | /* | ||
| 594 | ** mark that a function needs a vararg table. (The flag PF_VAHID will | ||
| 595 | ** be cleared later.) | ||
| 596 | */ | ||
| 597 | #define needvatab(p) ((p)->flag |= PF_VATAB) | ||
| 590 | 598 | ||
| 591 | /* | 599 | /* |
| 592 | ** Function Prototypes | 600 | ** Function Prototypes |
| @@ -224,8 +224,8 @@ enum OpMode {iABC, ivABC, iABx, iAsBx, iAx, isJ}; | |||
| 224 | 224 | ||
| 225 | 225 | ||
| 226 | /* | 226 | /* |
| 227 | ** Grep "ORDER OP" if you change these enums. Opcodes marked with a (*) | 227 | ** Grep "ORDER OP" if you change this enum. |
| 228 | ** has extra descriptions in the notes after the enumeration. | 228 | ** See "Notes" below for more information about some instructions. |
| 229 | */ | 229 | */ |
| 230 | 230 | ||
| 231 | typedef enum { | 231 | typedef enum { |
| @@ -238,7 +238,7 @@ OP_LOADF,/* A sBx R[A] := (lua_Number)sBx */ | |||
| 238 | OP_LOADK,/* A Bx R[A] := K[Bx] */ | 238 | OP_LOADK,/* A Bx R[A] := K[Bx] */ |
| 239 | OP_LOADKX,/* A R[A] := K[extra arg] */ | 239 | OP_LOADKX,/* A R[A] := K[extra arg] */ |
| 240 | OP_LOADFALSE,/* A R[A] := false */ | 240 | OP_LOADFALSE,/* A R[A] := false */ |
| 241 | OP_LFALSESKIP,/*A R[A] := false; pc++ (*) */ | 241 | OP_LFALSESKIP,/*A R[A] := false; pc++ */ |
| 242 | OP_LOADTRUE,/* A R[A] := true */ | 242 | OP_LOADTRUE,/* A R[A] := true */ |
| 243 | OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */ | 243 | OP_LOADNIL,/* A B R[A], R[A+1], ..., R[A+B] := nil */ |
| 244 | OP_GETUPVAL,/* A B R[A] := UpValue[B] */ | 244 | OP_GETUPVAL,/* A B R[A] := UpValue[B] */ |
| @@ -289,7 +289,7 @@ OP_BXOR,/* A B C R[A] := R[B] ~ R[C] */ | |||
| 289 | OP_SHL,/* A B C R[A] := R[B] << R[C] */ | 289 | OP_SHL,/* A B C R[A] := R[B] << R[C] */ |
| 290 | OP_SHR,/* A B C R[A] := R[B] >> R[C] */ | 290 | OP_SHR,/* A B C R[A] := R[B] >> R[C] */ |
| 291 | 291 | ||
| 292 | OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] (*) */ | 292 | OP_MMBIN,/* A B C call C metamethod over R[A] and R[B] */ |
| 293 | OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */ | 293 | OP_MMBINI,/* A sB C k call C metamethod over R[A] and sB */ |
| 294 | OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */ | 294 | OP_MMBINK,/* A B C k call C metamethod over R[A] and K[B] */ |
| 295 | 295 | ||
| @@ -315,12 +315,12 @@ OP_GTI,/* A sB k if ((R[A] > sB) ~= k) then pc++ */ | |||
| 315 | OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */ | 315 | OP_GEI,/* A sB k if ((R[A] >= sB) ~= k) then pc++ */ |
| 316 | 316 | ||
| 317 | OP_TEST,/* A k if (not R[A] == k) then pc++ */ | 317 | OP_TEST,/* A k if (not R[A] == k) then pc++ */ |
| 318 | OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] (*) */ | 318 | OP_TESTSET,/* A B k if (not R[B] == k) then pc++ else R[A] := R[B] */ |
| 319 | 319 | ||
| 320 | OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */ | 320 | OP_CALL,/* A B C R[A], ... ,R[A+C-2] := R[A](R[A+1], ... ,R[A+B-1]) */ |
| 321 | OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */ | 321 | OP_TAILCALL,/* A B C k return R[A](R[A+1], ... ,R[A+B-1]) */ |
| 322 | 322 | ||
| 323 | OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] (see note) */ | 323 | OP_RETURN,/* A B C k return R[A], ... ,R[A+B-2] */ |
| 324 | OP_RETURN0,/* return */ | 324 | OP_RETURN0,/* return */ |
| 325 | OP_RETURN1,/* A return R[A] */ | 325 | OP_RETURN1,/* A return R[A] */ |
| 326 | 326 | ||
| @@ -336,13 +336,13 @@ 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+C-2] = vararg, R[B] is vararg param. */ | 339 | OP_VARARG,/* A B C k R[A], ..., R[A+C-2] = varargs */ |
| 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 | ||
| 343 | OP_ERRNNIL,/* A Bx raise error if R[A] ~= nil (K[Bx - 1] is global name)*/ | 343 | OP_ERRNNIL,/* A Bx raise error if R[A] ~= nil (K[Bx - 1] is global name)*/ |
| 344 | 344 | ||
| 345 | OP_VARARGPREP,/* (adjust vararg parameters) */ | 345 | OP_VARARGPREP,/* (adjust varargs) */ |
| 346 | 346 | ||
| 347 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | 347 | OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ |
| 348 | } OpCode; | 348 | } OpCode; |
| @@ -371,7 +371,8 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | |||
| 371 | OP_RETURN*, OP_SETLIST) may use 'top'. | 371 | OP_RETURN*, OP_SETLIST) may use 'top'. |
| 372 | 372 | ||
| 373 | (*) In OP_VARARG, if (C == 0) then use actual number of varargs and | 373 | (*) In OP_VARARG, if (C == 0) then use actual number of varargs and |
| 374 | set top (like in OP_CALL with C == 0). | 374 | set top (like in OP_CALL with C == 0). 'k' means function has a |
| 375 | vararg table, which is in R[B]. | ||
| 375 | 376 | ||
| 376 | (*) In OP_RETURN, if (B == 0) then return up to 'top'. | 377 | (*) In OP_RETURN, if (B == 0) then return up to 'top'. |
| 377 | 378 | ||
| @@ -387,20 +388,22 @@ OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ | |||
| 387 | is vC. Otherwise, the array size is EXTRAARG _ vC. | 388 | is vC. Otherwise, the array size is EXTRAARG _ vC. |
| 388 | 389 | ||
| 389 | (*) In OP_ERRNNIL, (Bx == 0) means index of global name doesn't | 390 | (*) In OP_ERRNNIL, (Bx == 0) means index of global name doesn't |
| 390 | fit in Bx. (So, that name is not available for the instruction.) | 391 | fit in Bx. (So, that name is not available for the error message.) |
| 391 | 392 | ||
| 392 | (*) For comparisons, k specifies what condition the test should accept | 393 | (*) For comparisons, k specifies what condition the test should accept |
| 393 | (true or false). | 394 | (true or false). |
| 394 | 395 | ||
| 395 | (*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped | 396 | (*) In OP_MMBINI/OP_MMBINK, k means the arguments were flipped |
| 396 | (the constant is the first operand). | 397 | (the constant is the first operand). |
| 397 | 398 | ||
| 398 | (*) All 'skips' (pc++) assume that next instruction is a jump. | 399 | (*) All comparison and test instructions assume that the instruction |
| 400 | being skipped (pc++) is a jump. | ||
| 399 | 401 | ||
| 400 | (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the | 402 | (*) In instructions OP_RETURN/OP_TAILCALL, 'k' specifies that the |
| 401 | function builds upvalues, which may need to be closed. C > 0 means | 403 | function builds upvalues, which may need to be closed. C > 0 means |
| 402 | the function is vararg, so that its 'func' must be corrected before | 404 | the function has hidden vararg arguments, so that its 'func' must be |
| 403 | returning; in this case, (C - 1) is its number of fixed parameters. | 405 | corrected before returning; in this case, (C - 1) is its number of |
| 406 | fixed parameters. | ||
| 404 | 407 | ||
| 405 | (*) In comparisons with an immediate operand, C signals whether the | 408 | (*) In comparisons with an immediate operand, C signals whether the |
| 406 | original operand was a float. (It must be corrected in case of | 409 | original operand was a float. (It must be corrected in case of |
| @@ -304,7 +304,7 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
| 304 | break; | 304 | break; |
| 305 | } | 305 | } |
| 306 | case VVARGIND: { | 306 | case VVARGIND: { |
| 307 | fs->f->flag |= PF_VATAB; /* function will need a vararg table */ | 307 | needvatab(fs->f); /* function will need a vararg table */ |
| 308 | e->k = VINDEXED; | 308 | e->k = VINDEXED; |
| 309 | } /* FALLTHROUGH */ | 309 | } /* FALLTHROUGH */ |
| 310 | case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ | 310 | case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ |
| @@ -1057,7 +1057,7 @@ static void constructor (LexState *ls, expdesc *t) { | |||
| 1057 | 1057 | ||
| 1058 | 1058 | ||
| 1059 | static void setvararg (FuncState *fs) { | 1059 | static void setvararg (FuncState *fs) { |
| 1060 | fs->f->flag |= PF_ISVARARG; | 1060 | fs->f->flag |= PF_VAHID; /* by default, use hidden vararg arguments */ |
| 1061 | luaK_codeABC(fs, OP_VARARGPREP, 0, 0, 0); | 1061 | luaK_codeABC(fs, OP_VARARGPREP, 0, 0, 0); |
| 1062 | } | 1062 | } |
| 1063 | 1063 | ||
| @@ -1283,7 +1283,7 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
| 1283 | } | 1283 | } |
| 1284 | case TK_DOTS: { /* vararg */ | 1284 | case TK_DOTS: { /* vararg */ |
| 1285 | FuncState *fs = ls->fs; | 1285 | FuncState *fs = ls->fs; |
| 1286 | check_condition(ls, fs->f->flag & PF_ISVARARG, | 1286 | check_condition(ls, isvararg(fs->f), |
| 1287 | "cannot use '...' outside a vararg function"); | 1287 | "cannot use '...' outside a vararg function"); |
| 1288 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, fs->f->numparams, 1)); | 1288 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, fs->f->numparams, 1)); |
| 1289 | break; | 1289 | break; |
| @@ -250,31 +250,42 @@ static void createvarargtab (lua_State *L, StkId f, int n) { | |||
| 250 | ** initial stack: func arg1 ... argn extra1 ... | 250 | ** initial stack: func arg1 ... argn extra1 ... |
| 251 | ** ^ ci->func ^ L->top | 251 | ** ^ ci->func ^ L->top |
| 252 | ** final stack: func nil ... nil extra1 ... func arg1 ... argn | 252 | ** final stack: func nil ... nil extra1 ... func arg1 ... argn |
| 253 | ** ^ ci->func ^ L->top | 253 | ** ^ ci->func |
| 254 | */ | 254 | */ |
| 255 | void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) { | 255 | static void buildhiddenargs (lua_State *L, CallInfo *ci, const Proto *p, |
| 256 | int totalargs, int nfixparams, int nextra) { | ||
| 256 | int i; | 257 | int i; |
| 257 | int totalargs = cast_int(L->top.p - ci->func.p) - 1; | ||
| 258 | int nfixparams = p->numparams; | ||
| 259 | int nextra = totalargs - nfixparams; /* number of extra arguments */ | ||
| 260 | ci->u.l.nextraargs = nextra; | 258 | ci->u.l.nextraargs = nextra; |
| 261 | luaD_checkstack(L, p->maxstacksize + 1); | 259 | luaD_checkstack(L, p->maxstacksize + 1); |
| 262 | /* copy function to the top of the stack */ | 260 | /* copy function to the top of the stack, after extra arguments */ |
| 263 | setobjs2s(L, L->top.p++, ci->func.p); | 261 | setobjs2s(L, L->top.p++, ci->func.p); |
| 264 | /* move fixed parameters to the top of the stack */ | 262 | /* move fixed parameters to after the copied function */ |
| 265 | for (i = 1; i <= nfixparams; i++) { | 263 | for (i = 1; i <= nfixparams; i++) { |
| 266 | setobjs2s(L, L->top.p++, ci->func.p + i); | 264 | setobjs2s(L, L->top.p++, ci->func.p + i); |
| 267 | setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ | 265 | setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ |
| 268 | } | 266 | } |
| 269 | if (p->flag & PF_VATAB) /* does it need a vararg table? */ | 267 | ci->func.p += totalargs + 1; /* 'func' now lives after hidden arguments */ |
| 268 | ci->top.p += totalargs + 1; | ||
| 269 | } | ||
| 270 | |||
| 271 | |||
| 272 | void luaT_adjustvarargs (lua_State *L, CallInfo *ci, const Proto *p) { | ||
| 273 | int totalargs = cast_int(L->top.p - ci->func.p) - 1; | ||
| 274 | int nfixparams = p->numparams; | ||
| 275 | int nextra = totalargs - nfixparams; /* number of extra arguments */ | ||
| 276 | if (p->flag & PF_VATAB) { /* does it need a vararg table? */ | ||
| 277 | lua_assert(!(p->flag & PF_VAHID)); | ||
| 270 | createvarargtab(L, ci->func.p + nfixparams + 1, nextra); | 278 | createvarargtab(L, ci->func.p + nfixparams + 1, nextra); |
| 271 | else { /* no table; set parameter to nil */ | 279 | /* move table to proper place (last parameter) */ |
| 272 | setnilvalue(s2v(L->top.p)); | 280 | setobjs2s(L, ci->func.p + nfixparams + 1, L->top.p - 1); |
| 273 | L->top.p++; | 281 | } |
| 282 | else { /* no table */ | ||
| 283 | lua_assert(p->flag & PF_VAHID); | ||
| 284 | buildhiddenargs(L, ci, p, totalargs, nfixparams, nextra); | ||
| 285 | /* set vararg parameter to nil */ | ||
| 286 | setnilvalue(s2v(ci->func.p + nfixparams + 1)); | ||
| 287 | lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p); | ||
| 274 | } | 288 | } |
| 275 | ci->func.p += totalargs + 1; | ||
| 276 | ci->top.p += totalargs + 1; | ||
| 277 | lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p); | ||
| 278 | } | 289 | } |
| 279 | 290 | ||
| 280 | 291 | ||
diff --git a/manual/manual.of b/manual/manual.of index 9b8e144d..54f67b3e 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -2425,7 +2425,7 @@ The conditions are as follows: | |||
| 2425 | If the vararg table has a name, | 2425 | If the vararg table has a name, |
| 2426 | that name is not an upvalue in a nested function | 2426 | that name is not an upvalue in a nested function |
| 2427 | and it is used only as the base table | 2427 | and it is used only as the base table |
| 2428 | in the syntactic constructions @T{t[exp]} or @T{t.id}). | 2428 | in the syntactic constructions @T{t[exp]} or @T{t.id}. |
| 2429 | Note that an anonymous vararg table always satisfy these conditions. | 2429 | Note that an anonymous vararg table always satisfy these conditions. |
| 2430 | 2430 | ||
| 2431 | } | 2431 | } |
diff --git a/testes/db.lua b/testes/db.lua index 4220b68b..e15a5be6 100644 --- a/testes/db.lua +++ b/testes/db.lua | |||
| @@ -726,6 +726,9 @@ assert(t.isvararg == false and t.nparams == 3 and t.nups == 0) | |||
| 726 | t = debug.getinfo(function (a,b,...) return t[a] end, "u") | 726 | t = debug.getinfo(function (a,b,...) return t[a] end, "u") |
| 727 | assert(t.isvararg == true and t.nparams == 2 and t.nups == 1) | 727 | assert(t.isvararg == true and t.nparams == 2 and t.nups == 1) |
| 728 | 728 | ||
| 729 | t = debug.getinfo(function (a,b,...t) t.n = 2; return t[a] end, "u") | ||
| 730 | assert(t.isvararg == true and t.nparams == 2 and t.nups == 0) | ||
| 731 | |||
| 729 | t = debug.getinfo(1) -- main | 732 | t = debug.getinfo(1) -- main |
| 730 | assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and | 733 | assert(t.isvararg == true and t.nparams == 0 and t.nups == 1 and |
| 731 | debug.getupvalue(t.func, 1) == "_ENV") | 734 | debug.getupvalue(t.func, 1) == "_ENV") |
