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) |