aboutsummaryrefslogtreecommitdiff
path: root/lfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lfunc.c')
-rw-r--r--lfunc.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/lfunc.c b/lfunc.c
index 6f2f897f..8f39f6b0 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -124,11 +124,23 @@ static int prepclosingmethod (lua_State *L, TValue *obj, TValue *err) {
124 124
125 125
126/* 126/*
127** Raise an error with message 'msg', inserting the name of the
128** local variable at position 'level' in the stack.
129*/
130static void varerror (lua_State *L, StkId level, const char *msg) {
131 int idx = cast_int(level - L->ci->func);
132 const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
133 if (vname == NULL) vname = "?";
134 luaG_runerror(L, msg, vname);
135}
136
137
138/*
127** Prepare and call a closing method. If status is OK, code is still 139** Prepare and call a closing method. If status is OK, code is still
128** inside the original protected call, and so any error will be handled 140** inside the original protected call, and so any error will be handled
129** there. Otherwise, a previous error already activated original 141** there. Otherwise, a previous error already activated the original
130** protected call, and so the call to the closing method must be 142** protected call, and so the call to the closing method must be
131** protected here. (A status = CLOSEPROTECT behaves like a previous 143** protected here. (A status == CLOSEPROTECT behaves like a previous
132** error, to also run the closing method in protected mode). 144** error, to also run the closing method in protected mode).
133** If status is OK, the call to the closing method will be pushed 145** If status is OK, the call to the closing method will be pushed
134** at the top of the stack. Otherwise, values are pushed after 146** at the top of the stack. Otherwise, values are pushed after
@@ -140,12 +152,8 @@ static int callclosemth (lua_State *L, StkId level, int status) {
140 if (likely(status == LUA_OK)) { 152 if (likely(status == LUA_OK)) {
141 if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */ 153 if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
142 callclose(L, NULL); /* call closing method */ 154 callclose(L, NULL); /* call closing method */
143 else if (!ttisnil(uv)) { /* non-closable non-nil value? */ 155 else if (!l_isfalse(uv)) /* non-closable non-false value? */
144 int idx = cast_int(level - L->ci->func); 156 varerror(L, level, "attempt to close non-closable variable '%s'");
145 const char *vname = luaG_findlocal(L, L->ci, idx, NULL);
146 if (vname == NULL) vname = "?";
147 luaG_runerror(L, "attempt to close non-closable variable '%s'", vname);
148 }
149 } 157 }
150 else { /* must close the object in protected mode */ 158 else { /* must close the object in protected mode */
151 ptrdiff_t oldtop; 159 ptrdiff_t oldtop;
@@ -170,9 +178,7 @@ static int callclosemth (lua_State *L, StkId level, int status) {
170** (can raise a memory-allocation error) 178** (can raise a memory-allocation error)
171*/ 179*/
172static void trynewtbcupval (lua_State *L, void *ud) { 180static void trynewtbcupval (lua_State *L, void *ud) {
173 StkId level = cast(StkId, ud); 181 newupval(L, 1, cast(StkId, ud), &L->openupval);
174 lua_assert(L->openupval == NULL || uplevel(L->openupval) < level);
175 newupval(L, 1, level, &L->openupval);
176} 182}
177 183
178 184
@@ -182,13 +188,22 @@ static void trynewtbcupval (lua_State *L, void *ud) {
182** as there is no upvalue to call it later. 188** as there is no upvalue to call it later.
183*/ 189*/
184void luaF_newtbcupval (lua_State *L, StkId level) { 190void luaF_newtbcupval (lua_State *L, StkId level) {
185 int status = luaD_rawrunprotected(L, trynewtbcupval, level); 191 TValue *obj = s2v(level);
186 if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */ 192 lua_assert(L->openupval == NULL || uplevel(L->openupval) < level);
187 lua_assert(status == LUA_ERRMEM); 193 if (!l_isfalse(obj)) { /* false doesn't need to be closed */
188 luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */ 194 int status;
189 if (prepclosingmethod(L, s2v(level), s2v(level + 1))) 195 const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE);
196 if (ttisnil(tm)) /* no metamethod? */
197 varerror(L, level, "variable '%s' got a non-closable value");
198 status = luaD_rawrunprotected(L, trynewtbcupval, level);
199 if (unlikely(status != LUA_OK)) { /* memory error creating upvalue? */
200 lua_assert(status == LUA_ERRMEM);
201 luaD_seterrorobj(L, LUA_ERRMEM, level + 1); /* save error message */
202 /* next call must succeed, as object is closable */
203 prepclosingmethod(L, s2v(level), s2v(level + 1));
190 callclose(L, NULL); /* call closing method */ 204 callclose(L, NULL); /* call closing method */
191 luaD_throw(L, LUA_ERRMEM); /* throw memory error */ 205 luaD_throw(L, LUA_ERRMEM); /* throw memory error */
206 }
192 } 207 }
193} 208}
194 209