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.
diff --git a/lparser.c b/lparser.c
index 4c2ddbf..4e6c27f 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1621,6 +1621,7 @@
if (strcmp(getstr(attr), "toclose") != 0)
luaK_semerror(ls,
luaO_pushfstring(ls->L, "unknown attribute '%s'", getstr(attr)));
+ testnext(ls, '>');
new_localvar(ls, str_checkname(ls));
checknext(ls, '=');
exp1(ls);
@@ -1634,7 +1635,7 @@
static void localstat (LexState *ls) {
/* stat -> LOCAL NAME {',' NAME} ['=' explist]
| LOCAL *toclose NAME '=' exp */
- if (testnext(ls, '*'))
+ if (testnext(ls, '<'))
tocloselocalstat(ls);
else
commonlocalstat(ls);
diff --git a/manual/manual.of b/manual/manual.of
index cf44b4f..54a0787 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -1509,7 +1509,7 @@
with the following syntax:
@Produc{
@producname{stat}@producbody{
- @Rw{local} @bnfter{*} @bnfter{toclose} Name @bnfter{=} exp
+ @Rw{local} @bnfter{<} @bnfter{toclose} @bnfter{>} Name @bnfter{=} exp
}}
A to-be-closed variable behaves like a normal local variable,
except that its value is @emph{closed} whenever the variable
@@ -8949,7 +8949,7 @@
@OrNL @Rw{function} funcname funcbody
@OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody
@OrNL @Rw{local} namelist @bnfopt{@bnfter{=} explist}
-@OrNL @Rw{local} @bnfter{*} @bnfter{toclose} Name @bnfter{=} exp
+@OrNL @Rw{local} @bnfter{<} @bnfter{toclose} @bnfter{>} Name @bnfter{=} exp
}
@producname{retstat}@producbody{@Rw{return}
diff --git a/testes/api.lua b/testes/api.lua
index 08672e8..bcc04da 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -1137,7 +1137,8 @@
testamem("to-be-closed variables", function()
local flag
do
- local *toclose x = setmetatable({}, {__close = function () flag = true end})
+ local <toclose> x =
+ setmetatable({}, {__close = function () flag = true end})
flag = false
local x = {}
end
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
index 9dd501e..db6d074 100644
--- a/testes/coroutine.lua
+++ b/testes/coroutine.lua
@@ -151,7 +151,7 @@
end
co = coroutine.create(function ()
- local *toclose x = func2close(function (self, err)
+ local <toclose> x = func2close(function (self, err)
assert(err == nil); X = false
end)
X = true
@@ -164,7 +164,7 @@
-- error killing a coroutine
co = coroutine.create(function()
- local *toclose x = func2close(function (self, err)
+ local <toclose> x = func2close(function (self, err)
assert(err == nil); error(111)
end)
coroutine.yield()
@@ -348,7 +348,7 @@
local X = false
A = coroutine.wrap(function()
- local *toclose _ = setmetatable({}, {__close = function () X = true end})
+ local <toclose> _ = setmetatable({}, {__close = function () X = true end})
return pcall(A, 1)
end)
st, res = A()
diff --git a/testes/files.lua b/testes/files.lua
index 38d3a66..eb100fe 100644
--- a/testes/files.lua
+++ b/testes/files.lua
@@ -125,7 +125,7 @@
-- closing file by scope
local F = nil
do
- local *toclose f = assert(io.open(file, "w"))
+ local <toclose> f = assert(io.open(file, "w"))
F = f
end
assert(tostring(F) == "file (closed)")
@@ -135,7 +135,7 @@
do
-- test writing/reading numbers
- local *toclose f = assert(io.open(file, "w"))
+ local <toclose> f = assert(io.open(file, "w"))
f:write(maxint, '\n')
f:write(string.format("0X%x\n", maxint))
f:write("0xABCp-3", '\n')
@@ -158,7 +158,7 @@
-- testing multiple arguments to io.read
do
- local *toclose f = assert(io.open(file, "w"))
+ local <toclose> f = assert(io.open(file, "w"))
f:write[[
a line
another line
diff --git a/testes/goto.lua b/testes/goto.lua
index f3dcfd4..c9e4807 100644
--- a/testes/goto.lua
+++ b/testes/goto.lua
@@ -258,7 +258,7 @@
::L2:: goto L3
::L1:: do
- local *toclose a = setmetatable({}, {__close = function () X = true end})
+ local <toclose> a = setmetatable({}, {__close = function () X = true end})
assert(X == nil)
if a then goto L2 end -- jumping back out of scope of 'a'
end
diff --git a/testes/locals.lua b/testes/locals.lua
index 814d1b1..c176f50 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -185,9 +185,9 @@
do
local a = {}
do
- local *toclose x = setmetatable({"x"}, {__close = function (self)
+ local <toclose> x = setmetatable({"x"}, {__close = function (self)
a[#a + 1] = self[1] end})
- local *toclose y = func2close(function (self, err)
+ local <toclose> y = func2close(function (self, err)
assert(err == nil); a[#a + 1] = "y"
end)
a[#a + 1] = "in"
@@ -203,7 +203,7 @@
-- closing functions do not corrupt returning values
local function foo (x)
- local *toclose _ = closescope
+ local <toclose> _ = closescope
return x, X, 23
end
@@ -212,7 +212,7 @@
X = false
foo = function (x)
- local *toclose _ = closescope
+ local <toclose> _ = closescope
local y = 15
return y
end
@@ -221,7 +221,7 @@
X = false
foo = function ()
- local *toclose x = closescope
+ local <toclose> x = closescope
return x
end
@@ -234,13 +234,13 @@
-- calls cannot be tail in the scope of to-be-closed variables
local X, Y
local function foo ()
- local *toclose _ = func2close(function () Y = 10 end)
+ local <toclose> _ = func2close(function () Y = 10 end)
assert(X == true and Y == nil) -- 'X' not closed yet
return 1,2,3
end
local function bar ()
- local *toclose _ = func2close(function () X = false end)
+ local <toclose> _ = func2close(function () X = false end)
X = true
do
return foo() -- not a tail call!
@@ -255,14 +255,14 @@
do -- errors in __close
local log = {}
local function foo (err)
- local *toclose x =
+ local <toclose> x =
func2close(function (self, msg) log[#log + 1] = msg; error(1) end)
- local *toclose x1 =
+ local <toclose> x1 =
func2close(function (self, msg) log[#log + 1] = msg; end)
- local *toclose gc = func2close(function () collectgarbage() end)
- local *toclose y =
+ local <toclose> gc = func2close(function () collectgarbage() end)
+ local <toclose> y =
func2close(function (self, msg) log[#log + 1] = msg; error(2) end)
- local *toclose z =
+ local <toclose> z =
func2close(function (self, msg) log[#log + 1] = msg or 10; error(3) end)
if err then error(4) end
end
@@ -283,7 +283,7 @@
-- errors due to non-closable values
local function foo ()
- local *toclose x = 34
+ local <toclose> x = 34
end
local stat, msg = pcall(foo)
assert(not stat and string.find(msg, "variable 'x'"))
@@ -291,8 +291,8 @@
-- with other errors, non-closable values are ignored
local function foo ()
- local *toclose x = 34
- local *toclose y = func2close(function () error(32) end)
+ local <toclose> x = 34
+ local <toclose> y = func2close(function () error(32) end)
end
local stat, msg = pcall(foo)
assert(not stat and msg == 32)
@@ -304,8 +304,8 @@
-- memory error inside closing function
local function foo ()
- local *toclose y = func2close(function () T.alloccount() end)
- local *toclose x = setmetatable({}, {__close = function ()
+ local <toclose> y = func2close(function () T.alloccount() end)
+ local <toclose> x = setmetatable({}, {__close = function ()
T.alloccount(0); local x = {} -- force a memory error
end})
error("a") -- common error inside the function's body
@@ -331,7 +331,7 @@
end
local function test ()
- local *toclose x = enter(0) -- set a memory limit
+ local <toclose> x = enter(0) -- set a memory limit
-- creation of previous upvalue will raise a memory error
assert(false) -- should not run
end
@@ -346,14 +346,14 @@
-- repeat test with extra closing upvalues
local function test ()
- local *toclose xxx = func2close(function (self, msg)
+ local <toclose> xxx = func2close(function (self, msg)
assert(msg == "not enough memory");
error(1000) -- raise another error
end)
- local *toclose xx = func2close(function (self, msg)
+ local <toclose> xx = func2close(function (self, msg)
assert(msg == "not enough memory");
end)
- local *toclose x = enter(0) -- set a memory limit
+ local <toclose> x = enter(0) -- set a memory limit
-- creation of previous upvalue will raise a memory error
os.exit(false) -- should not run
end
@@ -424,9 +424,9 @@
local x = false
local y = false
local co = coroutine.wrap(function ()
- local *toclose xv = func2close(function () x = true end)
+ local <toclose> xv = func2close(function () x = true end)
do
- local *toclose yv = func2close(function () y = true end)
+ local <toclose> yv = func2close(function () y = true end)
coroutine.yield(100) -- yield doesn't close variable
end
coroutine.yield(200) -- yield doesn't close variable
@@ -446,7 +446,7 @@
-- error in a wrapped coroutine raising errors when closing a variable
local x = false
local co = coroutine.wrap(function ()
- local *toclose xv = func2close(function () error("XXX") end)
+ local <toclose> xv = func2close(function () error("XXX") end)
coroutine.yield(100)
error(200)
end)
@@ -461,7 +461,7 @@
-- a suspended coroutine should not close its variables when collected
local co
co = coroutine.wrap(function()
- local *toclose x = function () os.exit(false) end -- should not run
+ local <toclose> x = function () os.exit(false) end -- should not run
co = nil
coroutine.yield()
end)
diff --git a/testes/main.lua b/testes/main.lua
index aab490c..47d84d4 100644
--- a/testes/main.lua
+++ b/testes/main.lua
@@ -320,11 +320,11 @@
-- to-be-closed variables in main chunk
prepfile[[
- local *toclose x = function (err)
+ local <toclose> x = function (err)
assert(err == 120)
print("Ok")
end
- local *toclose e1 = function () error(120) end
+ local <toclose> e1 = function () error(120) end
os.exit(true, true)
]]
RUN('lua %s > %s', prog, out)