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 /ldo.c | |
parent | 47eda6ebd83785908ac26f8dd06dff36a7d42664 (diff) | |
download | lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.tar.gz lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.tar.bz2 lua-616438fe9ab5e3ae7d73e9ad838e9b7bdea1ea59.zip |
new way to use `vararg' parameters (with `...')
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 66 |
1 files changed, 43 insertions, 23 deletions
@@ -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 */ |