diff options
-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 | } |