diff options
| author | Li Jin <dragon-fly@qq.com> | 2021-03-03 21:31:01 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2021-03-03 21:33:37 +0800 |
| commit | 1df786307c1983b8ce693e3916081a8bcd4e95ae (patch) | |
| tree | 6c7aeb2198d825877fd3d179c394b7a5c1f06a17 /src/lua/lfunc.c | |
| parent | 66168b112b707172b9035edf8c1daed469781e06 (diff) | |
| download | yuescript-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 '')
| -rw-r--r-- | src/lua/lfunc.c | 69 |
1 files changed, 34 insertions, 35 deletions
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 | */ |
| 126 | static void checkclosemth (lua_State *L, StkId level, const TValue *obj) { | 126 | static 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 | */ | ||
| 161 | static 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 | */ |
| 171 | void luaF_newtbcupval (lua_State *L, StkId level) { | 160 | void 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 | */ |
| 201 | void luaF_close (lua_State *L, StkId level, int status, int yy) { | 187 | void 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 | */ | ||
| 208 | void 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 | } |
