mirror of https://github.com/rusefi/lua.git
new API for 'lua_resume' + cleaning the uses of the 'extra' field in
'CallInfo'
This commit is contained in:
parent
b9e76be8a6
commit
ba36180fd7
7
lapi.c
7
lapi.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lapi.c,v 2.271 2017/10/11 12:38:45 roberto Exp roberto $
|
** $Id: lapi.c,v 2.272 2017/11/01 18:20:48 roberto Exp roberto $
|
||||||
** Lua API
|
** Lua API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -58,10 +58,9 @@ const char lua_ident[] =
|
||||||
|
|
||||||
|
|
||||||
static TValue *index2value (lua_State *L, int idx) {
|
static TValue *index2value (lua_State *L, int idx) {
|
||||||
CallInfo *ci = L->ci;
|
|
||||||
if (idx > 0) {
|
if (idx > 0) {
|
||||||
StkId o = L->func + idx;
|
StkId o = L->func + idx;
|
||||||
api_check(L, idx <= ci->top - (L->func + 1), "unacceptable index");
|
api_check(L, idx <= L->ci->top - (L->func + 1), "unacceptable index");
|
||||||
if (o >= L->top) return NONVALIDVALUE;
|
if (o >= L->top) return NONVALIDVALUE;
|
||||||
else return s2v(o);
|
else return s2v(o);
|
||||||
}
|
}
|
||||||
|
@ -1000,7 +999,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
|
||||||
ci->u.c.k = k; /* save continuation */
|
ci->u.c.k = k; /* save continuation */
|
||||||
ci->u.c.ctx = ctx; /* save context */
|
ci->u.c.ctx = ctx; /* save context */
|
||||||
/* save information for error recovery */
|
/* save information for error recovery */
|
||||||
ci->extra = savestack(L, c.func);
|
ci->u2.funcidx = savestack(L, c.func);
|
||||||
ci->u.c.old_errfunc = L->errfunc;
|
ci->u.c.old_errfunc = L->errfunc;
|
||||||
L->errfunc = func;
|
L->errfunc = func;
|
||||||
setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */
|
setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lcorolib.c,v 1.9 2014/11/02 19:19:04 roberto Exp roberto $
|
** $Id: lcorolib.c,v 1.10 2016/04/11 19:19:55 roberto Exp roberto $
|
||||||
** Coroutine Library
|
** Coroutine Library
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -26,7 +26,7 @@ static lua_State *getco (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
static int auxresume (lua_State *L, lua_State *co, int narg) {
|
static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||||
int status;
|
int status, nres;
|
||||||
if (!lua_checkstack(co, narg)) {
|
if (!lua_checkstack(co, narg)) {
|
||||||
lua_pushliteral(L, "too many arguments to resume");
|
lua_pushliteral(L, "too many arguments to resume");
|
||||||
return -1; /* error flag */
|
return -1; /* error flag */
|
||||||
|
@ -36,9 +36,8 @@ static int auxresume (lua_State *L, lua_State *co, int narg) {
|
||||||
return -1; /* error flag */
|
return -1; /* error flag */
|
||||||
}
|
}
|
||||||
lua_xmove(L, co, narg);
|
lua_xmove(L, co, narg);
|
||||||
status = lua_resume(co, L, narg);
|
status = lua_resume(co, L, narg, &nres);
|
||||||
if (status == LUA_OK || status == LUA_YIELD) {
|
if (status == LUA_OK || status == LUA_YIELD) {
|
||||||
int nres = lua_gettop(co);
|
|
||||||
if (!lua_checkstack(L, nres + 1)) {
|
if (!lua_checkstack(L, nres + 1)) {
|
||||||
lua_pop(co, nres); /* remove results anyway */
|
lua_pop(co, nres); /* remove results anyway */
|
||||||
lua_pushliteral(L, "too many results to resume");
|
lua_pushliteral(L, "too many results to resume");
|
||||||
|
|
25
ldebug.c
25
ldebug.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldebug.c,v 2.133 2017/10/31 17:14:02 roberto Exp roberto $
|
** $Id: ldebug.c,v 2.134 2017/11/01 18:20:48 roberto Exp roberto $
|
||||||
** Debug Interface
|
** Debug Interface
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -106,22 +106,6 @@ static int currentline (CallInfo *ci) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** If function yielded, its 'func' can be in the 'extra' field. The
|
|
||||||
** next function restores 'func' to its correct value for debugging
|
|
||||||
** purposes. (It exchanges 'func' and 'extra'; so, when called again,
|
|
||||||
** after debugging, it also "re-restores" ** 'func' to its altered value.
|
|
||||||
*/
|
|
||||||
static void swapextra (lua_State *L) {
|
|
||||||
if (L->status == LUA_YIELD) {
|
|
||||||
CallInfo *ci = L->ci; /* get function that yielded */
|
|
||||||
StkId temp = ci->func; /* exchange its 'func' and 'extra' values */
|
|
||||||
L->func = ci->func = restorestack(L, ci->extra);
|
|
||||||
ci->extra = savestack(L, temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function can be called asynchronously (e.g. during a signal).
|
** This function can be called asynchronously (e.g. during a signal).
|
||||||
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
|
** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by
|
||||||
|
@ -209,7 +193,6 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n,
|
||||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||||
const char *name;
|
const char *name;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
swapextra(L);
|
|
||||||
if (ar == NULL) { /* information about non-active function? */
|
if (ar == NULL) { /* information about non-active function? */
|
||||||
if (!isLfunction(s2v(L->top - 1))) /* not a Lua function? */
|
if (!isLfunction(s2v(L->top - 1))) /* not a Lua function? */
|
||||||
name = NULL;
|
name = NULL;
|
||||||
|
@ -224,7 +207,6 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
swapextra(L);
|
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -234,13 +216,11 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {
|
||||||
StkId pos = NULL; /* to avoid warnings */
|
StkId pos = NULL; /* to avoid warnings */
|
||||||
const char *name;
|
const char *name;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
swapextra(L);
|
|
||||||
name = findlocal(L, ar->i_ci, n, &pos);
|
name = findlocal(L, ar->i_ci, n, &pos);
|
||||||
if (name) {
|
if (name) {
|
||||||
setobjs2s(L, pos, L->top - 1);
|
setobjs2s(L, pos, L->top - 1);
|
||||||
L->top--; /* pop value */
|
L->top--; /* pop value */
|
||||||
}
|
}
|
||||||
swapextra(L);
|
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -361,7 +341,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
TValue *func;
|
TValue *func;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
swapextra(L);
|
|
||||||
if (*what == '>') {
|
if (*what == '>') {
|
||||||
ci = NULL;
|
ci = NULL;
|
||||||
func = s2v(L->top - 1);
|
func = s2v(L->top - 1);
|
||||||
|
@ -380,7 +359,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
|
||||||
setobj2s(L, L->top, func);
|
setobj2s(L, L->top, func);
|
||||||
api_incr_top(L);
|
api_incr_top(L);
|
||||||
}
|
}
|
||||||
swapextra(L); /* correct before option 'L', which can raise a mem. error */
|
|
||||||
if (strchr(what, 'L'))
|
if (strchr(what, 'L'))
|
||||||
collectvalidlines(L, cl);
|
collectvalidlines(L, cl);
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
|
@ -790,7 +768,6 @@ void luaG_traceexec (lua_State *L) {
|
||||||
L->hookcount = 1; /* undo decrement to zero */
|
L->hookcount = 1; /* undo decrement to zero */
|
||||||
ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
|
ci->u.l.savedpc--; /* undo increment (resume will increment it again) */
|
||||||
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
|
ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */
|
||||||
L->func = ci->func = L->top - 1; /* protect stack below results */
|
|
||||||
luaD_throw(L, LUA_YIELD);
|
luaD_throw(L, LUA_YIELD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
ldo.c
14
ldo.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 2.163 2017/10/31 17:54:35 roberto Exp roberto $
|
** $Id: ldo.c,v 2.164 2017/11/01 18:20:48 roberto Exp roberto $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -559,7 +559,7 @@ static int recover (lua_State *L, int status) {
|
||||||
CallInfo *ci = findpcall(L);
|
CallInfo *ci = findpcall(L);
|
||||||
if (ci == NULL) return 0; /* no recovery point */
|
if (ci == NULL) return 0; /* no recovery point */
|
||||||
/* "finish" luaD_pcall */
|
/* "finish" luaD_pcall */
|
||||||
oldtop = restorestack(L, ci->extra);
|
oldtop = restorestack(L, ci->u2.funcidx);
|
||||||
luaF_close(L, oldtop);
|
luaF_close(L, oldtop);
|
||||||
seterrorobj(L, status, oldtop);
|
seterrorobj(L, status, oldtop);
|
||||||
L->ci = ci;
|
L->ci = ci;
|
||||||
|
@ -604,7 +604,6 @@ static void resume (lua_State *L, void *ud) {
|
||||||
else { /* resuming from previous yield */
|
else { /* resuming from previous yield */
|
||||||
lua_assert(L->status == LUA_YIELD);
|
lua_assert(L->status == LUA_YIELD);
|
||||||
L->status = LUA_OK; /* mark that it is running (again) */
|
L->status = LUA_OK; /* mark that it is running (again) */
|
||||||
L->func = ci->func = restorestack(L, ci->extra);
|
|
||||||
if (isLua(ci)) /* yielded inside a hook? */
|
if (isLua(ci)) /* yielded inside a hook? */
|
||||||
luaV_execute(L); /* just continue running Lua code */
|
luaV_execute(L); /* just continue running Lua code */
|
||||||
else { /* 'common' yield */
|
else { /* 'common' yield */
|
||||||
|
@ -622,7 +621,8 @@ static void resume (lua_State *L, void *ud) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
|
LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
|
||||||
|
int *nresults) {
|
||||||
int status;
|
int status;
|
||||||
unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */
|
unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
|
@ -653,6 +653,8 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) {
|
||||||
}
|
}
|
||||||
else lua_assert(status == L->status); /* normal end or yield */
|
else lua_assert(status == L->status); /* normal end or yield */
|
||||||
}
|
}
|
||||||
|
*nresults = (status == LUA_YIELD) ? L->ci->u2.nyield
|
||||||
|
: L->top - (L->func + 1);
|
||||||
L->nny = oldnny; /* restore 'nny' */
|
L->nny = oldnny; /* restore 'nny' */
|
||||||
L->nCcalls--;
|
L->nCcalls--;
|
||||||
lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
|
lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0));
|
||||||
|
@ -679,14 +681,14 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
|
||||||
luaG_runerror(L, "attempt to yield from outside a coroutine");
|
luaG_runerror(L, "attempt to yield from outside a coroutine");
|
||||||
}
|
}
|
||||||
L->status = LUA_YIELD;
|
L->status = LUA_YIELD;
|
||||||
ci->extra = savestack(L, L->func); /* save current 'func' */
|
|
||||||
if (isLua(ci)) { /* inside a hook? */
|
if (isLua(ci)) { /* inside a hook? */
|
||||||
api_check(L, k == NULL, "hooks cannot continue after yielding");
|
api_check(L, k == NULL, "hooks cannot continue after yielding");
|
||||||
|
ci->u2.nyield = 0; /* no results */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
|
if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
|
||||||
ci->u.c.ctx = ctx; /* save context */
|
ci->u.c.ctx = ctx; /* save context */
|
||||||
L->func = ci->func = L->top - nresults - 1; /* protect stack below results */
|
ci->u2.nyield = nresults; /* save number of results */
|
||||||
luaD_throw(L, LUA_YIELD);
|
luaD_throw(L, LUA_YIELD);
|
||||||
}
|
}
|
||||||
lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
|
lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
|
||||||
|
|
13
lstate.h
13
lstate.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lstate.h,v 2.144 2017/07/27 13:50:16 roberto Exp roberto $
|
** $Id: lstate.h,v 2.145 2017/10/31 17:54:35 roberto Exp roberto $
|
||||||
** Global State
|
** Global State
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -83,12 +83,6 @@ typedef struct stringtable {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Information about a call.
|
** Information about a call.
|
||||||
** When a thread yields, 'func' is adjusted to pretend that the
|
|
||||||
** top function has only the yielded values in its stack; in that
|
|
||||||
** case, the actual 'func' value is saved in field 'extra'.
|
|
||||||
** When a function calls another with a continuation, 'extra' keeps
|
|
||||||
** the function index so that, in case of errors, the continuation
|
|
||||||
** function can be called with the correct top.
|
|
||||||
*/
|
*/
|
||||||
typedef struct CallInfo {
|
typedef struct CallInfo {
|
||||||
StkId func; /* function index in the stack */
|
StkId func; /* function index in the stack */
|
||||||
|
@ -104,7 +98,10 @@ typedef struct CallInfo {
|
||||||
lua_KContext ctx; /* context info. in case of yields */
|
lua_KContext ctx; /* context info. in case of yields */
|
||||||
} c;
|
} c;
|
||||||
} u;
|
} u;
|
||||||
ptrdiff_t extra;
|
union {
|
||||||
|
ptrdiff_t funcidx; /* called-function index */
|
||||||
|
int nyield; /* number of values yielded */
|
||||||
|
} u2;
|
||||||
short nresults; /* expected number of results from this function */
|
short nresults; /* expected number of results from this function */
|
||||||
unsigned short callstatus;
|
unsigned short callstatus;
|
||||||
} CallInfo;
|
} CallInfo;
|
||||||
|
|
18
ltests.c
18
ltests.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ltests.c,v 2.225 2017/10/04 21:56:32 roberto Exp roberto $
|
** $Id: ltests.c,v 2.226 2017/11/01 18:20:48 roberto Exp roberto $
|
||||||
** Internal Module for Debugging of the Lua Implementation
|
** Internal Module for Debugging of the Lua Implementation
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -309,13 +309,10 @@ static void checkLclosure (global_State *g, LClosure *cl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int lua_checkpc (lua_State *L, CallInfo *ci) {
|
static int lua_checkpc (CallInfo *ci) {
|
||||||
if (!isLua(ci)) return 1;
|
if (!isLua(ci)) return 1;
|
||||||
else {
|
else {
|
||||||
/* if function yielded (inside a hook), real 'func' is in 'extra' field */
|
StkId f = ci->func;
|
||||||
StkId f = (L->status != LUA_YIELD || ci != L->ci)
|
|
||||||
? ci->func
|
|
||||||
: restorestack(L, ci->extra);
|
|
||||||
Proto *p = clLvalue(s2v(f))->p;
|
Proto *p = clLvalue(s2v(f))->p;
|
||||||
return p->code <= ci->u.l.savedpc &&
|
return p->code <= ci->u.l.savedpc &&
|
||||||
ci->u.l.savedpc <= p->code + p->sizecode;
|
ci->u.l.savedpc <= p->code + p->sizecode;
|
||||||
|
@ -332,7 +329,7 @@ static void checkstack (global_State *g, lua_State *L1) {
|
||||||
lua_assert(upisopen(uv)); /* must be open */
|
lua_assert(upisopen(uv)); /* must be open */
|
||||||
for (ci = L1->ci; ci != NULL; ci = ci->previous) {
|
for (ci = L1->ci; ci != NULL; ci = ci->previous) {
|
||||||
lua_assert(ci->top <= L1->stack_last);
|
lua_assert(ci->top <= L1->stack_last);
|
||||||
lua_assert(lua_checkpc(L1, ci));
|
lua_assert(lua_checkpc(ci));
|
||||||
}
|
}
|
||||||
if (L1->stack) { /* complete thread? */
|
if (L1->stack) { /* complete thread? */
|
||||||
for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++)
|
for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++)
|
||||||
|
@ -1411,7 +1408,8 @@ static int runC (lua_State *L, lua_State *L1, const char *pc) {
|
||||||
}
|
}
|
||||||
else if EQ("resume") {
|
else if EQ("resume") {
|
||||||
int i = getindex;
|
int i = getindex;
|
||||||
status = lua_resume(lua_tothread(L1, i), L, getnum);
|
int nres;
|
||||||
|
status = lua_resume(lua_tothread(L1, i), L, getnum, &nres);
|
||||||
}
|
}
|
||||||
else if EQ("return") {
|
else if EQ("return") {
|
||||||
int n = getnum;
|
int n = getnum;
|
||||||
|
@ -1616,10 +1614,10 @@ static int sethook (lua_State *L) {
|
||||||
|
|
||||||
|
|
||||||
static int coresume (lua_State *L) {
|
static int coresume (lua_State *L) {
|
||||||
int status;
|
int status, nres;
|
||||||
lua_State *co = lua_tothread(L, 1);
|
lua_State *co = lua_tothread(L, 1);
|
||||||
luaL_argcheck(L, co, 1, "coroutine expected");
|
luaL_argcheck(L, co, 1, "coroutine expected");
|
||||||
status = lua_resume(co, L, 0);
|
status = lua_resume(co, L, 0, &nres);
|
||||||
if (status != LUA_OK && status != LUA_YIELD) {
|
if (status != LUA_OK && status != LUA_YIELD) {
|
||||||
lua_pushboolean(L, 0);
|
lua_pushboolean(L, 0);
|
||||||
lua_insert(L, -2);
|
lua_insert(L, -2);
|
||||||
|
|
5
lua.h
5
lua.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lua.h,v 1.335 2017/05/26 19:14:29 roberto Exp roberto $
|
** $Id: lua.h,v 1.336 2017/07/27 13:36:54 roberto Exp roberto $
|
||||||
** Lua - A Scripting Language
|
** Lua - A Scripting Language
|
||||||
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
||||||
** See Copyright Notice at the end of this file
|
** See Copyright Notice at the end of this file
|
||||||
|
@ -288,7 +288,8 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip);
|
||||||
*/
|
*/
|
||||||
LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
|
LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx,
|
||||||
lua_KFunction k);
|
lua_KFunction k);
|
||||||
LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg);
|
LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg,
|
||||||
|
int *nres);
|
||||||
LUA_API int (lua_status) (lua_State *L);
|
LUA_API int (lua_status) (lua_State *L);
|
||||||
LUA_API int (lua_isyieldable) (lua_State *L);
|
LUA_API int (lua_isyieldable) (lua_State *L);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue