Change in the syntax of attributes

Attributes changed to posfixed ('x <const>', instead of '<const> x'),
and "toclose" renamed to "close". Posfixed attributes seem to make it
clearer that it applies to only one variable when there are multiple
variables.
This commit is contained in:
Roberto Ierusalimschy 2019-07-30 12:18:19 -03:00
parent b80077b8f3
commit 0d52913804
11 changed files with 103 additions and 102 deletions

View File

@ -190,7 +190,7 @@ static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) {
** Create a new local variable with the given 'name'. Return its index
** in the function.
*/
static int new_localvar (LexState *ls, TString *name, int kind) {
static int new_localvar (LexState *ls, TString *name) {
lua_State *L = ls->L;
FuncState *fs = ls->fs;
Dyndata *dyd = ls->dyd;
@ -200,14 +200,14 @@ static int new_localvar (LexState *ls, TString *name, int kind) {
luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
dyd->actvar.size, Vardesc, USHRT_MAX, "local variables");
var = &dyd->actvar.arr[dyd->actvar.n++];
var->vd.kind = kind;
var->vd.kind = VDKREG; /* default */
var->vd.name = name;
return dyd->actvar.n - 1 - fs->firstlocal;
}
#define new_localvarliteral(ls,v) \
new_localvar(ls, \
luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1), VDKREG);
luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1));
@ -947,7 +947,7 @@ static void parlist (LexState *ls) {
do {
switch (ls->t.token) {
case TK_NAME: { /* param -> NAME */
new_localvar(ls, str_checkname(ls), VDKREG);
new_localvar(ls, str_checkname(ls));
nparams++;
break;
}
@ -1553,7 +1553,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for state)");
new_localvar(ls, varname, VDKREG);
new_localvar(ls, varname);
checknext(ls, '=');
exp1(ls); /* initial value */
checknext(ls, ',');
@ -1582,9 +1582,9 @@ static void forlist (LexState *ls, TString *indexname) {
new_localvarliteral(ls, "(for state)");
new_localvarliteral(ls, "(for state)");
/* create declared variables */
new_localvar(ls, indexname, VDKREG);
new_localvar(ls, indexname);
while (testnext(ls, ',')) {
new_localvar(ls, str_checkname(ls), VDKREG);
new_localvar(ls, str_checkname(ls));
nvars++;
}
checknext(ls, TK_IN);
@ -1708,7 +1708,7 @@ static void localfunc (LexState *ls) {
expdesc b;
FuncState *fs = ls->fs;
int fvar = fs->nactvar; /* function's variable index */
new_localvar(ls, str_checkname(ls), VDKREG); /* new local variable */
new_localvar(ls, str_checkname(ls)); /* new local variable */
adjustlocalvars(ls, 1); /* enter its scope */
body(ls, &b, 0, ls->linenumber); /* function created in next register */
/* debug information will only see the variable after this point! */
@ -1723,7 +1723,7 @@ static int getlocalattribute (LexState *ls) {
checknext(ls, '>');
if (strcmp(attr, "const") == 0)
return RDKCONST; /* read-only variable */
else if (strcmp(attr, "toclose") == 0)
else if (strcmp(attr, "close") == 0)
return RDKTOCLOSE; /* to-be-closed variable */
else
luaK_semerror(ls,
@ -1748,13 +1748,14 @@ static void localstat (LexState *ls) {
FuncState *fs = ls->fs;
int toclose = -1; /* index of to-be-closed variable (if any) */
Vardesc *var; /* last variable */
int ivar; /* index of last variable */
int ivar, kind; /* index and kind of last variable */
int nvars = 0;
int nexps;
expdesc e;
do {
int kind = getlocalattribute(ls);
ivar = new_localvar(ls, str_checkname(ls), kind);
ivar = new_localvar(ls, str_checkname(ls));
kind = getlocalattribute(ls);
getlocalvardesc(fs, ivar)->vd.kind = kind;
if (kind == RDKTOCLOSE) { /* to-be-closed? */
if (toclose != -1) /* one already present? */
luaK_semerror(ls, "multiple to-be-closed variables in local list");

View File

@ -1203,7 +1203,7 @@ end)
testamem("to-be-closed variables", function()
local flag
do
local <toclose> x =
local x <close> =
setmetatable({}, {__close = function () flag = true end})
flag = false
local x = {}

View File

@ -8,22 +8,22 @@ end
print "testing code generation and optimizations"
-- to test constant propagation
local <const> k0aux = 0
local <const> k0 = k0aux
local <const> k1 = 1
local <const> k3 = 3
local <const> k6 = k3 + (k3 << k0)
local <const> kFF0 = 0xFF0
local <const> k3_78 = 3.78
local <const> x, <const> k3_78_4 = 10, k3_78 / 4
local k0aux <const> = 0
local k0 <const> = k0aux
local k1 <const> = 1
local k3 <const> = 3
local k6 <const> = k3 + (k3 << k0)
local kFF0 <const> = 0xFF0
local k3_78 <const> = 3.78
local x, k3_78_4 <const> = 10, k3_78 / 4
assert(x == 10)
local <const> kx = "x"
local kx <const> = "x"
local <const> kTrue = true
local <const> kFalse = false
local kTrue <const> = true
local kFalse <const> = false
local <const> kNil = nil
local kNil <const> = nil
-- this code gave an error for the code checker
do
@ -105,7 +105,7 @@ end, 'CLOSURE', 'NEWTABLE', 'EXTRAARG', 'GETTABUP', 'CALL',
-- sequence of LOADNILs
check(function ()
local <const> kNil = nil
local kNil <const> = nil
local a,b,c
local d; local e;
local f,g,h;
@ -173,7 +173,7 @@ end,
-- "get/set table" with numeric indices
check(function (a)
local <const> k255 = 255
local k255 <const> = 255
a[1] = a[100]
a[k255] = a[256]
a[256] = 5
@ -276,14 +276,14 @@ checkI(function () return ((100 << k6) << -4) >> 2 end, 100)
-- borders around MAXARG_sBx ((((1 << 17) - 1) >> 1) == 65535)
local a = 17; local sbx = ((1 << a) - 1) >> 1 -- avoid folding
local <const> border = 65535
local border <const> = 65535
checkI(function () return border end, sbx)
checkI(function () return -border end, -sbx)
checkI(function () return border + 1 end, sbx + 1)
checkK(function () return border + 2 end, sbx + 2)
checkK(function () return -(border + 1) end, -(sbx + 1))
local <const> border = 65535.0
local border <const> = 65535.0
checkF(function () return border end, sbx + 0.0)
checkF(function () return -border end, -sbx + 0.0)
checkF(function () return border + 1 end, (sbx + 1.0))
@ -411,9 +411,9 @@ checkequal(function () return 6 and true or nil end,
do -- string constants
local <const> k0 = "00000000000000000000000000000000000000000000000000"
local k0 <const> = "00000000000000000000000000000000000000000000000000"
local function f1 ()
local <const> k = k0
local k <const> = k0
return function ()
return function () return k end
end

View File

@ -211,15 +211,15 @@ assert(a==1 and b==nil)
print'+';
do -- testing constants
local <const> prog = [[local <XXX> x = 10]]
local prog <const> = [[local x <XXX> = 10]]
checkload(prog, "unknown attribute 'XXX'")
checkload([[local <const> xxx = 20; xxx = 10]],
checkload([[local xxx <const> = 20; xxx = 10]],
":1: attempt to assign to const variable 'xxx'")
checkload([[
local xx;
local <const> xxx = 20;
local xxx <const> = 20;
local yyy;
local function foo ()
local abc = xx + yyy + xxx;
@ -228,7 +228,7 @@ do -- testing constants
]], ":6: attempt to assign to const variable 'xxx'")
checkload([[
local <toclose> x = nil
local x <close> = nil
x = io.open()
]], ":2: attempt to assign to const variable 'x'")
end
@ -304,7 +304,7 @@ if _ENV.GLOB1 == 0 then
basiccases[2][1] = "F" -- constant false
prog = [[
local <const> F = false
local F <const> = false
if %s then IX = true end
return %s
]]
@ -312,7 +312,7 @@ else
basiccases[4][1] = "k10" -- constant 10
prog = [[
local <const> k10 = 10
local k10 <const> = 10
if %s then IX = true end
return %s
]]
@ -322,12 +322,12 @@ print('testing short-circuit optimizations (' .. _ENV.GLOB1 .. ')')
-- operators with their respective values
local <const> binops = {
local binops <const> = {
{" and ", function (a,b) if not a then return a else return b end end},
{" or ", function (a,b) if a then return a else return b end end},
}
local <const> cases = {}
local cases <const> = {}
-- creates all combinations of '(cases[i] op cases[n-i])' plus
-- 'not(cases[i] op cases[n-i])' (syntax + value)

View File

@ -151,7 +151,7 @@ do
end
co = coroutine.create(function ()
local <toclose> x = func2close(function (self, err)
local x <close> = func2close(function (self, err)
assert(err == nil); X = false
end)
X = true
@ -165,12 +165,12 @@ do
-- error closing a coroutine
local x = 0
co = coroutine.create(function()
local <toclose> y = func2close(function (self,err)
local y <close> = func2close(function (self,err)
if (err ~= 111) then os.exit(false) end -- should not happen
x = 200
error(200)
end)
local <toclose> x = func2close(function (self, err)
local x <close> = func2close(function (self, err)
assert(err == nil); error(111)
end)
coroutine.yield()
@ -356,7 +356,7 @@ do
local X = false
A = coroutine.wrap(function()
local <toclose> _ = setmetatable({}, {__close = function () X = true end})
local _ <close> = setmetatable({}, {__close = function () X = true end})
return pcall(A, 1)
end)
st, res = A()

View File

@ -125,7 +125,7 @@ do
-- closing file by scope
local F = nil
do
local <toclose> f = assert(io.open(file, "w"))
local f <close> = assert(io.open(file, "w"))
F = f
end
assert(tostring(F) == "file (closed)")
@ -135,7 +135,7 @@ assert(os.remove(file))
do
-- test writing/reading numbers
local <toclose> f = assert(io.open(file, "w"))
local f <close> = assert(io.open(file, "w"))
f:write(maxint, '\n')
f:write(string.format("0X%x\n", maxint))
f:write("0xABCp-3", '\n')
@ -144,7 +144,7 @@ do
f:write(string.format("0x%X\n", -maxint))
f:write("-0xABCp-3", '\n')
assert(f:close())
local <toclose> f = assert(io.open(file, "r"))
local f <close> = assert(io.open(file, "r"))
assert(f:read("n") == maxint)
assert(f:read("n") == maxint)
assert(f:read("n") == 0xABCp-3)
@ -158,7 +158,7 @@ assert(os.remove(file))
-- testing multiple arguments to io.read
do
local <toclose> f = assert(io.open(file, "w"))
local f <close> = assert(io.open(file, "w"))
f:write[[
a line
another line
@ -170,18 +170,18 @@ three
]]
local l1, l2, l3, l4, n1, n2, c, dummy
assert(f:close())
local <toclose> f = assert(io.open(file, "r"))
local f <close> = assert(io.open(file, "r"))
l1, l2, n1, n2, dummy = f:read("l", "L", "n", "n")
assert(l1 == "a line" and l2 == "another line\n" and
n1 == 1234 and n2 == 3.45 and dummy == nil)
assert(f:close())
local <toclose> f = assert(io.open(file, "r"))
local f <close> = assert(io.open(file, "r"))
l1, l2, n1, n2, c, l3, l4, dummy = f:read(7, "l", "n", "n", 1, "l", "l")
assert(l1 == "a line\n" and l2 == "another line" and c == '\n' and
n1 == 1234 and n2 == 3.45 and l3 == "one" and l4 == "two"
and dummy == nil)
assert(f:close())
local <toclose> f = assert(io.open(file, "r"))
local f <close> = assert(io.open(file, "r"))
-- second item failing
l1, n1, n2, dummy = f:read("l", "n", "n", "l")
assert(l1 == "a line" and n1 == nil)

View File

@ -258,7 +258,7 @@ do
::L2:: goto L3
::L1:: do
local <toclose> a = setmetatable({}, {__close = function () X = true end})
local a <close> = setmetatable({}, {__close = function () X = true end})
assert(X == nil)
if a then goto L2 end -- jumping back out of scope of 'a'
end

View File

@ -174,7 +174,7 @@ assert(x==20)
do -- constants
local <const> a, b, <const> c = 10, 20, 30
local a<const>, b, c<const> = 10, 20, 30
b = a + c + b -- 'b' is not constant
assert(a == 10 and b == 60 and c == 30)
local function checkro (name, code)
@ -182,17 +182,17 @@ do -- constants
local gab = string.format("attempt to assign to const variable '%s'", name)
assert(not st and string.find(msg, gab))
end
checkro("y", "local x, <const> y, z = 10, 20, 30; x = 11; y = 12")
checkro("x", "local <const> x, y, <const> z = 10, 20, 30; x = 11")
checkro("z", "local <const> x, y, <const> z = 10, 20, 30; y = 10; z = 11")
checkro("y", "local x, y <const>, z = 10, 20, 30; x = 11; y = 12")
checkro("x", "local x <const>, y, z <const> = 10, 20, 30; x = 11")
checkro("z", "local x <const>, y, z <const> = 10, 20, 30; y = 10; z = 11")
checkro("z", [[
local a, <const> z, b = 10;
local a, z <const>, b = 10;
function foo() a = 20; z = 32; end
]])
checkro("var1", [[
local a, <const> var1 = 10;
local a, var1 <const> = 10;
function foo() a = 20; z = function () var1 = 12; end end
]])
end
@ -215,9 +215,9 @@ end
do
local a = {}
do
local <toclose> x = setmetatable({"x"}, {__close = function (self)
local x <close> = setmetatable({"x"}, {__close = function (self)
a[#a + 1] = self[1] end})
local w, <toclose> y, z = func2close(function (self, err)
local w, y <close>, z = func2close(function (self, err)
assert(err == nil); a[#a + 1] = "y"
end, 10, 20)
a[#a + 1] = "in"
@ -235,7 +235,7 @@ do
-- closing functions do not corrupt returning values
local function foo (x)
local <toclose> _ = closescope
local _ <close> = closescope
return x, X, 23
end
@ -244,7 +244,7 @@ do
X = false
foo = function (x)
local <toclose> _ = closescope
local _<close> = closescope
local y = 15
return y
end
@ -253,7 +253,7 @@ do
X = false
foo = function ()
local <toclose> x = closescope
local x <close> = closescope
return x
end
@ -266,13 +266,13 @@ do
-- 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 _ <close> = 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 _ <close> = func2close(function () X = false end)
X = true
do
return foo() -- not a tail call!
@ -287,14 +287,14 @@ end
do -- errors in __close
local log = {}
local function foo (err)
local <toclose> x =
local x <close> =
func2close(function (self, msg) log[#log + 1] = msg; error(1) end)
local <toclose> x1 =
local x1 <close> =
func2close(function (self, msg) log[#log + 1] = msg; end)
local <toclose> gc = func2close(function () collectgarbage() end)
local <toclose> y =
local gc <close> = func2close(function () collectgarbage() end)
local y <close> =
func2close(function (self, msg) log[#log + 1] = msg; error(2) end)
local <toclose> z =
local z <close> =
func2close(function (self, msg)
log[#log + 1] = (msg or 10) + 1;
error(3)
@ -316,7 +316,7 @@ do -- errors in __close
-- error in toclose in vararg function
function foo (...)
local <toclose> x123 = 10
local x123 <close> = 10
end
local st, msg = pcall(foo)
@ -329,7 +329,7 @@ do
-- errors due to non-closable values
local function foo ()
local <toclose> x = {}
local x <close> = {}
end
local stat, msg = pcall(foo)
assert(not stat and string.find(msg, "variable 'x'"))
@ -337,8 +337,8 @@ do
-- with other errors, non-closable values are ignored
local function foo ()
local <toclose> x = 34
local <toclose> y = func2close(function () error(32) end)
local x <close> = 34
local y <close> = func2close(function () error(32) end)
end
local stat, msg = pcall(foo)
assert(not stat and msg == 32)
@ -350,8 +350,8 @@ if rawget(_G, "T") then
-- memory error inside closing function
local function foo ()
local <toclose> y = func2close(function () T.alloccount() end)
local <toclose> x = setmetatable({}, {__close = function ()
local y <close> = func2close(function () T.alloccount() end)
local x <close> = setmetatable({}, {__close = function ()
T.alloccount(0); local x = {} -- force a memory error
end})
error(1000) -- common error inside the function's body
@ -377,7 +377,7 @@ if rawget(_G, "T") then
end
local function test ()
local <toclose> x = enter(0) -- set a memory limit
local x <close> = enter(0) -- set a memory limit
-- creation of previous upvalue will raise a memory error
assert(false) -- should not run
end
@ -392,14 +392,14 @@ if rawget(_G, "T") then
-- repeat test with extra closing upvalues
local function test ()
local <toclose> xxx = func2close(function (self, msg)
local xxx <close> = func2close(function (self, msg)
assert(msg == "not enough memory");
error(1000) -- raise another error
end)
local <toclose> xx = func2close(function (self, msg)
local xx <close> = func2close(function (self, msg)
assert(msg == "not enough memory");
end)
local <toclose> x = enter(0) -- set a memory limit
local x <close> = enter(0) -- set a memory limit
-- creation of previous upvalue will raise a memory error
os.exit(false) -- should not run
end
@ -469,9 +469,9 @@ do
local x = false
local y = false
local co = coroutine.wrap(function ()
local <toclose> xv = func2close(function () x = true end)
local xv <close> = func2close(function () x = true end)
do
local <toclose> yv = func2close(function () y = true end)
local yv <close> = func2close(function () y = true end)
coroutine.yield(100) -- yield doesn't close variable
end
coroutine.yield(200) -- yield doesn't close variable
@ -491,8 +491,8 @@ do
-- error in a wrapped coroutine raising errors when closing a variable
local x = 0
local co = coroutine.wrap(function ()
local <toclose> xx = func2close(function () x = x + 1; error("YYY") end)
local <toclose> xv = func2close(function () x = x + 1; error("XXX") end)
local xx <close> = func2close(function () x = x + 1; error("YYY") end)
local xv <close> = func2close(function () x = x + 1; error("XXX") end)
coroutine.yield(100)
error(200)
end)
@ -503,8 +503,8 @@ do
local x = 0
local y = 0
co = coroutine.wrap(function ()
local <toclose> xx = func2close(function () y = y + 1; error("YYY") end)
local <toclose> xv = func2close(function () x = x + 1; error("XXX") end)
local xx <close> = func2close(function () y = y + 1; error("YYY") end)
local xv <close> = func2close(function () x = x + 1; error("XXX") end)
coroutine.yield(100)
return 200
end)
@ -519,7 +519,7 @@ end
-- 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 x <close> = function () os.exit(false) end -- should not run
co = nil
coroutine.yield()
end)

View File

@ -320,11 +320,11 @@ NoRun("", "lua %s", prog) -- no message
-- to-be-closed variables in main chunk
prepfile[[
local <toclose> x = function (err)
local x <close> = function (err)
assert(err == 120)
print("Ok")
end
local <toclose> e1 = function () error(120) end
local e1 <close> = function () error(120) end
os.exit(true, true)
]]
RUN('lua %s > %s', prog, out)

View File

@ -3,10 +3,10 @@
print("testing numbers and math lib")
local <const> minint = math.mininteger
local <const> maxint = math.maxinteger
local minint <const> = math.mininteger
local maxint <const> = math.maxinteger
local <const> intbits = math.floor(math.log(maxint, 2) + 0.5) + 1
local intbits <const> = math.floor(math.log(maxint, 2) + 0.5) + 1
assert((1 << intbits) == 0)
assert(minint == 1 << (intbits - 1))
@ -270,7 +270,7 @@ else
end
do
local <const> NaN = 0/0
local NaN <const> = 0/0
assert(not (NaN < 0))
assert(not (NaN > minint))
assert(not (NaN <= -9))
@ -767,8 +767,8 @@ assert(a == '10' and b == '20')
do
print("testing -0 and NaN")
local <const> mz = -0.0
local <const> z = 0.0
local mz <const> = -0.0
local z <const> = 0.0
assert(mz == z)
assert(1/mz < 0 and 0 < 1/z)
local a = {[mz] = 1}
@ -776,18 +776,18 @@ do
a[z] = 2
assert(a[z] == 2 and a[mz] == 2)
local inf = math.huge * 2 + 1
local <const> mz = -1/inf
local <const> z = 1/inf
local mz <const> = -1/inf
local z <const> = 1/inf
assert(mz == z)
assert(1/mz < 0 and 0 < 1/z)
local <const> NaN = inf - inf
local NaN <const> = inf - inf
assert(NaN ~= NaN)
assert(not (NaN < NaN))
assert(not (NaN <= NaN))
assert(not (NaN > NaN))
assert(not (NaN >= NaN))
assert(not (0 < NaN) and not (NaN < 0))
local <const> NaN1 = 0/0
local NaN1 <const> = 0/0
assert(NaN ~= NaN1 and not (NaN <= NaN1) and not (NaN1 <= NaN))
local a = {}
assert(not pcall(rawset, a, NaN, 1))
@ -816,8 +816,8 @@ end
-- the first call after seed 1007 should return 0x7a7040a5a323c9d6
do
-- all computations should work with 32-bit integers
local <const> h = 0x7a7040a5 -- higher half
local <const> l = 0xa323c9d6 -- lower half
local h <const> = 0x7a7040a5 -- higher half
local l <const> = 0xa323c9d6 -- lower half
math.randomseed(1007)
-- get the low 'intbits' of the 64-bit expected result

View File

@ -3,8 +3,8 @@
print('testing strings and string library')
local <const> maxi = math.maxinteger
local <const> mini = math.mininteger
local maxi <const> = math.maxinteger
local mini <const> = math.mininteger
local function checkerror (msg, f, ...)