aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-05-09 12:10:31 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-05-09 12:10:31 -0300
commitd881325c2fcbb6d2c434ec403b0bbe51ac200c7b (patch)
tree811c1a1ffa8f91693b8df64e040c509c2cec6ded
parent3f253f116e8e292977a1bded964544fb35b3d1e3 (diff)
downloadlua-d881325c2fcbb6d2c434ec403b0bbe51ac200c7b.tar.gz
lua-d881325c2fcbb6d2c434ec403b0bbe51ac200c7b.tar.bz2
lua-d881325c2fcbb6d2c434ec403b0bbe51ac200c7b.zip
Flag for to-be-closed variables changed to '<toclose>'
The flag for to-be-closed variables was changed from '*toclose' to '<toclose>'. Several people found confusing the old syntax and the new one has a clear terminator, making it more flexible for future changes.
-rw-r--r--lparser.c3
-rw-r--r--manual/manual.of4
-rw-r--r--testes/api.lua3
-rw-r--r--testes/coroutine.lua6
-rw-r--r--testes/files.lua6
-rw-r--r--testes/goto.lua2
-rw-r--r--testes/locals.lua50
-rw-r--r--testes/main.lua4
8 files changed, 40 insertions, 38 deletions
diff --git a/lparser.c b/lparser.c
index 4c2ddbfe..4e6c27fe 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1621,6 +1621,7 @@ static void tocloselocalstat (LexState *ls) {
1621 if (strcmp(getstr(attr), "toclose") != 0) 1621 if (strcmp(getstr(attr), "toclose") != 0)
1622 luaK_semerror(ls, 1622 luaK_semerror(ls,
1623 luaO_pushfstring(ls->L, "unknown attribute '%s'", getstr(attr))); 1623 luaO_pushfstring(ls->L, "unknown attribute '%s'", getstr(attr)));
1624 testnext(ls, '>');
1624 new_localvar(ls, str_checkname(ls)); 1625 new_localvar(ls, str_checkname(ls));
1625 checknext(ls, '='); 1626 checknext(ls, '=');
1626 exp1(ls); 1627 exp1(ls);
@@ -1634,7 +1635,7 @@ static void tocloselocalstat (LexState *ls) {
1634static void localstat (LexState *ls) { 1635static void localstat (LexState *ls) {
1635 /* stat -> LOCAL NAME {',' NAME} ['=' explist] 1636 /* stat -> LOCAL NAME {',' NAME} ['=' explist]
1636 | LOCAL *toclose NAME '=' exp */ 1637 | LOCAL *toclose NAME '=' exp */
1637 if (testnext(ls, '*')) 1638 if (testnext(ls, '<'))
1638 tocloselocalstat(ls); 1639 tocloselocalstat(ls);
1639 else 1640 else
1640 commonlocalstat(ls); 1641 commonlocalstat(ls);
diff --git a/manual/manual.of b/manual/manual.of
index cf44b4f2..54a07879 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -1509,7 +1509,7 @@ A local variable can be declared as a @def{to-be-closed} variable,
1509with the following syntax: 1509with the following syntax:
1510@Produc{ 1510@Produc{
1511@producname{stat}@producbody{ 1511@producname{stat}@producbody{
1512 @Rw{local} @bnfter{*} @bnfter{toclose} Name @bnfter{=} exp 1512 @Rw{local} @bnfter{<} @bnfter{toclose} @bnfter{>} Name @bnfter{=} exp
1513}} 1513}}
1514A to-be-closed variable behaves like a normal local variable, 1514A to-be-closed variable behaves like a normal local variable,
1515except that its value is @emph{closed} whenever the variable 1515except that its value is @emph{closed} whenever the variable
@@ -8949,7 +8949,7 @@ and @bnfNter{LiteralString}, see @See{lexical}.)
8949@OrNL @Rw{function} funcname funcbody 8949@OrNL @Rw{function} funcname funcbody
8950@OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody 8950@OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody
8951@OrNL @Rw{local} namelist @bnfopt{@bnfter{=} explist} 8951@OrNL @Rw{local} namelist @bnfopt{@bnfter{=} explist}
8952@OrNL @Rw{local} @bnfter{*} @bnfter{toclose} Name @bnfter{=} exp 8952@OrNL @Rw{local} @bnfter{<} @bnfter{toclose} @bnfter{>} Name @bnfter{=} exp
8953} 8953}
8954 8954
8955@producname{retstat}@producbody{@Rw{return} 8955@producname{retstat}@producbody{@Rw{return}
diff --git a/testes/api.lua b/testes/api.lua
index 08672e8a..bcc04dac 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -1137,7 +1137,8 @@ end)
1137testamem("to-be-closed variables", function() 1137testamem("to-be-closed variables", function()
1138 local flag 1138 local flag
1139 do 1139 do
1140 local *toclose x = setmetatable({}, {__close = function () flag = true end}) 1140 local <toclose> x =
1141 setmetatable({}, {__close = function () flag = true end})
1141 flag = false 1142 flag = false
1142 local x = {} 1143 local x = {}
1143 end 1144 end
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 9dd501e7..db6d074e 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -151,7 +151,7 @@ do
151 end 151 end
152 152
153 co = coroutine.create(function () 153 co = coroutine.create(function ()
154 local *toclose x = func2close(function (self, err) 154 local <toclose> x = func2close(function (self, err)
155 assert(err == nil); X = false 155 assert(err == nil); X = false
156 end) 156 end)
157 X = true 157 X = true
@@ -164,7 +164,7 @@ do
164 164
165 -- error killing a coroutine 165 -- error killing a coroutine
166 co = coroutine.create(function() 166 co = coroutine.create(function()
167 local *toclose x = func2close(function (self, err) 167 local <toclose> x = func2close(function (self, err)
168 assert(err == nil); error(111) 168 assert(err == nil); error(111)
169 end) 169 end)
170 coroutine.yield() 170 coroutine.yield()
@@ -348,7 +348,7 @@ do
348 348
349 local X = false 349 local X = false
350 A = coroutine.wrap(function() 350 A = coroutine.wrap(function()
351 local *toclose _ = setmetatable({}, {__close = function () X = true end}) 351 local <toclose> _ = setmetatable({}, {__close = function () X = true end})
352 return pcall(A, 1) 352 return pcall(A, 1)
353 end) 353 end)
354 st, res = A() 354 st, res = A()
diff --git a/testes/files.lua b/testes/files.lua
index 38d3a669..eb100fe1 100644
--- a/testes/files.lua
+++ b/testes/files.lua
@@ -125,7 +125,7 @@ do
125 -- closing file by scope 125 -- closing file by scope
126 local F = nil 126 local F = nil
127 do 127 do
128 local *toclose f = assert(io.open(file, "w")) 128 local <toclose> f = assert(io.open(file, "w"))
129 F = f 129 F = f
130 end 130 end
131 assert(tostring(F) == "file (closed)") 131 assert(tostring(F) == "file (closed)")
@@ -135,7 +135,7 @@ assert(os.remove(file))
135 135
136do 136do
137 -- test writing/reading numbers 137 -- test writing/reading numbers
138 local *toclose f = assert(io.open(file, "w")) 138 local <toclose> f = assert(io.open(file, "w"))
139 f:write(maxint, '\n') 139 f:write(maxint, '\n')
140 f:write(string.format("0X%x\n", maxint)) 140 f:write(string.format("0X%x\n", maxint))
141 f:write("0xABCp-3", '\n') 141 f:write("0xABCp-3", '\n')
@@ -158,7 +158,7 @@ assert(os.remove(file))
158 158
159-- testing multiple arguments to io.read 159-- testing multiple arguments to io.read
160do 160do
161 local *toclose f = assert(io.open(file, "w")) 161 local <toclose> f = assert(io.open(file, "w"))
162 f:write[[ 162 f:write[[
163a line 163a line
164another line 164another line
diff --git a/testes/goto.lua b/testes/goto.lua
index f3dcfd4a..c9e48073 100644
--- a/testes/goto.lua
+++ b/testes/goto.lua
@@ -258,7 +258,7 @@ do
258 ::L2:: goto L3 258 ::L2:: goto L3
259 259
260 ::L1:: do 260 ::L1:: do
261 local *toclose a = setmetatable({}, {__close = function () X = true end}) 261 local <toclose> a = setmetatable({}, {__close = function () X = true end})
262 assert(X == nil) 262 assert(X == nil)
263 if a then goto L2 end -- jumping back out of scope of 'a' 263 if a then goto L2 end -- jumping back out of scope of 'a'
264 end 264 end
diff --git a/testes/locals.lua b/testes/locals.lua
index 814d1b16..c176f506 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -185,9 +185,9 @@ end
185do 185do
186 local a = {} 186 local a = {}
187 do 187 do
188 local *toclose x = setmetatable({"x"}, {__close = function (self) 188 local <toclose> x = setmetatable({"x"}, {__close = function (self)
189 a[#a + 1] = self[1] end}) 189 a[#a + 1] = self[1] end})
190 local *toclose y = func2close(function (self, err) 190 local <toclose> y = func2close(function (self, err)
191 assert(err == nil); a[#a + 1] = "y" 191 assert(err == nil); a[#a + 1] = "y"
192 end) 192 end)
193 a[#a + 1] = "in" 193 a[#a + 1] = "in"
@@ -203,7 +203,7 @@ do
203 203
204 -- closing functions do not corrupt returning values 204 -- closing functions do not corrupt returning values
205 local function foo (x) 205 local function foo (x)
206 local *toclose _ = closescope 206 local <toclose> _ = closescope
207 return x, X, 23 207 return x, X, 23
208 end 208 end
209 209
@@ -212,7 +212,7 @@ do
212 212
213 X = false 213 X = false
214 foo = function (x) 214 foo = function (x)
215 local *toclose _ = closescope 215 local <toclose> _ = closescope
216 local y = 15 216 local y = 15
217 return y 217 return y
218 end 218 end
@@ -221,7 +221,7 @@ do
221 221
222 X = false 222 X = false
223 foo = function () 223 foo = function ()
224 local *toclose x = closescope 224 local <toclose> x = closescope
225 return x 225 return x
226 end 226 end
227 227
@@ -234,13 +234,13 @@ do
234 -- calls cannot be tail in the scope of to-be-closed variables 234 -- calls cannot be tail in the scope of to-be-closed variables
235 local X, Y 235 local X, Y
236 local function foo () 236 local function foo ()
237 local *toclose _ = func2close(function () Y = 10 end) 237 local <toclose> _ = func2close(function () Y = 10 end)
238 assert(X == true and Y == nil) -- 'X' not closed yet 238 assert(X == true and Y == nil) -- 'X' not closed yet
239 return 1,2,3 239 return 1,2,3
240 end 240 end
241 241
242 local function bar () 242 local function bar ()
243 local *toclose _ = func2close(function () X = false end) 243 local <toclose> _ = func2close(function () X = false end)
244 X = true 244 X = true
245 do 245 do
246 return foo() -- not a tail call! 246 return foo() -- not a tail call!
@@ -255,14 +255,14 @@ end
255do -- errors in __close 255do -- errors in __close
256 local log = {} 256 local log = {}
257 local function foo (err) 257 local function foo (err)
258 local *toclose x = 258 local <toclose> x =
259 func2close(function (self, msg) log[#log + 1] = msg; error(1) end) 259 func2close(function (self, msg) log[#log + 1] = msg; error(1) end)
260 local *toclose x1 = 260 local <toclose> x1 =
261 func2close(function (self, msg) log[#log + 1] = msg; end) 261 func2close(function (self, msg) log[#log + 1] = msg; end)
262 local *toclose gc = func2close(function () collectgarbage() end) 262 local <toclose> gc = func2close(function () collectgarbage() end)
263 local *toclose y = 263 local <toclose> y =
264 func2close(function (self, msg) log[#log + 1] = msg; error(2) end) 264 func2close(function (self, msg) log[#log + 1] = msg; error(2) end)
265 local *toclose z = 265 local <toclose> z =
266 func2close(function (self, msg) log[#log + 1] = msg or 10; error(3) end) 266 func2close(function (self, msg) log[#log + 1] = msg or 10; error(3) end)
267 if err then error(4) end 267 if err then error(4) end
268 end 268 end
@@ -283,7 +283,7 @@ do
283 283
284 -- errors due to non-closable values 284 -- errors due to non-closable values
285 local function foo () 285 local function foo ()
286 local *toclose x = 34 286 local <toclose> x = 34
287 end 287 end
288 local stat, msg = pcall(foo) 288 local stat, msg = pcall(foo)
289 assert(not stat and string.find(msg, "variable 'x'")) 289 assert(not stat and string.find(msg, "variable 'x'"))
@@ -291,8 +291,8 @@ do
291 291
292 -- with other errors, non-closable values are ignored 292 -- with other errors, non-closable values are ignored
293 local function foo () 293 local function foo ()
294 local *toclose x = 34 294 local <toclose> x = 34
295 local *toclose y = func2close(function () error(32) end) 295 local <toclose> y = func2close(function () error(32) end)
296 end 296 end
297 local stat, msg = pcall(foo) 297 local stat, msg = pcall(foo)
298 assert(not stat and msg == 32) 298 assert(not stat and msg == 32)
@@ -304,8 +304,8 @@ if rawget(_G, "T") then
304 304
305 -- memory error inside closing function 305 -- memory error inside closing function
306 local function foo () 306 local function foo ()
307 local *toclose y = func2close(function () T.alloccount() end) 307 local <toclose> y = func2close(function () T.alloccount() end)
308 local *toclose x = setmetatable({}, {__close = function () 308 local <toclose> x = setmetatable({}, {__close = function ()
309 T.alloccount(0); local x = {} -- force a memory error 309 T.alloccount(0); local x = {} -- force a memory error
310 end}) 310 end})
311 error("a") -- common error inside the function's body 311 error("a") -- common error inside the function's body
@@ -331,7 +331,7 @@ if rawget(_G, "T") then
331 end 331 end
332 332
333 local function test () 333 local function test ()
334 local *toclose x = enter(0) -- set a memory limit 334 local <toclose> x = enter(0) -- set a memory limit
335 -- creation of previous upvalue will raise a memory error 335 -- creation of previous upvalue will raise a memory error
336 assert(false) -- should not run 336 assert(false) -- should not run
337 end 337 end
@@ -346,14 +346,14 @@ if rawget(_G, "T") then
346 346
347 -- repeat test with extra closing upvalues 347 -- repeat test with extra closing upvalues
348 local function test () 348 local function test ()
349 local *toclose xxx = func2close(function (self, msg) 349 local <toclose> xxx = func2close(function (self, msg)
350 assert(msg == "not enough memory"); 350 assert(msg == "not enough memory");
351 error(1000) -- raise another error 351 error(1000) -- raise another error
352 end) 352 end)
353 local *toclose xx = func2close(function (self, msg) 353 local <toclose> xx = func2close(function (self, msg)
354 assert(msg == "not enough memory"); 354 assert(msg == "not enough memory");
355 end) 355 end)
356 local *toclose x = enter(0) -- set a memory limit 356 local <toclose> x = enter(0) -- set a memory limit
357 -- creation of previous upvalue will raise a memory error 357 -- creation of previous upvalue will raise a memory error
358 os.exit(false) -- should not run 358 os.exit(false) -- should not run
359 end 359 end
@@ -424,9 +424,9 @@ do
424 local x = false 424 local x = false
425 local y = false 425 local y = false
426 local co = coroutine.wrap(function () 426 local co = coroutine.wrap(function ()
427 local *toclose xv = func2close(function () x = true end) 427 local <toclose> xv = func2close(function () x = true end)
428 do 428 do
429 local *toclose yv = func2close(function () y = true end) 429 local <toclose> yv = func2close(function () y = true end)
430 coroutine.yield(100) -- yield doesn't close variable 430 coroutine.yield(100) -- yield doesn't close variable
431 end 431 end
432 coroutine.yield(200) -- yield doesn't close variable 432 coroutine.yield(200) -- yield doesn't close variable
@@ -446,7 +446,7 @@ do
446 -- error in a wrapped coroutine raising errors when closing a variable 446 -- error in a wrapped coroutine raising errors when closing a variable
447 local x = false 447 local x = false
448 local co = coroutine.wrap(function () 448 local co = coroutine.wrap(function ()
449 local *toclose xv = func2close(function () error("XXX") end) 449 local <toclose> xv = func2close(function () error("XXX") end)
450 coroutine.yield(100) 450 coroutine.yield(100)
451 error(200) 451 error(200)
452 end) 452 end)
@@ -461,7 +461,7 @@ end
461-- a suspended coroutine should not close its variables when collected 461-- a suspended coroutine should not close its variables when collected
462local co 462local co
463co = coroutine.wrap(function() 463co = coroutine.wrap(function()
464 local *toclose x = function () os.exit(false) end -- should not run 464 local <toclose> x = function () os.exit(false) end -- should not run
465 co = nil 465 co = nil
466 coroutine.yield() 466 coroutine.yield()
467end) 467end)
diff --git a/testes/main.lua b/testes/main.lua
index aab490c8..47d84d4c 100644
--- a/testes/main.lua
+++ b/testes/main.lua
@@ -320,11 +320,11 @@ NoRun("", "lua %s", prog) -- no message
320 320
321-- to-be-closed variables in main chunk 321-- to-be-closed variables in main chunk
322prepfile[[ 322prepfile[[
323 local *toclose x = function (err) 323 local <toclose> x = function (err)
324 assert(err == 120) 324 assert(err == 120)
325 print("Ok") 325 print("Ok")
326 end 326 end
327 local *toclose e1 = function () error(120) end 327 local <toclose> e1 = function () error(120) end
328 os.exit(true, true) 328 os.exit(true, true)
329]] 329]]
330RUN('lua %s > %s', prog, out) 330RUN('lua %s > %s', prog, out)