summaryrefslogtreecommitdiff
path: root/testes
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-31 14:54:45 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-10-31 14:54:45 -0300
commit947a372f5860a76fcafb4a2845abc322e440d6fc (patch)
treee35840847207c850af5262f93f863f583d2af76d /testes
parente073cbc2e538369e0611abfc9948f301aea6aef3 (diff)
downloadlua-947a372f5860a76fcafb4a2845abc322e440d6fc.tar.gz
lua-947a372f5860a76fcafb4a2845abc322e440d6fc.tar.bz2
lua-947a372f5860a76fcafb4a2845abc322e440d6fc.zip
State in generic 'for' acts as a to-be-closed variable
The implicit variable 'state' in a generic 'for' is marked as a to-be-closed variable, so that the state will be closed as soon as the loop ends, no matter how. Taking advantage of this new facility, the call 'io.lines(filename)' now returns the open file as a second result. Therefore, an iteraction like 'for l in io.lines(name)...' will close the file even when the loop ends with a break or an error.
Diffstat (limited to 'testes')
-rw-r--r--testes/files.lua8
-rw-r--r--testes/locals.lua50
2 files changed, 53 insertions, 5 deletions
diff --git a/testes/files.lua b/testes/files.lua
index 9aae5913..a11c5e61 100644
--- a/testes/files.lua
+++ b/testes/files.lua
@@ -462,13 +462,13 @@ X
462- y; 462- y;
463]]:close() 463]]:close()
464_G.X = 1 464_G.X = 1
465assert(not load(io.lines(file))) 465assert(not load((io.lines(file))))
466collectgarbage() -- to close file in previous iteration 466collectgarbage() -- to close file in previous iteration
467load(io.lines(file, "L"))() 467load((io.lines(file, "L")))()
468assert(_G.X == 2) 468assert(_G.X == 2)
469load(io.lines(file, 1))() 469load((io.lines(file, 1)))()
470assert(_G.X == 4) 470assert(_G.X == 4)
471load(io.lines(file, 3))() 471load((io.lines(file, 3)))()
472assert(_G.X == 8) 472assert(_G.X == 8)
473 473
474print('+') 474print('+')
diff --git a/testes/locals.lua b/testes/locals.lua
index 65b145db..1e0f525b 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -108,7 +108,7 @@ print'+'
108if rawget(_G, "T") then 108if rawget(_G, "T") then
109 -- testing clearing of dead elements from tables 109 -- testing clearing of dead elements from tables
110 collectgarbage("stop") -- stop GC 110 collectgarbage("stop") -- stop GC
111 local a = {[{}] = 4, [3] = 0, alo = 1, 111 local a = {[{}] = 4, [3] = 0, alo = 1,
112 a1234567890123456789012345678901234567890 = 10} 112 a1234567890123456789012345678901234567890 = 10}
113 113
114 local t = T.querytab(a) 114 local t = T.querytab(a)
@@ -360,6 +360,54 @@ end)
360co() -- start coroutine 360co() -- start coroutine
361assert(co == nil) -- eventually it will be collected 361assert(co == nil) -- eventually it will be collected
362 362
363
364-- to-be-closed variables in generic for loops
365do
366 local numopen = 0
367 local function open (x)
368 numopen = numopen + 1
369 return
370 function () -- iteraction function
371 x = x - 1
372 if x > 0 then return x end
373 end,
374 function () -- closing function
375 numopen = numopen - 1
376 end
377 end
378
379 local s = 0
380 for i in open(10) do
381 s = s + i
382 end
383 assert(s == 45 and numopen == 0)
384
385 local s = 0
386 for i in open(10) do
387 if i < 5 then break end
388 s = s + i
389 end
390 assert(s == 35 and numopen == 0)
391
392 -- repeat test with '__open' metamethod instead of a function
393 local function open (x)
394 numopen = numopen + 1
395 return
396 function (t) -- iteraction function
397 t[1] = t[1] - 1
398 if t[1] > 0 then return t[1] end
399 end,
400 setmetatable({x}, {__close = function () numopen = numopen - 1 end})
401 end
402
403 local s = 0
404 for i in open(10) do
405 if (i < 5) then break end
406 s = s + i
407 end
408 assert(s == 35 and numopen == 0)
409end
410
363print('OK') 411print('OK')
364 412
365return 5,f 413return 5,f