From 825b5d96f8a0d146615f0c6a76feab46da9baa60 Mon Sep 17 00:00:00 2001 From: Li Jin Date: Mon, 22 Nov 2021 10:05:39 +0800 Subject: update macro spec and builtin Lua. --- spec/inputs/macro-todo.yue | 13 +++++ spec/inputs/macro.yue | 15 +----- spec/outputs/macro-todo.lua | 2 + spec/outputs/macro.lua | 2 +- src/3rdParty/lua/lauxlib.h | 2 +- src/3rdParty/lua/lcorolib.c | 4 +- src/3rdParty/lua/ldebug.c | 9 +++- src/3rdParty/lua/ldo.c | 125 +++++++++++++++++++++++++++----------------- src/3rdParty/lua/ldo.h | 2 +- src/3rdParty/lua/lstate.c | 4 +- src/3rdParty/lua/lvm.c | 19 ++----- 11 files changed, 114 insertions(+), 83 deletions(-) create mode 100644 spec/inputs/macro-todo.yue create mode 100644 spec/outputs/macro-todo.lua diff --git a/spec/inputs/macro-todo.yue b/spec/inputs/macro-todo.yue new file mode 100644 index 0000000..8477e5a --- /dev/null +++ b/spec/inputs/macro-todo.yue @@ -0,0 +1,13 @@ +export macro todoInner = (module, line, msg)-> + print "TODO#{msg and ': ' .. msg or ''} in file #{module}, at line #{line}" + { + code: "-- TODO#{msg and ': ' .. msg or ''}" + type: "lua" + } + +export macro todo = (msg)-> + if msg + "$todoInner $MODULE, $LINE, #{msg}" + else + "$todoInner $MODULE, $LINE" + diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue index 366a3d9..2742bd0 100644 --- a/spec/inputs/macro.yue +++ b/spec/inputs/macro.yue @@ -6,6 +6,8 @@ import "macro-export" as { $config:$myconfig, -- rename macro $config to $myconfig } +import "macro-todo" as $ + $asserts item == nil $myconfig false @@ -258,19 +260,6 @@ print $tb[1], $tb.a, ($tb)!, $tb! print "current line: #{ $LINE }" -macro todoInner = (module, line, msg)-> - print "TODO#{msg and ': ' .. msg or ''} in file #{module}, at line #{line}" - { - code: "-- TODO#{msg and ': ' .. msg or ''}" - type: "lua" - } - -macro todo = (msg)-> - if msg - "$todoInner $MODULE, $LINE, #{msg}" - else - "$todoInner $MODULE, $LINE" - $todo macro implicitReturnMacroIsAllowed = -> "print 'abc'\n123" diff --git a/spec/outputs/macro-todo.lua b/spec/outputs/macro-todo.lua new file mode 100644 index 0000000..b5a63f8 --- /dev/null +++ b/spec/outputs/macro-todo.lua @@ -0,0 +1,2 @@ +local _module_0 = { } +return _module_0 diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua index 7812182..9f04216 100644 --- a/spec/outputs/macro.lua +++ b/spec/outputs/macro.lua @@ -258,7 +258,7 @@ print((setmetatable({ return 998 end })) -print("current line: " .. tostring(259)) +print("current line: " .. tostring(261)); -- TODO print('abc') return 123 diff --git a/src/3rdParty/lua/lauxlib.h b/src/3rdParty/lua/lauxlib.h index 6f9695e..5b977e2 100644 --- a/src/3rdParty/lua/lauxlib.h +++ b/src/3rdParty/lua/lauxlib.h @@ -102,7 +102,7 @@ LUALIB_API lua_State *(luaL_newstate) (void); LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); -LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, +LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s, const char *p, const char *r); LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, const char *r); diff --git a/src/3rdParty/lua/lcorolib.c b/src/3rdParty/lua/lcorolib.c index fedbebe..785a1e8 100644 --- a/src/3rdParty/lua/lcorolib.c +++ b/src/3rdParty/lua/lcorolib.c @@ -78,7 +78,7 @@ static int luaB_auxwrap (lua_State *L) { if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ stat = lua_resetthread(co); /* close its tbc variables */ lua_assert(stat != LUA_OK); - lua_xmove(co, L, 1); /* copy error message */ + lua_xmove(co, L, 1); /* move error message to the caller */ } if (stat != LUA_ERRMEM && /* not a memory error and ... */ lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ @@ -179,7 +179,7 @@ static int luaB_close (lua_State *L) { } else { lua_pushboolean(L, 0); - lua_xmove(co, L, 1); /* copy error message */ + lua_xmove(co, L, 1); /* move error message */ return 2; } } diff --git a/src/3rdParty/lua/ldebug.c b/src/3rdParty/lua/ldebug.c index dde4669..30a2882 100644 --- a/src/3rdParty/lua/ldebug.c +++ b/src/3rdParty/lua/ldebug.c @@ -301,7 +301,14 @@ static void collectvalidlines (lua_State *L, Closure *f) { sethvalue2s(L, L->top, t); /* push it on stack */ api_incr_top(L); setbtvalue(&v); /* boolean 'true' to be the value of all indices */ - for (i = 0; i < p->sizelineinfo; i++) { /* for all instructions */ + if (!p->is_vararg) /* regular function? */ + i = 0; /* consider all instructions */ + else { /* vararg function */ + lua_assert(p->code[0] == OP_VARARGPREP); + currentline = nextline(p, currentline, 0); + i = 1; /* skip first instruction (OP_VARARGPREP) */ + } + for (; i < p->sizelineinfo; i++) { /* for each instruction */ currentline = nextline(p, currentline, i); /* get its line */ luaH_setint(L, t, currentline, &v); /* table[line] = true */ } diff --git a/src/3rdParty/lua/ldo.c b/src/3rdParty/lua/ldo.c index 88b20f9..f282a77 100644 --- a/src/3rdParty/lua/ldo.c +++ b/src/3rdParty/lua/ldo.c @@ -388,9 +388,10 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { ** an error if there is no '__call' metafield. */ StkId luaD_tryfuncTM (lua_State *L, StkId func) { - const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); + const TValue *tm; StkId p; checkstackGCp(L, 1, func); /* space for metamethod */ + tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ if (l_unlikely(ttisnil(tm))) luaG_callerror(L, s2v(func)); /* nothing to call */ for (p = L->top; p > func; p--) /* open space for metamethod */ @@ -475,30 +476,6 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) -/* -** Prepare a function for a tail call, building its call info on top -** of the current call info. 'narg1' is the number of arguments plus 1 -** (so that it includes the function itself). -*/ -void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1) { - Proto *p = clLvalue(s2v(func))->p; - int fsize = p->maxstacksize; /* frame size */ - int nfixparams = p->numparams; - int i; - for (i = 0; i < narg1; i++) /* move down function and arguments */ - setobjs2s(L, ci->func + i, func + i); - checkstackGC(L, fsize); - func = ci->func; /* moved-down function */ - for (; narg1 <= nfixparams; narg1++) - setnilvalue(s2v(func + narg1)); /* complete missing arguments */ - ci->top = func + 1 + fsize; /* top for new function */ - lua_assert(ci->top <= L->stack_last); - ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus |= CIST_TAIL; - L->top = func + narg1; /* set top */ -} - - l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, int mask, StkId top) { CallInfo *ci = L->ci = next_ci(L); /* new frame */ @@ -510,6 +487,73 @@ l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, } +/* +** precall for C functions +*/ +l_sinline int precallC (lua_State *L, StkId func, int nresults, + lua_CFunction f) { + int n; /* number of returns */ + CallInfo *ci; + checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, + L->top + LUA_MINSTACK); + lua_assert(ci->top <= L->stack_last); + if (l_unlikely(L->hookmask & LUA_MASKCALL)) { + int narg = cast_int(L->top - func) - 1; + luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); + } + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, n); + return n; +} + + +/* +** Prepare a function for a tail call, building its call info on top +** of the current call info. 'narg1' is the number of arguments plus 1 +** (so that it includes the function itself). Return the number of +** results, if it was a C function, or -1 for a Lua function. +*/ +int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, + int narg1, int delta) { + retry: + switch (ttypetag(s2v(func))) { + case LUA_VCCL: /* C closure */ + return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f); + case LUA_VLCF: /* light C function */ + return precallC(L, func, LUA_MULTRET, fvalue(s2v(func))); + case LUA_VLCL: { /* Lua function */ + Proto *p = clLvalue(s2v(func))->p; + int fsize = p->maxstacksize; /* frame size */ + int nfixparams = p->numparams; + int i; + ci->func -= delta; /* restore 'func' (if vararg) */ + for (i = 0; i < narg1; i++) /* move down function and arguments */ + setobjs2s(L, ci->func + i, func + i); + checkstackGC(L, fsize); + func = ci->func; /* moved-down function */ + for (; narg1 <= nfixparams; narg1++) + setnilvalue(s2v(func + narg1)); /* complete missing arguments */ + ci->top = func + 1 + fsize; /* top for new function */ + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus |= CIST_TAIL; + L->top = func + narg1; /* set top */ + return -1; + } + default: { /* not a function */ + func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ + /* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */ + narg1++; + goto retry; /* try again */ + } + } +} + + /* ** Prepares the call to a function (C or Lua). For C functions, also do ** the call. The function to be called is at '*func'. The arguments @@ -519,32 +563,14 @@ l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, ** original function position. */ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { - lua_CFunction f; retry: switch (ttypetag(s2v(func))) { case LUA_VCCL: /* C closure */ - f = clCvalue(s2v(func))->f; - goto Cfunc; + precallC(L, func, nresults, clCvalue(s2v(func))->f); + return NULL; case LUA_VLCF: /* light C function */ - f = fvalue(s2v(func)); - Cfunc: { - int n; /* number of returns */ - CallInfo *ci; - checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ - L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, - L->top + LUA_MINSTACK); - lua_assert(ci->top <= L->stack_last); - if (l_unlikely(L->hookmask & LUA_MASKCALL)) { - int narg = cast_int(L->top - func) - 1; - luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); - } - lua_unlock(L); - n = (*f)(L); /* do the actual call */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, ci, n); + precallC(L, func, nresults, fvalue(s2v(func))); return NULL; - } case LUA_VLCL: { /* Lua function */ CallInfo *ci; Proto *p = clLvalue(s2v(func))->p; @@ -561,6 +587,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { } default: { /* not a function */ func = luaD_tryfuncTM(L, func); /* try to get '__call' metamethod */ + /* return luaD_precall(L, func, nresults); */ goto retry; /* try again with metamethod */ } } @@ -733,11 +760,10 @@ static void resume (lua_State *L, void *ud) { StkId firstArg = L->top - n; /* first argument */ CallInfo *ci = L->ci; if (L->status == LUA_OK) /* starting a coroutine? */ - ccall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */ + ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */ else { /* resuming from previous yield */ lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; /* mark that it is running (again) */ - luaE_incCstack(L); /* control the C stack */ if (isLua(ci)) { /* yielded inside a hook? */ L->top = firstArg; /* discard arguments */ luaV_execute(L, ci); /* just continue running Lua code */ @@ -788,6 +814,9 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, else if (L->status != LUA_YIELD) /* ended with errors? */ return resume_error(L, "cannot resume dead coroutine", nargs); L->nCcalls = (from) ? getCcalls(from) : 0; + if (getCcalls(L) >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow", nargs); + L->nCcalls++; luai_userstateresume(L, nargs); api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); status = luaD_rawrunprotected(L, resume, &nargs); diff --git a/src/3rdParty/lua/ldo.h b/src/3rdParty/lua/ldo.h index 9fb772f..911e67f 100644 --- a/src/3rdParty/lua/ldo.h +++ b/src/3rdParty/lua/ldo.h @@ -58,7 +58,7 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, int fTransfer, int nTransfer); LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); -LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n); +LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta); LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); diff --git a/src/3rdParty/lua/lstate.c b/src/3rdParty/lua/lstate.c index bfc5902..5cb0847 100644 --- a/src/3rdParty/lua/lstate.c +++ b/src/3rdParty/lua/lstate.c @@ -166,7 +166,7 @@ void luaE_checkcstack (lua_State *L) { if (getCcalls(L) == LUAI_MAXCCALLS) luaG_runerror(L, "C stack overflow"); else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11)) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ } @@ -330,13 +330,13 @@ int luaE_resetthread (lua_State *L, int status) { ci->callstatus = CIST_C; if (status == LUA_YIELD) status = LUA_OK; + L->status = LUA_OK; /* so it can run __close metamethods */ status = luaD_closeprotected(L, 1, status); if (status != LUA_OK) /* errors? */ luaD_seterrorobj(L, status, L->stack + 1); else L->top = L->stack + 1; ci->top = L->top + LUA_MINSTACK; - L->status = cast_byte(status); luaD_reallocstack(L, cast_int(ci->top - L->stack), 0); return status; } diff --git a/src/3rdParty/lua/lvm.c b/src/3rdParty/lua/lvm.c index 49ed3dd..2ec3440 100644 --- a/src/3rdParty/lua/lvm.c +++ b/src/3rdParty/lua/lvm.c @@ -1643,6 +1643,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_TAILCALL) { int b = GETARG_B(i); /* number of arguments + 1 (function) */ + int n; /* number of results when calling a C function */ int nparams1 = GETARG_C(i); /* delta is virtual 'func' - real 'func' (vararg functions) */ int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; @@ -1656,24 +1657,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { lua_assert(L->tbclist < base); /* no pending tbc variables */ lua_assert(base == ci->func + 1); } - while (!ttisfunction(s2v(ra))) { /* not a function? */ - ra = luaD_tryfuncTM(L, ra); /* try '__call' metamethod */ - b++; /* there is now one extra argument */ - } - if (!ttisLclosure(s2v(ra))) { /* C function? */ - luaD_precall(L, ra, LUA_MULTRET); /* call it */ - updatetrap(ci); - updatestack(ci); /* stack may have been relocated */ + if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */ + goto startfunc; /* execute the callee */ + else { /* C function? */ ci->func -= delta; /* restore 'func' (if vararg) */ - luaD_poscall(L, ci, cast_int(L->top - ra)); /* finish caller */ + luaD_poscall(L, ci, n); /* finish caller */ updatetrap(ci); /* 'luaD_poscall' can change hooks */ goto ret; /* caller returns after the tail call */ } - else { /* Lua function */ - ci->func -= delta; /* restore 'func' (if vararg) */ - luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ - goto startfunc; /* execute the callee */ - } } vmcase(OP_RETURN) { int n = GETARG_B(i) - 1; /* number of results */ -- cgit v1.2.3-55-g6feb