diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-05-31 15:51:50 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-05-31 15:51:50 -0300 |
| commit | 616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59 (patch) | |
| tree | 78322d820e3af1ca6645ed08eaa65a8f0aa04fec | |
| parent | 47eda6ebd83785908ac26f8dd06dff36a7d42664 (diff) | |
| download | lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.tar.gz lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.tar.bz2 lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.zip | |
new way to use `vararg' parameters (with `...')
| -rw-r--r-- | lcode.c | 28 | ||||
| -rw-r--r-- | lcode.h | 7 | ||||
| -rw-r--r-- | ldebug.c | 13 | ||||
| -rw-r--r-- | ldo.c | 66 | ||||
| -rw-r--r-- | lobject.h | 6 | ||||
| -rw-r--r-- | lopcodes.c | 6 | ||||
| -rw-r--r-- | lopcodes.h | 21 | ||||
| -rw-r--r-- | lparser.c | 60 | ||||
| -rw-r--r-- | lparser.h | 5 | ||||
| -rw-r--r-- | lstate.c | 3 | ||||
| -rw-r--r-- | lstate.h | 9 | ||||
| -rw-r--r-- | lua.c | 37 | ||||
| -rw-r--r-- | lvm.c | 37 |
13 files changed, 192 insertions, 106 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.1 2003/12/10 12:13:36 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.2 2004/04/30 20:13:38 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -252,13 +252,26 @@ static int nil_constant (FuncState *fs) { | |||
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | 254 | ||
| 255 | void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) { | 255 | void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { |
| 256 | if (e->k == VCALL) { /* expression is an open function call? */ | 256 | if (e->k == VCALL) { /* expression is an open function call? */ |
| 257 | SETARG_C(getcode(fs, e), nresults+1); | 257 | SETARG_C(getcode(fs, e), nresults+1); |
| 258 | if (nresults == 1) { /* `regular' expression? */ | 258 | } |
| 259 | e->k = VNONRELOC; | 259 | else if (e->k == VVARARG) { |
| 260 | e->info = GETARG_A(getcode(fs, e)); | 260 | SETARG_B(getcode(fs, e), nresults+1); |
| 261 | } | 261 | SETARG_A(getcode(fs, e), fs->freereg); |
| 262 | luaK_reserveregs(fs, 1); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | |||
| 267 | void luaK_setoneret (FuncState *fs, expdesc *e) { | ||
| 268 | if (e->k == VCALL) { /* expression is an open function call? */ | ||
| 269 | e->k = VNONRELOC; | ||
| 270 | e->info = GETARG_A(getcode(fs, e)); | ||
| 271 | } | ||
| 272 | else if (e->k == VVARARG) { | ||
| 273 | SETARG_B(getcode(fs, e), 2); | ||
| 274 | e->k = VRELOCABLE; /* can relocate its simple result */ | ||
| 262 | } | 275 | } |
| 263 | } | 276 | } |
| 264 | 277 | ||
| @@ -286,8 +299,9 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
| 286 | e->k = VRELOCABLE; | 299 | e->k = VRELOCABLE; |
| 287 | break; | 300 | break; |
| 288 | } | 301 | } |
| 302 | case VVARARG: | ||
| 289 | case VCALL: { | 303 | case VCALL: { |
| 290 | luaK_setcallreturns(fs, e, 1); | 304 | luaK_setoneret(fs, e); |
| 291 | break; | 305 | break; |
| 292 | } | 306 | } |
| 293 | default: break; /* there is one value available (somewhere) */ | 307 | default: break; /* there is one value available (somewhere) */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.h,v 1.37 2002/06/12 19:16:00 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.38 2002/12/11 12:34:22 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -41,6 +41,8 @@ typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; | |||
| 41 | 41 | ||
| 42 | #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) | 42 | #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) |
| 43 | 43 | ||
| 44 | #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) | ||
| 45 | |||
| 44 | int luaK_code (FuncState *fs, Instruction i, int line); | 46 | int luaK_code (FuncState *fs, Instruction i, int line); |
| 45 | int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); | 47 | int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); |
| 46 | int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); | 48 | int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); |
| @@ -60,7 +62,8 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); | |||
| 60 | void luaK_goiftrue (FuncState *fs, expdesc *e); | 62 | void luaK_goiftrue (FuncState *fs, expdesc *e); |
| 61 | void luaK_goiffalse (FuncState *fs, expdesc *e); | 63 | void luaK_goiffalse (FuncState *fs, expdesc *e); |
| 62 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); | 64 | void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); |
| 63 | void luaK_setcallreturns (FuncState *fs, expdesc *var, int nresults); | 65 | void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); |
| 66 | void luaK_setoneret (FuncState *fs, expdesc *e); | ||
| 64 | int luaK_jump (FuncState *fs); | 67 | int luaK_jump (FuncState *fs); |
| 65 | void luaK_patchlist (FuncState *fs, int list, int target); | 68 | void luaK_patchlist (FuncState *fs, int list, int target); |
| 66 | void luaK_patchtohere (FuncState *fs, int list); | 69 | void luaK_patchtohere (FuncState *fs, int list); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldebug.c,v 2.3 2004/03/23 13:10:16 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.4 2004/04/30 20:13: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 | */ |
| @@ -221,8 +221,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
| 221 | } | 221 | } |
| 222 | else if (ar->i_ci != 0) { /* no tail call? */ | 222 | else if (ar->i_ci != 0) { /* no tail call? */ |
| 223 | CallInfo *ci = L->base_ci + ar->i_ci; | 223 | CallInfo *ci = L->base_ci + ar->i_ci; |
| 224 | lua_assert(ttisfunction(ci->base - 1)); | 224 | lua_assert(ttisfunction(ci->func)); |
| 225 | status = auxgetinfo(L, what, ar, ci->base - 1, ci); | 225 | status = auxgetinfo(L, what, ar, ci->func, ci); |
| 226 | } | 226 | } |
| 227 | else | 227 | else |
| 228 | info_tailcall(L, ar); | 228 | info_tailcall(L, ar); |
| @@ -405,6 +405,13 @@ static Instruction luaG_symbexec (const Proto *pt, int lastpc, int reg) { | |||
| 405 | } | 405 | } |
| 406 | break; | 406 | break; |
| 407 | } | 407 | } |
| 408 | case OP_VARARG: { | ||
| 409 | check(pt->is_vararg & NEWSTYLEVARARG); | ||
| 410 | b--; | ||
| 411 | if (b == LUA_MULTRET) check(checkopenop(pt, pc)); | ||
| 412 | checkreg(pt, a+b-1); | ||
| 413 | break; | ||
| 414 | } | ||
| 408 | default: break; | 415 | default: break; |
| 409 | } | 416 | } |
| 410 | } | 417 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 2.4 2004/05/10 17:50:51 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.5 2004/05/14 19:25:09 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 | */ |
| @@ -113,6 +113,7 @@ static void correctstack (lua_State *L, TValue *oldstack) { | |||
| 113 | for (ci = L->base_ci; ci <= L->ci; ci++) { | 113 | for (ci = L->base_ci; ci <= L->ci; ci++) { |
| 114 | ci->top = (ci->top - oldstack) + L->stack; | 114 | ci->top = (ci->top - oldstack) + L->stack; |
| 115 | ci->base = (ci->base - oldstack) + L->stack; | 115 | ci->base = (ci->base - oldstack) + L->stack; |
| 116 | ci->func = (ci->func - oldstack) + L->stack; | ||
| 116 | } | 117 | } |
| 117 | L->base = L->ci->base; | 118 | L->base = L->ci->base; |
| 118 | } | 119 | } |
| @@ -181,26 +182,37 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
| 181 | } | 182 | } |
| 182 | 183 | ||
| 183 | 184 | ||
| 184 | static void adjust_varargs (lua_State *L, int nfixargs, StkId base) { | 185 | static StkId adjust_varargs (lua_State *L, int nfixargs, int actual, |
| 186 | int style) { | ||
| 185 | int i; | 187 | int i; |
| 186 | Table *htab; | 188 | Table *htab = NULL; |
| 187 | int actual = L->top - base; /* actual number of arguments */ | 189 | StkId base, fixed; |
| 188 | if (actual < nfixargs) { | 190 | if (actual < nfixargs) { |
| 189 | luaD_checkstack(L, nfixargs - actual); | ||
| 190 | for (; actual < nfixargs; ++actual) | 191 | for (; actual < nfixargs; ++actual) |
| 191 | setnilvalue(L->top++); | 192 | setnilvalue(L->top++); |
| 192 | } | 193 | } |
| 193 | actual -= nfixargs; /* number of extra arguments */ | 194 | if (style != NEWSTYLEVARARG) { /* compatibility with old-style vararg */ |
| 194 | htab = luaH_new(L, actual, 1); /* create `arg' table */ | 195 | int nvar = actual - nfixargs; /* number of extra arguments */ |
| 195 | for (i=0; i<actual; i++) /* put extra arguments into `arg' table */ | 196 | htab = luaH_new(L, nvar, 1); /* create `arg' table */ |
| 196 | setobj2n(L, luaH_setnum(L, htab, i+LUA_FIRSTINDEX), L->top - actual + i); | 197 | for (i=0; i<nvar; i++) /* put extra arguments into `arg' table */ |
| 197 | /* store counter in field `n' */ | 198 | setobj2n(L, luaH_setnum(L, htab, i+LUA_FIRSTINDEX), L->top - nvar + i); |
| 198 | setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), | 199 | /* store counter in field `n' */ |
| 199 | cast(lua_Number, actual)); | 200 | setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), |
| 200 | L->top -= actual; /* remove extra elements from the stack */ | 201 | cast(lua_Number, nvar)); |
| 201 | sethvalue(L, L->top, htab); | 202 | } |
| 202 | lua_assert(iswhite(obj2gco(htab))); | 203 | /* move fixed parameters to final position */ |
| 203 | incr_top(L); | 204 | fixed = L->top - actual; /* first fixed argument */ |
| 205 | base = L->top; /* final position of first argument */ | ||
| 206 | for (i=0; i<nfixargs; i++) { | ||
| 207 | setobjs2s(L, L->top++, fixed+i); | ||
| 208 | setnilvalue(fixed+i); | ||
| 209 | } | ||
| 210 | /* add `arg' parameter */ | ||
| 211 | if (htab) { | ||
| 212 | sethvalue(L, L->top++, htab); | ||
| 213 | lua_assert(iswhite(obj2gco(htab))); | ||
| 214 | } | ||
| 215 | return base; | ||
| 204 | } | 216 | } |
| 205 | 217 | ||
| 206 | 218 | ||
| @@ -221,21 +233,28 @@ static StkId tryfuncTM (lua_State *L, StkId func) { | |||
| 221 | 233 | ||
| 222 | int luaD_precall (lua_State *L, StkId func, int nresults) { | 234 | int luaD_precall (lua_State *L, StkId func, int nresults) { |
| 223 | LClosure *cl; | 235 | LClosure *cl; |
| 224 | ptrdiff_t funcr = savestack(L, func); | 236 | ptrdiff_t funcr; |
| 225 | if (!ttisfunction(func)) /* `func' is not a function? */ | 237 | if (!ttisfunction(func)) /* `func' is not a function? */ |
| 226 | func = tryfuncTM(L, func); /* check the `function' tag method */ | 238 | func = tryfuncTM(L, func); /* check the `function' tag method */ |
| 239 | funcr = savestack(L, func); | ||
| 227 | if (L->ci + 1 == L->end_ci) luaD_growCI(L); | 240 | if (L->ci + 1 == L->end_ci) luaD_growCI(L); |
| 228 | else condhardstacktests(luaD_reallocCI(L, L->size_ci)); | 241 | else condhardstacktests(luaD_reallocCI(L, L->size_ci)); |
| 229 | cl = &clvalue(func)->l; | 242 | cl = &clvalue(func)->l; |
| 230 | if (!cl->isC) { /* Lua function? prepare its call */ | 243 | if (!cl->isC) { /* Lua function? prepare its call */ |
| 231 | CallInfo *ci; | 244 | CallInfo *ci; |
| 232 | StkId st; | 245 | StkId st, base; |
| 233 | Proto *p = cl->p; | 246 | Proto *p = cl->p; |
| 234 | if (p->is_vararg) /* varargs? */ | ||
| 235 | adjust_varargs(L, p->numparams, func+1); | ||
| 236 | luaD_checkstack(L, p->maxstacksize); | 247 | luaD_checkstack(L, p->maxstacksize); |
| 248 | func = restorestack(L, funcr); | ||
| 249 | if (p->is_vararg) { /* varargs? */ | ||
| 250 | int nargs = L->top - func - 1; | ||
| 251 | base = adjust_varargs(L, p->numparams, nargs, p->is_vararg); | ||
| 252 | } | ||
| 253 | else | ||
| 254 | base = func + 1; | ||
| 237 | ci = ++L->ci; /* now `enter' new function */ | 255 | ci = ++L->ci; /* now `enter' new function */ |
| 238 | L->base = L->ci->base = restorestack(L, funcr) + 1; | 256 | ci->func = func; |
| 257 | L->base = ci->base = base; | ||
| 239 | ci->top = L->base + p->maxstacksize; | 258 | ci->top = L->base + p->maxstacksize; |
| 240 | ci->u.l.savedpc = p->code; /* starting point */ | 259 | ci->u.l.savedpc = p->code; /* starting point */ |
| 241 | ci->u.l.tailcalls = 0; | 260 | ci->u.l.tailcalls = 0; |
| @@ -250,7 +269,8 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
| 250 | int n; | 269 | int n; |
| 251 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 270 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 252 | ci = ++L->ci; /* now `enter' new function */ | 271 | ci = ++L->ci; /* now `enter' new function */ |
| 253 | L->base = L->ci->base = restorestack(L, funcr) + 1; | 272 | ci->func = restorestack(L, funcr); |
| 273 | L->base = ci->base = ci->func + 1; | ||
| 254 | ci->top = L->top + LUA_MINSTACK; | 274 | ci->top = L->top + LUA_MINSTACK; |
| 255 | if (L->hookmask & LUA_MASKCALL) | 275 | if (L->hookmask & LUA_MASKCALL) |
| 256 | luaD_callhook(L, LUA_HOOKCALL, -1); | 276 | luaD_callhook(L, LUA_HOOKCALL, -1); |
| @@ -284,7 +304,7 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | |||
| 284 | StkId res; | 304 | StkId res; |
| 285 | if (L->hookmask & LUA_MASKRET) | 305 | if (L->hookmask & LUA_MASKRET) |
| 286 | firstResult = callrethooks(L, firstResult); | 306 | firstResult = callrethooks(L, firstResult); |
| 287 | res = L->base - 1; /* res == final position of 1st result */ | 307 | res = L->ci->func; /* res == final position of 1st result */ |
| 288 | L->ci--; | 308 | L->ci--; |
| 289 | L->base = L->ci->base; /* restore base */ | 309 | L->base = L->ci->base; /* restore base */ |
| 290 | /* move results to correct place */ | 310 | /* move results to correct place */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.3 2004/02/20 16:01:05 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.4 2004/03/15 21:04:33 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -249,6 +249,10 @@ typedef struct Proto { | |||
| 249 | } Proto; | 249 | } Proto; |
| 250 | 250 | ||
| 251 | 251 | ||
| 252 | /* mask for new-style vararg */ | ||
| 253 | #define NEWSTYLEVARARG 2 | ||
| 254 | |||
| 255 | |||
| 252 | typedef struct LocVar { | 256 | typedef struct LocVar { |
| 253 | TString *varname; | 257 | TString *varname; |
| 254 | int startpc; /* first point where variable is active */ | 258 | int startpc; /* first point where variable is active */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.c,v 1.25 2003/05/14 21:09:53 roberto Exp roberto $ | 2 | ** $Id: lopcodes.c,v 1.26 2004/04/30 20:13:38 roberto Exp roberto $ |
| 3 | ** See Copyright Notice in lua.h | 3 | ** See Copyright Notice in lua.h |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| @@ -53,7 +53,8 @@ const char *const luaP_opnames[NUM_OPCODES] = { | |||
| 53 | "SETLIST", | 53 | "SETLIST", |
| 54 | "SETLISTO", | 54 | "SETLISTO", |
| 55 | "CLOSE", | 55 | "CLOSE", |
| 56 | "CLOSURE" | 56 | "CLOSURE", |
| 57 | "VARARG" | ||
| 57 | }; | 58 | }; |
| 58 | 59 | ||
| 59 | #endif | 60 | #endif |
| @@ -98,5 +99,6 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { | |||
| 98 | ,opmode(0, 0, OpArgU, OpArgN, iABx) /* OP_SETLISTO */ | 99 | ,opmode(0, 0, OpArgU, OpArgN, iABx) /* OP_SETLISTO */ |
| 99 | ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ | 100 | ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ |
| 100 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ | 101 | ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ |
| 102 | ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ | ||
| 101 | }; | 103 | }; |
| 102 | 104 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lopcodes.h,v 1.107 2004/04/30 20:13:38 roberto Exp roberto $ | 2 | ** $Id: lopcodes.h,v 1.108 2004/05/17 12:34:00 roberto Exp roberto $ |
| 3 | ** Opcodes for Lua virtual machine | 3 | ** Opcodes for Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -79,7 +79,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ | |||
| 79 | #define GET_OPCODE(i) (cast(OpCode, (i)&MASK1(SIZE_OP,0))) | 79 | #define GET_OPCODE(i) (cast(OpCode, (i)&MASK1(SIZE_OP,0))) |
| 80 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | cast(Instruction, o))) | 80 | #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,0)) | cast(Instruction, o))) |
| 81 | 81 | ||
| 82 | #define GETARG_A(i) (cast(int, (i)>>POS_A) & MASK1(SIZE_A,0)) | 82 | #define GETARG_A(i) (cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0))) |
| 83 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ | 83 | #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ |
| 84 | ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A)))) | 84 | ((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A)))) |
| 85 | 85 | ||
| @@ -183,25 +183,30 @@ OP_SETLIST,/* A Bx R(A)[Bx-Bx%FPF+i] := R(A+i), 1 <= i <= Bx%FPF+1 */ | |||
| 183 | OP_SETLISTO,/* A Bx */ | 183 | OP_SETLISTO,/* A Bx */ |
| 184 | 184 | ||
| 185 | OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ | 185 | OP_CLOSE,/* A close all variables in the stack up to (>=) R(A)*/ |
| 186 | OP_CLOSURE/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ | 186 | OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ |
| 187 | |||
| 188 | OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ | ||
| 187 | } OpCode; | 189 | } OpCode; |
| 188 | 190 | ||
| 189 | 191 | ||
| 190 | #define NUM_OPCODES (cast(int, OP_CLOSURE+1)) | 192 | #define NUM_OPCODES (cast(int, OP_VARARG+1)) |
| 191 | 193 | ||
| 192 | 194 | ||
| 193 | 195 | ||
| 194 | /*=========================================================================== | 196 | /*=========================================================================== |
| 195 | Notes: | 197 | Notes: |
| 196 | (1) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, | 198 | (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, |
| 197 | and can be 0: OP_CALL then sets `top' to last_result+1, so | 199 | and can be 0: OP_CALL then sets `top' to last_result+1, so |
| 198 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. | 200 | next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. |
| 199 | 201 | ||
| 200 | (2) In OP_RETURN, if (B == 0) then return up to `top' | 202 | (*) In OP_VARARG, if (B == 0) then use actual number of varargs and |
| 203 | set top (like in OP_CALL). | ||
| 204 | |||
| 205 | (*) In OP_RETURN, if (B == 0) then return up to `top' | ||
| 201 | 206 | ||
| 202 | (3) For comparisons, B specifies what conditions the test should accept. | 207 | (*) For comparisons, B specifies what conditions the test should accept. |
| 203 | 208 | ||
| 204 | (4) All `skips' (pc++) assume that next instruction is a jump | 209 | (*) All `skips' (pc++) assume that next instruction is a jump |
| 205 | ===========================================================================*/ | 210 | ===========================================================================*/ |
| 206 | 211 | ||
| 207 | 212 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 2.3 2004/03/26 14:02:41 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.4 2004/04/30 20:13:38 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 | */ |
| @@ -27,6 +27,8 @@ | |||
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) | ||
| 31 | |||
| 30 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) | 32 | #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) |
| 31 | 33 | ||
| 32 | #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m) | 34 | #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) luaY_errorlimit(fs,l,m) |
| @@ -272,11 +274,11 @@ static TString *singlevar (LexState *ls, expdesc *var, int base) { | |||
| 272 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | 274 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
| 273 | FuncState *fs = ls->fs; | 275 | FuncState *fs = ls->fs; |
| 274 | int extra = nvars - nexps; | 276 | int extra = nvars - nexps; |
| 275 | if (e->k == VCALL) { | 277 | if (hasmultret(e->k)) { |
| 276 | extra++; /* includes call itself */ | 278 | extra++; /* includes call itself */ |
| 277 | if (extra <= 0) extra = 0; | 279 | if (extra < 0) extra = 0; |
| 278 | else luaK_reserveregs(fs, extra-1); | 280 | luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ |
| 279 | luaK_setcallreturns(fs, e, extra); /* call provides the difference */ | 281 | if (extra > 1) luaK_reserveregs(fs, extra-1); |
| 280 | } | 282 | } |
| 281 | else { | 283 | else { |
| 282 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ | 284 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ |
| @@ -392,6 +394,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { | |||
| 392 | lexstate.nestlevel = 0; | 394 | lexstate.nestlevel = 0; |
| 393 | luaX_setinput(L, &lexstate, z, luaS_new(L, name)); | 395 | luaX_setinput(L, &lexstate, z, luaS_new(L, name)); |
| 394 | open_func(&lexstate, &funcstate); | 396 | open_func(&lexstate, &funcstate); |
| 397 | funcstate.f->is_vararg = NEWSTYLEVARARG; | ||
| 395 | next(&lexstate); /* read first token */ | 398 | next(&lexstate); /* read first token */ |
| 396 | chunk(&lexstate); | 399 | chunk(&lexstate); |
| 397 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); | 400 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); |
| @@ -481,8 +484,8 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) { | |||
| 481 | 484 | ||
| 482 | static void lastlistfield (FuncState *fs, struct ConsControl *cc) { | 485 | static void lastlistfield (FuncState *fs, struct ConsControl *cc) { |
| 483 | if (cc->tostore == 0) return; | 486 | if (cc->tostore == 0) return; |
| 484 | if (cc->v.k == VCALL) { | 487 | if (hasmultret(cc->v.k)) { |
| 485 | luaK_setcallreturns(fs, &cc->v, LUA_MULTRET); | 488 | luaK_setmultret(fs, &cc->v); |
| 486 | luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1); | 489 | luaK_codeABx(fs, OP_SETLISTO, cc->t->info, cc->na-1); |
| 487 | cc->na--; /* do not count last expression (unknown number of elements) */ | 490 | cc->na--; /* do not count last expression (unknown number of elements) */ |
| 488 | } | 491 | } |
| @@ -558,12 +561,8 @@ static void parlist (LexState *ls) { | |||
| 558 | if (ls->t.token != ')') { /* is `parlist' not empty? */ | 561 | if (ls->t.token != ')') { /* is `parlist' not empty? */ |
| 559 | do { | 562 | do { |
| 560 | switch (ls->t.token) { | 563 | switch (ls->t.token) { |
| 561 | case TK_NAME: { /* param -> NAME [ `=' `...' ] */ | 564 | case TK_NAME: { /* param -> NAME */ |
| 562 | new_localvar(ls, str_checkname(ls), nparams++); | 565 | new_localvar(ls, str_checkname(ls), nparams++); |
| 563 | if (testnext(ls, '=')) { | ||
| 564 | check(ls, TK_DOTS); | ||
| 565 | f->is_vararg = 1; | ||
| 566 | } | ||
| 567 | break; | 566 | break; |
| 568 | } | 567 | } |
| 569 | case TK_DOTS: { /* param -> `...' */ | 568 | case TK_DOTS: { /* param -> `...' */ |
| @@ -629,7 +628,7 @@ static void funcargs (LexState *ls, expdesc *f) { | |||
| 629 | args.k = VVOID; | 628 | args.k = VVOID; |
| 630 | else { | 629 | else { |
| 631 | explist1(ls, &args); | 630 | explist1(ls, &args); |
| 632 | luaK_setcallreturns(fs, &args, LUA_MULTRET); | 631 | luaK_setmultret(fs, &args); |
| 633 | } | 632 | } |
| 634 | check_match(ls, ')', '(', line); | 633 | check_match(ls, ')', '(', line); |
| 635 | break; | 634 | break; |
| @@ -650,7 +649,7 @@ static void funcargs (LexState *ls, expdesc *f) { | |||
| 650 | } | 649 | } |
| 651 | lua_assert(f->k == VNONRELOC); | 650 | lua_assert(f->k == VNONRELOC); |
| 652 | base = f->info; /* base register for call */ | 651 | base = f->info; /* base register for call */ |
| 653 | if (args.k == VCALL) | 652 | if (hasmultret(args.k)) |
| 654 | nparams = LUA_MULTRET; /* open call */ | 653 | nparams = LUA_MULTRET; /* open call */ |
| 655 | else { | 654 | else { |
| 656 | if (args.k != VVOID) | 655 | if (args.k != VVOID) |
| @@ -739,43 +738,47 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
| 739 | switch (ls->t.token) { | 738 | switch (ls->t.token) { |
| 740 | case TK_NUMBER: { | 739 | case TK_NUMBER: { |
| 741 | init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r)); | 740 | init_exp(v, VK, luaK_numberK(ls->fs, ls->t.seminfo.r)); |
| 742 | next(ls); /* must use `seminfo' before `next' */ | ||
| 743 | break; | 741 | break; |
| 744 | } | 742 | } |
| 745 | case TK_STRING: { | 743 | case TK_STRING: { |
| 746 | codestring(ls, v, ls->t.seminfo.ts); | 744 | codestring(ls, v, ls->t.seminfo.ts); |
| 747 | next(ls); /* must use `seminfo' before `next' */ | ||
| 748 | break; | 745 | break; |
| 749 | } | 746 | } |
| 750 | case TK_NIL: { | 747 | case TK_NIL: { |
| 751 | init_exp(v, VNIL, 0); | 748 | init_exp(v, VNIL, 0); |
| 752 | next(ls); | ||
| 753 | break; | 749 | break; |
| 754 | } | 750 | } |
| 755 | case TK_TRUE: { | 751 | case TK_TRUE: { |
| 756 | init_exp(v, VTRUE, 0); | 752 | init_exp(v, VTRUE, 0); |
| 757 | next(ls); | ||
| 758 | break; | 753 | break; |
| 759 | } | 754 | } |
| 760 | case TK_FALSE: { | 755 | case TK_FALSE: { |
| 761 | init_exp(v, VFALSE, 0); | 756 | init_exp(v, VFALSE, 0); |
| 762 | next(ls); | 757 | break; |
| 758 | } | ||
| 759 | case TK_DOTS: { /* vararg */ | ||
| 760 | FuncState *fs = ls->fs; | ||
| 761 | check_condition(ls, fs->f->is_vararg, | ||
| 762 | "cannot use `...' outside a vararg function"); | ||
| 763 | fs->f->is_vararg = NEWSTYLEVARARG; | ||
| 764 | init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); | ||
| 763 | break; | 765 | break; |
| 764 | } | 766 | } |
| 765 | case '{': { /* constructor */ | 767 | case '{': { /* constructor */ |
| 766 | constructor(ls, v); | 768 | constructor(ls, v); |
| 767 | break; | 769 | return; |
| 768 | } | 770 | } |
| 769 | case TK_FUNCTION: { | 771 | case TK_FUNCTION: { |
| 770 | next(ls); | 772 | next(ls); |
| 771 | body(ls, v, 0, ls->linenumber); | 773 | body(ls, v, 0, ls->linenumber); |
| 772 | break; | 774 | return; |
| 773 | } | 775 | } |
| 774 | default: { | 776 | default: { |
| 775 | primaryexp(ls, v); | 777 | primaryexp(ls, v); |
| 776 | break; | 778 | return; |
| 777 | } | 779 | } |
| 778 | } | 780 | } |
| 781 | next(ls); | ||
| 779 | } | 782 | } |
| 780 | 783 | ||
| 781 | 784 | ||
| @@ -952,7 +955,7 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | |||
| 952 | ls->fs->freereg -= nexps - nvars; /* remove extra values */ | 955 | ls->fs->freereg -= nexps - nvars; /* remove extra values */ |
| 953 | } | 956 | } |
| 954 | else { | 957 | else { |
| 955 | luaK_setcallreturns(ls->fs, &e, 1); /* close last expression */ | 958 | luaK_setoneret(ls->fs, &e); /* close last expression */ |
| 956 | luaK_storevar(ls->fs, &lh->v, &e); | 959 | luaK_storevar(ls->fs, &lh->v, &e); |
| 957 | return; /* avoid default */ | 960 | return; /* avoid default */ |
| 958 | } | 961 | } |
| @@ -1236,9 +1239,8 @@ static void exprstat (LexState *ls) { | |||
| 1236 | FuncState *fs = ls->fs; | 1239 | FuncState *fs = ls->fs; |
| 1237 | struct LHS_assign v; | 1240 | struct LHS_assign v; |
| 1238 | primaryexp(ls, &v.v); | 1241 | primaryexp(ls, &v.v); |
| 1239 | if (v.v.k == VCALL) { /* stat -> func */ | 1242 | if (v.v.k == VCALL) /* stat -> func */ |
| 1240 | luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */ | 1243 | SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ |
| 1241 | } | ||
| 1242 | else { /* stat -> assignment */ | 1244 | else { /* stat -> assignment */ |
| 1243 | v.prev = NULL; | 1245 | v.prev = NULL; |
| 1244 | assignment(ls, &v, 1); | 1246 | assignment(ls, &v, 1); |
| @@ -1256,9 +1258,9 @@ static void retstat (LexState *ls) { | |||
| 1256 | first = nret = 0; /* return no values */ | 1258 | first = nret = 0; /* return no values */ |
| 1257 | else { | 1259 | else { |
| 1258 | nret = explist1(ls, &e); /* optional return values */ | 1260 | nret = explist1(ls, &e); /* optional return values */ |
| 1259 | if (e.k == VCALL) { | 1261 | if (hasmultret(e.k)) { |
| 1260 | luaK_setcallreturns(fs, &e, LUA_MULTRET); | 1262 | luaK_setmultret(fs, &e); |
| 1261 | if (nret == 1) { /* tail call? */ | 1263 | if (e.k == VCALL && nret == 1) { /* tail call? */ |
| 1262 | SET_OPCODE(getcode(fs,&e), OP_TAILCALL); | 1264 | SET_OPCODE(getcode(fs,&e), OP_TAILCALL); |
| 1263 | lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); | 1265 | lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); |
| 1264 | } | 1266 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.h,v 1.49 2003/07/09 20:11:30 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.50 2003/08/25 19:51:54 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 | */ |
| @@ -30,7 +30,8 @@ typedef enum { | |||
| 30 | VJMP, /* info = instruction pc */ | 30 | VJMP, /* info = instruction pc */ |
| 31 | VRELOCABLE, /* info = instruction pc */ | 31 | VRELOCABLE, /* info = instruction pc */ |
| 32 | VNONRELOC, /* info = result register */ | 32 | VNONRELOC, /* info = result register */ |
| 33 | VCALL /* info = result register */ | 33 | VCALL, /* info = instruction pc */ |
| 34 | VVARARG /* info = instruction pc */ | ||
| 34 | } expkind; | 35 | } expkind; |
| 35 | 36 | ||
| 36 | typedef struct expdesc { | 37 | typedef struct expdesc { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 2.5 2004/03/23 12:57:12 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.6 2004/04/30 20:13:38 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -57,6 +57,7 @@ static void stack_init (lua_State *L1, lua_State *L) { | |||
| 57 | L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; | 57 | L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; |
| 58 | L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); | 58 | L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); |
| 59 | L1->ci = L1->base_ci; | 59 | L1->ci = L1->base_ci; |
| 60 | L1->ci->func = L1->top; | ||
| 60 | setnilvalue(L1->top++); /* `function' entry for this `ci' */ | 61 | setnilvalue(L1->top++); /* `function' entry for this `ci' */ |
| 61 | L1->base = L1->ci->base = L1->top; | 62 | L1->base = L1->ci->base = L1->top; |
| 62 | L1->ci->top = L1->top + LUA_MINSTACK; | 63 | L1->ci->top = L1->top + LUA_MINSTACK; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.2 2004/03/23 17:02:58 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.3 2004/05/14 19:25:09 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -71,6 +71,7 @@ typedef struct stringtable { | |||
| 71 | */ | 71 | */ |
| 72 | typedef struct CallInfo { | 72 | typedef struct CallInfo { |
| 73 | StkId base; /* base for this function */ | 73 | StkId base; /* base for this function */ |
| 74 | StkId func; /* function index in the stack */ | ||
| 74 | StkId top; /* top for this function */ | 75 | StkId top; /* top for this function */ |
| 75 | int nresults; /* expected number of results from this function */ | 76 | int nresults; /* expected number of results from this function */ |
| 76 | union { | 77 | union { |
| @@ -86,10 +87,10 @@ typedef struct CallInfo { | |||
| 86 | 87 | ||
| 87 | 88 | ||
| 88 | 89 | ||
| 89 | #define curr_func(L) (clvalue(L->base - 1)) | 90 | #define curr_func(L) (clvalue(L->ci->func)) |
| 90 | #define ci_func(ci) (clvalue((ci)->base - 1)) | 91 | #define ci_func(ci) (clvalue((ci)->func)) |
| 91 | #define f_isLua(ci) (!ci_func(ci)->c.isC) | 92 | #define f_isLua(ci) (!ci_func(ci)->c.isC) |
| 92 | #define isLua(ci) (ttisfunction((ci)->base - 1) && f_isLua(ci)) | 93 | #define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) |
| 93 | 94 | ||
| 94 | 95 | ||
| 95 | /* | 96 | /* |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lua.c,v 1.124 2003/10/23 18:06:22 roberto Exp roberto $ | 2 | ** $Id: lua.c,v 1.125 2004/04/30 20:13:38 roberto Exp roberto $ |
| 3 | ** Lua stand-alone interpreter | 3 | ** Lua stand-alone interpreter |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -113,30 +113,32 @@ static void print_version (void) { | |||
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | static void getargs (char *argv[], int n) { | 116 | static int getargs (char *argv[], int n) { |
| 117 | int i; | 117 | int i, narg; |
| 118 | for (i=n+1; argv[i]; i++) { | ||
| 119 | luaL_checkstack(L, 1, "too many arguments to script"); | ||
| 120 | lua_pushstring(L, argv[i]); | ||
| 121 | } | ||
| 122 | narg = i-(n+1); /* number of arguments to the script (not to `lua.c') */ | ||
| 118 | lua_newtable(L); | 123 | lua_newtable(L); |
| 119 | for (i=0; argv[i]; i++) { | 124 | for (i=0; argv[i]; i++) { |
| 120 | lua_pushnumber(L, i - n); | 125 | lua_pushnumber(L, i - n); |
| 121 | lua_pushstring(L, argv[i]); | 126 | lua_pushstring(L, argv[i]); |
| 122 | lua_rawset(L, -3); | 127 | lua_rawset(L, -3); |
| 123 | } | 128 | } |
| 124 | } | 129 | return narg; |
| 125 | |||
| 126 | |||
| 127 | static int docall (int status) { | ||
| 128 | if (status == 0) status = lcall(0, 1); | ||
| 129 | return report(status); | ||
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | 132 | ||
| 133 | static int file_input (const char *name) { | 133 | static int file_input (const char *name) { |
| 134 | return docall(luaL_loadfile(L, name)); | 134 | int status = luaL_loadfile(L, name) || lcall(0, 1); |
| 135 | return report(status); | ||
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | 138 | ||
| 138 | static int dostring (const char *s, const char *name) { | 139 | static int dostring (const char *s, const char *name) { |
| 139 | return docall(luaL_loadbuffer(L, s, strlen(s), name)); | 140 | int status = luaL_loadbuffer(L, s, strlen(s), name) || lcall(0, 1); |
| 141 | return report(status); | ||
| 140 | } | 142 | } |
| 141 | 143 | ||
| 142 | 144 | ||
| @@ -329,10 +331,17 @@ static int handle_argv (char *argv[], int *interactive) { | |||
| 329 | } endloop: | 331 | } endloop: |
| 330 | if (argv[i] != NULL) { | 332 | if (argv[i] != NULL) { |
| 331 | const char *filename = argv[i]; | 333 | const char *filename = argv[i]; |
| 332 | getargs(argv, i); /* collect arguments */ | 334 | int narg = getargs(argv, i); /* collect arguments */ |
| 333 | clearinteractive(interactive); | 335 | int status; |
| 334 | lua_setglobal(L, "arg"); | 336 | lua_setglobal(L, "arg"); |
| 335 | return file_input(filename); /* stop scanning arguments */ | 337 | clearinteractive(interactive); |
| 338 | status = luaL_loadfile(L, filename); | ||
| 339 | lua_insert(L, -(narg+1)); | ||
| 340 | if (status == 0) | ||
| 341 | status = lcall(narg, 0); | ||
| 342 | else | ||
| 343 | lua_pop(L, narg); | ||
| 344 | return report(status); | ||
| 336 | } | 345 | } |
| 337 | } | 346 | } |
| 338 | return 0; | 347 | return 0; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.5 2004/05/10 17:50:51 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.6 2004/05/14 19:25:09 roberto Exp $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -387,8 +387,8 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 387 | luaD_callhook(L, LUA_HOOKCALL, -1); | 387 | luaD_callhook(L, LUA_HOOKCALL, -1); |
| 388 | retentry: /* entry point when returning to old functions */ | 388 | retentry: /* entry point when returning to old functions */ |
| 389 | pc = L->ci->u.l.savedpc; | 389 | pc = L->ci->u.l.savedpc; |
| 390 | cl = &clvalue(L->ci->func)->l; | ||
| 390 | base = L->base; | 391 | base = L->base; |
| 391 | cl = &clvalue(base - 1)->l; | ||
| 392 | k = cl->p->k; | 392 | k = cl->p->k; |
| 393 | /* main loop of interpreter */ | 393 | /* main loop of interpreter */ |
| 394 | for (;;) { | 394 | for (;;) { |
| @@ -615,17 +615,19 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 615 | pcr = luaD_precall(L, ra, LUA_MULTRET); | 615 | pcr = luaD_precall(L, ra, LUA_MULTRET); |
| 616 | if (pcr == PCRLUA) { | 616 | if (pcr == PCRLUA) { |
| 617 | /* tail call: put new frame in place of previous one */ | 617 | /* tail call: put new frame in place of previous one */ |
| 618 | CallInfo *ci = L->ci - 1; /* previous frame */ | ||
| 618 | int aux; | 619 | int aux; |
| 619 | base = (L->ci - 1)->base; /* `luaD_precall' may change the stack */ | 620 | StkId func = ci->func; |
| 620 | ra = RA(i); | 621 | StkId pfunc = (ci+1)->func; /* previous function index */ |
| 622 | base = ci->base = ci->func + ((ci+1)->base - pfunc); | ||
| 623 | L->base = base; | ||
| 621 | if (L->openupval) luaF_close(L, base); | 624 | if (L->openupval) luaF_close(L, base); |
| 622 | for (aux = 0; ra+aux < L->top; aux++) /* move frame down */ | 625 | for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ |
| 623 | setobjs2s(L, base+aux-1, ra+aux); | 626 | setobjs2s(L, func+aux, pfunc+aux); |
| 624 | (L->ci - 1)->top = L->top = base+aux; /* correct top */ | 627 | ci->top = L->top = base+aux; /* correct top */ |
| 625 | (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; | 628 | ci->u.l.savedpc = L->ci->u.l.savedpc; |
| 626 | (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ | 629 | ci->u.l.tailcalls++; /* one more call lost */ |
| 627 | L->ci--; /* remove new frame */ | 630 | L->ci--; /* remove new frame */ |
| 628 | L->base = L->ci->base; | ||
| 629 | goto callentry; | 631 | goto callentry; |
| 630 | } | 632 | } |
| 631 | else if (pcr == PCRC) { | 633 | else if (pcr == PCRC) { |
| @@ -758,6 +760,21 @@ StkId luaV_execute (lua_State *L, int nexeccalls) { | |||
| 758 | base = L->base; | 760 | base = L->base; |
| 759 | break; | 761 | break; |
| 760 | } | 762 | } |
| 763 | case OP_VARARG: { | ||
| 764 | int b = GETARG_B(i) - 1; | ||
| 765 | int j; | ||
| 766 | CallInfo *ci = L->ci; | ||
| 767 | int n = ci->base - ci->func - cl->p->numparams - 1; | ||
| 768 | if (b == LUA_MULTRET) { | ||
| 769 | b = n; | ||
| 770 | L->top = ra + n; | ||
| 771 | } | ||
| 772 | for (j=0; j<b && j<n; j++) | ||
| 773 | setobjs2s(L, ra+j, ci->base - n + j); | ||
| 774 | for (; j<b; j++) | ||
| 775 | setnilvalue(ra+j); | ||
| 776 | break; | ||
| 777 | } | ||
| 761 | } | 778 | } |
| 762 | } | 779 | } |
| 763 | } | 780 | } |
