aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-03-03 21:31:01 +0800
committerLi Jin <dragon-fly@qq.com>2021-03-03 21:33:37 +0800
commit1df786307c1983b8ce693e3916081a8bcd4e95ae (patch)
tree6c7aeb2198d825877fd3d179c394b7a5c1f06a17 /src
parent66168b112b707172b9035edf8c1daed469781e06 (diff)
downloadyuescript-1df786307c1983b8ce693e3916081a8bcd4e95ae.tar.gz
yuescript-1df786307c1983b8ce693e3916081a8bcd4e95ae.tar.bz2
yuescript-1df786307c1983b8ce693e3916081a8bcd4e95ae.zip
add new metatable syntax for issue #41, fix reusing local variable issue, update built-in Lua.
Diffstat (limited to 'src')
-rw-r--r--src/lua/lapi.c15
-rw-r--r--src/lua/lapi.h2
-rw-r--r--src/lua/lauxlib.c44
-rw-r--r--src/lua/lauxlib.h8
-rw-r--r--src/lua/lbaselib.c15
-rw-r--r--src/lua/lcode.c16
-rw-r--r--src/lua/lcorolib.c10
-rw-r--r--src/lua/ldblib.c7
-rw-r--r--src/lua/ldebug.c105
-rw-r--r--src/lua/ldebug.h10
-rw-r--r--src/lua/ldo.c299
-rw-r--r--src/lua/ldo.h2
-rw-r--r--src/lua/lfunc.c69
-rw-r--r--src/lua/lfunc.h9
-rw-r--r--src/lua/lgc.c38
-rw-r--r--src/lua/liolib.c17
-rw-r--r--src/lua/llimits.h16
-rw-r--r--src/lua/lmathlib.c5
-rw-r--r--src/lua/lmem.c33
-rw-r--r--src/lua/loadlib.c17
-rw-r--r--src/lua/lobject.h10
-rw-r--r--src/lua/lopcodes.h14
-rw-r--r--src/lua/loslib.c8
-rw-r--r--src/lua/lparser.c8
-rw-r--r--src/lua/lstate.c24
-rw-r--r--src/lua/lstate.h46
-rw-r--r--src/lua/lstring.c8
-rw-r--r--src/lua/lstrlib.c41
-rw-r--r--src/lua/ltable.c8
-rw-r--r--src/lua/ltablib.c11
-rw-r--r--src/lua/ltm.c5
-rw-r--r--src/lua/luaconf.h103
-rw-r--r--src/lua/lvm.c60
-rw-r--r--src/lua/lvm.h6
-rw-r--r--src/yuescript/ast.hpp4
-rw-r--r--src/yuescript/yue_ast.h35
-rw-r--r--src/yuescript/yue_compiler.cpp379
-rw-r--r--src/yuescript/yue_parser.cpp16
-rw-r--r--src/yuescript/yue_parser.h4
39 files changed, 974 insertions, 553 deletions
diff --git a/src/lua/lapi.c b/src/lua/lapi.c
index 3583e9c..a9cf2fd 100644
--- a/src/lua/lapi.c
+++ b/src/lua/lapi.c
@@ -39,7 +39,7 @@ const char lua_ident[] =
39 39
40 40
41/* 41/*
42** Test for a valid index. 42** Test for a valid index (one that is not the 'nilvalue').
43** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed. 43** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed.
44** However, it covers the most common cases in a faster way. 44** However, it covers the most common cases in a faster way.
45*/ 45*/
@@ -74,7 +74,8 @@ static TValue *index2value (lua_State *L, int idx) {
74 return &G(L)->nilvalue; /* it has no upvalues */ 74 return &G(L)->nilvalue; /* it has no upvalues */
75 else { 75 else {
76 CClosure *func = clCvalue(s2v(ci->func)); 76 CClosure *func = clCvalue(s2v(ci->func));
77 return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : &G(L)->nilvalue; 77 return (idx <= func->nupvalues) ? &func->upvalue[idx-1]
78 : &G(L)->nilvalue;
78 } 79 }
79 } 80 }
80} 81}
@@ -191,9 +192,8 @@ LUA_API void lua_settop (lua_State *L, int idx) {
191 if (diff < 0 && hastocloseCfunc(ci->nresults)) 192 if (diff < 0 && hastocloseCfunc(ci->nresults))
192 luaF_close(L, L->top + diff, CLOSEKTOP, 0); 193 luaF_close(L, L->top + diff, CLOSEKTOP, 0);
193#endif 194#endif
195 api_check(L, L->tbclist < L->top + diff, "cannot pop an unclosed slot");
194 L->top += diff; 196 L->top += diff;
195 api_check(L, L->openupval == NULL || uplevel(L->openupval) < L->top,
196 "cannot pop an unclosed slot");
197 lua_unlock(L); 197 lua_unlock(L);
198} 198}
199 199
@@ -202,10 +202,10 @@ LUA_API void lua_closeslot (lua_State *L, int idx) {
202 StkId level; 202 StkId level;
203 lua_lock(L); 203 lua_lock(L);
204 level = index2stack(L, idx); 204 level = index2stack(L, idx);
205 api_check(L, hastocloseCfunc(L->ci->nresults) && L->openupval != NULL && 205 api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist == level,
206 uplevel(L->openupval) == level,
207 "no variable to close at given level"); 206 "no variable to close at given level");
208 luaF_close(L, level, CLOSEKTOP, 0); 207 luaF_close(L, level, CLOSEKTOP, 0);
208 level = index2stack(L, idx); /* stack may be moved */
209 setnilvalue(s2v(level)); 209 setnilvalue(s2v(level));
210 lua_unlock(L); 210 lua_unlock(L);
211} 211}
@@ -1264,8 +1264,7 @@ LUA_API void lua_toclose (lua_State *L, int idx) {
1264 lua_lock(L); 1264 lua_lock(L);
1265 o = index2stack(L, idx); 1265 o = index2stack(L, idx);
1266 nresults = L->ci->nresults; 1266 nresults = L->ci->nresults;
1267 api_check(L, L->openupval == NULL || uplevel(L->openupval) <= o, 1267 api_check(L, L->tbclist < o, "given index below or equal a marked one");
1268 "marked index below or equal new one");
1269 luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ 1268 luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */
1270 if (!hastocloseCfunc(nresults)) /* function not marked yet? */ 1269 if (!hastocloseCfunc(nresults)) /* function not marked yet? */
1271 L->ci->nresults = codeNresults(nresults); /* mark it */ 1270 L->ci->nresults = codeNresults(nresults); /* mark it */
diff --git a/src/lua/lapi.h b/src/lua/lapi.h
index 41216b2..9e99cc4 100644
--- a/src/lua/lapi.h
+++ b/src/lua/lapi.h
@@ -42,6 +42,8 @@
42 42
43#define hastocloseCfunc(n) ((n) < LUA_MULTRET) 43#define hastocloseCfunc(n) ((n) < LUA_MULTRET)
44 44
45/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */
45#define codeNresults(n) (-(n) - 3) 46#define codeNresults(n) (-(n) - 3)
47#define decodeNresults(n) (-(n) - 3)
46 48
47#endif 49#endif
diff --git a/src/lua/lauxlib.c b/src/lua/lauxlib.c
index e8fc486..94835ef 100644
--- a/src/lua/lauxlib.c
+++ b/src/lua/lauxlib.c
@@ -190,7 +190,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
190} 190}
191 191
192 192
193int luaL_typeerror (lua_State *L, int arg, const char *tname) { 193LUALIB_API int luaL_typeerror (lua_State *L, int arg, const char *tname) {
194 const char *msg; 194 const char *msg;
195 const char *typearg; /* name for the type of the actual argument */ 195 const char *typearg; /* name for the type of the actual argument */
196 if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) 196 if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING)
@@ -378,7 +378,7 @@ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
378** but without 'msg'.) 378** but without 'msg'.)
379*/ 379*/
380LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { 380LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
381 if (!lua_checkstack(L, space)) { 381 if (l_unlikely(!lua_checkstack(L, space))) {
382 if (msg) 382 if (msg)
383 luaL_error(L, "stack overflow (%s)", msg); 383 luaL_error(L, "stack overflow (%s)", msg);
384 else 384 else
@@ -388,20 +388,20 @@ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
388 388
389 389
390LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { 390LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) {
391 if (lua_type(L, arg) != t) 391 if (l_unlikely(lua_type(L, arg) != t))
392 tag_error(L, arg, t); 392 tag_error(L, arg, t);
393} 393}
394 394
395 395
396LUALIB_API void luaL_checkany (lua_State *L, int arg) { 396LUALIB_API void luaL_checkany (lua_State *L, int arg) {
397 if (lua_type(L, arg) == LUA_TNONE) 397 if (l_unlikely(lua_type(L, arg) == LUA_TNONE))
398 luaL_argerror(L, arg, "value expected"); 398 luaL_argerror(L, arg, "value expected");
399} 399}
400 400
401 401
402LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { 402LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) {
403 const char *s = lua_tolstring(L, arg, len); 403 const char *s = lua_tolstring(L, arg, len);
404 if (!s) tag_error(L, arg, LUA_TSTRING); 404 if (l_unlikely(!s)) tag_error(L, arg, LUA_TSTRING);
405 return s; 405 return s;
406} 406}
407 407
@@ -420,7 +420,7 @@ LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
420LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { 420LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) {
421 int isnum; 421 int isnum;
422 lua_Number d = lua_tonumberx(L, arg, &isnum); 422 lua_Number d = lua_tonumberx(L, arg, &isnum);
423 if (!isnum) 423 if (l_unlikely(!isnum))
424 tag_error(L, arg, LUA_TNUMBER); 424 tag_error(L, arg, LUA_TNUMBER);
425 return d; 425 return d;
426} 426}
@@ -442,7 +442,7 @@ static void interror (lua_State *L, int arg) {
442LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { 442LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) {
443 int isnum; 443 int isnum;
444 lua_Integer d = lua_tointegerx(L, arg, &isnum); 444 lua_Integer d = lua_tointegerx(L, arg, &isnum);
445 if (!isnum) { 445 if (l_unlikely(!isnum)) {
446 interror(L, arg); 446 interror(L, arg);
447 } 447 }
448 return d; 448 return d;
@@ -475,7 +475,7 @@ static void *resizebox (lua_State *L, int idx, size_t newsize) {
475 lua_Alloc allocf = lua_getallocf(L, &ud); 475 lua_Alloc allocf = lua_getallocf(L, &ud);
476 UBox *box = (UBox *)lua_touserdata(L, idx); 476 UBox *box = (UBox *)lua_touserdata(L, idx);
477 void *temp = allocf(ud, box->box, box->bsize, newsize); 477 void *temp = allocf(ud, box->box, box->bsize, newsize);
478 if (temp == NULL && newsize > 0) { /* allocation error? */ 478 if (l_unlikely(temp == NULL && newsize > 0)) { /* allocation error? */
479 lua_pushliteral(L, "not enough memory"); 479 lua_pushliteral(L, "not enough memory");
480 lua_error(L); /* raise a memory error */ 480 lua_error(L); /* raise a memory error */
481 } 481 }
@@ -516,12 +516,21 @@ static void newbox (lua_State *L) {
516 516
517 517
518/* 518/*
519** Whenever buffer is accessed, slot 'idx' must either be a box (which
520** cannot be NULL) or it is a placeholder for the buffer.
521*/
522#define checkbufferlevel(B,idx) \
523 lua_assert(buffonstack(B) ? lua_touserdata(B->L, idx) != NULL \
524 : lua_touserdata(B->L, idx) == (void*)B)
525
526
527/*
519** Compute new size for buffer 'B', enough to accommodate extra 'sz' 528** Compute new size for buffer 'B', enough to accommodate extra 'sz'
520** bytes. 529** bytes.
521*/ 530*/
522static size_t newbuffsize (luaL_Buffer *B, size_t sz) { 531static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
523 size_t newsize = B->size * 2; /* double buffer size */ 532 size_t newsize = B->size * 2; /* double buffer size */
524 if (MAX_SIZET - sz < B->n) /* overflow in (B->n + sz)? */ 533 if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */
525 return luaL_error(B->L, "buffer too large"); 534 return luaL_error(B->L, "buffer too large");
526 if (newsize < B->n + sz) /* double is not big enough? */ 535 if (newsize < B->n + sz) /* double is not big enough? */
527 newsize = B->n + sz; 536 newsize = B->n + sz;
@@ -531,10 +540,11 @@ static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
531 540
532/* 541/*
533** Returns a pointer to a free area with at least 'sz' bytes in buffer 542** Returns a pointer to a free area with at least 'sz' bytes in buffer
534** 'B'. 'boxidx' is the relative position in the stack where the 543** 'B'. 'boxidx' is the relative position in the stack where is the
535** buffer's box is or should be. 544** buffer's box or its placeholder.
536*/ 545*/
537static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) { 546static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
547 checkbufferlevel(B, boxidx);
538 if (B->size - B->n >= sz) /* enough space? */ 548 if (B->size - B->n >= sz) /* enough space? */
539 return B->b + B->n; 549 return B->b + B->n;
540 else { 550 else {
@@ -545,6 +555,7 @@ static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
545 if (buffonstack(B)) /* buffer already has a box? */ 555 if (buffonstack(B)) /* buffer already has a box? */
546 newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */ 556 newbuff = (char *)resizebox(L, boxidx, newsize); /* resize it */
547 else { /* no box yet */ 557 else { /* no box yet */
558 lua_remove(L, boxidx); /* remove placeholder */
548 newbox(L); /* create a new box */ 559 newbox(L); /* create a new box */
549 lua_insert(L, boxidx); /* move box to its intended position */ 560 lua_insert(L, boxidx); /* move box to its intended position */
550 lua_toclose(L, boxidx); 561 lua_toclose(L, boxidx);
@@ -581,11 +592,11 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
581 592
582LUALIB_API void luaL_pushresult (luaL_Buffer *B) { 593LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
583 lua_State *L = B->L; 594 lua_State *L = B->L;
595 checkbufferlevel(B, -1);
584 lua_pushlstring(L, B->b, B->n); 596 lua_pushlstring(L, B->b, B->n);
585 if (buffonstack(B)) { 597 if (buffonstack(B))
586 lua_closeslot(L, -2); /* close the box */ 598 lua_closeslot(L, -2); /* close the box */
587 lua_remove(L, -2); /* remove box from the stack */ 599 lua_remove(L, -2); /* remove box or placeholder from the stack */
588 }
589} 600}
590 601
591 602
@@ -620,6 +631,7 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
620 B->b = B->init.b; 631 B->b = B->init.b;
621 B->n = 0; 632 B->n = 0;
622 B->size = LUAL_BUFFERSIZE; 633 B->size = LUAL_BUFFERSIZE;
634 lua_pushlightuserdata(L, (void*)B); /* push placeholder */
623} 635}
624 636
625 637
@@ -861,7 +873,7 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
861 int isnum; 873 int isnum;
862 lua_len(L, idx); 874 lua_len(L, idx);
863 l = lua_tointegerx(L, -1, &isnum); 875 l = lua_tointegerx(L, -1, &isnum);
864 if (!isnum) 876 if (l_unlikely(!isnum))
865 luaL_error(L, "object length is not an integer"); 877 luaL_error(L, "object length is not an integer");
866 lua_pop(L, 1); /* remove object */ 878 lua_pop(L, 1); /* remove object */
867 return l; 879 return l;
@@ -1074,7 +1086,7 @@ static void warnfon (void *ud, const char *message, int tocont) {
1074 1086
1075LUALIB_API lua_State *luaL_newstate (void) { 1087LUALIB_API lua_State *luaL_newstate (void) {
1076 lua_State *L = lua_newstate(l_alloc, NULL); 1088 lua_State *L = lua_newstate(l_alloc, NULL);
1077 if (L) { 1089 if (l_likely(L)) {
1078 lua_atpanic(L, &panic); 1090 lua_atpanic(L, &panic);
1079 lua_setwarnf(L, warnfoff, L); /* default is warnings off */ 1091 lua_setwarnf(L, warnfoff, L); /* default is warnings off */
1080 } 1092 }
diff --git a/src/lua/lauxlib.h b/src/lua/lauxlib.h
index 6571491..9058e26 100644
--- a/src/lua/lauxlib.h
+++ b/src/lua/lauxlib.h
@@ -122,6 +122,10 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
122** =============================================================== 122** ===============================================================
123*/ 123*/
124 124
125#if !defined(l_likely)
126#define l_likely(x) x
127#endif
128
125 129
126#define luaL_newlibtable(L,l) \ 130#define luaL_newlibtable(L,l) \
127 lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) 131 lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
@@ -130,10 +134,10 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname,
130 (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) 134 (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
131 135
132#define luaL_argcheck(L, cond,arg,extramsg) \ 136#define luaL_argcheck(L, cond,arg,extramsg) \
133 ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) 137 ((void)(l_likely(cond) || luaL_argerror(L, (arg), (extramsg))))
134 138
135#define luaL_argexpected(L,cond,arg,tname) \ 139#define luaL_argexpected(L,cond,arg,tname) \
136 ((void)((cond) || luaL_typeerror(L, (arg), (tname)))) 140 ((void)(l_likely(cond) || luaL_typeerror(L, (arg), (tname))))
137 141
138#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) 142#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
139#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) 143#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
diff --git a/src/lua/lbaselib.c b/src/lua/lbaselib.c
index 747fd45..83ad306 100644
--- a/src/lua/lbaselib.c
+++ b/src/lua/lbaselib.c
@@ -138,7 +138,7 @@ static int luaB_setmetatable (lua_State *L) {
138 int t = lua_type(L, 2); 138 int t = lua_type(L, 2);
139 luaL_checktype(L, 1, LUA_TTABLE); 139 luaL_checktype(L, 1, LUA_TTABLE);
140 luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table"); 140 luaL_argexpected(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table");
141 if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) 141 if (l_unlikely(luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL))
142 return luaL_error(L, "cannot change a protected metatable"); 142 return luaL_error(L, "cannot change a protected metatable");
143 lua_settop(L, 2); 143 lua_settop(L, 2);
144 lua_setmetatable(L, 1); 144 lua_setmetatable(L, 1);
@@ -182,7 +182,8 @@ static int luaB_rawset (lua_State *L) {
182 182
183 183
184static int pushmode (lua_State *L, int oldmode) { 184static int pushmode (lua_State *L, int oldmode) {
185 lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental" : "generational"); 185 lua_pushstring(L, (oldmode == LUA_GCINC) ? "incremental"
186 : "generational");
186 return 1; 187 return 1;
187} 188}
188 189
@@ -299,7 +300,7 @@ static int luaB_ipairs (lua_State *L) {
299 300
300 301
301static int load_aux (lua_State *L, int status, int envidx) { 302static int load_aux (lua_State *L, int status, int envidx) {
302 if (status == LUA_OK) { 303 if (l_likely(status == LUA_OK)) {
303 if (envidx != 0) { /* 'env' parameter? */ 304 if (envidx != 0) { /* 'env' parameter? */
304 lua_pushvalue(L, envidx); /* environment for loaded function */ 305 lua_pushvalue(L, envidx); /* environment for loaded function */
305 if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ 306 if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
@@ -355,7 +356,7 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
355 *size = 0; 356 *size = 0;
356 return NULL; 357 return NULL;
357 } 358 }
358 else if (!lua_isstring(L, -1)) 359 else if (l_unlikely(!lua_isstring(L, -1)))
359 luaL_error(L, "reader function must return a string"); 360 luaL_error(L, "reader function must return a string");
360 lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ 361 lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
361 return lua_tolstring(L, RESERVEDSLOT, size); 362 return lua_tolstring(L, RESERVEDSLOT, size);
@@ -393,7 +394,7 @@ static int dofilecont (lua_State *L, int d1, lua_KContext d2) {
393static int luaB_dofile (lua_State *L) { 394static int luaB_dofile (lua_State *L) {
394 const char *fname = luaL_optstring(L, 1, NULL); 395 const char *fname = luaL_optstring(L, 1, NULL);
395 lua_settop(L, 1); 396 lua_settop(L, 1);
396 if (luaL_loadfile(L, fname) != LUA_OK) 397 if (l_unlikely(luaL_loadfile(L, fname) != LUA_OK))
397 return lua_error(L); 398 return lua_error(L);
398 lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); 399 lua_callk(L, 0, LUA_MULTRET, 0, dofilecont);
399 return dofilecont(L, 0, 0); 400 return dofilecont(L, 0, 0);
@@ -401,7 +402,7 @@ static int luaB_dofile (lua_State *L) {
401 402
402 403
403static int luaB_assert (lua_State *L) { 404static int luaB_assert (lua_State *L) {
404 if (lua_toboolean(L, 1)) /* condition is true? */ 405 if (l_likely(lua_toboolean(L, 1))) /* condition is true? */
405 return lua_gettop(L); /* return all arguments */ 406 return lua_gettop(L); /* return all arguments */
406 else { /* error */ 407 else { /* error */
407 luaL_checkany(L, 1); /* there must be a condition */ 408 luaL_checkany(L, 1); /* there must be a condition */
@@ -437,7 +438,7 @@ static int luaB_select (lua_State *L) {
437** ignored). 438** ignored).
438*/ 439*/
439static int finishpcall (lua_State *L, int status, lua_KContext extra) { 440static int finishpcall (lua_State *L, int status, lua_KContext extra) {
440 if (status != LUA_OK && status != LUA_YIELD) { /* error? */ 441 if (l_unlikely(status != LUA_OK && status != LUA_YIELD)) { /* error? */
441 lua_pushboolean(L, 0); /* first result (false) */ 442 lua_pushboolean(L, 0); /* first result (false) */
442 lua_pushvalue(L, -2); /* error message */ 443 lua_pushvalue(L, -2); /* error message */
443 return 2; /* return false, msg */ 444 return 2; /* return false, msg */
diff --git a/src/lua/lcode.c b/src/lua/lcode.c
index d8d353f..80d975c 100644
--- a/src/lua/lcode.c
+++ b/src/lua/lcode.c
@@ -314,15 +314,6 @@ void luaK_patchtohere (FuncState *fs, int list) {
314} 314}
315 315
316 316
317/*
318** MAXimum number of successive Instructions WiTHout ABSolute line
319** information.
320*/
321#if !defined(MAXIWTHABS)
322#define MAXIWTHABS 120
323#endif
324
325
326/* limit for difference between lines in relative line info. */ 317/* limit for difference between lines in relative line info. */
327#define LIMLINEDIFF 0x80 318#define LIMLINEDIFF 0x80
328 319
@@ -337,13 +328,13 @@ void luaK_patchtohere (FuncState *fs, int list) {
337static void savelineinfo (FuncState *fs, Proto *f, int line) { 328static void savelineinfo (FuncState *fs, Proto *f, int line) {
338 int linedif = line - fs->previousline; 329 int linedif = line - fs->previousline;
339 int pc = fs->pc - 1; /* last instruction coded */ 330 int pc = fs->pc - 1; /* last instruction coded */
340 if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ > MAXIWTHABS) { 331 if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ >= MAXIWTHABS) {
341 luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, 332 luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo,
342 f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); 333 f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines");
343 f->abslineinfo[fs->nabslineinfo].pc = pc; 334 f->abslineinfo[fs->nabslineinfo].pc = pc;
344 f->abslineinfo[fs->nabslineinfo++].line = line; 335 f->abslineinfo[fs->nabslineinfo++].line = line;
345 linedif = ABSLINEINFO; /* signal that there is absolute information */ 336 linedif = ABSLINEINFO; /* signal that there is absolute information */
346 fs->iwthabs = 0; /* restart counter */ 337 fs->iwthabs = 1; /* restart counter */
347 } 338 }
348 luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, 339 luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte,
349 MAX_INT, "opcodes"); 340 MAX_INT, "opcodes");
@@ -1307,7 +1298,8 @@ static int validop (int op, TValue *v1, TValue *v2) {
1307 case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: 1298 case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
1308 case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ 1299 case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */
1309 lua_Integer i; 1300 lua_Integer i;
1310 return (tointegerns(v1, &i) && tointegerns(v2, &i)); 1301 return (luaV_tointegerns(v1, &i, LUA_FLOORN2I) &&
1302 luaV_tointegerns(v2, &i, LUA_FLOORN2I));
1311 } 1303 }
1312 case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ 1304 case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */
1313 return (nvalue(v2) != 0); 1305 return (nvalue(v2) != 0);
diff --git a/src/lua/lcorolib.c b/src/lua/lcorolib.c
index ed7c58b..fedbebe 100644
--- a/src/lua/lcorolib.c
+++ b/src/lua/lcorolib.c
@@ -31,14 +31,14 @@ static lua_State *getco (lua_State *L) {
31*/ 31*/
32static int auxresume (lua_State *L, lua_State *co, int narg) { 32static int auxresume (lua_State *L, lua_State *co, int narg) {
33 int status, nres; 33 int status, nres;
34 if (!lua_checkstack(co, narg)) { 34 if (l_unlikely(!lua_checkstack(co, narg))) {
35 lua_pushliteral(L, "too many arguments to resume"); 35 lua_pushliteral(L, "too many arguments to resume");
36 return -1; /* error flag */ 36 return -1; /* error flag */
37 } 37 }
38 lua_xmove(L, co, narg); 38 lua_xmove(L, co, narg);
39 status = lua_resume(co, L, narg, &nres); 39 status = lua_resume(co, L, narg, &nres);
40 if (status == LUA_OK || status == LUA_YIELD) { 40 if (l_likely(status == LUA_OK || status == LUA_YIELD)) {
41 if (!lua_checkstack(L, nres + 1)) { 41 if (l_unlikely(!lua_checkstack(L, nres + 1))) {
42 lua_pop(co, nres); /* remove results anyway */ 42 lua_pop(co, nres); /* remove results anyway */
43 lua_pushliteral(L, "too many results to resume"); 43 lua_pushliteral(L, "too many results to resume");
44 return -1; /* error flag */ 44 return -1; /* error flag */
@@ -57,7 +57,7 @@ static int luaB_coresume (lua_State *L) {
57 lua_State *co = getco(L); 57 lua_State *co = getco(L);
58 int r; 58 int r;
59 r = auxresume(L, co, lua_gettop(L) - 1); 59 r = auxresume(L, co, lua_gettop(L) - 1);
60 if (r < 0) { 60 if (l_unlikely(r < 0)) {
61 lua_pushboolean(L, 0); 61 lua_pushboolean(L, 0);
62 lua_insert(L, -2); 62 lua_insert(L, -2);
63 return 2; /* return false + error message */ 63 return 2; /* return false + error message */
@@ -73,7 +73,7 @@ static int luaB_coresume (lua_State *L) {
73static int luaB_auxwrap (lua_State *L) { 73static int luaB_auxwrap (lua_State *L) {
74 lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 74 lua_State *co = lua_tothread(L, lua_upvalueindex(1));
75 int r = auxresume(L, co, lua_gettop(L)); 75 int r = auxresume(L, co, lua_gettop(L));
76 if (r < 0) { /* error? */ 76 if (l_unlikely(r < 0)) { /* error? */
77 int stat = lua_status(co); 77 int stat = lua_status(co);
78 if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ 78 if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */
79 stat = lua_resetthread(co); /* close its tbc variables */ 79 stat = lua_resetthread(co); /* close its tbc variables */
diff --git a/src/lua/ldblib.c b/src/lua/ldblib.c
index 15593bf..6dcbaa9 100644
--- a/src/lua/ldblib.c
+++ b/src/lua/ldblib.c
@@ -33,7 +33,7 @@ static const char *const HOOKKEY = "_HOOKKEY";
33** checked. 33** checked.
34*/ 34*/
35static void checkstack (lua_State *L, lua_State *L1, int n) { 35static void checkstack (lua_State *L, lua_State *L1, int n) {
36 if (L != L1 && !lua_checkstack(L1, n)) 36 if (l_unlikely(L != L1 && !lua_checkstack(L1, n)))
37 luaL_error(L, "stack overflow"); 37 luaL_error(L, "stack overflow");
38} 38}
39 39
@@ -152,6 +152,7 @@ static int db_getinfo (lua_State *L) {
152 lua_State *L1 = getthread(L, &arg); 152 lua_State *L1 = getthread(L, &arg);
153 const char *options = luaL_optstring(L, arg+2, "flnSrtu"); 153 const char *options = luaL_optstring(L, arg+2, "flnSrtu");
154 checkstack(L, L1, 3); 154 checkstack(L, L1, 3);
155 luaL_argcheck(L, options[0] != '>', arg + 2, "invalid option '>'");
155 if (lua_isfunction(L, arg + 1)) { /* info about a function? */ 156 if (lua_isfunction(L, arg + 1)) { /* info about a function? */
156 options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ 157 options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */
157 lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ 158 lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */
@@ -212,7 +213,7 @@ static int db_getlocal (lua_State *L) {
212 lua_Debug ar; 213 lua_Debug ar;
213 const char *name; 214 const char *name;
214 int level = (int)luaL_checkinteger(L, arg + 1); 215 int level = (int)luaL_checkinteger(L, arg + 1);
215 if (!lua_getstack(L1, level, &ar)) /* out of range? */ 216 if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
216 return luaL_argerror(L, arg+1, "level out of range"); 217 return luaL_argerror(L, arg+1, "level out of range");
217 checkstack(L, L1, 1); 218 checkstack(L, L1, 1);
218 name = lua_getlocal(L1, &ar, nvar); 219 name = lua_getlocal(L1, &ar, nvar);
@@ -237,7 +238,7 @@ static int db_setlocal (lua_State *L) {
237 lua_Debug ar; 238 lua_Debug ar;
238 int level = (int)luaL_checkinteger(L, arg + 1); 239 int level = (int)luaL_checkinteger(L, arg + 1);
239 int nvar = (int)luaL_checkinteger(L, arg + 2); 240 int nvar = (int)luaL_checkinteger(L, arg + 2);
240 if (!lua_getstack(L1, level, &ar)) /* out of range? */ 241 if (l_unlikely(!lua_getstack(L1, level, &ar))) /* out of range? */
241 return luaL_argerror(L, arg+1, "level out of range"); 242 return luaL_argerror(L, arg+1, "level out of range");
242 luaL_checkany(L, arg+3); 243 luaL_checkany(L, arg+3);
243 lua_settop(L, arg+3); 244 lua_settop(L, arg+3);
diff --git a/src/lua/ldebug.c b/src/lua/ldebug.c
index 819550d..8e3657a 100644
--- a/src/lua/ldebug.c
+++ b/src/lua/ldebug.c
@@ -33,8 +33,6 @@
33 33
34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) 34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
35 35
36/* inverse of 'pcRel' */
37#define invpcRel(pc, p) ((p)->code + (pc) + 1)
38 36
39static const char *funcnamefromcode (lua_State *L, CallInfo *ci, 37static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
40 const char **name); 38 const char **name);
@@ -48,10 +46,14 @@ static int currentpc (CallInfo *ci) {
48 46
49/* 47/*
50** Get a "base line" to find the line corresponding to an instruction. 48** Get a "base line" to find the line corresponding to an instruction.
51** For that, search the array of absolute line info for the largest saved 49** Base lines are regularly placed at MAXIWTHABS intervals, so usually
52** instruction smaller or equal to the wanted instruction. A special 50** an integer division gets the right place. When the source file has
53** case is when there is no absolute info or the instruction is before 51** large sequences of empty/comment lines, it may need extra entries,
54** the first absolute one. 52** so the original estimate needs a correction.
53** The assertion that the estimate is a lower bound for the correct base
54** is valid as long as the debug info has been generated with the same
55** value for MAXIWTHABS or smaller. (Previous releases use a little
56** smaller value.)
55*/ 57*/
56static int getbaseline (const Proto *f, int pc, int *basepc) { 58static int getbaseline (const Proto *f, int pc, int *basepc) {
57 if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) { 59 if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
@@ -59,20 +61,11 @@ static int getbaseline (const Proto *f, int pc, int *basepc) {
59 return f->linedefined; 61 return f->linedefined;
60 } 62 }
61 else { 63 else {
62 unsigned int i; 64 int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */
63 if (pc >= f->abslineinfo[f->sizeabslineinfo - 1].pc) 65 /* estimate must be a lower bond of the correct base */
64 i = f->sizeabslineinfo - 1; /* instruction is after last saved one */ 66 lua_assert(i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc);
65 else { /* binary search */ 67 while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc)
66 unsigned int j = f->sizeabslineinfo - 1; /* pc < anchorlines[j] */ 68 i++; /* low estimate; adjust it */
67 i = 0; /* abslineinfo[i] <= pc */
68 while (i < j - 1) {
69 unsigned int m = (j + i) / 2;
70 if (pc >= f->abslineinfo[m].pc)
71 i = m;
72 else
73 j = m;
74 }
75 }
76 *basepc = f->abslineinfo[i].pc; 69 *basepc = f->abslineinfo[i].pc;
77 return f->abslineinfo[i].line; 70 return f->abslineinfo[i].line;
78 } 71 }
@@ -305,8 +298,8 @@ static void collectvalidlines (lua_State *L, Closure *f) {
305 sethvalue2s(L, L->top, t); /* push it on stack */ 298 sethvalue2s(L, L->top, t); /* push it on stack */
306 api_incr_top(L); 299 api_incr_top(L);
307 setbtvalue(&v); /* boolean 'true' to be the value of all indices */ 300 setbtvalue(&v); /* boolean 'true' to be the value of all indices */
308 for (i = 0; i < p->sizelineinfo; i++) { /* for all lines with code */ 301 for (i = 0; i < p->sizelineinfo; i++) { /* for all instructions */
309 currentline = nextline(p, currentline, i); 302 currentline = nextline(p, currentline, i); /* get its line */
310 luaH_setint(L, t, currentline, &v); /* table[line] = true */ 303 luaH_setint(L, t, currentline, &v); /* table[line] = true */
311 } 304 }
312 } 305 }
@@ -645,14 +638,18 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
645 638
646 639
647/* 640/*
648** The subtraction of two potentially unrelated pointers is 641** Check whether pointer 'o' points to some value in the stack
649** not ISO C, but it should not crash a program; the subsequent 642** frame of the current function. Because 'o' may not point to a
650** checks are ISO C and ensure a correct result. 643** value in this stack, we cannot compare it with the region
644** boundaries (undefined behaviour in ISO C).
651*/ 645*/
652static int isinstack (CallInfo *ci, const TValue *o) { 646static int isinstack (CallInfo *ci, const TValue *o) {
653 StkId base = ci->func + 1; 647 StkId pos;
654 ptrdiff_t i = cast(StkId, o) - base; 648 for (pos = ci->func + 1; pos < ci->top; pos++) {
655 return (0 <= i && i < (ci->top - base) && s2v(base + i) == o); 649 if (o == s2v(pos))
650 return 1;
651 }
652 return 0; /* not found */
656} 653}
657 654
658 655
@@ -733,7 +730,7 @@ l_noret luaG_opinterror (lua_State *L, const TValue *p1,
733*/ 730*/
734l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { 731l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
735 lua_Integer temp; 732 lua_Integer temp;
736 if (!tointegerns(p1, &temp)) 733 if (!luaV_tointegerns(p1, &temp, LUA_FLOORN2I))
737 p2 = p1; 734 p2 = p1;
738 luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); 735 luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
739} 736}
@@ -791,16 +788,30 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
791 788
792/* 789/*
793** Check whether new instruction 'newpc' is in a different line from 790** Check whether new instruction 'newpc' is in a different line from
794** previous instruction 'oldpc'. 791** previous instruction 'oldpc'. More often than not, 'newpc' is only
792** one or a few instructions after 'oldpc' (it must be after, see
793** caller), so try to avoid calling 'luaG_getfuncline'. If they are
794** too far apart, there is a good chance of a ABSLINEINFO in the way,
795** so it goes directly to 'luaG_getfuncline'.
795*/ 796*/
796static int changedline (const Proto *p, int oldpc, int newpc) { 797static int changedline (const Proto *p, int oldpc, int newpc) {
797 if (p->lineinfo == NULL) /* no debug information? */ 798 if (p->lineinfo == NULL) /* no debug information? */
798 return 0; 799 return 0;
799 while (oldpc++ < newpc) { 800 if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */
800 if (p->lineinfo[oldpc] != 0) 801 int delta = 0; /* line diference */
801 return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc)); 802 int pc = oldpc;
803 for (;;) {
804 int lineinfo = p->lineinfo[++pc];
805 if (lineinfo == ABSLINEINFO)
806 break; /* cannot compute delta; fall through */
807 delta += lineinfo;
808 if (pc == newpc)
809 return (delta != 0); /* delta computed successfully */
810 }
802 } 811 }
803 return 0; /* no line changes between positions */ 812 /* either instructions are too far apart or there is an absolute line
813 info in the way; compute line difference explicitly */
814 return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc));
804} 815}
805 816
806 817
@@ -808,20 +819,19 @@ static int changedline (const Proto *p, int oldpc, int newpc) {
808** Traces the execution of a Lua function. Called before the execution 819** Traces the execution of a Lua function. Called before the execution
809** of each opcode, when debug is on. 'L->oldpc' stores the last 820** of each opcode, when debug is on. 'L->oldpc' stores the last
810** instruction traced, to detect line changes. When entering a new 821** instruction traced, to detect line changes. When entering a new
811** function, 'npci' will be zero and will test as a new line without 822** function, 'npci' will be zero and will test as a new line whatever
812** the need for 'oldpc'; so, 'oldpc' does not need to be initialized 823** the value of 'oldpc'. Some exceptional conditions may return to
813** before. Some exceptional conditions may return to a function without 824** a function without setting 'oldpc'. In that case, 'oldpc' may be
814** updating 'oldpc'. In that case, 'oldpc' may be invalid; if so, it is 825** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc'
815** reset to zero. (A wrong but valid 'oldpc' at most causes an extra 826** at most causes an extra call to a line hook.)
816** call to a line hook.) 827** This function is not "Protected" when called, so it should correct
828** 'L->top' before calling anything that can run the GC.
817*/ 829*/
818int luaG_traceexec (lua_State *L, const Instruction *pc) { 830int luaG_traceexec (lua_State *L, const Instruction *pc) {
819 CallInfo *ci = L->ci; 831 CallInfo *ci = L->ci;
820 lu_byte mask = L->hookmask; 832 lu_byte mask = L->hookmask;
821 const Proto *p = ci_func(ci)->p; 833 const Proto *p = ci_func(ci)->p;
822 int counthook; 834 int counthook;
823 /* 'L->oldpc' may be invalid; reset it in this case */
824 int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
825 if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ 835 if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
826 ci->u.l.trap = 0; /* don't need to stop again */ 836 ci->u.l.trap = 0; /* don't need to stop again */
827 return 0; /* turn off 'trap' */ 837 return 0; /* turn off 'trap' */
@@ -837,15 +847,16 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
837 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ 847 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
838 return 1; /* do not call hook again (VM yielded, so it did not move) */ 848 return 1; /* do not call hook again (VM yielded, so it did not move) */
839 } 849 }
840 if (!isIT(*(ci->u.l.savedpc - 1))) 850 if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */
841 L->top = ci->top; /* prepare top */ 851 L->top = ci->top; /* correct top */
842 if (counthook) 852 if (counthook)
843 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ 853 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
844 if (mask & LUA_MASKLINE) { 854 if (mask & LUA_MASKLINE) {
855 /* 'L->oldpc' may be invalid; use zero in this case */
856 int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
845 int npci = pcRel(pc, p); 857 int npci = pcRel(pc, p);
846 if (npci == 0 || /* call linehook when enter a new function, */ 858 if (npci <= oldpc || /* call hook when jump back (loop), */
847 pc <= invpcRel(oldpc, p) || /* when jump back (loop), or when */ 859 changedline(p, oldpc, npci)) { /* or when enter new line */
848 changedline(p, oldpc, npci)) { /* enter new line */
849 int newline = luaG_getfuncline(p, npci); 860 int newline = luaG_getfuncline(p, npci);
850 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ 861 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
851 } 862 }
diff --git a/src/lua/ldebug.h b/src/lua/ldebug.h
index 55b3ae0..974960e 100644
--- a/src/lua/ldebug.h
+++ b/src/lua/ldebug.h
@@ -26,6 +26,16 @@
26*/ 26*/
27#define ABSLINEINFO (-0x80) 27#define ABSLINEINFO (-0x80)
28 28
29
30/*
31** MAXimum number of successive Instructions WiTHout ABSolute line
32** information. (A power of two allows fast divisions.)
33*/
34#if !defined(MAXIWTHABS)
35#define MAXIWTHABS 128
36#endif
37
38
29LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc); 39LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
30LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, 40LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
31 StkId *pos); 41 StkId *pos);
diff --git a/src/lua/ldo.c b/src/lua/ldo.c
index aa159cf..7135079 100644
--- a/src/lua/ldo.c
+++ b/src/lua/ldo.c
@@ -160,9 +160,8 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
160static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { 160static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {
161 CallInfo *ci; 161 CallInfo *ci;
162 UpVal *up; 162 UpVal *up;
163 if (oldstack == newstack)
164 return; /* stack address did not change */
165 L->top = (L->top - oldstack) + newstack; 163 L->top = (L->top - oldstack) + newstack;
164 L->tbclist = (L->tbclist - oldstack) + newstack;
166 for (up = L->openupval; up != NULL; up = up->u.open.next) 165 for (up = L->openupval; up != NULL; up = up->u.open.next)
167 up->v = s2v((uplevel(up) - oldstack) + newstack); 166 up->v = s2v((uplevel(up) - oldstack) + newstack);
168 for (ci = L->ci; ci != NULL; ci = ci->previous) { 167 for (ci = L->ci; ci != NULL; ci = ci->previous) {
@@ -178,19 +177,35 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {
178#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) 177#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
179 178
180 179
180/*
181** Reallocate the stack to a new size, correcting all pointers into
182** it. (There are pointers to a stack from its upvalues, from its list
183** of call infos, plus a few individual pointers.) The reallocation is
184** done in two steps (allocation + free) because the correction must be
185** done while both addresses (the old stack and the new one) are valid.
186** (In ISO C, any pointer use after the pointer has been deallocated is
187** undefined behavior.)
188** In case of allocation error, raise an error or return false according
189** to 'raiseerror'.
190*/
181int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { 191int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
182 int lim = stacksize(L); 192 int oldsize = stacksize(L);
183 StkId newstack = luaM_reallocvector(L, L->stack, 193 int i;
184 lim + EXTRA_STACK, newsize + EXTRA_STACK, StackValue); 194 StkId newstack = luaM_reallocvector(L, NULL, 0,
195 newsize + EXTRA_STACK, StackValue);
185 lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); 196 lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
186 if (unlikely(newstack == NULL)) { /* reallocation failed? */ 197 if (l_unlikely(newstack == NULL)) { /* reallocation failed? */
187 if (raiseerror) 198 if (raiseerror)
188 luaM_error(L); 199 luaM_error(L);
189 else return 0; /* do not raise an error */ 200 else return 0; /* do not raise an error */
190 } 201 }
191 for (; lim < newsize; lim++) 202 /* number of elements to be copied to the new stack */
192 setnilvalue(s2v(newstack + lim + EXTRA_STACK)); /* erase new segment */ 203 i = ((oldsize <= newsize) ? oldsize : newsize) + EXTRA_STACK;
204 memcpy(newstack, L->stack, i * sizeof(StackValue));
205 for (; i < newsize + EXTRA_STACK; i++)
206 setnilvalue(s2v(newstack + i)); /* erase new segment */
193 correctstack(L, L->stack, newstack); 207 correctstack(L, L->stack, newstack);
208 luaM_freearray(L, L->stack, oldsize + EXTRA_STACK);
194 L->stack = newstack; 209 L->stack = newstack;
195 L->stack_last = L->stack + newsize; 210 L->stack_last = L->stack + newsize;
196 return 1; 211 return 1;
@@ -203,7 +218,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) {
203*/ 218*/
204int luaD_growstack (lua_State *L, int n, int raiseerror) { 219int luaD_growstack (lua_State *L, int n, int raiseerror) {
205 int size = stacksize(L); 220 int size = stacksize(L);
206 if (unlikely(size > LUAI_MAXSTACK)) { 221 if (l_unlikely(size > LUAI_MAXSTACK)) {
207 /* if stack is larger than maximum, thread is already using the 222 /* if stack is larger than maximum, thread is already using the
208 extra space reserved for errors, that is, thread is handling 223 extra space reserved for errors, that is, thread is handling
209 a stack error; cannot grow further than that. */ 224 a stack error; cannot grow further than that. */
@@ -219,7 +234,7 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) {
219 newsize = LUAI_MAXSTACK; 234 newsize = LUAI_MAXSTACK;
220 if (newsize < needed) /* but must respect what was asked for */ 235 if (newsize < needed) /* but must respect what was asked for */
221 newsize = needed; 236 newsize = needed;
222 if (likely(newsize <= LUAI_MAXSTACK)) 237 if (l_likely(newsize <= LUAI_MAXSTACK))
223 return luaD_reallocstack(L, newsize, raiseerror); 238 return luaD_reallocstack(L, newsize, raiseerror);
224 else { /* stack overflow */ 239 else { /* stack overflow */
225 /* add extra size to be able to handle the error message */ 240 /* add extra size to be able to handle the error message */
@@ -294,8 +309,8 @@ void luaD_hook (lua_State *L, int event, int line,
294 if (hook && L->allowhook) { /* make sure there is a hook */ 309 if (hook && L->allowhook) { /* make sure there is a hook */
295 int mask = CIST_HOOKED; 310 int mask = CIST_HOOKED;
296 CallInfo *ci = L->ci; 311 CallInfo *ci = L->ci;
297 ptrdiff_t top = savestack(L, L->top); 312 ptrdiff_t top = savestack(L, L->top); /* preserve original 'top' */
298 ptrdiff_t ci_top = savestack(L, ci->top); 313 ptrdiff_t ci_top = savestack(L, ci->top); /* idem for 'ci->top' */
299 lua_Debug ar; 314 lua_Debug ar;
300 ar.event = event; 315 ar.event = event;
301 ar.currentline = line; 316 ar.currentline = line;
@@ -305,8 +320,10 @@ void luaD_hook (lua_State *L, int event, int line,
305 ci->u2.transferinfo.ftransfer = ftransfer; 320 ci->u2.transferinfo.ftransfer = ftransfer;
306 ci->u2.transferinfo.ntransfer = ntransfer; 321 ci->u2.transferinfo.ntransfer = ntransfer;
307 } 322 }
323 if (isLua(ci) && L->top < ci->top)
324 L->top = ci->top; /* protect entire activation register */
308 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ 325 luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */
309 if (L->top + LUA_MINSTACK > ci->top) 326 if (ci->top < L->top + LUA_MINSTACK)
310 ci->top = L->top + LUA_MINSTACK; 327 ci->top = L->top + LUA_MINSTACK;
311 L->allowhook = 0; /* cannot call hooks inside a hook */ 328 L->allowhook = 0; /* cannot call hooks inside a hook */
312 ci->callstatus |= mask; 329 ci->callstatus |= mask;
@@ -328,38 +345,40 @@ void luaD_hook (lua_State *L, int event, int line,
328** active. 345** active.
329*/ 346*/
330void luaD_hookcall (lua_State *L, CallInfo *ci) { 347void luaD_hookcall (lua_State *L, CallInfo *ci) {
331 int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL; 348 L->oldpc = 0; /* set 'oldpc' for new function */
332 Proto *p; 349 if (L->hookmask & LUA_MASKCALL) { /* is call hook on? */
333 if (!(L->hookmask & LUA_MASKCALL)) /* some other hook? */ 350 int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL
334 return; /* don't call hook */ 351 : LUA_HOOKCALL;
335 p = clLvalue(s2v(ci->func))->p;
336 L->top = ci->top; /* prepare top */
337 ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
338 luaD_hook(L, hook, -1, 1, p->numparams);
339 ci->u.l.savedpc--; /* correct 'pc' */
340}
341
342
343static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
344 ptrdiff_t oldtop = savestack(L, L->top); /* hook may change top */
345 int delta = 0;
346 if (isLuacode(ci)) {
347 Proto *p = ci_func(ci)->p; 352 Proto *p = ci_func(ci)->p;
348 if (p->is_vararg) 353 ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */
349 delta = ci->u.l.nextraargs + p->numparams + 1; 354 luaD_hook(L, event, -1, 1, p->numparams);
350 if (L->top < ci->top) 355 ci->u.l.savedpc--; /* correct 'pc' */
351 L->top = ci->top; /* correct top to run hook */
352 } 356 }
357}
358
359
360/*
361** Executes a return hook for Lua and C functions and sets/corrects
362** 'oldpc'. (Note that this correction is needed by the line hook, so it
363** is done even when return hooks are off.)
364*/
365static void rethook (lua_State *L, CallInfo *ci, int nres) {
353 if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ 366 if (L->hookmask & LUA_MASKRET) { /* is return hook on? */
367 StkId firstres = L->top - nres; /* index of first result */
368 int delta = 0; /* correction for vararg functions */
354 int ftransfer; 369 int ftransfer;
370 if (isLua(ci)) {
371 Proto *p = ci_func(ci)->p;
372 if (p->is_vararg)
373 delta = ci->u.l.nextraargs + p->numparams + 1;
374 }
355 ci->func += delta; /* if vararg, back to virtual 'func' */ 375 ci->func += delta; /* if vararg, back to virtual 'func' */
356 ftransfer = cast(unsigned short, firstres - ci->func); 376 ftransfer = cast(unsigned short, firstres - ci->func);
357 luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ 377 luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */
358 ci->func -= delta; 378 ci->func -= delta;
359 } 379 }
360 if (isLua(ci = ci->previous)) 380 if (isLua(ci = ci->previous))
361 L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* update 'oldpc' */ 381 L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */
362 return restorestack(L, oldtop);
363} 382}
364 383
365 384
@@ -371,7 +390,7 @@ static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
371void luaD_tryfuncTM (lua_State *L, StkId func) { 390void luaD_tryfuncTM (lua_State *L, StkId func) {
372 const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); 391 const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL);
373 StkId p; 392 StkId p;
374 if (unlikely(ttisnil(tm))) 393 if (l_unlikely(ttisnil(tm)))
375 luaG_callerror(L, s2v(func)); /* nothing to call */ 394 luaG_callerror(L, s2v(func)); /* nothing to call */
376 for (p = L->top; p > func; p--) /* open space for metamethod */ 395 for (p = L->top; p > func; p--) /* open space for metamethod */
377 setobjs2s(L, p, p-1); 396 setobjs2s(L, p, p-1);
@@ -396,27 +415,34 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
396 case 1: /* one value needed */ 415 case 1: /* one value needed */
397 if (nres == 0) /* no results? */ 416 if (nres == 0) /* no results? */
398 setnilvalue(s2v(res)); /* adjust with nil */ 417 setnilvalue(s2v(res)); /* adjust with nil */
399 else 418 else /* at least one result */
400 setobjs2s(L, res, L->top - nres); /* move it to proper place */ 419 setobjs2s(L, res, L->top - nres); /* move it to proper place */
401 L->top = res + 1; 420 L->top = res + 1;
402 return; 421 return;
403 case LUA_MULTRET: 422 case LUA_MULTRET:
404 wanted = nres; /* we want all results */ 423 wanted = nres; /* we want all results */
405 break; 424 break;
406 default: /* multiple results (or to-be-closed variables) */ 425 default: /* two/more results and/or to-be-closed variables */
407 if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ 426 if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */
408 ptrdiff_t savedres = savestack(L, res); 427 ptrdiff_t savedres = savestack(L, res);
409 luaF_close(L, res, CLOSEKTOP, 0); /* may change the stack */ 428 L->ci->callstatus |= CIST_CLSRET; /* in case of yields */
410 res = restorestack(L, savedres); 429 L->ci->u2.nres = nres;
411 wanted = codeNresults(wanted); /* correct value */ 430 luaF_close(L, res, CLOSEKTOP, 1);
431 L->ci->callstatus &= ~CIST_CLSRET;
432 if (L->hookmask) /* if needed, call hook after '__close's */
433 rethook(L, L->ci, nres);
434 res = restorestack(L, savedres); /* close and hook can move stack */
435 wanted = decodeNresults(wanted);
412 if (wanted == LUA_MULTRET) 436 if (wanted == LUA_MULTRET)
413 wanted = nres; 437 wanted = nres; /* we want all results */
414 } 438 }
415 break; 439 break;
416 } 440 }
441 /* generic case */
417 firstresult = L->top - nres; /* index of first result */ 442 firstresult = L->top - nres; /* index of first result */
418 /* move all results to correct place */ 443 if (nres > wanted) /* extra results? */
419 for (i = 0; i < nres && i < wanted; i++) 444 nres = wanted; /* don't need them */
445 for (i = 0; i < nres; i++) /* move all results to correct place */
420 setobjs2s(L, res + i, firstresult + i); 446 setobjs2s(L, res + i, firstresult + i);
421 for (; i < wanted; i++) /* complete wanted number of results */ 447 for (; i < wanted; i++) /* complete wanted number of results */
422 setnilvalue(s2v(res + i)); 448 setnilvalue(s2v(res + i));
@@ -425,15 +451,21 @@ static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
425 451
426 452
427/* 453/*
428** Finishes a function call: calls hook if necessary, removes CallInfo, 454** Finishes a function call: calls hook if necessary, moves current
429** moves current number of results to proper place. 455** number of results to proper place, and returns to previous call
456** info. If function has to close variables, hook must be called after
457** that.
430*/ 458*/
431void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { 459void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
432 if (L->hookmask) 460 int wanted = ci->nresults;
433 L->top = rethook(L, ci, L->top - nres, nres); 461 if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted)))
434 L->ci = ci->previous; /* back to caller */ 462 rethook(L, ci, nres);
435 /* move results to proper place */ 463 /* move results to proper place */
436 moveresults(L, ci->func, nres, ci->nresults); 464 moveresults(L, ci->func, nres, wanted);
465 /* function cannot be in any of these cases when returning */
466 lua_assert(!(ci->callstatus &
467 (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET)));
468 L->ci = ci->previous; /* back to caller (after closing variables) */
437} 469}
438 470
439 471
@@ -492,7 +524,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
492 ci->top = L->top + LUA_MINSTACK; 524 ci->top = L->top + LUA_MINSTACK;
493 ci->func = func; 525 ci->func = func;
494 lua_assert(ci->top <= L->stack_last); 526 lua_assert(ci->top <= L->stack_last);
495 if (L->hookmask & LUA_MASKCALL) { 527 if (l_unlikely(L->hookmask & LUA_MASKCALL)) {
496 int narg = cast_int(L->top - func) - 1; 528 int narg = cast_int(L->top - func) - 1;
497 luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); 529 luaD_hook(L, LUA_HOOKCALL, -1, 1, narg);
498 } 530 }
@@ -538,7 +570,7 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
538static void ccall (lua_State *L, StkId func, int nResults, int inc) { 570static void ccall (lua_State *L, StkId func, int nResults, int inc) {
539 CallInfo *ci; 571 CallInfo *ci;
540 L->nCcalls += inc; 572 L->nCcalls += inc;
541 if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) 573 if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
542 luaE_checkcstack(L); 574 luaE_checkcstack(L);
543 if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ 575 if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */
544 ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ 576 ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */
@@ -565,27 +597,74 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
565 597
566 598
567/* 599/*
568** Completes the execution of an interrupted C function, calling its 600** Finish the job of 'lua_pcallk' after it was interrupted by an yield.
569** continuation function. 601** (The caller, 'finishCcall', does the final call to 'adjustresults'.)
602** The main job is to complete the 'luaD_pcall' called by 'lua_pcallk'.
603** If a '__close' method yields here, eventually control will be back
604** to 'finishCcall' (when that '__close' method finally returns) and
605** 'finishpcallk' will run again and close any still pending '__close'
606** methods. Similarly, if a '__close' method errs, 'precover' calls
607** 'unroll' which calls ''finishCcall' and we are back here again, to
608** close any pending '__close' methods.
609** Note that, up to the call to 'luaF_close', the corresponding
610** 'CallInfo' is not modified, so that this repeated run works like the
611** first one (except that it has at least one less '__close' to do). In
612** particular, field CIST_RECST preserves the error status across these
613** multiple runs, changing only if there is a new error.
570*/ 614*/
571static void finishCcall (lua_State *L, int status) { 615static int finishpcallk (lua_State *L, CallInfo *ci) {
572 CallInfo *ci = L->ci; 616 int status = getcistrecst(ci); /* get original status */
573 int n; 617 if (l_likely(status == LUA_OK)) /* no error? */
574 /* must have a continuation and must be able to call it */ 618 status = LUA_YIELD; /* was interrupted by an yield */
575 lua_assert(ci->u.c.k != NULL && yieldable(L)); 619 else { /* error */
576 /* error status can only happen in a protected call */ 620 StkId func = restorestack(L, ci->u2.funcidx);
577 lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); 621 L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */
578 if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ 622 luaF_close(L, func, status, 1); /* can yield or raise an error */
579 ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ 623 func = restorestack(L, ci->u2.funcidx); /* stack may be moved */
580 L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ 624 luaD_seterrorobj(L, status, func);
581 } 625 luaD_shrinkstack(L); /* restore stack size in case of overflow */
582 /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already 626 setcistrecst(ci, LUA_OK); /* clear original status */
583 handled */ 627 }
584 adjustresults(L, ci->nresults); 628 ci->callstatus &= ~CIST_YPCALL;
585 lua_unlock(L); 629 L->errfunc = ci->u.c.old_errfunc;
586 n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ 630 /* if it is here, there were errors or yields; unlike 'lua_pcallk',
587 lua_lock(L); 631 do not change status */
588 api_checknelems(L, n); 632 return status;
633}
634
635
636/*
637** Completes the execution of a C function interrupted by an yield.
638** The interruption must have happened while the function was either
639** closing its tbc variables in 'moveresults' or executing
640** 'lua_callk'/'lua_pcallk'. In the first case, it just redoes
641** 'luaD_poscall'. In the second case, the call to 'finishpcallk'
642** finishes the interrupted execution of 'lua_pcallk'. After that, it
643** calls the continuation of the interrupted function and finally it
644** completes the job of the 'luaD_call' that called the function. In
645** the call to 'adjustresults', we do not know the number of results
646** of the function called by 'lua_callk'/'lua_pcallk', so we are
647** conservative and use LUA_MULTRET (always adjust).
648*/
649static void finishCcall (lua_State *L, CallInfo *ci) {
650 int n; /* actual number of results from C function */
651 if (ci->callstatus & CIST_CLSRET) { /* was returning? */
652 lua_assert(hastocloseCfunc(ci->nresults));
653 n = ci->u2.nres; /* just redo 'luaD_poscall' */
654 /* don't need to reset CIST_CLSRET, as it will be set again anyway */
655 }
656 else {
657 int status = LUA_YIELD; /* default if there were no errors */
658 /* must have a continuation and must be able to call it */
659 lua_assert(ci->u.c.k != NULL && yieldable(L));
660 if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */
661 status = finishpcallk(L, ci); /* finish it */
662 adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */
663 lua_unlock(L);
664 n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */
665 lua_lock(L);
666 api_checknelems(L, n);
667 }
589 luaD_poscall(L, ci, n); /* finish 'luaD_call' */ 668 luaD_poscall(L, ci, n); /* finish 'luaD_call' */
590} 669}
591 670
@@ -600,7 +679,7 @@ static void unroll (lua_State *L, void *ud) {
600 UNUSED(ud); 679 UNUSED(ud);
601 while ((ci = L->ci) != &L->base_ci) { /* something in the stack */ 680 while ((ci = L->ci) != &L->base_ci) { /* something in the stack */
602 if (!isLua(ci)) /* C function? */ 681 if (!isLua(ci)) /* C function? */
603 finishCcall(L, LUA_YIELD); /* complete its execution */ 682 finishCcall(L, ci); /* complete its execution */
604 else { /* Lua function */ 683 else { /* Lua function */
605 luaV_finishOp(L); /* finish interrupted instruction */ 684 luaV_finishOp(L); /* finish interrupted instruction */
606 luaV_execute(L, ci); /* execute down to higher C 'boundary' */ 685 luaV_execute(L, ci); /* execute down to higher C 'boundary' */
@@ -624,40 +703,6 @@ static CallInfo *findpcall (lua_State *L) {
624 703
625 704
626/* 705/*
627** Auxiliary structure to call 'recover' in protected mode.
628*/
629struct RecoverS {
630 int status;
631 CallInfo *ci;
632};
633
634
635/*
636** Recovers from an error in a coroutine: completes the execution of the
637** interrupted 'luaD_pcall', completes the interrupted C function which
638** called 'lua_pcallk', and continues running the coroutine. If there is
639** an error in 'luaF_close', this function will be called again and the
640** coroutine will continue from where it left.
641*/
642static void recover (lua_State *L, void *ud) {
643 struct RecoverS *r = cast(struct RecoverS *, ud);
644 int status = r->status;
645 CallInfo *ci = r->ci; /* recover point */
646 StkId func = restorestack(L, ci->u2.funcidx);
647 /* "finish" luaD_pcall */
648 L->ci = ci;
649 L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
650 luaF_close(L, func, status, 0); /* may change the stack */
651 func = restorestack(L, ci->u2.funcidx);
652 luaD_seterrorobj(L, status, func);
653 luaD_shrinkstack(L); /* restore stack size in case of overflow */
654 L->errfunc = ci->u.c.old_errfunc;
655 finishCcall(L, status); /* finish 'lua_pcallk' callee */
656 unroll(L, NULL); /* continue running the coroutine */
657}
658
659
660/*
661** Signal an error in the call to 'lua_resume', not in the execution 706** Signal an error in the call to 'lua_resume', not in the execution
662** of the coroutine itself. (Such errors should not be handled by any 707** of the coroutine itself. (Such errors should not be handled by any
663** coroutine error handler and should not kill the coroutine.) 708** coroutine error handler and should not kill the coroutine.)
@@ -688,8 +733,10 @@ static void resume (lua_State *L, void *ud) {
688 lua_assert(L->status == LUA_YIELD); 733 lua_assert(L->status == LUA_YIELD);
689 L->status = LUA_OK; /* mark that it is running (again) */ 734 L->status = LUA_OK; /* mark that it is running (again) */
690 luaE_incCstack(L); /* control the C stack */ 735 luaE_incCstack(L); /* control the C stack */
691 if (isLua(ci)) /* yielded inside a hook? */ 736 if (isLua(ci)) { /* yielded inside a hook? */
737 L->top = firstArg; /* discard arguments */
692 luaV_execute(L, ci); /* just continue running Lua code */ 738 luaV_execute(L, ci); /* just continue running Lua code */
739 }
693 else { /* 'common' yield */ 740 else { /* 'common' yield */
694 if (ci->u.c.k != NULL) { /* does it have a continuation function? */ 741 if (ci->u.c.k != NULL) { /* does it have a continuation function? */
695 lua_unlock(L); 742 lua_unlock(L);
@@ -705,19 +752,21 @@ static void resume (lua_State *L, void *ud) {
705 752
706 753
707/* 754/*
708** Calls 'recover' in protected mode, repeating while there are 755** Unrolls a coroutine in protected mode while there are recoverable
709** recoverable errors, that is, errors inside a protected call. (Any 756** errors, that is, errors inside a protected call. (Any error
710** error interrupts 'recover', and this loop protects it again so it 757** interrupts 'unroll', and this loop protects it again so it can
711** can continue.) Stops with a normal end (status == LUA_OK), an yield 758** continue.) Stops with a normal end (status == LUA_OK), an yield
712** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't 759** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't
713** find a recover point). 760** find a recover point).
714*/ 761*/
715static int p_recover (lua_State *L, int status) { 762static int precover (lua_State *L, int status) {
716 struct RecoverS r; 763 CallInfo *ci;
717 r.status = status; 764 while (errorstatus(status) && (ci = findpcall(L)) != NULL) {
718 while (errorstatus(status) && (r.ci = findpcall(L)) != NULL) 765 L->ci = ci; /* go down to recovery functions */
719 r.status = luaD_rawrunprotected(L, recover, &r); 766 setcistrecst(ci, status); /* status to finish 'pcall' */
720 return r.status; 767 status = luaD_rawrunprotected(L, unroll, NULL);
768 }
769 return status;
721} 770}
722 771
723 772
@@ -738,8 +787,8 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
738 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 787 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
739 status = luaD_rawrunprotected(L, resume, &nargs); 788 status = luaD_rawrunprotected(L, resume, &nargs);
740 /* continue running after recoverable errors */ 789 /* continue running after recoverable errors */
741 status = p_recover(L, status); 790 status = precover(L, status);
742 if (likely(!errorstatus(status))) 791 if (l_likely(!errorstatus(status)))
743 lua_assert(status == L->status); /* normal end or yield */ 792 lua_assert(status == L->status); /* normal end or yield */
744 else { /* unrecoverable error */ 793 else { /* unrecoverable error */
745 L->status = cast_byte(status); /* mark thread as 'dead' */ 794 L->status = cast_byte(status); /* mark thread as 'dead' */
@@ -765,22 +814,22 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
765 lua_lock(L); 814 lua_lock(L);
766 ci = L->ci; 815 ci = L->ci;
767 api_checknelems(L, nresults); 816 api_checknelems(L, nresults);
768 if (unlikely(!yieldable(L))) { 817 if (l_unlikely(!yieldable(L))) {
769 if (L != G(L)->mainthread) 818 if (L != G(L)->mainthread)
770 luaG_runerror(L, "attempt to yield across a C-call boundary"); 819 luaG_runerror(L, "attempt to yield across a C-call boundary");
771 else 820 else
772 luaG_runerror(L, "attempt to yield from outside a coroutine"); 821 luaG_runerror(L, "attempt to yield from outside a coroutine");
773 } 822 }
774 L->status = LUA_YIELD; 823 L->status = LUA_YIELD;
824 ci->u2.nyield = nresults; /* save number of results */
775 if (isLua(ci)) { /* inside a hook? */ 825 if (isLua(ci)) { /* inside a hook? */
776 lua_assert(!isLuacode(ci)); 826 lua_assert(!isLuacode(ci));
827 api_check(L, nresults == 0, "hooks cannot yield values");
777 api_check(L, k == NULL, "hooks cannot continue after yielding"); 828 api_check(L, k == NULL, "hooks cannot continue after yielding");
778 ci->u2.nyield = 0; /* no results */
779 } 829 }
780 else { 830 else {
781 if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ 831 if ((ci->u.c.k = k) != NULL) /* is there a continuation? */
782 ci->u.c.ctx = ctx; /* save context */ 832 ci->u.c.ctx = ctx; /* save context */
783 ci->u2.nyield = nresults; /* save number of results */
784 luaD_throw(L, LUA_YIELD); 833 luaD_throw(L, LUA_YIELD);
785 } 834 }
786 lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ 835 lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */
@@ -818,7 +867,7 @@ int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) {
818 struct CloseP pcl; 867 struct CloseP pcl;
819 pcl.level = restorestack(L, level); pcl.status = status; 868 pcl.level = restorestack(L, level); pcl.status = status;
820 status = luaD_rawrunprotected(L, &closepaux, &pcl); 869 status = luaD_rawrunprotected(L, &closepaux, &pcl);
821 if (likely(status == LUA_OK)) /* no more errors? */ 870 if (l_likely(status == LUA_OK)) /* no more errors? */
822 return pcl.status; 871 return pcl.status;
823 else { /* an error occurred; restore saved state and repeat */ 872 else { /* an error occurred; restore saved state and repeat */
824 L->ci = old_ci; 873 L->ci = old_ci;
@@ -841,7 +890,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u,
841 ptrdiff_t old_errfunc = L->errfunc; 890 ptrdiff_t old_errfunc = L->errfunc;
842 L->errfunc = ef; 891 L->errfunc = ef;
843 status = luaD_rawrunprotected(L, func, u); 892 status = luaD_rawrunprotected(L, func, u);
844 if (unlikely(status != LUA_OK)) { /* an error occurred? */ 893 if (l_unlikely(status != LUA_OK)) { /* an error occurred? */
845 L->ci = old_ci; 894 L->ci = old_ci;
846 L->allowhook = old_allowhooks; 895 L->allowhook = old_allowhooks;
847 status = luaD_closeprotected(L, old_top, status); 896 status = luaD_closeprotected(L, old_top, status);
diff --git a/src/lua/ldo.h b/src/lua/ldo.h
index c7721d6..6bf0ed8 100644
--- a/src/lua/ldo.h
+++ b/src/lua/ldo.h
@@ -23,7 +23,7 @@
23** at every check. 23** at every check.
24*/ 24*/
25#define luaD_checkstackaux(L,n,pre,pos) \ 25#define luaD_checkstackaux(L,n,pre,pos) \
26 if (L->stack_last - L->top <= (n)) \ 26 if (l_unlikely(L->stack_last - L->top <= (n))) \
27 { pre; luaD_growstack(L, n, 1); pos; } \ 27 { pre; luaD_growstack(L, n, 1); pos; } \
28 else { condmovestack(L,pre,pos); } 28 else { condmovestack(L,pre,pos); }
29 29
diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c
index 13e44d4..b4c04bd 100644
--- a/src/lua/lfunc.c
+++ b/src/lua/lfunc.c
@@ -120,11 +120,11 @@ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) {
120 120
121 121
122/* 122/*
123** Check whether 'obj' has a close metamethod and raise an error 123** Check whether object at given level has a close metamethod and raise
124** if not. 124** an error if not.
125*/ 125*/
126static void checkclosemth (lua_State *L, StkId level, const TValue *obj) { 126static void checkclosemth (lua_State *L, StkId level) {
127 const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); 127 const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE);
128 if (ttisnil(tm)) { /* no metamethod? */ 128 if (ttisnil(tm)) { /* no metamethod? */
129 int idx = cast_int(level - L->ci->func); /* variable index */ 129 int idx = cast_int(level - L->ci->func); /* variable index */
130 const char *vname = luaG_findlocal(L, L->ci, idx, NULL); 130 const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
@@ -155,33 +155,21 @@ static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) {
155 155
156 156
157/* 157/*
158** Try to create a to-be-closed upvalue 158** Insert a variable in the list of to-be-closed variables.
159** (can raise a memory-allocation error)
160*/
161static void trynewtbcupval (lua_State *L, void *ud) {
162 newupval(L, 1, cast(StkId, ud), &L->openupval);
163}
164
165
166/*
167** Create a to-be-closed upvalue. If there is a memory error
168** when creating the upvalue, the closing method must be called here,
169** as there is no upvalue to call it later.
170*/ 159*/
171void luaF_newtbcupval (lua_State *L, StkId level) { 160void luaF_newtbcupval (lua_State *L, StkId level) {
172 TValue *obj = s2v(level); 161 lua_assert(level > L->tbclist);
173 lua_assert(L->openupval == NULL || uplevel(L->openupval) < level); 162 if (l_isfalse(s2v(level)))
174 if (!l_isfalse(obj)) { /* false doesn't need to be closed */ 163 return; /* false doesn't need to be closed */
175 int status; 164 checkclosemth(L, level); /* value must have a close method */
176 checkclosemth(L, level, obj); 165 while (level - L->tbclist > USHRT_MAX) { /* is delta too large? */
177 status = luaD_rawrunprotected(L, trynewtbcupval, level); 166 L->tbclist += USHRT_MAX; /* create a dummy node at maximum delta */
178 if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */ 167 L->tbclist->tbclist.delta = USHRT_MAX;
179 lua_assert(status == LUA_ERRMEM); 168 L->tbclist->tbclist.isdummy = 1;
180 luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */
181 callclosemethod(L, s2v(level), s2v(level + 1), 0);
182 luaD_throw(L, LUA_ERRMEM); /* throw memory error */
183 }
184 } 169 }
170 level->tbclist.delta = level - L->tbclist;
171 level->tbclist.isdummy = 0;
172 L->tbclist = level;
185} 173}
186 174
187 175
@@ -194,11 +182,9 @@ void luaF_unlinkupval (UpVal *uv) {
194 182
195 183
196/* 184/*
197** Close all upvalues up to the given stack level. A 'status' equal 185** Close all upvalues up to the given stack level.
198** to NOCLOSINGMETH closes upvalues without running any __close
199** metamethods.
200*/ 186*/
201void luaF_close (lua_State *L, StkId level, int status, int yy) { 187void luaF_closeupval (lua_State *L, StkId level) {
202 UpVal *uv; 188 UpVal *uv;
203 StkId upl; /* stack index pointed by 'uv' */ 189 StkId upl; /* stack index pointed by 'uv' */
204 while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { 190 while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) {
@@ -211,9 +197,22 @@ void luaF_close (lua_State *L, StkId level, int status, int yy) {
211 nw2black(uv); /* closed upvalues cannot be gray */ 197 nw2black(uv); /* closed upvalues cannot be gray */
212 luaC_barrier(L, uv, slot); 198 luaC_barrier(L, uv, slot);
213 } 199 }
214 if (uv->tbc && status != NOCLOSINGMETH) { 200 }
215 ptrdiff_t levelrel = savestack(L, level); 201}
216 prepcallclosemth(L, upl, status, yy); /* may change the stack */ 202
203
204/*
205** Close all upvalues and to-be-closed variables up to the given stack
206** level.
207*/
208void luaF_close (lua_State *L, StkId level, int status, int yy) {
209 ptrdiff_t levelrel = savestack(L, level);
210 luaF_closeupval(L, level); /* first, close the upvalues */
211 while (L->tbclist >= level) { /* traverse tbc's down to that level */
212 StkId tbc = L->tbclist; /* get variable index */
213 L->tbclist -= tbc->tbclist.delta; /* remove it from list */
214 if (!tbc->tbclist.isdummy) { /* not a dummy entry? */
215 prepcallclosemth(L, tbc, status, yy); /* close variable */
217 level = restorestack(L, levelrel); 216 level = restorestack(L, levelrel);
218 } 217 }
219 } 218 }
diff --git a/src/lua/lfunc.h b/src/lua/lfunc.h
index 2e6df53..dc1cebc 100644
--- a/src/lua/lfunc.h
+++ b/src/lua/lfunc.h
@@ -42,15 +42,9 @@
42#define MAXMISS 10 42#define MAXMISS 10
43 43
44 44
45/*
46** Special "status" for 'luaF_close'
47*/
48
49/* close upvalues without running their closing methods */
50#define NOCLOSINGMETH (-1)
51 45
52/* special status to close upvalues preserving the top of the stack */ 46/* special status to close upvalues preserving the top of the stack */
53#define CLOSEKTOP (-2) 47#define CLOSEKTOP (-1)
54 48
55 49
56LUAI_FUNC Proto *luaF_newproto (lua_State *L); 50LUAI_FUNC Proto *luaF_newproto (lua_State *L);
@@ -59,6 +53,7 @@ LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nupvals);
59LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); 53LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
60LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); 54LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
61LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); 55LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level);
56LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level);
62LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy); 57LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy);
63LUAI_FUNC void luaF_unlinkupval (UpVal *uv); 58LUAI_FUNC void luaF_unlinkupval (UpVal *uv);
64LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); 59LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
diff --git a/src/lua/lgc.c b/src/lua/lgc.c
index bab9beb..b360eed 100644
--- a/src/lua/lgc.c
+++ b/src/lua/lgc.c
@@ -916,7 +916,7 @@ static void GCTM (lua_State *L) {
916 L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ 916 L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */
917 L->allowhook = oldah; /* restore hooks */ 917 L->allowhook = oldah; /* restore hooks */
918 g->gcrunning = running; /* restore state */ 918 g->gcrunning = running; /* restore state */
919 if (unlikely(status != LUA_OK)) { /* error while running __gc? */ 919 if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */
920 luaE_warnerror(L, "__gc metamethod"); 920 luaE_warnerror(L, "__gc metamethod");
921 L->top--; /* pops error object */ 921 L->top--; /* pops error object */
922 } 922 }
@@ -1575,52 +1575,64 @@ static int sweepstep (lua_State *L, global_State *g,
1575 1575
1576static lu_mem singlestep (lua_State *L) { 1576static lu_mem singlestep (lua_State *L) {
1577 global_State *g = G(L); 1577 global_State *g = G(L);
1578 lu_mem work;
1579 lua_assert(!g->gcstopem); /* collector is not reentrant */
1580 g->gcstopem = 1; /* no emergency collections while collecting */
1578 switch (g->gcstate) { 1581 switch (g->gcstate) {
1579 case GCSpause: { 1582 case GCSpause: {
1580 restartcollection(g); 1583 restartcollection(g);
1581 g->gcstate = GCSpropagate; 1584 g->gcstate = GCSpropagate;
1582 return 1; 1585 work = 1;
1586 break;
1583 } 1587 }
1584 case GCSpropagate: { 1588 case GCSpropagate: {
1585 if (g->gray == NULL) { /* no more gray objects? */ 1589 if (g->gray == NULL) { /* no more gray objects? */
1586 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1590 g->gcstate = GCSenteratomic; /* finish propagate phase */
1587 return 0; 1591 work = 0;
1588 } 1592 }
1589 else 1593 else
1590 return propagatemark(g); /* traverse one gray object */ 1594 work = propagatemark(g); /* traverse one gray object */
1595 break;
1591 } 1596 }
1592 case GCSenteratomic: { 1597 case GCSenteratomic: {
1593 lu_mem work = atomic(L); /* work is what was traversed by 'atomic' */ 1598 work = atomic(L); /* work is what was traversed by 'atomic' */
1594 entersweep(L); 1599 entersweep(L);
1595 g->GCestimate = gettotalbytes(g); /* first estimate */; 1600 g->GCestimate = gettotalbytes(g); /* first estimate */;
1596 return work; 1601 break;
1597 } 1602 }
1598 case GCSswpallgc: { /* sweep "regular" objects */ 1603 case GCSswpallgc: { /* sweep "regular" objects */
1599 return sweepstep(L, g, GCSswpfinobj, &g->finobj); 1604 work = sweepstep(L, g, GCSswpfinobj, &g->finobj);
1605 break;
1600 } 1606 }
1601 case GCSswpfinobj: { /* sweep objects with finalizers */ 1607 case GCSswpfinobj: { /* sweep objects with finalizers */
1602 return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1608 work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1609 break;
1603 } 1610 }
1604 case GCSswptobefnz: { /* sweep objects to be finalized */ 1611 case GCSswptobefnz: { /* sweep objects to be finalized */
1605 return sweepstep(L, g, GCSswpend, NULL); 1612 work = sweepstep(L, g, GCSswpend, NULL);
1613 break;
1606 } 1614 }
1607 case GCSswpend: { /* finish sweeps */ 1615 case GCSswpend: { /* finish sweeps */
1608 checkSizes(L, g); 1616 checkSizes(L, g);
1609 g->gcstate = GCScallfin; 1617 g->gcstate = GCScallfin;
1610 return 0; 1618 work = 0;
1619 break;
1611 } 1620 }
1612 case GCScallfin: { /* call remaining finalizers */ 1621 case GCScallfin: { /* call remaining finalizers */
1613 if (g->tobefnz && !g->gcemergency) { 1622 if (g->tobefnz && !g->gcemergency) {
1614 int n = runafewfinalizers(L, GCFINMAX); 1623 g->gcstopem = 0; /* ok collections during finalizers */
1615 return n * GCFINALIZECOST; 1624 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST;
1616 } 1625 }
1617 else { /* emergency mode or no more finalizers */ 1626 else { /* emergency mode or no more finalizers */
1618 g->gcstate = GCSpause; /* finish collection */ 1627 g->gcstate = GCSpause; /* finish collection */
1619 return 0; 1628 work = 0;
1620 } 1629 }
1630 break;
1621 } 1631 }
1622 default: lua_assert(0); return 0; 1632 default: lua_assert(0); return 0;
1623 } 1633 }
1634 g->gcstopem = 0;
1635 return work;
1624} 1636}
1625 1637
1626 1638
diff --git a/src/lua/liolib.c b/src/lua/liolib.c
index 7951672..b08397d 100644
--- a/src/lua/liolib.c
+++ b/src/lua/liolib.c
@@ -186,7 +186,7 @@ static int f_tostring (lua_State *L) {
186 186
187static FILE *tofile (lua_State *L) { 187static FILE *tofile (lua_State *L) {
188 LStream *p = tolstream(L); 188 LStream *p = tolstream(L);
189 if (isclosed(p)) 189 if (l_unlikely(isclosed(p)))
190 luaL_error(L, "attempt to use a closed file"); 190 luaL_error(L, "attempt to use a closed file");
191 lua_assert(p->f); 191 lua_assert(p->f);
192 return p->f; 192 return p->f;
@@ -261,7 +261,7 @@ static LStream *newfile (lua_State *L) {
261static void opencheck (lua_State *L, const char *fname, const char *mode) { 261static void opencheck (lua_State *L, const char *fname, const char *mode) {
262 LStream *p = newfile(L); 262 LStream *p = newfile(L);
263 p->f = fopen(fname, mode); 263 p->f = fopen(fname, mode);
264 if (p->f == NULL) 264 if (l_unlikely(p->f == NULL))
265 luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); 265 luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
266} 266}
267 267
@@ -309,7 +309,7 @@ static FILE *getiofile (lua_State *L, const char *findex) {
309 LStream *p; 309 LStream *p;
310 lua_getfield(L, LUA_REGISTRYINDEX, findex); 310 lua_getfield(L, LUA_REGISTRYINDEX, findex);
311 p = (LStream *)lua_touserdata(L, -1); 311 p = (LStream *)lua_touserdata(L, -1);
312 if (isclosed(p)) 312 if (l_unlikely(isclosed(p)))
313 luaL_error(L, "default %s file is closed", findex + IOPREF_LEN); 313 luaL_error(L, "default %s file is closed", findex + IOPREF_LEN);
314 return p->f; 314 return p->f;
315} 315}
@@ -436,7 +436,7 @@ typedef struct {
436** Add current char to buffer (if not out of space) and read next one 436** Add current char to buffer (if not out of space) and read next one
437*/ 437*/
438static int nextc (RN *rn) { 438static int nextc (RN *rn) {
439 if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */ 439 if (l_unlikely(rn->n >= L_MAXLENNUM)) { /* buffer overflow? */
440 rn->buff[0] = '\0'; /* invalidate result */ 440 rn->buff[0] = '\0'; /* invalidate result */
441 return 0; /* fail */ 441 return 0; /* fail */
442 } 442 }
@@ -499,8 +499,8 @@ static int read_number (lua_State *L, FILE *f) {
499 ungetc(rn.c, rn.f); /* unread look-ahead char */ 499 ungetc(rn.c, rn.f); /* unread look-ahead char */
500 l_unlockfile(rn.f); 500 l_unlockfile(rn.f);
501 rn.buff[rn.n] = '\0'; /* finish string */ 501 rn.buff[rn.n] = '\0'; /* finish string */
502 if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */ 502 if (l_likely(lua_stringtonumber(L, rn.buff)))
503 return 1; /* ok */ 503 return 1; /* ok, it is a valid number */
504 else { /* invalid format */ 504 else { /* invalid format */
505 lua_pushnil(L); /* "result" to be removed */ 505 lua_pushnil(L); /* "result" to be removed */
506 return 0; /* read fails */ 506 return 0; /* read fails */
@@ -676,7 +676,8 @@ static int g_write (lua_State *L, FILE *f, int arg) {
676 status = status && (fwrite(s, sizeof(char), l, f) == l); 676 status = status && (fwrite(s, sizeof(char), l, f) == l);
677 } 677 }
678 } 678 }
679 if (status) return 1; /* file handle already on stack top */ 679 if (l_likely(status))
680 return 1; /* file handle already on stack top */
680 else return luaL_fileresult(L, status, NULL); 681 else return luaL_fileresult(L, status, NULL);
681} 682}
682 683
@@ -703,7 +704,7 @@ static int f_seek (lua_State *L) {
703 luaL_argcheck(L, (lua_Integer)offset == p3, 3, 704 luaL_argcheck(L, (lua_Integer)offset == p3, 3,
704 "not an integer in proper range"); 705 "not an integer in proper range");
705 op = l_fseek(f, offset, mode[op]); 706 op = l_fseek(f, offset, mode[op]);
706 if (op) 707 if (l_unlikely(op))
707 return luaL_fileresult(L, 0, NULL); /* error */ 708 return luaL_fileresult(L, 0, NULL); /* error */
708 else { 709 else {
709 lua_pushinteger(L, (lua_Integer)l_ftell(f)); 710 lua_pushinteger(L, (lua_Integer)l_ftell(f));
diff --git a/src/lua/llimits.h b/src/lua/llimits.h
index d039483..025f1c8 100644
--- a/src/lua/llimits.h
+++ b/src/lua/llimits.h
@@ -150,22 +150,6 @@ typedef LUAI_UACINT l_uacInt;
150 150
151 151
152/* 152/*
153** macros to improve jump prediction (used mainly for error handling)
154*/
155#if !defined(likely)
156
157#if defined(__GNUC__)
158#define likely(x) (__builtin_expect(((x) != 0), 1))
159#define unlikely(x) (__builtin_expect(((x) != 0), 0))
160#else
161#define likely(x) (x)
162#define unlikely(x) (x)
163#endif
164
165#endif
166
167
168/*
169** non-return type 153** non-return type
170*/ 154*/
171#if !defined(l_noret) 155#if !defined(l_noret)
diff --git a/src/lua/lmathlib.c b/src/lua/lmathlib.c
index 86def47..5f5983a 100644
--- a/src/lua/lmathlib.c
+++ b/src/lua/lmathlib.c
@@ -73,7 +73,7 @@ static int math_atan (lua_State *L) {
73static int math_toint (lua_State *L) { 73static int math_toint (lua_State *L) {
74 int valid; 74 int valid;
75 lua_Integer n = lua_tointegerx(L, 1, &valid); 75 lua_Integer n = lua_tointegerx(L, 1, &valid);
76 if (valid) 76 if (l_likely(valid))
77 lua_pushinteger(L, n); 77 lua_pushinteger(L, n);
78 else { 78 else {
79 luaL_checkany(L, 1); 79 luaL_checkany(L, 1);
@@ -175,7 +175,8 @@ static int math_log (lua_State *L) {
175 lua_Number base = luaL_checknumber(L, 2); 175 lua_Number base = luaL_checknumber(L, 2);
176#if !defined(LUA_USE_C89) 176#if !defined(LUA_USE_C89)
177 if (base == l_mathop(2.0)) 177 if (base == l_mathop(2.0))
178 res = l_mathop(log2)(x); else 178 res = l_mathop(log2)(x);
179 else
179#endif 180#endif
180 if (base == l_mathop(10.0)) 181 if (base == l_mathop(10.0))
181 res = l_mathop(log10)(x); 182 res = l_mathop(log10)(x);
diff --git a/src/lua/lmem.c b/src/lua/lmem.c
index 43739bf..9029d58 100644
--- a/src/lua/lmem.c
+++ b/src/lua/lmem.c
@@ -24,12 +24,12 @@
24 24
25#if defined(EMERGENCYGCTESTS) 25#if defined(EMERGENCYGCTESTS)
26/* 26/*
27** First allocation will fail whenever not building initial state 27** First allocation will fail whenever not building initial state.
28** and not shrinking a block. (This fail will trigger 'tryagain' and 28** (This fail will trigger 'tryagain' and a full GC cycle at every
29** a full GC cycle at every allocation.) 29** allocation.)
30*/ 30*/
31static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { 31static void *firsttry (global_State *g, void *block, size_t os, size_t ns) {
32 if (ttisnil(&g->nilvalue) && ns > os) 32 if (completestate(g) && ns > 0) /* frees never fail */
33 return NULL; /* fail */ 33 return NULL; /* fail */
34 else /* normal allocation */ 34 else /* normal allocation */
35 return (*g->frealloc)(g->ud, block, os, ns); 35 return (*g->frealloc)(g->ud, block, os, ns);
@@ -83,7 +83,7 @@ void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize,
83 if (nelems + 1 <= size) /* does one extra element still fit? */ 83 if (nelems + 1 <= size) /* does one extra element still fit? */
84 return block; /* nothing to be done */ 84 return block; /* nothing to be done */
85 if (size >= limit / 2) { /* cannot double it? */ 85 if (size >= limit / 2) { /* cannot double it? */
86 if (unlikely(size >= limit)) /* cannot grow even a little? */ 86 if (l_unlikely(size >= limit)) /* cannot grow even a little? */
87 luaG_runerror(L, "too many %s (limit is %d)", what, limit); 87 luaG_runerror(L, "too many %s (limit is %d)", what, limit);
88 size = limit; /* still have at least one free place */ 88 size = limit; /* still have at least one free place */
89 } 89 }
@@ -138,15 +138,17 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) {
138 138
139 139
140/* 140/*
141** In case of allocation fail, this function will call the GC to try 141** In case of allocation fail, this function will do an emergency
142** to free some memory and then try the allocation again. 142** collection to free some memory and then try the allocation again.
143** (It should not be called when shrinking a block, because then the 143** The GC should not be called while state is not fully built, as the
144** interpreter may be in the middle of a collection step.) 144** collector is not yet fully initialized. Also, it should not be called
145** when 'gcstopem' is true, because then the interpreter is in the
146** middle of a collection step.
145*/ 147*/
146static void *tryagain (lua_State *L, void *block, 148static void *tryagain (lua_State *L, void *block,
147 size_t osize, size_t nsize) { 149 size_t osize, size_t nsize) {
148 global_State *g = G(L); 150 global_State *g = G(L);
149 if (ttisnil(&g->nilvalue)) { /* is state fully build? */ 151 if (completestate(g) && !g->gcstopem) {
150 luaC_fullgc(L, 1); /* try to free some memory... */ 152 luaC_fullgc(L, 1); /* try to free some memory... */
151 return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ 153 return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
152 } 154 }
@@ -156,17 +158,14 @@ static void *tryagain (lua_State *L, void *block,
156 158
157/* 159/*
158** Generic allocation routine. 160** Generic allocation routine.
159** If allocation fails while shrinking a block, do not try again; the
160** GC shrinks some blocks and it is not reentrant.
161*/ 161*/
162void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { 162void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
163 void *newblock; 163 void *newblock;
164 global_State *g = G(L); 164 global_State *g = G(L);
165 lua_assert((osize == 0) == (block == NULL)); 165 lua_assert((osize == 0) == (block == NULL));
166 newblock = firsttry(g, block, osize, nsize); 166 newblock = firsttry(g, block, osize, nsize);
167 if (unlikely(newblock == NULL && nsize > 0)) { 167 if (l_unlikely(newblock == NULL && nsize > 0)) {
168 if (nsize > osize) /* not shrinking a block? */ 168 newblock = tryagain(L, block, osize, nsize);
169 newblock = tryagain(L, block, osize, nsize);
170 if (newblock == NULL) /* still no memory? */ 169 if (newblock == NULL) /* still no memory? */
171 return NULL; /* do not update 'GCdebt' */ 170 return NULL; /* do not update 'GCdebt' */
172 } 171 }
@@ -179,7 +178,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
179void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize, 178void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize,
180 size_t nsize) { 179 size_t nsize) {
181 void *newblock = luaM_realloc_(L, block, osize, nsize); 180 void *newblock = luaM_realloc_(L, block, osize, nsize);
182 if (unlikely(newblock == NULL && nsize > 0)) /* allocation failed? */ 181 if (l_unlikely(newblock == NULL && nsize > 0)) /* allocation failed? */
183 luaM_error(L); 182 luaM_error(L);
184 return newblock; 183 return newblock;
185} 184}
@@ -191,7 +190,7 @@ void *luaM_malloc_ (lua_State *L, size_t size, int tag) {
191 else { 190 else {
192 global_State *g = G(L); 191 global_State *g = G(L);
193 void *newblock = firsttry(g, NULL, tag, size); 192 void *newblock = firsttry(g, NULL, tag, size);
194 if (unlikely(newblock == NULL)) { 193 if (l_unlikely(newblock == NULL)) {
195 newblock = tryagain(L, NULL, tag, size); 194 newblock = tryagain(L, NULL, tag, size);
196 if (newblock == NULL) 195 if (newblock == NULL)
197 luaM_error(L); 196 luaM_error(L);
diff --git a/src/lua/loadlib.c b/src/lua/loadlib.c
index c0ec9a1..6f9fa37 100644
--- a/src/lua/loadlib.c
+++ b/src/lua/loadlib.c
@@ -132,14 +132,16 @@ static void lsys_unloadlib (void *lib) {
132 132
133static void *lsys_load (lua_State *L, const char *path, int seeglb) { 133static void *lsys_load (lua_State *L, const char *path, int seeglb) {
134 void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); 134 void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL));
135 if (lib == NULL) lua_pushstring(L, dlerror()); 135 if (l_unlikely(lib == NULL))
136 lua_pushstring(L, dlerror());
136 return lib; 137 return lib;
137} 138}
138 139
139 140
140static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { 141static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) {
141 lua_CFunction f = cast_func(dlsym(lib, sym)); 142 lua_CFunction f = cast_func(dlsym(lib, sym));
142 if (f == NULL) lua_pushstring(L, dlerror()); 143 if (l_unlikely(f == NULL))
144 lua_pushstring(L, dlerror());
143 return f; 145 return f;
144} 146}
145 147
@@ -410,7 +412,7 @@ static int ll_loadlib (lua_State *L) {
410 const char *path = luaL_checkstring(L, 1); 412 const char *path = luaL_checkstring(L, 1);
411 const char *init = luaL_checkstring(L, 2); 413 const char *init = luaL_checkstring(L, 2);
412 int stat = lookforfunc(L, path, init); 414 int stat = lookforfunc(L, path, init);
413 if (stat == 0) /* no errors? */ 415 if (l_likely(stat == 0)) /* no errors? */
414 return 1; /* return the loaded function */ 416 return 1; /* return the loaded function */
415 else { /* error; error message is on stack top */ 417 else { /* error; error message is on stack top */
416 luaL_pushfail(L); 418 luaL_pushfail(L);
@@ -523,14 +525,14 @@ static const char *findfile (lua_State *L, const char *name,
523 const char *path; 525 const char *path;
524 lua_getfield(L, lua_upvalueindex(1), pname); 526 lua_getfield(L, lua_upvalueindex(1), pname);
525 path = lua_tostring(L, -1); 527 path = lua_tostring(L, -1);
526 if (path == NULL) 528 if (l_unlikely(path == NULL))
527 luaL_error(L, "'package.%s' must be a string", pname); 529 luaL_error(L, "'package.%s' must be a string", pname);
528 return searchpath(L, name, path, ".", dirsep); 530 return searchpath(L, name, path, ".", dirsep);
529} 531}
530 532
531 533
532static int checkload (lua_State *L, int stat, const char *filename) { 534static int checkload (lua_State *L, int stat, const char *filename) {
533 if (stat) { /* module loaded successfully? */ 535 if (l_likely(stat)) { /* module loaded successfully? */
534 lua_pushstring(L, filename); /* will be 2nd argument to module */ 536 lua_pushstring(L, filename); /* will be 2nd argument to module */
535 return 2; /* return open function and file name */ 537 return 2; /* return open function and file name */
536 } 538 }
@@ -623,13 +625,14 @@ static void findloader (lua_State *L, const char *name) {
623 int i; 625 int i;
624 luaL_Buffer msg; /* to build error message */ 626 luaL_Buffer msg; /* to build error message */
625 /* push 'package.searchers' to index 3 in the stack */ 627 /* push 'package.searchers' to index 3 in the stack */
626 if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) 628 if (l_unlikely(lua_getfield(L, lua_upvalueindex(1), "searchers")
629 != LUA_TTABLE))
627 luaL_error(L, "'package.searchers' must be a table"); 630 luaL_error(L, "'package.searchers' must be a table");
628 luaL_buffinit(L, &msg); 631 luaL_buffinit(L, &msg);
629 /* iterate over available searchers to find a loader */ 632 /* iterate over available searchers to find a loader */
630 for (i = 1; ; i++) { 633 for (i = 1; ; i++) {
631 luaL_addstring(&msg, "\n\t"); /* error-message prefix */ 634 luaL_addstring(&msg, "\n\t"); /* error-message prefix */
632 if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ 635 if (l_unlikely(lua_rawgeti(L, 3, i) == LUA_TNIL)) { /* no more searchers? */
633 lua_pop(L, 1); /* remove nil */ 636 lua_pop(L, 1); /* remove nil */
634 luaL_buffsub(&msg, 2); /* remove prefix */ 637 luaL_buffsub(&msg, 2); /* remove prefix */
635 luaL_pushresult(&msg); /* create error message */ 638 luaL_pushresult(&msg); /* create error message */
diff --git a/src/lua/lobject.h b/src/lua/lobject.h
index 470b17d..1a7a737 100644
--- a/src/lua/lobject.h
+++ b/src/lua/lobject.h
@@ -136,10 +136,18 @@ typedef struct TValue {
136 136
137 137
138/* 138/*
139** Entries in the Lua stack 139** Entries in a Lua stack. Field 'tbclist' forms a list of all
140** to-be-closed variables active in this stack. Dummy entries are
141** used when the distance between two tbc variables does not fit
142** in an unsigned short.
140*/ 143*/
141typedef union StackValue { 144typedef union StackValue {
142 TValue val; 145 TValue val;
146 struct {
147 TValuefields;
148 lu_byte isdummy;
149 unsigned short delta;
150 } tbclist;
143} StackValue; 151} StackValue;
144 152
145 153
diff --git a/src/lua/lopcodes.h b/src/lua/lopcodes.h
index 120cdd9..d6a47e5 100644
--- a/src/lua/lopcodes.h
+++ b/src/lua/lopcodes.h
@@ -225,13 +225,13 @@ OP_SELF,/* A B C R[A+1] := R[B]; R[A] := R[B][RK(C):string] */
225 225
226OP_ADDI,/* A B sC R[A] := R[B] + sC */ 226OP_ADDI,/* A B sC R[A] := R[B] + sC */
227 227
228OP_ADDK,/* A B C R[A] := R[B] + K[C] */ 228OP_ADDK,/* A B C R[A] := R[B] + K[C]:number */
229OP_SUBK,/* A B C R[A] := R[B] - K[C] */ 229OP_SUBK,/* A B C R[A] := R[B] - K[C]:number */
230OP_MULK,/* A B C R[A] := R[B] * K[C] */ 230OP_MULK,/* A B C R[A] := R[B] * K[C]:number */
231OP_MODK,/* A B C R[A] := R[B] % K[C] */ 231OP_MODK,/* A B C R[A] := R[B] % K[C]:number */
232OP_POWK,/* A B C R[A] := R[B] ^ K[C] */ 232OP_POWK,/* A B C R[A] := R[B] ^ K[C]:number */
233OP_DIVK,/* A B C R[A] := R[B] / K[C] */ 233OP_DIVK,/* A B C R[A] := R[B] / K[C]:number */
234OP_IDIVK,/* A B C R[A] := R[B] // K[C] */ 234OP_IDIVK,/* A B C R[A] := R[B] // K[C]:number */
235 235
236OP_BANDK,/* A B C R[A] := R[B] & K[C]:integer */ 236OP_BANDK,/* A B C R[A] := R[B] & K[C]:integer */
237OP_BORK,/* A B C R[A] := R[B] | K[C]:integer */ 237OP_BORK,/* A B C R[A] := R[B] | K[C]:integer */
diff --git a/src/lua/loslib.c b/src/lua/loslib.c
index e65e188..3e20d62 100644
--- a/src/lua/loslib.c
+++ b/src/lua/loslib.c
@@ -170,7 +170,7 @@ static int os_tmpname (lua_State *L) {
170 char buff[LUA_TMPNAMBUFSIZE]; 170 char buff[LUA_TMPNAMBUFSIZE];
171 int err; 171 int err;
172 lua_tmpnam(buff, err); 172 lua_tmpnam(buff, err);
173 if (err) 173 if (l_unlikely(err))
174 return luaL_error(L, "unable to generate a unique filename"); 174 return luaL_error(L, "unable to generate a unique filename");
175 lua_pushstring(L, buff); 175 lua_pushstring(L, buff);
176 return 1; 176 return 1;
@@ -208,7 +208,7 @@ static int os_clock (lua_State *L) {
208*/ 208*/
209static void setfield (lua_State *L, const char *key, int value, int delta) { 209static void setfield (lua_State *L, const char *key, int value, int delta) {
210 #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX) 210 #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX)
211 if (value > LUA_MAXINTEGER - delta) 211 if (l_unlikely(value > LUA_MAXINTEGER - delta))
212 luaL_error(L, "field '%s' is out-of-bound", key); 212 luaL_error(L, "field '%s' is out-of-bound", key);
213 #endif 213 #endif
214 lua_pushinteger(L, (lua_Integer)value + delta); 214 lua_pushinteger(L, (lua_Integer)value + delta);
@@ -253,9 +253,9 @@ static int getfield (lua_State *L, const char *key, int d, int delta) {
253 int t = lua_getfield(L, -1, key); /* get field and its type */ 253 int t = lua_getfield(L, -1, key); /* get field and its type */
254 lua_Integer res = lua_tointegerx(L, -1, &isnum); 254 lua_Integer res = lua_tointegerx(L, -1, &isnum);
255 if (!isnum) { /* field is not an integer? */ 255 if (!isnum) { /* field is not an integer? */
256 if (t != LUA_TNIL) /* some other value? */ 256 if (l_unlikely(t != LUA_TNIL)) /* some other value? */
257 return luaL_error(L, "field '%s' is not an integer", key); 257 return luaL_error(L, "field '%s' is not an integer", key);
258 else if (d < 0) /* absent field; no default? */ 258 else if (l_unlikely(d < 0)) /* absent field; no default? */
259 return luaL_error(L, "field '%s' missing in date table", key); 259 return luaL_error(L, "field '%s' missing in date table", key);
260 res = d; 260 res = d;
261 } 261 }
diff --git a/src/lua/lparser.c b/src/lua/lparser.c
index 249ba9a..284ef1f 100644
--- a/src/lua/lparser.c
+++ b/src/lua/lparser.c
@@ -128,7 +128,7 @@ static void checknext (LexState *ls, int c) {
128** in line 'where' (if that is not the current line). 128** in line 'where' (if that is not the current line).
129*/ 129*/
130static void check_match (LexState *ls, int what, int who, int where) { 130static void check_match (LexState *ls, int what, int who, int where) {
131 if (unlikely(!testnext(ls, what))) { 131 if (l_unlikely(!testnext(ls, what))) {
132 if (where == ls->linenumber) /* all in the same line? */ 132 if (where == ls->linenumber) /* all in the same line? */
133 error_expected(ls, what); /* do not need a complex message */ 133 error_expected(ls, what); /* do not need a complex message */
134 else { 134 else {
@@ -517,7 +517,7 @@ static void solvegoto (LexState *ls, int g, Labeldesc *label) {
517 Labellist *gl = &ls->dyd->gt; /* list of goto's */ 517 Labellist *gl = &ls->dyd->gt; /* list of goto's */
518 Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */ 518 Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */
519 lua_assert(eqstr(gt->name, label->name)); 519 lua_assert(eqstr(gt->name, label->name));
520 if (unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */ 520 if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */
521 jumpscopeerror(ls, gt); 521 jumpscopeerror(ls, gt);
522 luaK_patchlist(ls->fs, gt->pc, label->pc); 522 luaK_patchlist(ls->fs, gt->pc, label->pc);
523 for (i = g; i < gl->n - 1; i++) /* remove goto from pending list */ 523 for (i = g; i < gl->n - 1; i++) /* remove goto from pending list */
@@ -1435,7 +1435,7 @@ static void breakstat (LexState *ls) {
1435*/ 1435*/
1436static void checkrepeated (LexState *ls, TString *name) { 1436static void checkrepeated (LexState *ls, TString *name) {
1437 Labeldesc *lb = findlabel(ls, name); 1437 Labeldesc *lb = findlabel(ls, name);
1438 if (unlikely(lb != NULL)) { /* already defined? */ 1438 if (l_unlikely(lb != NULL)) { /* already defined? */
1439 const char *msg = "label '%s' already defined on line %d"; 1439 const char *msg = "label '%s' already defined on line %d";
1440 msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line); 1440 msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line);
1441 luaK_semerror(ls, msg); /* error */ 1441 luaK_semerror(ls, msg); /* error */
@@ -1520,7 +1520,7 @@ static void fixforjump (FuncState *fs, int pc, int dest, int back) {
1520 int offset = dest - (pc + 1); 1520 int offset = dest - (pc + 1);
1521 if (back) 1521 if (back)
1522 offset = -offset; 1522 offset = -offset;
1523 if (unlikely(offset > MAXARG_Bx)) 1523 if (l_unlikely(offset > MAXARG_Bx))
1524 luaX_syntaxerror(fs->ls, "control structure too long"); 1524 luaX_syntaxerror(fs->ls, "control structure too long");
1525 SETARG_Bx(*jmp, offset); 1525 SETARG_Bx(*jmp, offset);
1526} 1526}
diff --git a/src/lua/lstate.c b/src/lua/lstate.c
index 92ccbf9..c5e3b43 100644
--- a/src/lua/lstate.c
+++ b/src/lua/lstate.c
@@ -172,7 +172,7 @@ void luaE_checkcstack (lua_State *L) {
172 172
173LUAI_FUNC void luaE_incCstack (lua_State *L) { 173LUAI_FUNC void luaE_incCstack (lua_State *L) {
174 L->nCcalls++; 174 L->nCcalls++;
175 if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) 175 if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
176 luaE_checkcstack(L); 176 luaE_checkcstack(L);
177} 177}
178 178
@@ -181,6 +181,7 @@ static void stack_init (lua_State *L1, lua_State *L) {
181 int i; CallInfo *ci; 181 int i; CallInfo *ci;
182 /* initialize stack array */ 182 /* initialize stack array */
183 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); 183 L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
184 L1->tbclist = L1->stack;
184 for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) 185 for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
185 setnilvalue(s2v(L1->stack + i)); /* erase new stack */ 186 setnilvalue(s2v(L1->stack + i)); /* erase new stack */
186 L1->top = L1->stack; 187 L1->top = L1->stack;
@@ -226,8 +227,6 @@ static void init_registry (lua_State *L, global_State *g) {
226 227
227/* 228/*
228** open parts of the state that may cause memory-allocation errors. 229** open parts of the state that may cause memory-allocation errors.
229** ('g->nilvalue' being a nil value flags that the state was completely
230** build.)
231*/ 230*/
232static void f_luaopen (lua_State *L, void *ud) { 231static void f_luaopen (lua_State *L, void *ud) {
233 global_State *g = G(L); 232 global_State *g = G(L);
@@ -238,7 +237,7 @@ static void f_luaopen (lua_State *L, void *ud) {
238 luaT_init(L); 237 luaT_init(L);
239 luaX_init(L); 238 luaX_init(L);
240 g->gcrunning = 1; /* allow gc */ 239 g->gcrunning = 1; /* allow gc */
241 setnilvalue(&g->nilvalue); 240 setnilvalue(&g->nilvalue); /* now state is complete */
242 luai_userstateopen(L); 241 luai_userstateopen(L);
243} 242}
244 243
@@ -253,6 +252,7 @@ static void preinit_thread (lua_State *L, global_State *g) {
253 L->ci = NULL; 252 L->ci = NULL;
254 L->nci = 0; 253 L->nci = 0;
255 L->twups = L; /* thread has no upvalues */ 254 L->twups = L; /* thread has no upvalues */
255 L->nCcalls = 0;
256 L->errorJmp = NULL; 256 L->errorJmp = NULL;
257 L->hook = NULL; 257 L->hook = NULL;
258 L->hookmask = 0; 258 L->hookmask = 0;
@@ -268,10 +268,13 @@ static void preinit_thread (lua_State *L, global_State *g) {
268 268
269static void close_state (lua_State *L) { 269static void close_state (lua_State *L) {
270 global_State *g = G(L); 270 global_State *g = G(L);
271 luaD_closeprotected(L, 0, LUA_OK); /* close all upvalues */ 271 if (!completestate(g)) /* closing a partially built state? */
272 luaC_freeallobjects(L); /* collect all objects */ 272 luaC_freeallobjects(L); /* jucst collect its objects */
273 if (ttisnil(&g->nilvalue)) /* closing a fully built state? */ 273 else { /* closing a fully built state */
274 luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */
275 luaC_freeallobjects(L); /* collect all objects */
274 luai_userstateclose(L); 276 luai_userstateclose(L);
277 }
275 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); 278 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
276 freestack(L); 279 freestack(L);
277 lua_assert(gettotalbytes(g) == sizeof(LG)); 280 lua_assert(gettotalbytes(g) == sizeof(LG));
@@ -296,7 +299,6 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
296 setthvalue2s(L, L->top, L1); 299 setthvalue2s(L, L->top, L1);
297 api_incr_top(L); 300 api_incr_top(L);
298 preinit_thread(L1, g); 301 preinit_thread(L1, g);
299 L1->nCcalls = 0;
300 L1->hookmask = L->hookmask; 302 L1->hookmask = L->hookmask;
301 L1->basehookcount = L->basehookcount; 303 L1->basehookcount = L->basehookcount;
302 L1->hook = L->hook; 304 L1->hook = L->hook;
@@ -313,7 +315,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
313 315
314void luaE_freethread (lua_State *L, lua_State *L1) { 316void luaE_freethread (lua_State *L, lua_State *L1) {
315 LX *l = fromstate(L1); 317 LX *l = fromstate(L1);
316 luaF_close(L1, L1->stack, NOCLOSINGMETH, 0); /* close all upvalues */ 318 luaF_closeupval(L1, L1->stack); /* close all upvalues */
317 lua_assert(L1->openupval == NULL); 319 lua_assert(L1->openupval == NULL);
318 luai_userstatefree(L, L1); 320 luai_userstatefree(L, L1);
319 freestack(L1); 321 freestack(L1);
@@ -328,7 +330,7 @@ int luaE_resetthread (lua_State *L, int status) {
328 ci->callstatus = CIST_C; 330 ci->callstatus = CIST_C;
329 if (status == LUA_YIELD) 331 if (status == LUA_YIELD)
330 status = LUA_OK; 332 status = LUA_OK;
331 status = luaD_closeprotected(L, 0, status); 333 status = luaD_closeprotected(L, 1, status);
332 if (status != LUA_OK) /* errors? */ 334 if (status != LUA_OK) /* errors? */
333 luaD_seterrorobj(L, status, L->stack + 1); 335 luaD_seterrorobj(L, status, L->stack + 1);
334 else 336 else
@@ -363,7 +365,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
363 preinit_thread(L, g); 365 preinit_thread(L, g);
364 g->allgc = obj2gco(L); /* by now, only object is the main thread */ 366 g->allgc = obj2gco(L); /* by now, only object is the main thread */
365 L->next = NULL; 367 L->next = NULL;
366 L->nCcalls = 0;
367 incnny(L); /* main thread is always non yieldable */ 368 incnny(L); /* main thread is always non yieldable */
368 g->frealloc = f; 369 g->frealloc = f;
369 g->ud = ud; 370 g->ud = ud;
@@ -378,6 +379,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
378 g->panic = NULL; 379 g->panic = NULL;
379 g->gcstate = GCSpause; 380 g->gcstate = GCSpause;
380 g->gckind = KGC_INC; 381 g->gckind = KGC_INC;
382 g->gcstopem = 0;
381 g->gcemergency = 0; 383 g->gcemergency = 0;
382 g->finobj = g->tobefnz = g->fixedgc = NULL; 384 g->finobj = g->tobefnz = g->fixedgc = NULL;
383 g->firstold1 = g->survival = g->old1 = g->reallyold = NULL; 385 g->firstold1 = g->survival = g->old1 = g->reallyold = NULL;
diff --git a/src/lua/lstate.h b/src/lua/lstate.h
index 38a6c9b..c1283bb 100644
--- a/src/lua/lstate.h
+++ b/src/lua/lstate.h
@@ -156,6 +156,18 @@ typedef struct stringtable {
156 156
157/* 157/*
158** Information about a call. 158** Information about a call.
159** About union 'u':
160** - field 'l' is used only for Lua functions;
161** - field 'c' is used only for C functions.
162** About union 'u2':
163** - field 'funcidx' is used only by C functions while doing a
164** protected call;
165** - field 'nyield' is used only while a function is "doing" an
166** yield (from the yield until the next resume);
167** - field 'nres' is used only while closing tbc variables when
168** returning from a C function;
169** - field 'transferinfo' is used only during call/returnhooks,
170** before the function starts or after it ends.
159*/ 171*/
160typedef struct CallInfo { 172typedef struct CallInfo {
161 StkId func; /* function index in the stack */ 173 StkId func; /* function index in the stack */
@@ -176,6 +188,7 @@ typedef struct CallInfo {
176 union { 188 union {
177 int funcidx; /* called-function index */ 189 int funcidx; /* called-function index */
178 int nyield; /* number of values yielded */ 190 int nyield; /* number of values yielded */
191 int nres; /* number of values returned */
179 struct { /* info about transferred values (for call/return hooks) */ 192 struct { /* info about transferred values (for call/return hooks) */
180 unsigned short ftransfer; /* offset of first value transferred */ 193 unsigned short ftransfer; /* offset of first value transferred */
181 unsigned short ntransfer; /* number of values transferred */ 194 unsigned short ntransfer; /* number of values transferred */
@@ -191,17 +204,34 @@ typedef struct CallInfo {
191*/ 204*/
192#define CIST_OAH (1<<0) /* original value of 'allowhook' */ 205#define CIST_OAH (1<<0) /* original value of 'allowhook' */
193#define CIST_C (1<<1) /* call is running a C function */ 206#define CIST_C (1<<1) /* call is running a C function */
194#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */ 207#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */
195#define CIST_HOOKED (1<<3) /* call is running a debug hook */ 208#define CIST_HOOKED (1<<3) /* call is running a debug hook */
196#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ 209#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */
197#define CIST_TAIL (1<<5) /* call was tail called */ 210#define CIST_TAIL (1<<5) /* call was tail called */
198#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ 211#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */
199#define CIST_FIN (1<<7) /* call is running a finalizer */ 212#define CIST_FIN (1<<7) /* call is running a finalizer */
200#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ 213#define CIST_TRAN (1<<8) /* 'ci' has transfer information */
214#define CIST_CLSRET (1<<9) /* function is closing tbc variables */
215/* Bits 10-12 are used for CIST_RECST (see below) */
216#define CIST_RECST 10
201#if defined(LUA_COMPAT_LT_LE) 217#if defined(LUA_COMPAT_LT_LE)
202#define CIST_LEQ (1<<9) /* using __lt for __le */ 218#define CIST_LEQ (1<<13) /* using __lt for __le */
203#endif 219#endif
204 220
221
222/*
223** Field CIST_RECST stores the "recover status", used to keep the error
224** status while closing to-be-closed variables in coroutines, so that
225** Lua can correctly resume after an yield from a __close method called
226** because of an error. (Three bits are enough for error status.)
227*/
228#define getcistrecst(ci) (((ci)->callstatus >> CIST_RECST) & 7)
229#define setcistrecst(ci,st) \
230 check_exp(((st) & 7) == (st), /* status must fit in three bits */ \
231 ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \
232 | ((st) << CIST_RECST)))
233
234
205/* active function is a Lua function */ 235/* active function is a Lua function */
206#define isLua(ci) (!((ci)->callstatus & CIST_C)) 236#define isLua(ci) (!((ci)->callstatus & CIST_C))
207 237
@@ -230,6 +260,7 @@ typedef struct global_State {
230 lu_byte currentwhite; 260 lu_byte currentwhite;
231 lu_byte gcstate; /* state of garbage collector */ 261 lu_byte gcstate; /* state of garbage collector */
232 lu_byte gckind; /* kind of GC running */ 262 lu_byte gckind; /* kind of GC running */
263 lu_byte gcstopem; /* stops emergency collections */
233 lu_byte genminormul; /* control for minor generational collections */ 264 lu_byte genminormul; /* control for minor generational collections */
234 lu_byte genmajormul; /* control for major generational collections */ 265 lu_byte genmajormul; /* control for major generational collections */
235 lu_byte gcrunning; /* true if GC is running */ 266 lu_byte gcrunning; /* true if GC is running */
@@ -281,6 +312,7 @@ struct lua_State {
281 StkId stack_last; /* end of stack (last element + 1) */ 312 StkId stack_last; /* end of stack (last element + 1) */
282 StkId stack; /* stack base */ 313 StkId stack; /* stack base */
283 UpVal *openupval; /* list of open upvalues in this stack */ 314 UpVal *openupval; /* list of open upvalues in this stack */
315 StkId tbclist; /* list of to-be-closed variables */
284 GCObject *gclist; 316 GCObject *gclist;
285 struct lua_State *twups; /* list of threads with open upvalues */ 317 struct lua_State *twups; /* list of threads with open upvalues */
286 struct lua_longjmp *errorJmp; /* current error recover point */ 318 struct lua_longjmp *errorJmp; /* current error recover point */
@@ -297,6 +329,12 @@ struct lua_State {
297 329
298#define G(L) (L->l_G) 330#define G(L) (L->l_G)
299 331
332/*
333** 'g->nilvalue' being a nil value flags that the state was completely
334** build.
335*/
336#define completestate(g) ttisnil(&g->nilvalue)
337
300 338
301/* 339/*
302** Union of all collectable objects (only for conversions) 340** Union of all collectable objects (only for conversions)
diff --git a/src/lua/lstring.c b/src/lua/lstring.c
index 138871c..13dcaf4 100644
--- a/src/lua/lstring.c
+++ b/src/lua/lstring.c
@@ -89,7 +89,7 @@ void luaS_resize (lua_State *L, int nsize) {
89 if (nsize < osize) /* shrinking table? */ 89 if (nsize < osize) /* shrinking table? */
90 tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */ 90 tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */
91 newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*); 91 newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*);
92 if (unlikely(newvect == NULL)) { /* reallocation failed? */ 92 if (l_unlikely(newvect == NULL)) { /* reallocation failed? */
93 if (nsize < osize) /* was it shrinking table? */ 93 if (nsize < osize) /* was it shrinking table? */
94 tablerehash(tb->hash, nsize, osize); /* restore to original size */ 94 tablerehash(tb->hash, nsize, osize); /* restore to original size */
95 /* leave table as it was */ 95 /* leave table as it was */
@@ -172,7 +172,7 @@ void luaS_remove (lua_State *L, TString *ts) {
172 172
173 173
174static void growstrtab (lua_State *L, stringtable *tb) { 174static void growstrtab (lua_State *L, stringtable *tb) {
175 if (unlikely(tb->nuse == MAX_INT)) { /* too many strings? */ 175 if (l_unlikely(tb->nuse == MAX_INT)) { /* too many strings? */
176 luaC_fullgc(L, 1); /* try to free some... */ 176 luaC_fullgc(L, 1); /* try to free some... */
177 if (tb->nuse == MAX_INT) /* still too many? */ 177 if (tb->nuse == MAX_INT) /* still too many? */
178 luaM_error(L); /* cannot even create a message... */ 178 luaM_error(L); /* cannot even create a message... */
@@ -223,7 +223,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
223 return internshrstr(L, str, l); 223 return internshrstr(L, str, l);
224 else { 224 else {
225 TString *ts; 225 TString *ts;
226 if (unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char))) 226 if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char)))
227 luaM_toobig(L); 227 luaM_toobig(L);
228 ts = luaS_createlngstrobj(L, l); 228 ts = luaS_createlngstrobj(L, l);
229 memcpy(getstr(ts), str, l * sizeof(char)); 229 memcpy(getstr(ts), str, l * sizeof(char));
@@ -259,7 +259,7 @@ Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) {
259 Udata *u; 259 Udata *u;
260 int i; 260 int i;
261 GCObject *o; 261 GCObject *o;
262 if (unlikely(s > MAX_SIZE - udatamemoffset(nuvalue))) 262 if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue)))
263 luaM_toobig(L); 263 luaM_toobig(L);
264 o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s)); 264 o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s));
265 u = gco2u(o); 265 u = gco2u(o);
diff --git a/src/lua/lstrlib.c b/src/lua/lstrlib.c
index c7242ea..47e5b27 100644
--- a/src/lua/lstrlib.c
+++ b/src/lua/lstrlib.c
@@ -152,8 +152,9 @@ static int str_rep (lua_State *L) {
152 const char *s = luaL_checklstring(L, 1, &l); 152 const char *s = luaL_checklstring(L, 1, &l);
153 lua_Integer n = luaL_checkinteger(L, 2); 153 lua_Integer n = luaL_checkinteger(L, 2);
154 const char *sep = luaL_optlstring(L, 3, "", &lsep); 154 const char *sep = luaL_optlstring(L, 3, "", &lsep);
155 if (n <= 0) lua_pushliteral(L, ""); 155 if (n <= 0)
156 else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */ 156 lua_pushliteral(L, "");
157 else if (l_unlikely(l + lsep < l || l + lsep > MAXSIZE / n))
157 return luaL_error(L, "resulting string too large"); 158 return luaL_error(L, "resulting string too large");
158 else { 159 else {
159 size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; 160 size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep;
@@ -181,7 +182,7 @@ static int str_byte (lua_State *L) {
181 size_t pose = getendpos(L, 3, pi, l); 182 size_t pose = getendpos(L, 3, pi, l);
182 int n, i; 183 int n, i;
183 if (posi > pose) return 0; /* empty interval; return no values */ 184 if (posi > pose) return 0; /* empty interval; return no values */
184 if (pose - posi >= (size_t)INT_MAX) /* arithmetic overflow? */ 185 if (l_unlikely(pose - posi >= (size_t)INT_MAX)) /* arithmetic overflow? */
185 return luaL_error(L, "string slice too long"); 186 return luaL_error(L, "string slice too long");
186 n = (int)(pose - posi) + 1; 187 n = (int)(pose - posi) + 1;
187 luaL_checkstack(L, n, "string slice too long"); 188 luaL_checkstack(L, n, "string slice too long");
@@ -235,7 +236,7 @@ static int str_dump (lua_State *L) {
235 luaL_checktype(L, 1, LUA_TFUNCTION); 236 luaL_checktype(L, 1, LUA_TFUNCTION);
236 lua_settop(L, 1); /* ensure function is on the top of the stack */ 237 lua_settop(L, 1); /* ensure function is on the top of the stack */
237 state.init = 0; 238 state.init = 0;
238 if (lua_dump(L, writer, &state, strip) != 0) 239 if (l_unlikely(lua_dump(L, writer, &state, strip) != 0))
239 return luaL_error(L, "unable to dump given function"); 240 return luaL_error(L, "unable to dump given function");
240 luaL_pushresult(&state.B); 241 luaL_pushresult(&state.B);
241 return 1; 242 return 1;
@@ -275,7 +276,8 @@ static int tonum (lua_State *L, int arg) {
275 276
276static void trymt (lua_State *L, const char *mtname) { 277static void trymt (lua_State *L, const char *mtname) {
277 lua_settop(L, 2); /* back to the original arguments */ 278 lua_settop(L, 2); /* back to the original arguments */
278 if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname)) 279 if (l_unlikely(lua_type(L, 2) == LUA_TSTRING ||
280 !luaL_getmetafield(L, 2, mtname)))
279 luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2, 281 luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
280 luaL_typename(L, -2), luaL_typename(L, -1)); 282 luaL_typename(L, -2), luaL_typename(L, -1));
281 lua_insert(L, -3); /* put metamethod before arguments */ 283 lua_insert(L, -3); /* put metamethod before arguments */
@@ -383,7 +385,8 @@ static const char *match (MatchState *ms, const char *s, const char *p);
383 385
384static int check_capture (MatchState *ms, int l) { 386static int check_capture (MatchState *ms, int l) {
385 l -= '1'; 387 l -= '1';
386 if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED) 388 if (l_unlikely(l < 0 || l >= ms->level ||
389 ms->capture[l].len == CAP_UNFINISHED))
387 return luaL_error(ms->L, "invalid capture index %%%d", l + 1); 390 return luaL_error(ms->L, "invalid capture index %%%d", l + 1);
388 return l; 391 return l;
389} 392}
@@ -400,14 +403,14 @@ static int capture_to_close (MatchState *ms) {
400static const char *classend (MatchState *ms, const char *p) { 403static const char *classend (MatchState *ms, const char *p) {
401 switch (*p++) { 404 switch (*p++) {
402 case L_ESC: { 405 case L_ESC: {
403 if (p == ms->p_end) 406 if (l_unlikely(p == ms->p_end))
404 luaL_error(ms->L, "malformed pattern (ends with '%%')"); 407 luaL_error(ms->L, "malformed pattern (ends with '%%')");
405 return p+1; 408 return p+1;
406 } 409 }
407 case '[': { 410 case '[': {
408 if (*p == '^') p++; 411 if (*p == '^') p++;
409 do { /* look for a ']' */ 412 do { /* look for a ']' */
410 if (p == ms->p_end) 413 if (l_unlikely(p == ms->p_end))
411 luaL_error(ms->L, "malformed pattern (missing ']')"); 414 luaL_error(ms->L, "malformed pattern (missing ']')");
412 if (*(p++) == L_ESC && p < ms->p_end) 415 if (*(p++) == L_ESC && p < ms->p_end)
413 p++; /* skip escapes (e.g. '%]') */ 416 p++; /* skip escapes (e.g. '%]') */
@@ -482,7 +485,7 @@ static int singlematch (MatchState *ms, const char *s, const char *p,
482 485
483static const char *matchbalance (MatchState *ms, const char *s, 486static const char *matchbalance (MatchState *ms, const char *s,
484 const char *p) { 487 const char *p) {
485 if (p >= ms->p_end - 1) 488 if (l_unlikely(p >= ms->p_end - 1))
486 luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); 489 luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
487 if (*s != *p) return NULL; 490 if (*s != *p) return NULL;
488 else { 491 else {
@@ -565,7 +568,7 @@ static const char *match_capture (MatchState *ms, const char *s, int l) {
565 568
566 569
567static const char *match (MatchState *ms, const char *s, const char *p) { 570static const char *match (MatchState *ms, const char *s, const char *p) {
568 if (ms->matchdepth-- == 0) 571 if (l_unlikely(ms->matchdepth-- == 0))
569 luaL_error(ms->L, "pattern too complex"); 572 luaL_error(ms->L, "pattern too complex");
570 init: /* using goto's to optimize tail recursion */ 573 init: /* using goto's to optimize tail recursion */
571 if (p != ms->p_end) { /* end of pattern? */ 574 if (p != ms->p_end) { /* end of pattern? */
@@ -599,7 +602,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) {
599 case 'f': { /* frontier? */ 602 case 'f': { /* frontier? */
600 const char *ep; char previous; 603 const char *ep; char previous;
601 p += 2; 604 p += 2;
602 if (*p != '[') 605 if (l_unlikely(*p != '['))
603 luaL_error(ms->L, "missing '[' after '%%f' in pattern"); 606 luaL_error(ms->L, "missing '[' after '%%f' in pattern");
604 ep = classend(ms, p); /* points to what is next */ 607 ep = classend(ms, p); /* points to what is next */
605 previous = (s == ms->src_init) ? '\0' : *(s - 1); 608 previous = (s == ms->src_init) ? '\0' : *(s - 1);
@@ -699,7 +702,7 @@ static const char *lmemfind (const char *s1, size_t l1,
699static size_t get_onecapture (MatchState *ms, int i, const char *s, 702static size_t get_onecapture (MatchState *ms, int i, const char *s,
700 const char *e, const char **cap) { 703 const char *e, const char **cap) {
701 if (i >= ms->level) { 704 if (i >= ms->level) {
702 if (i != 0) 705 if (l_unlikely(i != 0))
703 luaL_error(ms->L, "invalid capture index %%%d", i + 1); 706 luaL_error(ms->L, "invalid capture index %%%d", i + 1);
704 *cap = s; 707 *cap = s;
705 return e - s; 708 return e - s;
@@ -707,7 +710,7 @@ static size_t get_onecapture (MatchState *ms, int i, const char *s,
707 else { 710 else {
708 ptrdiff_t capl = ms->capture[i].len; 711 ptrdiff_t capl = ms->capture[i].len;
709 *cap = ms->capture[i].init; 712 *cap = ms->capture[i].init;
710 if (capl == CAP_UNFINISHED) 713 if (l_unlikely(capl == CAP_UNFINISHED))
711 luaL_error(ms->L, "unfinished capture"); 714 luaL_error(ms->L, "unfinished capture");
712 else if (capl == CAP_POSITION) 715 else if (capl == CAP_POSITION)
713 lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); 716 lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
@@ -926,7 +929,7 @@ static int add_value (MatchState *ms, luaL_Buffer *b, const char *s,
926 luaL_addlstring(b, s, e - s); /* keep original text */ 929 luaL_addlstring(b, s, e - s); /* keep original text */
927 return 0; /* no changes */ 930 return 0; /* no changes */
928 } 931 }
929 else if (!lua_isstring(L, -1)) 932 else if (l_unlikely(!lua_isstring(L, -1)))
930 return luaL_error(L, "invalid replacement value (a %s)", 933 return luaL_error(L, "invalid replacement value (a %s)",
931 luaL_typename(L, -1)); 934 luaL_typename(L, -1));
932 else { 935 else {
@@ -1058,7 +1061,7 @@ static int lua_number2strx (lua_State *L, char *buff, int sz,
1058 for (i = 0; i < n; i++) 1061 for (i = 0; i < n; i++)
1059 buff[i] = toupper(uchar(buff[i])); 1062 buff[i] = toupper(uchar(buff[i]));
1060 } 1063 }
1061 else if (fmt[SIZELENMOD] != 'a') 1064 else if (l_unlikely(fmt[SIZELENMOD] != 'a'))
1062 return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); 1065 return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
1063 return n; 1066 return n;
1064} 1067}
@@ -1411,7 +1414,7 @@ static int getnum (const char **fmt, int df) {
1411*/ 1414*/
1412static int getnumlimit (Header *h, const char **fmt, int df) { 1415static int getnumlimit (Header *h, const char **fmt, int df) {
1413 int sz = getnum(fmt, df); 1416 int sz = getnum(fmt, df);
1414 if (sz > MAXINTSIZE || sz <= 0) 1417 if (l_unlikely(sz > MAXINTSIZE || sz <= 0))
1415 return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", 1418 return luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
1416 sz, MAXINTSIZE); 1419 sz, MAXINTSIZE);
1417 return sz; 1420 return sz;
@@ -1452,7 +1455,7 @@ static KOption getoption (Header *h, const char **fmt, int *size) {
1452 case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; 1455 case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
1453 case 'c': 1456 case 'c':
1454 *size = getnum(fmt, -1); 1457 *size = getnum(fmt, -1);
1455 if (*size == -1) 1458 if (l_unlikely(*size == -1))
1456 luaL_error(h->L, "missing size for format option 'c'"); 1459 luaL_error(h->L, "missing size for format option 'c'");
1457 return Kchar; 1460 return Kchar;
1458 case 'z': return Kzstr; 1461 case 'z': return Kzstr;
@@ -1491,7 +1494,7 @@ static KOption getdetails (Header *h, size_t totalsize,
1491 else { 1494 else {
1492 if (align > h->maxalign) /* enforce maximum alignment */ 1495 if (align > h->maxalign) /* enforce maximum alignment */
1493 align = h->maxalign; 1496 align = h->maxalign;
1494 if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ 1497 if (l_unlikely((align & (align - 1)) != 0)) /* not a power of 2? */
1495 luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); 1498 luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
1496 *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); 1499 *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
1497 } 1500 }
@@ -1683,7 +1686,7 @@ static lua_Integer unpackint (lua_State *L, const char *str,
1683 else if (size > SZINT) { /* must check unread bytes */ 1686 else if (size > SZINT) { /* must check unread bytes */
1684 int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; 1687 int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
1685 for (i = limit; i < size; i++) { 1688 for (i = limit; i < size; i++) {
1686 if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) 1689 if (l_unlikely((unsigned char)str[islittle ? i : size - 1 - i] != mask))
1687 luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); 1690 luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
1688 } 1691 }
1689 } 1692 }
diff --git a/src/lua/ltable.c b/src/lua/ltable.c
index e98bab7..b520cdf 100644
--- a/src/lua/ltable.c
+++ b/src/lua/ltable.c
@@ -307,7 +307,7 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key,
307 return i; /* yes; that's the index */ 307 return i; /* yes; that's the index */
308 else { 308 else {
309 const TValue *n = getgeneric(t, key, 1); 309 const TValue *n = getgeneric(t, key, 1);
310 if (unlikely(isabstkey(n))) 310 if (l_unlikely(isabstkey(n)))
311 luaG_runerror(L, "invalid key to 'next'"); /* key not found */ 311 luaG_runerror(L, "invalid key to 'next'"); /* key not found */
312 i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ 312 i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */
313 /* hash elements are numbered after array ones */ 313 /* hash elements are numbered after array ones */
@@ -541,7 +541,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
541 } 541 }
542 /* allocate new array */ 542 /* allocate new array */
543 newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue); 543 newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue);
544 if (unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */ 544 if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */
545 freehash(L, &newt); /* release new hash part */ 545 freehash(L, &newt); /* release new hash part */
546 luaM_error(L); /* raise error (with array unchanged) */ 546 luaM_error(L); /* raise error (with array unchanged) */
547 } 547 }
@@ -635,7 +635,7 @@ static Node *getfreepos (Table *t) {
635void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { 635void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
636 Node *mp; 636 Node *mp;
637 TValue aux; 637 TValue aux;
638 if (unlikely(ttisnil(key))) 638 if (l_unlikely(ttisnil(key)))
639 luaG_runerror(L, "table index is nil"); 639 luaG_runerror(L, "table index is nil");
640 else if (ttisfloat(key)) { 640 else if (ttisfloat(key)) {
641 lua_Number f = fltvalue(key); 641 lua_Number f = fltvalue(key);
@@ -644,7 +644,7 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
644 setivalue(&aux, k); 644 setivalue(&aux, k);
645 key = &aux; /* insert it as an integer */ 645 key = &aux; /* insert it as an integer */
646 } 646 }
647 else if (unlikely(luai_numisnan(f))) 647 else if (l_unlikely(luai_numisnan(f)))
648 luaG_runerror(L, "table index is NaN"); 648 luaG_runerror(L, "table index is NaN");
649 } 649 }
650 if (ttisnil(value)) 650 if (ttisnil(value))
diff --git a/src/lua/ltablib.c b/src/lua/ltablib.c
index d344a47..d80eb80 100644
--- a/src/lua/ltablib.c
+++ b/src/lua/ltablib.c
@@ -145,8 +145,8 @@ static int tmove (lua_State *L) {
145 145
146static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { 146static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) {
147 lua_geti(L, 1, i); 147 lua_geti(L, 1, i);
148 if (!lua_isstring(L, -1)) 148 if (l_unlikely(!lua_isstring(L, -1)))
149 luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", 149 luaL_error(L, "invalid value (%s) at index %I in table for 'concat'",
150 luaL_typename(L, -1), i); 150 luaL_typename(L, -1), i);
151 luaL_addvalue(b); 151 luaL_addvalue(b);
152} 152}
@@ -196,7 +196,8 @@ static int tunpack (lua_State *L) {
196 lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); 196 lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));
197 if (i > e) return 0; /* empty range */ 197 if (i > e) return 0; /* empty range */
198 n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ 198 n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */
199 if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) 199 if (l_unlikely(n >= (unsigned int)INT_MAX ||
200 !lua_checkstack(L, (int)(++n))))
200 return luaL_error(L, "too many results to unpack"); 201 return luaL_error(L, "too many results to unpack");
201 for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ 202 for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */
202 lua_geti(L, 1, i); 203 lua_geti(L, 1, i);
@@ -300,14 +301,14 @@ static IdxT partition (lua_State *L, IdxT lo, IdxT up) {
300 for (;;) { 301 for (;;) {
301 /* next loop: repeat ++i while a[i] < P */ 302 /* next loop: repeat ++i while a[i] < P */
302 while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { 303 while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) {
303 if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ 304 if (l_unlikely(i == up - 1)) /* a[i] < P but a[up - 1] == P ?? */
304 luaL_error(L, "invalid order function for sorting"); 305 luaL_error(L, "invalid order function for sorting");
305 lua_pop(L, 1); /* remove a[i] */ 306 lua_pop(L, 1); /* remove a[i] */
306 } 307 }
307 /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ 308 /* after the loop, a[i] >= P and a[lo .. i - 1] < P */
308 /* next loop: repeat --j while P < a[j] */ 309 /* next loop: repeat --j while P < a[j] */
309 while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { 310 while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) {
310 if (j < i) /* j < i but a[j] > P ?? */ 311 if (l_unlikely(j < i)) /* j < i but a[j] > P ?? */
311 luaL_error(L, "invalid order function for sorting"); 312 luaL_error(L, "invalid order function for sorting");
312 lua_pop(L, 1); /* remove a[j] */ 313 lua_pop(L, 1); /* remove a[j] */
313 } 314 }
diff --git a/src/lua/ltm.c b/src/lua/ltm.c
index 4770f96..b657b78 100644
--- a/src/lua/ltm.c
+++ b/src/lua/ltm.c
@@ -147,7 +147,7 @@ static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
147 147
148void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, 148void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
149 StkId res, TMS event) { 149 StkId res, TMS event) {
150 if (!callbinTM(L, p1, p2, res, event)) { 150 if (l_unlikely(!callbinTM(L, p1, p2, res, event))) {
151 switch (event) { 151 switch (event) {
152 case TM_BAND: case TM_BOR: case TM_BXOR: 152 case TM_BAND: case TM_BOR: case TM_BXOR:
153 case TM_SHL: case TM_SHR: case TM_BNOT: { 153 case TM_SHL: case TM_SHR: case TM_BNOT: {
@@ -166,7 +166,8 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2,
166 166
167void luaT_tryconcatTM (lua_State *L) { 167void luaT_tryconcatTM (lua_State *L) {
168 StkId top = L->top; 168 StkId top = L->top;
169 if (!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT)) 169 if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2,
170 TM_CONCAT)))
170 luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); 171 luaG_concaterror(L, s2v(top - 2), s2v(top - 1));
171} 172}
172 173
diff --git a/src/lua/luaconf.h b/src/lua/luaconf.h
index d9cf18c..ae73e2f 100644
--- a/src/lua/luaconf.h
+++ b/src/lua/luaconf.h
@@ -16,13 +16,13 @@
16** =================================================================== 16** ===================================================================
17** General Configuration File for Lua 17** General Configuration File for Lua
18** 18**
19** Some definitions here can be changed externally, through the 19** Some definitions here can be changed externally, through the compiler
20** compiler (e.g., with '-D' options). Those are protected by 20** (e.g., with '-D' options): They are commented out or protected
21** '#if !defined' guards. However, several other definitions should 21** by '#if !defined' guards. However, several other definitions
22** be changed directly here, either because they affect the Lua 22** should be changed directly here, either because they affect the
23** ABI (by making the changes here, you ensure that all software 23** Lua ABI (by making the changes here, you ensure that all software
24** connected to Lua, such as C libraries, will be compiled with the 24** connected to Lua, such as C libraries, will be compiled with the same
25** same configuration); or because they are seldom changed. 25** configuration); or because they are seldom changed.
26** 26**
27** Search for "@@" to find all configurable definitions. 27** Search for "@@" to find all configurable definitions.
28** =================================================================== 28** ===================================================================
@@ -81,27 +81,13 @@
81 81
82/* 82/*
83** {================================================================== 83** {==================================================================
84** Configuration for Number types. 84** Configuration for Number types. These options should not be
85** set externally, because any other code connected to Lua must
86** use the same configuration.
85** =================================================================== 87** ===================================================================
86*/ 88*/
87 89
88/* 90/*
89@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
90*/
91/* #define LUA_32BITS */
92
93
94/*
95@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
96** C89 ('long' and 'double'); Windows always has '__int64', so it does
97** not need to use this case.
98*/
99#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
100#define LUA_C89_NUMBERS
101#endif
102
103
104/*
105@@ LUA_INT_TYPE defines the type for Lua integers. 91@@ LUA_INT_TYPE defines the type for Lua integers.
106@@ LUA_FLOAT_TYPE defines the type for Lua floats. 92@@ LUA_FLOAT_TYPE defines the type for Lua floats.
107** Lua should work fine with any mix of these options supported 93** Lua should work fine with any mix of these options supported
@@ -121,7 +107,31 @@
121#define LUA_FLOAT_DOUBLE 2 107#define LUA_FLOAT_DOUBLE 2
122#define LUA_FLOAT_LONGDOUBLE 3 108#define LUA_FLOAT_LONGDOUBLE 3
123 109
124#if defined(LUA_32BITS) /* { */ 110
111/* Default configuration ('long long' and 'double', for 64-bit Lua) */
112#define LUA_INT_DEFAULT LUA_INT_LONGLONG
113#define LUA_FLOAT_DEFAULT LUA_FLOAT_DOUBLE
114
115
116/*
117@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats.
118*/
119#define LUA_32BITS 0
120
121
122/*
123@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for
124** C89 ('long' and 'double'); Windows always has '__int64', so it does
125** not need to use this case.
126*/
127#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS)
128#define LUA_C89_NUMBERS 1
129#else
130#define LUA_C89_NUMBERS 0
131#endif
132
133
134#if LUA_32BITS /* { */
125/* 135/*
126** 32-bit integers and 'float' 136** 32-bit integers and 'float'
127*/ 137*/
@@ -132,26 +142,21 @@
132#endif 142#endif
133#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT 143#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT
134 144
135#elif defined(LUA_C89_NUMBERS) /* }{ */ 145#elif LUA_C89_NUMBERS /* }{ */
136/* 146/*
137** largest types available for C89 ('long' and 'double') 147** largest types available for C89 ('long' and 'double')
138*/ 148*/
139#define LUA_INT_TYPE LUA_INT_LONG 149#define LUA_INT_TYPE LUA_INT_LONG
140#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE 150#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
141 151
142#endif /* } */ 152#else /* }{ */
153/* use defaults */
143 154
155#define LUA_INT_TYPE LUA_INT_DEFAULT
156#define LUA_FLOAT_TYPE LUA_FLOAT_DEFAULT
144 157
145/* 158#endif /* } */
146** default configuration for 64-bit Lua ('long long' and 'double')
147*/
148#if !defined(LUA_INT_TYPE)
149#define LUA_INT_TYPE LUA_INT_LONGLONG
150#endif
151 159
152#if !defined(LUA_FLOAT_TYPE)
153#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE
154#endif
155 160
156/* }================================================================== */ 161/* }================================================================== */
157 162
@@ -373,14 +378,13 @@
373 378
374/* 379/*
375** {================================================================== 380** {==================================================================
376** Configuration for Numbers. 381** Configuration for Numbers (low-level part).
377** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* 382** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_*
378** satisfy your needs. 383** satisfy your needs.
379** =================================================================== 384** ===================================================================
380*/ 385*/
381 386
382/* 387/*
383@@ LUA_NUMBER is the floating-point type used by Lua.
384@@ LUAI_UACNUMBER is the result of a 'default argument promotion' 388@@ LUAI_UACNUMBER is the result of a 'default argument promotion'
385@@ over a floating number. 389@@ over a floating number.
386@@ l_floatatt(x) corrects float attribute 'x' to the proper float type 390@@ l_floatatt(x) corrects float attribute 'x' to the proper float type
@@ -473,10 +477,7 @@
473 477
474 478
475/* 479/*
476@@ LUA_INTEGER is the integer type used by Lua.
477**
478@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. 480@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER.
479**
480@@ LUAI_UACINT is the result of a 'default argument promotion' 481@@ LUAI_UACINT is the result of a 'default argument promotion'
481@@ over a LUA_INTEGER. 482@@ over a LUA_INTEGER.
482@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. 483@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers.
@@ -659,6 +660,26 @@
659#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) 660#define lua_getlocaledecpoint() (localeconv()->decimal_point[0])
660#endif 661#endif
661 662
663
664/*
665** macros to improve jump prediction, used mostly for error handling
666** and debug facilities.
667*/
668#if (defined(LUA_CORE) || defined(LUA_LIB)) && !defined(l_likely)
669
670#include <stdio.h>
671#if defined(__GNUC__)
672#define l_likely(x) (__builtin_expect(((x) != 0), 1))
673#define l_unlikely(x) (__builtin_expect(((x) != 0), 0))
674#else
675#define l_likely(x) (x)
676#define l_unlikely(x) (x)
677#endif
678
679#endif
680
681
682
662/* }================================================================== */ 683/* }================================================================== */
663 684
664 685
diff --git a/src/lua/lvm.c b/src/lua/lvm.c
index d6c05bb..c9729bc 100644
--- a/src/lua/lvm.c
+++ b/src/lua/lvm.c
@@ -235,11 +235,11 @@ static int forprep (lua_State *L, StkId ra) {
235 } 235 }
236 else { /* try making all values floats */ 236 else { /* try making all values floats */
237 lua_Number init; lua_Number limit; lua_Number step; 237 lua_Number init; lua_Number limit; lua_Number step;
238 if (unlikely(!tonumber(plimit, &limit))) 238 if (l_unlikely(!tonumber(plimit, &limit)))
239 luaG_forerror(L, plimit, "limit"); 239 luaG_forerror(L, plimit, "limit");
240 if (unlikely(!tonumber(pstep, &step))) 240 if (l_unlikely(!tonumber(pstep, &step)))
241 luaG_forerror(L, pstep, "step"); 241 luaG_forerror(L, pstep, "step");
242 if (unlikely(!tonumber(pinit, &init))) 242 if (l_unlikely(!tonumber(pinit, &init)))
243 luaG_forerror(L, pinit, "initial value"); 243 luaG_forerror(L, pinit, "initial value");
244 if (step == 0) 244 if (step == 0)
245 luaG_runerror(L, "'for' step is zero"); 245 luaG_runerror(L, "'for' step is zero");
@@ -292,7 +292,7 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
292 if (slot == NULL) { /* 't' is not a table? */ 292 if (slot == NULL) { /* 't' is not a table? */
293 lua_assert(!ttistable(t)); 293 lua_assert(!ttistable(t));
294 tm = luaT_gettmbyobj(L, t, TM_INDEX); 294 tm = luaT_gettmbyobj(L, t, TM_INDEX);
295 if (unlikely(notm(tm))) 295 if (l_unlikely(notm(tm)))
296 luaG_typeerror(L, t, "index"); /* no metamethod */ 296 luaG_typeerror(L, t, "index"); /* no metamethod */
297 /* else will try the metamethod */ 297 /* else will try the metamethod */
298 } 298 }
@@ -346,7 +346,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
346 } 346 }
347 else { /* not a table; check metamethod */ 347 else { /* not a table; check metamethod */
348 tm = luaT_gettmbyobj(L, t, TM_NEWINDEX); 348 tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
349 if (unlikely(notm(tm))) 349 if (l_unlikely(notm(tm)))
350 luaG_typeerror(L, t, "index"); 350 luaG_typeerror(L, t, "index");
351 } 351 }
352 /* try the metamethod */ 352 /* try the metamethod */
@@ -568,8 +568,13 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
568 if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER) 568 if (ttype(t1) != ttype(t2) || ttype(t1) != LUA_TNUMBER)
569 return 0; /* only numbers can be equal with different variants */ 569 return 0; /* only numbers can be equal with different variants */
570 else { /* two numbers with different variants */ 570 else { /* two numbers with different variants */
571 lua_Integer i1, i2; /* compare them as integers */ 571 /* One of them is an integer. If the other does not have an
572 return (tointegerns(t1, &i1) && tointegerns(t2, &i2) && i1 == i2); 572 integer value, they cannot be equal; otherwise, compare their
573 integer values. */
574 lua_Integer i1, i2;
575 return (luaV_tointegerns(t1, &i1, F2Ieq) &&
576 luaV_tointegerns(t2, &i2, F2Ieq) &&
577 i1 == i2);
573 } 578 }
574 } 579 }
575 /* values have same type and same variant */ 580 /* values have same type and same variant */
@@ -651,7 +656,7 @@ void luaV_concat (lua_State *L, int total) {
651 /* collect total length and number of strings */ 656 /* collect total length and number of strings */
652 for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { 657 for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
653 size_t l = vslen(s2v(top - n - 1)); 658 size_t l = vslen(s2v(top - n - 1));
654 if (unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) 659 if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl))
655 luaG_runerror(L, "string length overflow"); 660 luaG_runerror(L, "string length overflow");
656 tl += l; 661 tl += l;
657 } 662 }
@@ -695,7 +700,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
695 } 700 }
696 default: { /* try metamethod */ 701 default: { /* try metamethod */
697 tm = luaT_gettmbyobj(L, rb, TM_LEN); 702 tm = luaT_gettmbyobj(L, rb, TM_LEN);
698 if (unlikely(notm(tm))) /* no metamethod? */ 703 if (l_unlikely(notm(tm))) /* no metamethod? */
699 luaG_typeerror(L, rb, "get length of"); 704 luaG_typeerror(L, rb, "get length of");
700 break; 705 break;
701 } 706 }
@@ -711,7 +716,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
711** otherwise 'floor(q) == trunc(q) - 1'. 716** otherwise 'floor(q) == trunc(q) - 1'.
712*/ 717*/
713lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) { 718lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) {
714 if (unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */ 719 if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
715 if (n == 0) 720 if (n == 0)
716 luaG_runerror(L, "attempt to divide by zero"); 721 luaG_runerror(L, "attempt to divide by zero");
717 return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ 722 return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */
@@ -731,7 +736,7 @@ lua_Integer luaV_idiv (lua_State *L, lua_Integer m, lua_Integer n) {
731** about luaV_idiv.) 736** about luaV_idiv.)
732*/ 737*/
733lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { 738lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
734 if (unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */ 739 if (l_unlikely(l_castS2U(n) + 1u <= 1u)) { /* special cases: -1 or 0 */
735 if (n == 0) 740 if (n == 0)
736 luaG_runerror(L, "attempt to perform 'n%%0'"); 741 luaG_runerror(L, "attempt to perform 'n%%0'");
737 return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ 742 return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
@@ -921,7 +926,7 @@ void luaV_finishOp (lua_State *L) {
921*/ 926*/
922#define op_arithfK(L,fop) { \ 927#define op_arithfK(L,fop) { \
923 TValue *v1 = vRB(i); \ 928 TValue *v1 = vRB(i); \
924 TValue *v2 = KC(i); \ 929 TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
925 op_arithf_aux(L, v1, v2, fop); } 930 op_arithf_aux(L, v1, v2, fop); }
926 931
927 932
@@ -950,7 +955,7 @@ void luaV_finishOp (lua_State *L) {
950*/ 955*/
951#define op_arithK(L,iop,fop) { \ 956#define op_arithK(L,iop,fop) { \
952 TValue *v1 = vRB(i); \ 957 TValue *v1 = vRB(i); \
953 TValue *v2 = KC(i); \ 958 TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \
954 op_arith_aux(L, v1, v2, iop, fop); } 959 op_arith_aux(L, v1, v2, iop, fop); }
955 960
956 961
@@ -1049,7 +1054,8 @@ void luaV_finishOp (lua_State *L) {
1049#define updatebase(ci) (base = ci->func + 1) 1054#define updatebase(ci) (base = ci->func + 1)
1050 1055
1051 1056
1052#define updatestack(ci) { if (trap) { updatebase(ci); ra = RA(i); } } 1057#define updatestack(ci) \
1058 { if (l_unlikely(trap)) { updatebase(ci); ra = RA(i); } }
1053 1059
1054 1060
1055/* 1061/*
@@ -1107,7 +1113,7 @@ void luaV_finishOp (lua_State *L) {
1107 1113
1108/* fetch an instruction and prepare its execution */ 1114/* fetch an instruction and prepare its execution */
1109#define vmfetch() { \ 1115#define vmfetch() { \
1110 if (trap) { /* stack reallocation or hooks? */ \ 1116 if (l_unlikely(trap)) { /* stack reallocation or hooks? */ \
1111 trap = luaG_traceexec(L, pc); /* handle hooks */ \ 1117 trap = luaG_traceexec(L, pc); /* handle hooks */ \
1112 updatebase(ci); /* correct stack */ \ 1118 updatebase(ci); /* correct stack */ \
1113 } \ 1119 } \
@@ -1135,7 +1141,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1135 cl = clLvalue(s2v(ci->func)); 1141 cl = clLvalue(s2v(ci->func));
1136 k = cl->p->k; 1142 k = cl->p->k;
1137 pc = ci->u.l.savedpc; 1143 pc = ci->u.l.savedpc;
1138 if (trap) { 1144 if (l_unlikely(trap)) {
1139 if (pc == cl->p->code) { /* first instruction (not resuming)? */ 1145 if (pc == cl->p->code) { /* first instruction (not resuming)? */
1140 if (cl->p->is_vararg) 1146 if (cl->p->is_vararg)
1141 trap = 0; /* hooks will start after VARARGPREP instruction */ 1147 trap = 0; /* hooks will start after VARARGPREP instruction */
@@ -1150,6 +1156,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1150 Instruction i; /* instruction being executed */ 1156 Instruction i; /* instruction being executed */
1151 StkId ra; /* instruction's A register */ 1157 StkId ra; /* instruction's A register */
1152 vmfetch(); 1158 vmfetch();
1159// low-level line tracing for debugging Lua
1160// printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p)));
1153 lua_assert(base == ci->func + 1); 1161 lua_assert(base == ci->func + 1);
1154 lua_assert(base <= L->top && L->top < L->stack_last); 1162 lua_assert(base <= L->top && L->top < L->stack_last);
1155 /* invalidate top for instructions not expecting it */ 1163 /* invalidate top for instructions not expecting it */
@@ -1633,10 +1641,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1633 b = cast_int(L->top - ra); 1641 b = cast_int(L->top - ra);
1634 savepc(ci); /* several calls here can raise errors */ 1642 savepc(ci); /* several calls here can raise errors */
1635 if (TESTARG_k(i)) { 1643 if (TESTARG_k(i)) {
1636 /* close upvalues from current call; the compiler ensures 1644 luaF_closeupval(L, base); /* close upvalues from current call */
1637 that there are no to-be-closed variables here, so this 1645 lua_assert(L->tbclist < base); /* no pending tbc variables */
1638 call cannot change the stack */
1639 luaF_close(L, base, NOCLOSINGMETH, 0);
1640 lua_assert(base == ci->func + 1); 1646 lua_assert(base == ci->func + 1);
1641 } 1647 }
1642 while (!ttisfunction(s2v(ra))) { /* not a function? */ 1648 while (!ttisfunction(s2v(ra))) { /* not a function? */
@@ -1678,23 +1684,23 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1678 goto ret; 1684 goto ret;
1679 } 1685 }
1680 vmcase(OP_RETURN0) { 1686 vmcase(OP_RETURN0) {
1681 if (L->hookmask) { 1687 if (l_unlikely(L->hookmask)) {
1682 L->top = ra; 1688 L->top = ra;
1683 savepc(ci); 1689 savepc(ci);
1684 luaD_poscall(L, ci, 0); /* no hurry... */ 1690 luaD_poscall(L, ci, 0); /* no hurry... */
1685 trap = 1; 1691 trap = 1;
1686 } 1692 }
1687 else { /* do the 'poscall' here */ 1693 else { /* do the 'poscall' here */
1688 int nres = ci->nresults; 1694 int nres;
1689 L->ci = ci->previous; /* back to caller */ 1695 L->ci = ci->previous; /* back to caller */
1690 L->top = base - 1; 1696 L->top = base - 1;
1691 while (nres-- > 0) 1697 for (nres = ci->nresults; l_unlikely(nres > 0); nres--)
1692 setnilvalue(s2v(L->top++)); /* all results are nil */ 1698 setnilvalue(s2v(L->top++)); /* all results are nil */
1693 } 1699 }
1694 goto ret; 1700 goto ret;
1695 } 1701 }
1696 vmcase(OP_RETURN1) { 1702 vmcase(OP_RETURN1) {
1697 if (L->hookmask) { 1703 if (l_unlikely(L->hookmask)) {
1698 L->top = ra + 1; 1704 L->top = ra + 1;
1699 savepc(ci); 1705 savepc(ci);
1700 luaD_poscall(L, ci, 1); /* no hurry... */ 1706 luaD_poscall(L, ci, 1); /* no hurry... */
@@ -1708,8 +1714,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1708 else { 1714 else {
1709 setobjs2s(L, base - 1, ra); /* at least this result */ 1715 setobjs2s(L, base - 1, ra); /* at least this result */
1710 L->top = base; 1716 L->top = base;
1711 while (--nres > 0) /* complete missing results */ 1717 for (; l_unlikely(nres > 1); nres--)
1712 setnilvalue(s2v(L->top++)); 1718 setnilvalue(s2v(L->top++)); /* complete missing results */
1713 } 1719 }
1714 } 1720 }
1715 ret: /* return from a Lua function */ 1721 ret: /* return from a Lua function */
@@ -1812,7 +1818,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1812 } 1818 }
1813 vmcase(OP_VARARGPREP) { 1819 vmcase(OP_VARARGPREP) {
1814 ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p)); 1820 ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p));
1815 if (trap) { 1821 if (l_unlikely(trap)) { /* previous "Protect" updated trap */
1816 luaD_hookcall(L, ci); 1822 luaD_hookcall(L, ci);
1817 L->oldpc = 1; /* next opcode will be seen as a "new" line */ 1823 L->oldpc = 1; /* next opcode will be seen as a "new" line */
1818 } 1824 }
diff --git a/src/lua/lvm.h b/src/lua/lvm.h
index 2d4ac16..1bc16f3 100644
--- a/src/lua/lvm.h
+++ b/src/lua/lvm.h
@@ -60,12 +60,14 @@ typedef enum {
60 60
61/* convert an object to an integer (including string coercion) */ 61/* convert an object to an integer (including string coercion) */
62#define tointeger(o,i) \ 62#define tointeger(o,i) \
63 (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) 63 (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \
64 : luaV_tointeger(o,i,LUA_FLOORN2I))
64 65
65 66
66/* convert an object to an integer (without string coercion) */ 67/* convert an object to an integer (without string coercion) */
67#define tointegerns(o,i) \ 68#define tointegerns(o,i) \
68 (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointegerns(o,i,LUA_FLOORN2I)) 69 (l_likely(ttisinteger(o)) ? (*(i) = ivalue(o), 1) \
70 : luaV_tointegerns(o,i,LUA_FLOORN2I))
69 71
70 72
71#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) 73#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp
index c88fcf9..eb5cd69 100644
--- a/src/yuescript/ast.hpp
+++ b/src/yuescript/ast.hpp
@@ -100,7 +100,9 @@ public:
100 inline ast_ptr<false, T> new_ptr() const { 100 inline ast_ptr<false, T> new_ptr() const {
101 auto item = new T; 101 auto item = new T;
102 item->m_begin.m_line = m_begin.m_line; 102 item->m_begin.m_line = m_begin.m_line;
103 item->m_end.m_line = m_begin.m_line; 103 item->m_begin.m_col = m_begin.m_col;
104 item->m_end.m_line = m_end.m_line;
105 item->m_end.m_col = m_end.m_col;
104 return ast_ptr<false, T>(item); 106 return ast_ptr<false, T>(item);
105 } 107 }
106private: 108private:
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index 2d4814d..535a239 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -161,10 +161,12 @@ AST_END(import_all_macro)
161 161
162class variable_pair_t; 162class variable_pair_t;
163class normal_pair_t; 163class normal_pair_t;
164class meta_variable_pair_t;
165class meta_normal_pair_t;
164 166
165AST_NODE(ImportTabLit) 167AST_NODE(ImportTabLit)
166 ast_ptr<true, Seperator_t> sep; 168 ast_ptr<true, Seperator_t> sep;
167 ast_sel_list<false, variable_pair_t, normal_pair_t, MacroName_t, macro_name_pair_t, import_all_macro_t, Exp_t> items; 169 ast_sel_list<false, variable_pair_t, normal_pair_t, MacroName_t, macro_name_pair_t, import_all_macro_t, Exp_t, meta_variable_pair_t, meta_normal_pair_t> items;
168 AST_MEMBER(ImportTabLit, &sep, &items) 170 AST_MEMBER(ImportTabLit, &sep, &items)
169AST_END(ImportTabLit) 171AST_END(ImportTabLit)
170 172
@@ -423,9 +425,20 @@ AST_NODE(normal_pair)
423 AST_MEMBER(normal_pair, &key, &value) 425 AST_MEMBER(normal_pair, &key, &value)
424AST_END(normal_pair) 426AST_END(normal_pair)
425 427
428AST_NODE(meta_variable_pair)
429 ast_ptr<true, Variable_t> name;
430 AST_MEMBER(meta_variable_pair, &name)
431AST_END(meta_variable_pair)
432
433AST_NODE(meta_normal_pair)
434 ast_sel<true, Name_t> key;
435 ast_sel<true, Exp_t, TableBlock_t> value;
436 AST_MEMBER(meta_normal_pair, &key, &value)
437AST_END(meta_normal_pair)
438
426AST_NODE(simple_table) 439AST_NODE(simple_table)
427 ast_ptr<true, Seperator_t> sep; 440 ast_ptr<true, Seperator_t> sep;
428 ast_sel_list<true, variable_pair_t, normal_pair_t> pairs; 441 ast_sel_list<true, variable_pair_t, normal_pair_t, meta_variable_pair_t, meta_normal_pair_t> pairs;
429 AST_MEMBER(simple_table, &sep, &pairs) 442 AST_MEMBER(simple_table, &sep, &pairs)
430AST_END(simple_table) 443AST_END(simple_table)
431 444
@@ -484,13 +497,21 @@ AST_NODE(String)
484 AST_MEMBER(String, &str) 497 AST_MEMBER(String, &str)
485AST_END(String) 498AST_END(String)
486 499
487AST_NODE(DotChainItem) 500AST_LEAF(Metatable)
501AST_END(Metatable)
502
503AST_NODE(Metamethod)
488 ast_ptr<true, Name_t> name; 504 ast_ptr<true, Name_t> name;
505 AST_MEMBER(Metamethod, &name)
506AST_END(Metamethod)
507
508AST_NODE(DotChainItem)
509 ast_sel<true, Name_t, Metatable_t, Metamethod_t> name;
489 AST_MEMBER(DotChainItem, &name) 510 AST_MEMBER(DotChainItem, &name)
490AST_END(DotChainItem) 511AST_END(DotChainItem)
491 512
492AST_NODE(ColonChainItem) 513AST_NODE(ColonChainItem)
493 ast_sel<true, LuaKeyword_t, Name_t> name; 514 ast_sel<true, LuaKeyword_t, Name_t, Metamethod_t> name;
494 bool switchToDot = false; 515 bool switchToDot = false;
495 AST_MEMBER(ColonChainItem, &name) 516 AST_MEMBER(ColonChainItem, &name)
496AST_END(ColonChainItem) 517AST_END(ColonChainItem)
@@ -542,19 +563,19 @@ AST_END(default_value)
542 563
543AST_NODE(TableLit) 564AST_NODE(TableLit)
544 ast_ptr<true, Seperator_t> sep; 565 ast_ptr<true, Seperator_t> sep;
545 ast_sel_list<false, variable_pair_t, normal_pair_t, Exp_t> values; 566 ast_sel_list<false, variable_pair_t, normal_pair_t, Exp_t, meta_variable_pair_t, meta_normal_pair_t> values;
546 AST_MEMBER(TableLit, &sep, &values) 567 AST_MEMBER(TableLit, &sep, &values)
547AST_END(TableLit) 568AST_END(TableLit)
548 569
549AST_NODE(TableBlockIndent) 570AST_NODE(TableBlockIndent)
550 ast_ptr<true, Seperator_t> sep; 571 ast_ptr<true, Seperator_t> sep;
551 ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t> values; 572 ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, meta_variable_pair_t, meta_normal_pair_t> values;
552 AST_MEMBER(TableBlockIndent, &sep, &values) 573 AST_MEMBER(TableBlockIndent, &sep, &values)
553AST_END(TableBlockIndent) 574AST_END(TableBlockIndent)
554 575
555AST_NODE(TableBlock) 576AST_NODE(TableBlock)
556 ast_ptr<true, Seperator_t> sep; 577 ast_ptr<true, Seperator_t> sep;
557 ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, Exp_t, TableBlock_t> values; 578 ast_sel_list<false, variable_pair_t, normal_pair_t, TableBlockIndent_t, Exp_t, TableBlock_t, meta_variable_pair_t, meta_normal_pair_t> values;
558 AST_MEMBER(TableBlock, &sep, &values) 579 AST_MEMBER(TableBlock, &sep, &values)
559AST_END(TableBlock) 580AST_END(TableBlock)
560 581
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 0e65ae9..043c705 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -48,9 +48,9 @@ using namespace parserlib;
48#define YUEE(msg,node) throw std::logic_error( \ 48#define YUEE(msg,node) throw std::logic_error( \
49 _info.errorMessage( \ 49 _info.errorMessage( \
50 std::string("[File] ") + __FILE__ \ 50 std::string("[File] ") + __FILE__ \
51 + ", [Func] " + __FUNCTION__ \ 51 + ",\n[Func] " + __FUNCTION__ \
52 + ", [Line] " + std::to_string(__LINE__) \ 52 + ",\n[Line] " + std::to_string(__LINE__) \
53 + ", [Error] " + msg, node)) 53 + ",\n[Error] " + msg, node))
54 54
55typedef std::list<std::string> str_list; 55typedef std::list<std::string> str_list;
56 56
@@ -58,7 +58,7 @@ inline std::string s(std::string_view sv) {
58 return std::string(sv); 58 return std::string(sv);
59} 59}
60 60
61const std::string_view version = "0.6.10"sv; 61const std::string_view version = "0.7.0"sv;
62const std::string_view extension = "yue"sv; 62const std::string_view extension = "yue"sv;
63 63
64class YueCompilerImpl { 64class YueCompilerImpl {
@@ -618,13 +618,11 @@ private:
618 template <class T> 618 template <class T>
619 ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { 619 ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) {
620 auto res = _parser.parse<T>(s(codes)); 620 auto res = _parser.parse<T>(s(codes));
621 int line = parent->m_begin.m_line;
622 int col = parent->m_begin.m_line;
623 res.node->traverse([&](ast_node* node) { 621 res.node->traverse([&](ast_node* node) {
624 node->m_begin.m_line = line; 622 node->m_begin.m_line = parent->m_begin.m_line;
625 node->m_end.m_line = line; 623 node->m_begin.m_col = parent->m_begin.m_col;
626 node->m_begin.m_col = col; 624 node->m_end.m_line = parent->m_end.m_line;
627 node->m_end.m_col = col; 625 node->m_end.m_col = parent->m_end.m_col;
628 return traversal::Continue; 626 return traversal::Continue;
629 }); 627 });
630 _codeCache.push_back(std::move(res.codes)); 628 _codeCache.push_back(std::move(res.codes));
@@ -641,7 +639,8 @@ private:
641 EndWithEOP, 639 EndWithEOP,
642 HasEOP, 640 HasEOP,
643 HasKeyword, 641 HasKeyword,
644 Macro 642 Macro,
643 Metatable
645 }; 644 };
646 645
647 ChainType specialChainValue(ChainValue_t* chainValue) const { 646 ChainType specialChainValue(ChainValue_t* chainValue) const {
@@ -654,6 +653,11 @@ private:
654 if (ast_is<existential_op_t>(chainValue->items.back())) { 653 if (ast_is<existential_op_t>(chainValue->items.back())) {
655 return ChainType::EndWithEOP; 654 return ChainType::EndWithEOP;
656 } 655 }
656 if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) {
657 if (dot->name.is<Metatable_t>()) {
658 return ChainType::Metatable;
659 }
660 }
657 ChainType type = ChainType::Common; 661 ChainType type = ChainType::Common;
658 for (auto item : chainValue->items.objects()) { 662 for (auto item : chainValue->items.objects()) {
659 if (auto colonChain = ast_cast<ColonChainItem_t>(item)) { 663 if (auto colonChain = ast_cast<ColonChainItem_t>(item)) {
@@ -798,6 +802,18 @@ private:
798 return false; 802 return false;
799 } 803 }
800 804
805 std::string globalVar(std::string_view var, ast_node* x) {
806 std::string str(var);
807 if (_config.lintGlobalVariable) {
808 if (!isDefined(str)) {
809 if (_globals.find(str) == _globals.end()) {
810 _globals[str] = {x->m_begin.m_line, x->m_begin.m_col};
811 }
812 }
813 }
814 return str;
815 }
816
801 void transformStatement(Statement_t* statement, str_list& out) { 817 void transformStatement(Statement_t* statement, str_list& out) {
802 auto x = statement; 818 auto x = statement;
803 if (statement->appendix) { 819 if (statement->appendix) {
@@ -1107,6 +1123,53 @@ private:
1107 BLOCK_START 1123 BLOCK_START
1108 auto assign = ast_cast<Assign_t>(assignment->action); 1124 auto assign = ast_cast<Assign_t>(assignment->action);
1109 BREAK_IF(!assign); 1125 BREAK_IF(!assign);
1126 auto x = assignment;
1127 const auto& exprs = assignment->expList->exprs.objects();
1128 const auto& values = assign->values.objects();
1129 auto vit = values.begin();
1130 for (auto it = exprs.begin(); it != exprs.end(); ++it) {
1131 BLOCK_START
1132 auto value = singleValueFrom(*it);
1133 BREAK_IF(!value);
1134 auto chainValue = value->item.as<ChainValue_t>();
1135 BREAK_IF(!chainValue);
1136 if (specialChainValue(chainValue) == ChainType::Metatable) {
1137 str_list args;
1138 chainValue->items.pop_back();
1139 transformExp(static_cast<Exp_t*>(*it), args, ExpUsage::Closure);
1140 if (vit != values.end()) transformAssignItem(*vit, args);
1141 else args.push_back(s("nil"sv));
1142 _buf << indent() << globalVar("setmetatable"sv, x) << '(' << join(args, ", "sv) << ')' << nll(x);
1143 str_list temp;
1144 temp.push_back(clearBuf());
1145 auto newExpList = x->new_ptr<ExpList_t>();
1146 auto newAssign = x->new_ptr<Assign_t>();
1147 auto newAssignment = x->new_ptr<ExpListAssign_t>();
1148 newAssignment->expList.set(newExpList);
1149 newAssignment->action.set(newAssign);
1150 for (auto exp : exprs) {
1151 if (exp != *it) newExpList->exprs.push_back(exp);
1152 }
1153 for (auto value : values) {
1154 if (value != *vit) newAssign->values.push_back(value);
1155 }
1156 if (newExpList->exprs.empty() && newAssign->values.empty()) {
1157 out.push_back(temp.back());
1158 return;
1159 }
1160 if (newExpList->exprs.size() < newAssign->values.size()) {
1161 auto exp = toAst<Exp_t>("_"sv, x);
1162 while (newExpList->exprs.size() < newAssign->values.size()) {
1163 newExpList->exprs.push_back(exp);
1164 }
1165 }
1166 transformAssignment(newAssignment, temp);
1167 out.push_back(join(temp));
1168 return;
1169 }
1170 BLOCK_END
1171 if (vit != values.end()) ++vit;
1172 }
1110 BREAK_IF(assign->values.objects().size() != 1); 1173 BREAK_IF(assign->values.objects().size() != 1);
1111 auto value = assign->values.objects().back(); 1174 auto value = assign->values.objects().back();
1112 if (ast_is<Exp_t>(value)) { 1175 if (ast_is<Exp_t>(value)) {
@@ -1221,15 +1284,19 @@ private:
1221 return; 1284 return;
1222 case ChainType::Common: 1285 case ChainType::Common:
1223 case ChainType::EndWithEOP: 1286 case ChainType::EndWithEOP:
1287 case ChainType::Metatable:
1224 break; 1288 break;
1225 } 1289 }
1226 } 1290 }
1227 BLOCK_END 1291 BLOCK_END
1228 auto info = extractDestructureInfo(assignment); 1292 auto info = extractDestructureInfo(assignment, false);
1229 if (info.first.empty()) { 1293 if (info.first.empty()) {
1230 transformAssignmentCommon(assignment, out); 1294 transformAssignmentCommon(assignment, out);
1231 } else { 1295 } else {
1232 str_list temp; 1296 str_list temp;
1297 if (info.second) {
1298 transformAssignmentCommon(info.second, temp);
1299 }
1233 for (const auto& destruct : info.first) { 1300 for (const auto& destruct : info.first) {
1234 if (destruct.items.size() == 1) { 1301 if (destruct.items.size() == 1) {
1235 auto& pair = destruct.items.front(); 1302 auto& pair = destruct.items.front();
@@ -1240,7 +1307,7 @@ private:
1240 _buf << pair.name << " = "sv << destruct.value << pair.structure << nll(assignment); 1307 _buf << pair.name << " = "sv << destruct.value << pair.structure << nll(assignment);
1241 addToScope(pair.name); 1308 addToScope(pair.name);
1242 temp.push_back(clearBuf()); 1309 temp.push_back(clearBuf());
1243 } else if (_parser.match<Name_t>(destruct.value)) { 1310 } else if (_parser.match<Name_t>(destruct.value) && isDefined(destruct.value)) {
1244 str_list defs, names, values; 1311 str_list defs, names, values;
1245 for (const auto& item : destruct.items) { 1312 for (const auto& item : destruct.items) {
1246 if (item.isVariable && addToScope(item.name)) { 1313 if (item.isVariable && addToScope(item.name)) {
@@ -1281,9 +1348,6 @@ private:
1281 temp.push_back(clearBuf()); 1348 temp.push_back(clearBuf());
1282 } 1349 }
1283 } 1350 }
1284 if (info.second) {
1285 transformAssignmentCommon(info.second, temp);
1286 }
1287 out.push_back(join(temp)); 1351 out.push_back(join(temp));
1288 } 1352 }
1289 } 1353 }
@@ -1426,13 +1490,13 @@ private:
1426 } 1490 }
1427 1491
1428 std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>> 1492 std::pair<std::list<Destructure>, ast_ptr<false, ExpListAssign_t>>
1429 extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly = false) { 1493 extractDestructureInfo(ExpListAssign_t* assignment, bool varDefOnly) {
1430 auto x = assignment; 1494 auto x = assignment;
1431 std::list<Destructure> destructs; 1495 std::list<Destructure> destructs;
1432 if (!assignment->action.is<Assign_t>()) return { destructs, nullptr }; 1496 if (!assignment->action.is<Assign_t>()) return {destructs, nullptr};
1433 auto exprs = assignment->expList->exprs.objects(); 1497 auto exprs = assignment->expList->exprs.objects();
1434 auto values = assignment->action.to<Assign_t>()->values.objects(); 1498 auto values = assignment->action.to<Assign_t>()->values.objects();
1435 size_t size = std::max(exprs.size(),values.size()); 1499 size_t size = std::max(exprs.size(), values.size());
1436 ast_ptr<false, Exp_t> var; 1500 ast_ptr<false, Exp_t> var;
1437 if (exprs.size() < size) { 1501 if (exprs.size() < size) {
1438 var = toAst<Exp_t>("_"sv, x); 1502 var = toAst<Exp_t>("_"sv, x);
@@ -1445,6 +1509,8 @@ private:
1445 } 1509 }
1446 using iter = node_container::iterator; 1510 using iter = node_container::iterator;
1447 std::vector<std::pair<iter,iter>> destructPairs; 1511 std::vector<std::pair<iter,iter>> destructPairs;
1512 ast_list<false, ast_node> valueItems;
1513 if (!varDefOnly) pushScope();
1448 str_list temp; 1514 str_list temp;
1449 for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) { 1515 for (auto i = exprs.begin(), j = values.begin(); i != exprs.end(); ++i, ++j) {
1450 auto expr = *i; 1516 auto expr = *i;
@@ -1459,26 +1525,86 @@ private:
1459 } 1525 }
1460 } 1526 }
1461 destructPairs.push_back({i,j}); 1527 destructPairs.push_back({i,j});
1462 auto& destruct = destructs.emplace_back(); 1528 auto subDestruct = destructNode->new_ptr<TableLit_t>();
1463 if (!varDefOnly) { 1529 auto subMetaDestruct = destructNode->new_ptr<TableLit_t>();
1464 pushScope(); 1530 const node_container* dlist = nullptr;
1465 transformAssignItem(*j, temp); 1531 switch (destructNode->getId()) {
1466 destruct.value = temp.back(); 1532 case id<TableLit_t>():
1467 temp.pop_back(); 1533 dlist = &static_cast<TableLit_t*>(destructNode)->values.objects();
1468 popScope(); 1534 break;
1535 case id<simple_table_t>():
1536 dlist = &static_cast<simple_table_t*>(destructNode)->pairs.objects();
1537 break;
1538 default: YUEE("AST node mismatch", destructNode); break;
1539 }
1540 for (auto item : *dlist) {
1541 switch (item->getId()) {
1542 case id<meta_variable_pair_t>(): {
1543 auto mp = static_cast<meta_variable_pair_t*>(item);
1544 auto name = _parser.toString(mp->name);
1545 _buf << "__"sv << name << ':' << name;
1546 auto newPair = toAst<normal_pair_t>(clearBuf(), item);
1547 subMetaDestruct->values.push_back(newPair);
1548 break;
1549 }
1550 case id<meta_normal_pair_t>(): {
1551 auto mp = static_cast<meta_normal_pair_t*>(item);
1552 auto key = _parser.toString(mp->key);
1553 _buf << "__"sv << key;
1554 auto newKey = toAst<KeyName_t>(clearBuf(), item);
1555 auto newPair = item->new_ptr<normal_pair_t>();
1556 newPair->key.set(newKey);
1557 newPair->value.set(mp->value);
1558 subMetaDestruct->values.push_back(newPair);
1559 break;
1560 }
1561 default:
1562 subDestruct->values.push_back(item);
1563 break;
1564 }
1469 } 1565 }
1470 auto pairs = destructFromExp(expr); 1566 valueItems.push_back(*j);
1471 destruct.items = std::move(pairs); 1567 if (!varDefOnly && !subDestruct->values.empty() && !subMetaDestruct->values.empty()) {
1472 if (*j == nullNode) { 1568 auto objVar = getUnusedName("_obj_"sv);
1473 for (auto& item : destruct.items) { 1569 addToScope(objVar);
1474 item.structure.clear(); 1570 valueItems.pop_back();
1571 valueItems.push_back(toAst<Exp_t>(objVar, *j));
1572 exprs.push_back(valueItems.back());
1573 values.push_back(*j);
1574 }
1575 TableLit_t* tabs[] = {subDestruct.get(), subMetaDestruct.get()};
1576 for (auto tab : tabs) {
1577 if (!tab->values.empty()) {
1578 auto& destruct = destructs.emplace_back();
1579 if (!varDefOnly) {
1580 transformAssignItem(valueItems.back(), temp);
1581 destruct.value = temp.back();
1582 temp.pop_back();
1583 }
1584 auto simpleValue = tab->new_ptr<SimpleValue_t>();
1585 simpleValue->value.set(tab);
1586 auto value = tab->new_ptr<Value_t>();
1587 value->item.set(simpleValue);
1588 auto pairs = destructFromExp(newExp(value, expr));
1589 destruct.items = std::move(pairs);
1590 if (!varDefOnly) {
1591 if (*j == nullNode) {
1592 for (auto& item : destruct.items) {
1593 item.structure.clear();
1594 }
1595 } else if (tab == subMetaDestruct.get()) {
1596 destruct.value.insert(0, globalVar("getmetatable"sv, tab) + '(');
1597 destruct.value.append(")"sv);
1598 } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) {
1599 destruct.value.insert(0, "("sv);
1600 destruct.value.append(")"sv);
1601 }
1602 }
1475 } 1603 }
1476 } else if (destruct.items.size() == 1 && !singleValueFrom(*j)) {
1477 destruct.value.insert(0, "("sv);
1478 destruct.value.append(")"sv);
1479 } 1604 }
1480 } 1605 }
1481 } 1606 }
1607 if (!varDefOnly) popScope();
1482 for (const auto& p : destructPairs) { 1608 for (const auto& p : destructPairs) {
1483 exprs.erase(p.first); 1609 exprs.erase(p.first);
1484 values.erase(p.second); 1610 values.erase(p.second);
@@ -1511,6 +1637,8 @@ private:
1511 auto leftValue = singleValueFrom(leftExp); 1637 auto leftValue = singleValueFrom(leftExp);
1512 if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp)); 1638 if (!leftValue) throw std::logic_error(_info.errorMessage("left hand expression is not assignable"sv, leftExp));
1513 if (auto chain = leftValue->item.as<ChainValue_t>()) { 1639 if (auto chain = leftValue->item.as<ChainValue_t>()) {
1640 if (specialChainValue(chain) == ChainType::Metatable) {throw std::logic_error(_info.errorMessage("can not apply update to a metatable"sv, leftExp));
1641 }
1514 auto tmpChain = x->new_ptr<ChainValue_t>(); 1642 auto tmpChain = x->new_ptr<ChainValue_t>();
1515 for (auto item : chain->items.objects()) { 1643 for (auto item : chain->items.objects()) {
1516 bool itemAdded = false; 1644 bool itemAdded = false;
@@ -1911,7 +2039,7 @@ private:
1911 switch (item->getId()) { 2039 switch (item->getId()) {
1912 case id<Variable_t>(): { 2040 case id<Variable_t>(): {
1913 transformVariable(static_cast<Variable_t*>(item), out); 2041 transformVariable(static_cast<Variable_t*>(item), out);
1914 if (_config.lintGlobalVariable && !isDefined(out.back())) { 2042 if (_config.lintGlobalVariable && !isSolidDefined(out.back())) {
1915 if (_globals.find(out.back()) == _globals.end()) { 2043 if (_globals.find(out.back()) == _globals.end()) {
1916 _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col}; 2044 _globals[out.back()] = {item->m_begin.m_line, item->m_begin.m_col};
1917 } 2045 }
@@ -1920,14 +2048,7 @@ private:
1920 } 2048 }
1921 case id<SelfName_t>(): { 2049 case id<SelfName_t>(): {
1922 transformSelfName(static_cast<SelfName_t*>(item), out, invoke); 2050 transformSelfName(static_cast<SelfName_t*>(item), out, invoke);
1923 if (_config.lintGlobalVariable) { 2051 globalVar("self"sv, item);
1924 std::string self("self"sv);
1925 if (!isDefined(self)) {
1926 if (_globals.find(self) == _globals.end()) {
1927 _globals[self] = {item->m_begin.m_line, item->m_begin.m_col};
1928 }
1929 }
1930 }
1931 break; 2052 break;
1932 } 2053 }
1933 case id<VarArg_t>(): 2054 case id<VarArg_t>():
@@ -3030,6 +3151,55 @@ private:
3030 return false; 3151 return false;
3031 } 3152 }
3032 3153
3154 bool transformChainWithMetatable(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) {
3155 auto opIt = std::find_if(chainList.begin(), chainList.end(), [](ast_node* node) {
3156 if (auto colonChain = ast_cast<ColonChainItem_t>(node)) {
3157 if (ast_is<Metamethod_t>(colonChain->name)) {
3158 return true;
3159 }
3160 } else if (auto dotChain = ast_cast<DotChainItem_t>(node)) {
3161 if (ast_is<Metatable_t, Metamethod_t>(dotChain->name)) {
3162 return true;
3163 }
3164 }
3165 return false;
3166 });
3167 if (opIt == chainList.end()) return false;
3168 auto x = chainList.front();
3169 auto chain = x->new_ptr<ChainValue_t>();
3170 for (auto it = chainList.begin(); it != opIt; ++it) {
3171 chain->items.push_back(*it);
3172 }
3173 auto value = x->new_ptr<Value_t>();
3174 value->item.set(chain);
3175 auto exp = newExp(value, x);
3176
3177 chain = toAst<ChainValue_t>("getmetatable()"sv, x);
3178 ast_to<Invoke_t>(chain->items.back())->args.push_back(exp);
3179 switch ((*opIt)->getId()) {
3180 case id<ColonChainItem_t>(): {
3181 auto colon = static_cast<ColonChainItem_t*>(*opIt);
3182 auto meta = colon->name.to<Metamethod_t>();
3183 auto newColon = toAst<ColonChainItem_t>(s("\\__"sv) + _parser.toString(meta->name), x);
3184 chain->items.push_back(newColon);
3185 break;
3186 }
3187 case id<DotChainItem_t>(): {
3188 auto dot = static_cast<DotChainItem_t*>(*opIt);
3189 if (dot->name.is<Metatable_t>()) break;
3190 auto meta = dot->name.to<Metamethod_t>();
3191 auto newDot = toAst<DotChainItem_t>(s(".__"sv) + _parser.toString(meta->name), x);
3192 chain->items.push_back(newDot);
3193 break;
3194 }
3195 }
3196 for (auto it = ++opIt; it != chainList.end(); ++it) {
3197 chain->items.push_back(*it);
3198 }
3199 transformChainValue(chain, out, usage, assignList);
3200 return true;
3201 }
3202
3033 void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 3203 void transformChainList(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
3034 auto x = chainList.front(); 3204 auto x = chainList.front();
3035 str_list temp; 3205 str_list temp;
@@ -3553,6 +3723,9 @@ private:
3553#endif // YUE_NO_MACRO 3723#endif // YUE_NO_MACRO
3554 } 3724 }
3555 const auto& chainList = chainValue->items.objects(); 3725 const auto& chainList = chainValue->items.objects();
3726 if (transformChainWithMetatable(chainList, out, usage, assignList)) {
3727 return;
3728 }
3556 if (transformChainEndWithEOP(chainList, out, usage, assignList)) { 3729 if (transformChainEndWithEOP(chainList, out, usage, assignList)) {
3557 return; 3730 return;
3558 } 3731 }
@@ -3801,7 +3974,8 @@ private:
3801 switch (loopTarget->getId()) { 3974 switch (loopTarget->getId()) {
3802 case id<star_exp_t>(): { 3975 case id<star_exp_t>(): {
3803 auto star_exp = static_cast<star_exp_t*>(loopTarget); 3976 auto star_exp = static_cast<star_exp_t*>(loopTarget);
3804 std::string listVar; 3977 auto listVar = singleVariableFrom(star_exp->value);
3978 if (!isSolidDefined(listVar)) listVar.clear();
3805 auto indexVar = getUnusedName("_index_"sv); 3979 auto indexVar = getUnusedName("_index_"sv);
3806 varAfter.push_back(indexVar); 3980 varAfter.push_back(indexVar);
3807 auto value = singleValueFrom(star_exp->value); 3981 auto value = singleValueFrom(star_exp->value);
@@ -3814,6 +3988,12 @@ private:
3814 auto slice = ast_cast<Slice_t>(chainList.back()); 3988 auto slice = ast_cast<Slice_t>(chainList.back());
3815 BREAK_IF(!slice); 3989 BREAK_IF(!slice);
3816 endWithSlice = true; 3990 endWithSlice = true;
3991 if (listVar.empty() && chainList.size() == 2) {
3992 if (auto var = chainList.front()->getByPath<Variable_t>()) {
3993 listVar = _parser.toString(var);
3994 if (!isSolidDefined(listVar)) listVar.clear();
3995 }
3996 }
3817 chainList.pop_back(); 3997 chainList.pop_back();
3818 auto chain = x->new_ptr<ChainValue_t>(); 3998 auto chain = x->new_ptr<ChainValue_t>();
3819 for (auto item : chainList) { 3999 for (auto item : chainList) {
@@ -3837,10 +4017,12 @@ private:
3837 stepValue = temp.back(); 4017 stepValue = temp.back();
3838 temp.pop_back(); 4018 temp.pop_back();
3839 } 4019 }
3840 listVar = getUnusedName("_list_"sv); 4020 if (listVar.empty()) {
3841 varBefore.push_back(listVar); 4021 listVar = getUnusedName("_list_"sv);
3842 transformChainValue(chain, temp, ExpUsage::Closure); 4022 varBefore.push_back(listVar);
3843 _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); 4023 transformChainValue(chain, temp, ExpUsage::Closure);
4024 _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList);
4025 }
3844 std::string maxVar; 4026 std::string maxVar;
3845 if (!stopValue.empty()) { 4027 if (!stopValue.empty()) {
3846 maxVar = getUnusedName("_max_"sv); 4028 maxVar = getUnusedName("_max_"sv);
@@ -4248,15 +4430,7 @@ private:
4248 } 4430 }
4249 case id<Exp_t>(): { 4431 case id<Exp_t>(): {
4250 transformExp(static_cast<Exp_t*>(content), temp, ExpUsage::Closure); 4432 transformExp(static_cast<Exp_t*>(content), temp, ExpUsage::Closure);
4251 std::string tostr("tostring"sv); 4433 temp.back() = globalVar("tostring"sv, content) + '(' + temp.back() + s(")"sv);
4252 temp.back() = tostr + '(' + temp.back() + s(")"sv);
4253 if (_config.lintGlobalVariable) {
4254 if (!isDefined(tostr)) {
4255 if (_globals.find(tostr) == _globals.end()) {
4256 _globals[tostr] = {content->m_begin.m_line, content->m_begin.m_col};
4257 }
4258 }
4259 }
4260 break; 4434 break;
4261 } 4435 }
4262 default: YUEE("AST node mismatch", content); break; 4436 default: YUEE("AST node mismatch", content); break;
@@ -4460,7 +4634,7 @@ private:
4460 if (extend) { 4634 if (extend) {
4461 _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nll(classDecl); 4635 _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nll(classDecl);
4462 } 4636 }
4463 _buf << indent() << classVar << " = setmetatable({"sv << nll(classDecl); 4637 _buf << indent() << classVar << " = " << globalVar("setmetatable"sv, classDecl) << "({"sv << nll(classDecl);
4464 if (!builtins.empty()) { 4638 if (!builtins.empty()) {
4465 _buf << join(builtins) << ","sv << nll(classDecl); 4639 _buf << join(builtins) << ","sv << nll(classDecl);
4466 } else { 4640 } else {
@@ -4673,8 +4847,14 @@ private:
4673 checkAssignable(with->valueList); 4847 checkAssignable(with->valueList);
4674 auto vars = getAssignVars(with); 4848 auto vars = getAssignVars(with);
4675 if (vars.front().empty()) { 4849 if (vars.front().empty()) {
4676 withVar = getUnusedName("_with_"sv); 4850 if (with->assigns->values.objects().size() == 1) {
4677 { 4851 auto var = singleVariableFrom(with->assigns->values.objects().front());
4852 if (!var.empty() && isSolidDefined(var)) {
4853 withVar = var;
4854 }
4855 }
4856 if (withVar.empty()) {
4857 withVar = getUnusedName("_with_"sv);
4678 auto assignment = x->new_ptr<ExpListAssign_t>(); 4858 auto assignment = x->new_ptr<ExpListAssign_t>();
4679 assignment->expList.set(toAst<ExpList_t>(withVar, x)); 4859 assignment->expList.set(toAst<ExpList_t>(withVar, x));
4680 auto assign = x->new_ptr<Assign_t>(); 4860 auto assign = x->new_ptr<Assign_t>();
@@ -4714,18 +4894,21 @@ private:
4714 transformAssignment(assignment, temp); 4894 transformAssignment(assignment, temp);
4715 } 4895 }
4716 } else { 4896 } else {
4717 withVar = getUnusedName("_with_"sv); 4897 withVar = singleVariableFrom(with->valueList);
4718 auto assignment = x->new_ptr<ExpListAssign_t>(); 4898 if (withVar.empty() || !isSolidDefined(withVar)) {
4719 assignment->expList.set(toAst<ExpList_t>(withVar, x)); 4899 withVar = getUnusedName("_with_"sv);
4720 auto assign = x->new_ptr<Assign_t>(); 4900 auto assignment = x->new_ptr<ExpListAssign_t>();
4721 assign->values.dup(with->valueList->exprs); 4901 assignment->expList.set(toAst<ExpList_t>(withVar, x));
4722 assignment->action.set(assign); 4902 auto assign = x->new_ptr<Assign_t>();
4723 if (!returnValue) { 4903 assign->values.dup(with->valueList->exprs);
4724 scoped = true; 4904 assignment->action.set(assign);
4725 temp.push_back(indent() + s("do"sv) + nll(with)); 4905 if (!returnValue) {
4726 pushScope(); 4906 scoped = true;
4907 temp.push_back(indent() + s("do"sv) + nll(with));
4908 pushScope();
4909 }
4910 transformAssignment(assignment, temp);
4727 } 4911 }
4728 transformAssignment(assignment, temp);
4729 } 4912 }
4730 if (!with->eop && !scoped && !returnValue) { 4913 if (!with->eop && !scoped && !returnValue) {
4731 pushScope(); 4914 pushScope();
@@ -4953,20 +5136,64 @@ private:
4953 } 5136 }
4954 str_list temp; 5137 str_list temp;
4955 incIndentOffset(); 5138 incIndentOffset();
5139 auto metatable = table->new_ptr<simple_table_t>();
4956 for (auto pair : pairs) { 5140 for (auto pair : pairs) {
5141 bool isMetamethod = false;
4957 switch (pair->getId()) { 5142 switch (pair->getId()) {
4958 case id<Exp_t>(): transformExp(static_cast<Exp_t*>(pair), temp, ExpUsage::Closure); break; 5143 case id<Exp_t>(): transformExp(static_cast<Exp_t*>(pair), temp, ExpUsage::Closure); break;
4959 case id<variable_pair_t>(): transform_variable_pair(static_cast<variable_pair_t*>(pair), temp); break; 5144 case id<variable_pair_t>(): transform_variable_pair(static_cast<variable_pair_t*>(pair), temp); break;
4960 case id<normal_pair_t>(): transform_normal_pair(static_cast<normal_pair_t*>(pair), temp); break; 5145 case id<normal_pair_t>(): transform_normal_pair(static_cast<normal_pair_t*>(pair), temp); break;
4961 case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(pair), temp); break; 5146 case id<TableBlockIndent_t>(): transformTableBlockIndent(static_cast<TableBlockIndent_t*>(pair), temp); break;
4962 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(pair), temp); break; 5147 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(pair), temp); break;
5148 case id<meta_variable_pair_t>(): {
5149 isMetamethod = true;
5150 auto mp = static_cast<meta_variable_pair_t*>(pair);
5151 auto name = _parser.toString(mp->name);
5152 _buf << "__"sv << name << ':' << name;
5153 auto newPair = toAst<normal_pair_t>(clearBuf(), pair);
5154 metatable->pairs.push_back(newPair);
5155 break;
5156 }
5157 case id<meta_normal_pair_t>(): {
5158 isMetamethod = true;
5159 auto mp = static_cast<meta_normal_pair_t*>(pair);
5160 auto key = _parser.toString(mp->key);
5161 _buf << "__"sv << key;
5162 auto newKey = toAst<KeyName_t>(clearBuf(), pair);
5163 auto newPair = pair->new_ptr<normal_pair_t>();
5164 newPair->key.set(newKey);
5165 newPair->value.set(mp->value);
5166 metatable->pairs.push_back(newPair);
5167 break;
5168 }
4963 default: YUEE("AST node mismatch", pair); break; 5169 default: YUEE("AST node mismatch", pair); break;
4964 } 5170 }
4965 temp.back() = indent() + temp.back() + (pair == pairs.back() ? Empty : s(","sv)) + nll(pair); 5171 if (!isMetamethod) {
5172 temp.back() = indent() + temp.back() + (pair == pairs.back() ? Empty : s(","sv)) + nll(pair);
5173 }
5174 }
5175 if (metatable->pairs.empty()) {
5176 out.push_back(s("{"sv) + nll(table) + join(temp));
5177 decIndentOffset();
5178 out.back() += (indent() + s("}"sv));
5179 } else {
5180 auto tabStr = globalVar("setmetatable"sv, table);
5181 tabStr += '(';
5182 if (temp.empty()) {
5183 decIndentOffset();
5184 tabStr += "{ }"sv;
5185 } else {
5186 tabStr += (s("{"sv) + nll(table) + join(temp));
5187 decIndentOffset();
5188 tabStr += (indent() + s("}"sv));
5189 }
5190 tabStr += ", "sv;
5191 str_list tmp;
5192 transform_simple_table(metatable, tmp);
5193 tabStr += tmp.back();
5194 tabStr += s(")"sv);
5195 out.push_back(tabStr);
4966 } 5196 }
4967 out.push_back(s("{"sv) + nll(table) + join(temp));
4968 decIndentOffset();
4969 out.back() += (indent() + s("}"sv));
4970 } 5197 }
4971 5198
4972 void transform_simple_table(simple_table_t* table, str_list& out) { 5199 void transform_simple_table(simple_table_t* table, str_list& out) {
@@ -5236,6 +5463,8 @@ private:
5236 break; 5463 break;
5237 case id<variable_pair_t>(): 5464 case id<variable_pair_t>():
5238 case id<normal_pair_t>(): 5465 case id<normal_pair_t>():
5466 case id<meta_variable_pair_t>():
5467 case id<meta_normal_pair_t>():
5239 case id<Exp_t>(): 5468 case id<Exp_t>():
5240 newTab->items.push_back(item); 5469 newTab->items.push_back(item);
5241 break; 5470 break;
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 7cf2ebe..c72c005 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -412,6 +412,9 @@ YueParser::YueParser() {
412 FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) | 412 FnArgs = (symx('(') >> *SpaceBreak >> -FnArgsExpList >> *SpaceBreak >> sym(')')) |
413 (sym('!') >> not_(expr('='))); 413 (sym('!') >> not_(expr('=')));
414 414
415 Metatable = expr('#');
416 Metamethod = Name >> expr('#');
417
415 existential_op = expr('?'); 418 existential_op = expr('?');
416 chain_call = (Callable | String) >> -existential_op >> ChainItems; 419 chain_call = (Callable | String) >> -existential_op >> ChainItems;
417 chain_item = and_(set(".\\")) >> ChainItems; 420 chain_item = and_(set(".\\")) >> ChainItems;
@@ -427,8 +430,8 @@ YueParser::YueParser() {
427 430
428 Index = symx('[') >> Exp >> sym(']'); 431 Index = symx('[') >> Exp >> sym(']');
429 ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op; 432 ChainItem = Invoke >> -existential_op | DotChainItem >> -existential_op | Slice | Index >> -existential_op;
430 DotChainItem = symx('.') >> Name; 433 DotChainItem = symx('.') >> (Name >> not_('#') | Metatable | Metamethod);
431 ColonChainItem = symx('\\') >> (LuaKeyword | Name); 434 ColonChainItem = symx('\\') >> ((LuaKeyword | Name) >> not_('#') | Metamethod);
432 invoke_chain = Invoke >> -existential_op >> -ChainItems; 435 invoke_chain = Invoke >> -existential_op >> -ChainItems;
433 ColonChain = ColonChainItem >> -existential_op >> -invoke_chain; 436 ColonChain = ColonChainItem >> -existential_op >> -invoke_chain;
434 437
@@ -508,7 +511,7 @@ YueParser::YueParser() {
508 }) >> ExpList >> -Assign) 511 }) >> ExpList >> -Assign)
509 | Macro) >> not_(Space >> statement_appendix); 512 | Macro) >> not_(Space >> statement_appendix);
510 513
511 variable_pair = sym(':') >> Variable; 514 variable_pair = sym(':') >> Variable >> not_('#');
512 515
513 normal_pair = ( 516 normal_pair = (
514 KeyName | 517 KeyName |
@@ -520,7 +523,12 @@ YueParser::YueParser() {
520 symx(':') >> 523 symx(':') >>
521 (Exp | TableBlock | +(SpaceBreak) >> Exp); 524 (Exp | TableBlock | +(SpaceBreak) >> Exp);
522 525
523 KeyValue = variable_pair | normal_pair; 526 meta_variable_pair = sym(':') >> Variable >> expr('#');
527
528 meta_normal_pair = Space >> Name >> expr("#:") >>
529 (Exp | TableBlock | +(SpaceBreak) >> Exp);
530
531 KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair;
524 532
525 KeyValueList = KeyValue >> *(sym(',') >> KeyValue); 533 KeyValueList = KeyValue >> *(sym(',') >> KeyValue);
526 KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (Exp | TableBlock)); 534 KeyValueLine = CheckIndent >> (KeyValueList >> -sym(',') | TableBlockIndent | Space >> expr('*') >> (Exp | TableBlock));
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index f9a0d54..729304a 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -265,6 +265,8 @@ private:
265 AST_RULE(Parens) 265 AST_RULE(Parens)
266 AST_RULE(DotChainItem) 266 AST_RULE(DotChainItem)
267 AST_RULE(ColonChainItem) 267 AST_RULE(ColonChainItem)
268 AST_RULE(Metatable)
269 AST_RULE(Metamethod)
268 AST_RULE(default_value) 270 AST_RULE(default_value)
269 AST_RULE(Slice) 271 AST_RULE(Slice)
270 AST_RULE(Invoke) 272 AST_RULE(Invoke)
@@ -282,6 +284,8 @@ private:
282 AST_RULE(Export) 284 AST_RULE(Export)
283 AST_RULE(variable_pair) 285 AST_RULE(variable_pair)
284 AST_RULE(normal_pair) 286 AST_RULE(normal_pair)
287 AST_RULE(meta_variable_pair)
288 AST_RULE(meta_normal_pair)
285 AST_RULE(FnArgDef) 289 AST_RULE(FnArgDef)
286 AST_RULE(FnArgDefList) 290 AST_RULE(FnArgDefList)
287 AST_RULE(outer_var_shadow) 291 AST_RULE(outer_var_shadow)