|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
** $Id: ldo.c,v 1.186 2002/07/08 18:21:33 roberto Exp roberto $ |
|
|
|
** $Id: ldo.c,v 1.187 2002/07/09 18:19:19 roberto Exp roberto $ |
|
|
|
** Stack and Call structure of Lua |
|
|
|
** See Copyright Notice in lua.h |
|
|
|
*/ |
|
|
@ -60,10 +60,10 @@ static void correctstack (lua_State *L, TObject *oldstack) { |
|
|
|
for (ci = L->base_ci; ci <= L->ci; ci++) { |
|
|
|
ci->base = (ci->base - oldstack) + L->stack; |
|
|
|
ci->top = (ci->top - oldstack) + L->stack; |
|
|
|
if (ci->pc) { /* entry is of an active Lua function? */ |
|
|
|
if (ci->pc != (ci-1)->pc) |
|
|
|
*ci->pb = (*ci->pb - oldstack) + L->stack; |
|
|
|
} |
|
|
|
if (isLua(ci) && /* is a Lua function... */ |
|
|
|
!(isLua(ci-1) && /* and next is not a Lua function... */ |
|
|
|
ci->u.l.pc == (ci-1)->u.l.pc)) /* sharing the same C frame? */ |
|
|
|
*ci->u.l.pb = (*ci->u.l.pb - oldstack) + L->stack; /* correct frame */ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -134,10 +134,6 @@ void luaD_callhook (lua_State *L, lua_Hookevent event, int line) { |
|
|
|
ar.event = event; |
|
|
|
ar.currentline = line; |
|
|
|
ar.i_ci = L->ci - L->base_ci; |
|
|
|
if (event <= LUA_HOOKRET) { /* `call' or `return' event? */ |
|
|
|
L->ci->pc = NULL; /* function is not active */ |
|
|
|
L->ci->top = L->ci->base; /* `top' may not have a valid value yet */ |
|
|
|
} |
|
|
|
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
|
|
|
L->ci->top = L->top + LUA_MINSTACK; |
|
|
|
setallowhook(L, 0); /* cannot call hooks inside a hook */ |
|
|
@ -152,11 +148,11 @@ void luaD_callhook (lua_State *L, lua_Hookevent event, int line) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void adjust_varargs (lua_State *L, int nfixargs) { |
|
|
|
static void adjust_varargs (lua_State *L, int nfixargs, StkId base) { |
|
|
|
int i; |
|
|
|
Table *htab; |
|
|
|
TObject nname; |
|
|
|
int actual = L->top - L->ci->base; /* actual number of arguments */ |
|
|
|
int actual = L->top - base; /* actual number of arguments */ |
|
|
|
if (actual < nfixargs) { |
|
|
|
luaD_checkstack(L, nfixargs - actual); |
|
|
|
for (; actual < nfixargs; ++actual) |
|
|
@ -178,49 +174,52 @@ static void adjust_varargs (lua_State *L, int nfixargs) { |
|
|
|
static StkId tryfuncTM (lua_State *L, StkId func) { |
|
|
|
const TObject *tm = luaT_gettmbyobj(L, func, TM_CALL); |
|
|
|
StkId p; |
|
|
|
if (ttype(tm) != LUA_TFUNCTION) { |
|
|
|
L->ci--; /* undo increment (no function here) */ |
|
|
|
ptrdiff_t funcr = savestack(L, func); |
|
|
|
if (ttype(tm) != LUA_TFUNCTION) |
|
|
|
luaG_typeerror(L, func, "call"); |
|
|
|
} |
|
|
|
/* Open a hole inside the stack at `func' */ |
|
|
|
for (p = L->top; p > func; p--) setobj(p, p-1); |
|
|
|
incr_top(L); |
|
|
|
func = L->ci->base - 1; /* previous call may change stack */ |
|
|
|
func = restorestack(L, funcr); /* previous call may change stack */ |
|
|
|
setobj(func, tm); /* tag method is the new function to be called */ |
|
|
|
return func; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
StkId luaD_precall (lua_State *L, StkId func) { |
|
|
|
CallInfo *ci; |
|
|
|
LClosure *cl; |
|
|
|
if (++L->ci == L->end_ci) luaD_growCI(L); |
|
|
|
ci = L->ci; |
|
|
|
ci->base = func+1; |
|
|
|
ci->pc = NULL; |
|
|
|
ptrdiff_t funcr = savestack(L, func); |
|
|
|
if (ttype(func) != LUA_TFUNCTION) /* `func' is not a function? */ |
|
|
|
func = tryfuncTM(L, func); /* check the `function' tag method */ |
|
|
|
if (L->ci + 1 == L->end_ci) luaD_growCI(L); |
|
|
|
cl = &clvalue(func)->l; |
|
|
|
if (L->hookmask & LUA_MASKCALL) { |
|
|
|
luaD_callhook(L, LUA_HOOKCALL, -1); |
|
|
|
ci = L->ci; /* previous call may realocate `ci' */ |
|
|
|
} |
|
|
|
if (!cl->isC) { /* Lua function? prepare its call */ |
|
|
|
CallInfo *ci; |
|
|
|
Proto *p = cl->p; |
|
|
|
ci->savedpc = p->code; /* starting point */ |
|
|
|
if (p->is_vararg) /* varargs? */ |
|
|
|
adjust_varargs(L, p->numparams); |
|
|
|
adjust_varargs(L, p->numparams, func+1); |
|
|
|
luaD_checkstack(L, p->maxstacksize); |
|
|
|
ci = ++L->ci; /* now `enter' new function */ |
|
|
|
ci->base = restorestack(L, funcr) + 1; |
|
|
|
ci->top = ci->base + p->maxstacksize; |
|
|
|
ci->savedpc = p->code; /* starting point */ |
|
|
|
while (L->top < ci->top) |
|
|
|
setnilvalue(L->top++); |
|
|
|
L->top = ci->top; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
else { /* if is a C function, call it */ |
|
|
|
CallInfo *ci; |
|
|
|
int n; |
|
|
|
luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
|
|
|
ci = ++L->ci; /* now `enter' new function */ |
|
|
|
ci->base = restorestack(L, funcr) + 1; |
|
|
|
ci->top = L->top + LUA_MINSTACK; |
|
|
|
ci->savedpc = NULL; /* not a Lua function */ |
|
|
|
if (L->hookmask & LUA_MASKCALL) { |
|
|
|
luaD_callhook(L, LUA_HOOKCALL, -1); |
|
|
|
ci = L->ci; /* previous call may realocate `ci' */ |
|
|
|
} |
|
|
|
lua_unlock(L); |
|
|
|
#if LUA_COMPATUPVALUES |
|
|
|
lua_pushupvalues(L); |
|
|
@ -296,9 +295,10 @@ struct ResS { |
|
|
|
static void resume (lua_State *L, void *ud) { |
|
|
|
StkId firstResult; |
|
|
|
CallInfo *ci = L->ci; |
|
|
|
if (ci->savedpc != ci_func(ci)->l.p->code) { /* not first time? */ |
|
|
|
/* finish interupted execution of `OP_CALL' */ |
|
|
|
if (!isLua(ci)) { /* not first time? */ |
|
|
|
/* finish interrupted execution of `OP_CALL' */ |
|
|
|
int nresults; |
|
|
|
lua_assert(isLua(ci - 1)); |
|
|
|
lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL); |
|
|
|
nresults = GETARG_C(*((ci-1)->savedpc - 1)) - 1; |
|
|
|
luaD_poscall(L, nresults, L->top); /* complete it */ |
|
|
@ -306,7 +306,7 @@ static void resume (lua_State *L, void *ud) { |
|
|
|
} |
|
|
|
firstResult = luaV_execute(L); |
|
|
|
if (firstResult == NULL) /* yield? */ |
|
|
|
cast(struct ResS *, ud)->numres = L->ci->yield_results; |
|
|
|
cast(struct ResS *, ud)->numres = L->ci->u.c.yield_results; |
|
|
|
else { /* return */ |
|
|
|
cast(struct ResS *, ud)->numres = L->top - firstResult; |
|
|
|
luaD_poscall(L, LUA_MULTRET, firstResult); /* finalize this coroutine */ |
|
|
@ -338,9 +338,10 @@ LUA_API int lua_yield (lua_State *L, int nresults) { |
|
|
|
CallInfo *ci; |
|
|
|
lua_lock(L); |
|
|
|
ci = L->ci; |
|
|
|
if (ci_func(ci-1)->c.isC) |
|
|
|
if (!isLua(ci-1)) |
|
|
|
luaG_runerror(L, "cannot yield a C function"); |
|
|
|
ci->yield_results = nresults; |
|
|
|
lua_assert(!isLua(ci)); |
|
|
|
ci->u.c.yield_results = nresults; |
|
|
|
lua_unlock(L); |
|
|
|
return -1; |
|
|
|
} |
|
|
|