diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-05-09 12:10:31 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2019-05-09 12:10:31 -0300 |
| commit | d881325c2fcbb6d2c434ec403b0bbe51ac200c7b (patch) | |
| tree | 811c1a1ffa8f91693b8df64e040c509c2cec6ded | |
| parent | 3f253f116e8e292977a1bded964544fb35b3d1e3 (diff) | |
| download | lua-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.c | 3 | ||||
| -rw-r--r-- | manual/manual.of | 4 | ||||
| -rw-r--r-- | testes/api.lua | 3 | ||||
| -rw-r--r-- | testes/coroutine.lua | 6 | ||||
| -rw-r--r-- | testes/files.lua | 6 | ||||
| -rw-r--r-- | testes/goto.lua | 2 | ||||
| -rw-r--r-- | testes/locals.lua | 50 | ||||
| -rw-r--r-- | testes/main.lua | 4 |
8 files changed, 40 insertions, 38 deletions
| @@ -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) { | |||
| 1634 | static void localstat (LexState *ls) { | 1635 | static 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, | |||
| 1509 | with the following syntax: | 1509 | with 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 | }} |
| 1514 | A to-be-closed variable behaves like a normal local variable, | 1514 | A to-be-closed variable behaves like a normal local variable, |
| 1515 | except that its value is @emph{closed} whenever the variable | 1515 | except 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) | |||
| 1137 | testamem("to-be-closed variables", function() | 1137 | testamem("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 | ||
| 136 | do | 136 | do |
| 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 |
| 160 | do | 160 | do |
| 161 | local *toclose f = assert(io.open(file, "w")) | 161 | local <toclose> f = assert(io.open(file, "w")) |
| 162 | f:write[[ | 162 | f:write[[ |
| 163 | a line | 163 | a line |
| 164 | another line | 164 | another 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 | |||
| 185 | do | 185 | do |
| 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 | |||
| 255 | do -- errors in __close | 255 | do -- 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 |
| 462 | local co | 462 | local co |
| 463 | co = coroutine.wrap(function() | 463 | co = 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() |
| 467 | end) | 467 | end) |
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 |
| 322 | prepfile[[ | 322 | prepfile[[ |
| 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 | ]] |
| 330 | RUN('lua %s > %s', prog, out) | 330 | RUN('lua %s > %s', prog, out) |
