aboutsummaryrefslogtreecommitdiff
path: root/lfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lfunc.c')
-rw-r--r--lfunc.c75
1 files changed, 22 insertions, 53 deletions
diff --git a/lfunc.c b/lfunc.c
index bfbf270b..ae68487c 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -100,12 +100,6 @@ UpVal *luaF_findupval (lua_State *L, StkId level) {
100} 100}
101 101
102 102
103static void callclose (lua_State *L, void *ud) {
104 UNUSED(ud);
105 luaD_callnoyield(L, L->top - 3, 0);
106}
107
108
109/* 103/*
110** Prepare closing method plus its arguments for object 'obj' with 104** Prepare closing method plus its arguments for object 'obj' with
111** error message 'err'. (This function assumes EXTRA_STACK.) 105** error message 'err'. (This function assumes EXTRA_STACK.)
@@ -136,40 +130,25 @@ static void varerror (lua_State *L, StkId level, const char *msg) {
136 130
137 131
138/* 132/*
139** Prepare and call a closing method. If status is OK, code is still 133** Prepare and call a closing method.
140** inside the original protected call, and so any error will be handled 134** If status is CLOSEKTOP, the call to the closing method will be pushed
141** there. Otherwise, a previous error already activated the original 135** at the top of the stack. Otherwise, values can be pushed right after
142** protected call, and so the call to the closing method must be 136** the 'level' of the upvalue being closed, as everything after that
143** protected here. (A status == CLOSEPROTECT behaves like a previous 137** won't be used again.
144** error, to also run the closing method in protected mode).
145** If status is OK, the call to the closing method will be pushed
146** at the top of the stack. Otherwise, values are pushed after
147** the 'level' of the upvalue being closed, as everything after
148** that won't be used again.
149*/ 138*/
150static int callclosemth (lua_State *L, StkId level, int status) { 139static void callclosemth (lua_State *L, StkId level, int status) {
151 TValue *uv = s2v(level); /* value being closed */ 140 TValue *uv = s2v(level); /* value being closed */
152 if (likely(status == LUA_OK)) { 141 TValue *errobj;
153 if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ 142 if (status == CLOSEKTOP)
154 callclose(L, NULL); /* call closing method */ 143 errobj = &G(L)->nilvalue; /* error object is nil */
155 else if (!l_isfalse(uv)) /* non-closable non-false value? */ 144 else { /* 'luaD_seterrorobj' will set top to level + 2 */
156 varerror(L, level, "attempt to close non-closable variable '%s'"); 145 errobj = s2v(level + 1); /* error object goes after 'uv' */
157 } 146 luaD_seterrorobj(L, status, level + 1); /* set error object */
158 else { /* must close the object in protected mode */
159 ptrdiff_t oldtop;
160 level++; /* space for error message */
161 oldtop = savestack(L, level + 1); /* top will be after that */
162 luaD_seterrorobj(L, status, level); /* set error message */
163 if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */
164 int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0);
165 if (newstatus != LUA_OK) /* new error? */
166 status = newstatus; /* this will be the error now */
167 else /* leave original error (or nil) on top */
168 L->top = restorestack(L, oldtop);
169 }
170 /* else no metamethod; ignore this case and keep original error */
171 } 147 }
172 return status; 148 if (prepclosingmethod(L, uv, errobj)) /* something to call? */
149 luaD_callnoyield(L, L->top - 3, 0); /* call method */
150 else if (!l_isfalse(uv)) /* non-closable non-false value? */
151 varerror(L, level, "attempt to close non-closable variable '%s'");
173} 152}
174 153
175 154
@@ -201,7 +180,7 @@ void luaF_newtbcupval (lua_State *L, StkId level) {
201 luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */ 180 luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */
202 /* next call must succeed, as object is closable */ 181 /* next call must succeed, as object is closable */
203 prepclosingmethod(L, s2v(level), s2v(level + 1)); 182 prepclosingmethod(L, s2v(level), s2v(level + 1));
204 callclose(L, NULL); /* call closing method */ 183 luaD_callnoyield(L, L->top - 3, 0); /* call method */
205 luaD_throw(L, LUA_ERRMEM); /* throw memory error */ 184 luaD_throw(L, LUA_ERRMEM); /* throw memory error */
206 } 185 }
207 } 186 }
@@ -217,19 +196,11 @@ void luaF_unlinkupval (UpVal *uv) {
217 196
218 197
219/* 198/*
220** Close all upvalues up to the given stack level. 'status' indicates 199** Close all upvalues up to the given stack level. A 'status' equal
221** how/why the function was called: 200** to NOCLOSINGMETH closes upvalues without running any __close
222** - LUA_OK: regular code exiting the scope of a variable; may raise 201** metamethods.
223** an error due to errors in __close metamethods;
224** - CLOSEPROTECT: finishing a thread; run all metamethods in protected
225** mode;
226** - NOCLOSINGMETH: close upvalues without running __close metamethods;
227** - other values: error status from previous errors, to be propagated.
228**
229** Returns the resulting status, either the original status or an error
230** in a closing method.
231*/ 202*/
232int luaF_close (lua_State *L, StkId level, int status) { 203void luaF_close (lua_State *L, StkId level, int status) {
233 UpVal *uv; 204 UpVal *uv;
234 StkId upl; /* stack index pointed by 'uv' */ 205 StkId upl; /* stack index pointed by 'uv' */
235 while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { 206 while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) {
@@ -243,13 +214,11 @@ int luaF_close (lua_State *L, StkId level, int status) {
243 luaC_barrier(L, uv, slot); 214 luaC_barrier(L, uv, slot);
244 } 215 }
245 if (uv->tbc && status != NOCLOSINGMETH) { 216 if (uv->tbc && status != NOCLOSINGMETH) {
246 /* must run closing method, which may change the stack */
247 ptrdiff_t levelrel = savestack(L, level); 217 ptrdiff_t levelrel = savestack(L, level);
248 status = callclosemth(L, upl, status); 218 callclosemth(L, upl, status); /* may change the stack */
249 level = restorestack(L, levelrel); 219 level = restorestack(L, levelrel);
250 } 220 }
251 } 221 }
252 return status;
253} 222}
254 223
255 224