Collective declaration for globals ('global *')
This commit is contained in:
55
lparser.c
55
lparser.c
@@ -405,7 +405,12 @@ static int searchvar (FuncState *fs, TString *n, expdesc *var) {
|
|||||||
int i;
|
int i;
|
||||||
for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
|
for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
|
||||||
Vardesc *vd = getlocalvardesc(fs, i);
|
Vardesc *vd = getlocalvardesc(fs, i);
|
||||||
if (eqstr(n, vd->vd.name)) { /* found? */
|
if (vd->vd.name == NULL) { /* 'global *'? */
|
||||||
|
if (var->u.info == -1) { /* no previous collective declaration? */
|
||||||
|
var->u.info = fs->firstlocal + i; /* will use this one as default */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (eqstr(n, vd->vd.name)) { /* found? */
|
||||||
if (vd->vd.kind == RDKCTC) /* compile-time constant? */
|
if (vd->vd.kind == RDKCTC) /* compile-time constant? */
|
||||||
init_exp(var, VCONST, fs->firstlocal + i);
|
init_exp(var, VCONST, fs->firstlocal + i);
|
||||||
else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST)
|
else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST)
|
||||||
@@ -449,18 +454,16 @@ static void marktobeclosed (FuncState *fs) {
|
|||||||
** 'var' as 'void' as a flag.
|
** 'var' as 'void' as a flag.
|
||||||
*/
|
*/
|
||||||
static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
|
static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
|
||||||
int v = searchvar(fs, n, var); /* look up locals at current level */
|
int v = searchvar(fs, n, var); /* look up variables at current level */
|
||||||
if (v >= 0) { /* found? */
|
if (v >= 0) { /* found? */
|
||||||
if (v == VLOCAL && !base)
|
if (v == VLOCAL && !base)
|
||||||
markupval(fs, var->u.var.vidx); /* local will be used as an upval */
|
markupval(fs, var->u.var.vidx); /* local will be used as an upval */
|
||||||
}
|
}
|
||||||
else { /* not found as local at current level; try upvalues */
|
else { /* not found at current level; try upvalues */
|
||||||
int idx = searchupvalue(fs, n); /* try existing upvalues */
|
int idx = searchupvalue(fs, n); /* try existing upvalues */
|
||||||
if (idx < 0) { /* not found? */
|
if (idx < 0) { /* not found? */
|
||||||
if (fs->prev != NULL) /* more levels? */
|
if (fs->prev != NULL) /* more levels? */
|
||||||
singlevaraux(fs->prev, n, var, 0); /* try upper levels */
|
singlevaraux(fs->prev, n, var, 0); /* try upper levels */
|
||||||
else /* no more levels */
|
|
||||||
init_exp(var, VGLOBAL, -1); /* global by default */
|
|
||||||
if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */
|
if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */
|
||||||
idx = newupvalue(fs, n, var); /* will be a new upvalue */
|
idx = newupvalue(fs, n, var); /* will be a new upvalue */
|
||||||
else /* it is a global or a constant */
|
else /* it is a global or a constant */
|
||||||
@@ -477,6 +480,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
|
|||||||
*/
|
*/
|
||||||
static void buildvar (LexState *ls, TString *varname, expdesc *var) {
|
static void buildvar (LexState *ls, TString *varname, expdesc *var) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
|
init_exp(var, VGLOBAL, -1); /* global by default */
|
||||||
singlevaraux(fs, varname, var, 1);
|
singlevaraux(fs, varname, var, 1);
|
||||||
if (var->k == VGLOBAL) { /* global name? */
|
if (var->k == VGLOBAL) { /* global name? */
|
||||||
expdesc key;
|
expdesc key;
|
||||||
@@ -1796,20 +1800,33 @@ static void localstat (LexState *ls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static lu_byte getglobalattribute (LexState *ls) {
|
||||||
|
lu_byte kind = getvarattribute(ls);
|
||||||
|
if (kind == RDKTOCLOSE)
|
||||||
|
luaK_semerror(ls, "global variables cannot be to-be-closed");
|
||||||
|
/* adjust kind for global variable */
|
||||||
|
return (kind == VDKREG) ? GDKREG : GDKCONST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void globalstat (LexState *ls) {
|
static void globalstat (LexState *ls) {
|
||||||
/* globalstat -> (GLOBAL) NAME attrib {',' NAME attrib} */
|
/* globalstat -> (GLOBAL) '*' attrib
|
||||||
|
globalstat -> (GLOBAL) NAME attrib {',' NAME attrib} */
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
do {
|
if (testnext(ls, '*')) {
|
||||||
TString *vname = str_checkname(ls);
|
lu_byte kind = getglobalattribute(ls);
|
||||||
lu_byte kind = getvarattribute(ls);
|
/* use NULL as name to represent '*' entries */
|
||||||
if (kind == RDKTOCLOSE)
|
new_varkind(ls, NULL, kind);
|
||||||
luaK_semerror(ls, "global variable ('%s') cannot be to-be-closed",
|
|
||||||
getstr(vname));
|
|
||||||
/* adjust kind for global variable */
|
|
||||||
kind = (kind == VDKREG) ? GDKREG : GDKCONST;
|
|
||||||
new_varkind(ls, vname, kind);
|
|
||||||
fs->nactvar++; /* activate declaration */
|
fs->nactvar++; /* activate declaration */
|
||||||
} while (testnext(ls, ','));
|
}
|
||||||
|
else {
|
||||||
|
do {
|
||||||
|
TString *vname = str_checkname(ls);
|
||||||
|
lu_byte kind = getglobalattribute(ls);
|
||||||
|
new_varkind(ls, vname, kind);
|
||||||
|
fs->nactvar++; /* activate declaration */
|
||||||
|
} while (testnext(ls, ','));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1983,10 +2000,10 @@ static void statement (LexState *ls) {
|
|||||||
case TK_NAME: {
|
case TK_NAME: {
|
||||||
/* compatibility code to parse global keyword when "global"
|
/* compatibility code to parse global keyword when "global"
|
||||||
is not reserved */
|
is not reserved */
|
||||||
if (eqstr(ls->t.seminfo.ts, luaS_newliteral(ls->L, "global"))) {
|
if (strcmp(getstr(ls->t.seminfo.ts), "global") == 0) {
|
||||||
int lk = luaX_lookahead(ls);
|
int lk = luaX_lookahead(ls);
|
||||||
if (lk == TK_NAME || lk == TK_FUNCTION) {
|
if (lk == TK_NAME || lk == '*' || lk == TK_FUNCTION) {
|
||||||
/* 'global <name>' or 'global function' */
|
/* 'global <name>' or 'global *' or 'global function' */
|
||||||
globalstatfunc(ls, line);
|
globalstatfunc(ls, line);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,14 +223,15 @@ a function's formal parameter is equivalent to a local variable.)
|
|||||||
|
|
||||||
All chunks start with an implicit declaration @T{global *},
|
All chunks start with an implicit declaration @T{global *},
|
||||||
which declares all free names as global variables;
|
which declares all free names as global variables;
|
||||||
this implicit declaration becomes void inside the scope of any other
|
this preambular declaration becomes void inside the scope of any other
|
||||||
@Rw{global} declaration, regardless of the names being declared.
|
@Rw{global} declaration,
|
||||||
|
as the following example illustrates:
|
||||||
@verbatim{
|
@verbatim{
|
||||||
X = 1 -- Ok, global by default
|
X = 1 -- Ok, global by default
|
||||||
do
|
do
|
||||||
global Y -- voids implicit initial declaration
|
global Y -- voids implicit initial declaration
|
||||||
X = 1 -- ERROR, X not declared
|
|
||||||
Y = 1 -- Ok, Y declared as global
|
Y = 1 -- Ok, Y declared as global
|
||||||
|
X = 1 -- ERROR, X not declared
|
||||||
end
|
end
|
||||||
X = 2 -- Ok, global by default again
|
X = 2 -- Ok, global by default again
|
||||||
}
|
}
|
||||||
@@ -1110,9 +1111,9 @@ and cannot be used as names:
|
|||||||
@index{reserved words}
|
@index{reserved words}
|
||||||
@verbatim{
|
@verbatim{
|
||||||
and break do else elseif end
|
and break do else elseif end
|
||||||
false for function goto if in
|
false for function global goto if
|
||||||
local nil not or repeat return
|
in local nil not or repeat
|
||||||
then true until while
|
return then true until while
|
||||||
}
|
}
|
||||||
|
|
||||||
Lua is a case-sensitive language:
|
Lua is a case-sensitive language:
|
||||||
@@ -1653,7 +1654,8 @@ The declaration for locals can include an initialization:
|
|||||||
@producname{stat}@producbody{@Rw{local} attnamelist @bnfopt{@bnfter{=} explist}}
|
@producname{stat}@producbody{@Rw{local} attnamelist @bnfopt{@bnfter{=} explist}}
|
||||||
@producname{stat}@producbody{@Rw{global} attnamelist}
|
@producname{stat}@producbody{@Rw{global} attnamelist}
|
||||||
@producname{attnamelist}@producbody{
|
@producname{attnamelist}@producbody{
|
||||||
@bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}}
|
@bnfNter{Name} @bnfopt{attrib}
|
||||||
|
@bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}}
|
||||||
}
|
}
|
||||||
If present, an initial assignment has the same semantics
|
If present, an initial assignment has the same semantics
|
||||||
of a multiple assignment @see{assignment}.
|
of a multiple assignment @see{assignment}.
|
||||||
@@ -1662,24 +1664,55 @@ Otherwise, all local variables are initialized with @nil.
|
|||||||
Each variable name may be postfixed by an attribute
|
Each variable name may be postfixed by an attribute
|
||||||
(a name between angle brackets):
|
(a name between angle brackets):
|
||||||
@Produc{
|
@Produc{
|
||||||
@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}}
|
@producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}}
|
||||||
}
|
}
|
||||||
There are two possible attributes:
|
There are two possible attributes:
|
||||||
@id{const}, which declares a @emph{constant} or @emph{read-only} variable,
|
@id{const}, which declares a @emph{constant} or @emph{read-only} variable,
|
||||||
@index{constant variable}
|
@index{constant variable}
|
||||||
that is, a variable that cannot be assigned to
|
that is, a variable that cannot be used as the left-hand side of an
|
||||||
after its initialization;
|
assignment,
|
||||||
and @id{close}, which declares a to-be-closed variable @see{to-be-closed}.
|
and @id{close}, which declares a to-be-closed variable @see{to-be-closed}.
|
||||||
A list of variables can contain at most one to-be-closed variable.
|
A list of variables can contain at most one to-be-closed variable.
|
||||||
Only local variables can have the @id{close} attribute.
|
Only local variables can have the @id{close} attribute.
|
||||||
|
|
||||||
Note that, for global variables,
|
Lua offers also a collective declaration for global variables:
|
||||||
the @emph{read-only} atribute is only a syntactical restriction:
|
@Produc{
|
||||||
|
@producname{stat}@producbody{@Rw{global} @bnfter{*} @bnfopt{attrib}}
|
||||||
|
}
|
||||||
|
This special form implicitly declares
|
||||||
|
as globals all names not explicitly declared previously.
|
||||||
|
In particular,
|
||||||
|
@T{global * <const>} implicitly declares
|
||||||
|
as read-only globals all names not explicitly declared previously;
|
||||||
|
see the following example:
|
||||||
@verbatim{
|
@verbatim{
|
||||||
global X <const>
|
global X
|
||||||
X = 1 -- ERROR
|
global * <const>
|
||||||
_ENV.X = 1 -- Ok
|
print(math.pi) -- Ok, 'print' and 'math' are read-only
|
||||||
foo() -- 'foo' can freely change the global X
|
X = 1 -- Ok, declared as read-write
|
||||||
|
Y = 1 -- Error, Y is read-only
|
||||||
|
}
|
||||||
|
|
||||||
|
As noted in @See{globalenv},
|
||||||
|
all chunks start with an implicit declaration @T{global *},
|
||||||
|
but this preambular declaration becomes void inside
|
||||||
|
the scope of any other @Rw{global} declaration.
|
||||||
|
Therefore, a program that does not use global declarations
|
||||||
|
or start with @T{global *}
|
||||||
|
has free read-write access to any global;
|
||||||
|
a program that starts with @T{global * <const>}
|
||||||
|
has free read-only access to any global;
|
||||||
|
and a program that starts with any other global declaration
|
||||||
|
(e.g., @T{global none}) can only refer to declared variables.
|
||||||
|
|
||||||
|
Note that, for global variables,
|
||||||
|
the effect of any declaration is only syntactical:
|
||||||
|
@verbatim{
|
||||||
|
global X <const>, _G
|
||||||
|
X = 1 -- ERROR
|
||||||
|
_ENV.X = 1 -- Ok
|
||||||
|
_G.print(X) -- Ok
|
||||||
|
foo() -- 'foo' can freely change any global
|
||||||
}
|
}
|
||||||
|
|
||||||
A chunk is also a block @see{chunks},
|
A chunk is also a block @see{chunks},
|
||||||
@@ -9453,7 +9486,12 @@ change between versions.
|
|||||||
@itemize{
|
@itemize{
|
||||||
|
|
||||||
@item{
|
@item{
|
||||||
The control variable in @Rw{for} loops are read only.
|
The word @Rw{global} is a reserved word.
|
||||||
|
Do not use it as a regular name.
|
||||||
|
}
|
||||||
|
|
||||||
|
@item{
|
||||||
|
The control variable in @Rw{for} loops is read only.
|
||||||
If you need to change it,
|
If you need to change it,
|
||||||
declare a local variable with the same name in the loop body.
|
declare a local variable with the same name in the loop body.
|
||||||
}
|
}
|
||||||
@@ -9582,12 +9620,14 @@ and @bnfNter{LiteralString}, see @See{lexical}.)
|
|||||||
@OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody
|
@OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody
|
||||||
@OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist}
|
@OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist}
|
||||||
@OrNL @Rw{global} attnamelist
|
@OrNL @Rw{global} attnamelist
|
||||||
|
@OrNL @Rw{global} @bnfter{*} @bnfopt{attrib}
|
||||||
}
|
}
|
||||||
|
|
||||||
@producname{attnamelist}@producbody{
|
@producname{attnamelist}@producbody{
|
||||||
@bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}}
|
@bnfNter{Name} @bnfopt{attrib}
|
||||||
|
@bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}}
|
||||||
|
|
||||||
@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}}
|
@producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}}
|
||||||
|
|
||||||
@producname{retstat}@producbody{@Rw{return}
|
@producname{retstat}@producbody{@Rw{return}
|
||||||
@bnfopt{explist} @bnfopt{@bnfter{;}}}
|
@bnfopt{explist} @bnfopt{@bnfter{;}}}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
-- $Id: testes/all.lua $
|
-- $Id: testes/all.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
|
global _soft, _port, _nomsg
|
||||||
|
global T
|
||||||
|
|
||||||
local version = "Lua 5.5"
|
local version = "Lua 5.5"
|
||||||
if _VERSION ~= version then
|
if _VERSION ~= version then
|
||||||
@@ -34,7 +38,7 @@ if usertests then
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- tests should require debug when needed
|
-- tests should require debug when needed
|
||||||
debug = nil
|
global debug; debug = nil
|
||||||
|
|
||||||
|
|
||||||
if usertests then
|
if usertests then
|
||||||
@@ -71,7 +75,7 @@ do -- (
|
|||||||
|
|
||||||
-- track messages for tests not performed
|
-- track messages for tests not performed
|
||||||
local msgs = {}
|
local msgs = {}
|
||||||
function Message (m)
|
global function Message (m)
|
||||||
if not _nomsg then
|
if not _nomsg then
|
||||||
print(m)
|
print(m)
|
||||||
msgs[#msgs+1] = string.sub(m, 3, -3)
|
msgs[#msgs+1] = string.sub(m, 3, -3)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
-- $Id: testes/calls.lua $
|
-- $Id: testes/calls.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
print("testing functions and calls")
|
print("testing functions and calls")
|
||||||
|
|
||||||
local debug = require "debug"
|
local debug = require "debug"
|
||||||
@@ -22,7 +24,7 @@ assert(not pcall(type))
|
|||||||
|
|
||||||
|
|
||||||
-- testing local-function recursion
|
-- testing local-function recursion
|
||||||
fact = false
|
global fact; fact = false
|
||||||
do
|
do
|
||||||
local res = 1
|
local res = 1
|
||||||
local function fact (n)
|
local function fact (n)
|
||||||
@@ -63,7 +65,7 @@ a.b.c:f2('k', 12); assert(a.b.c.k == 12)
|
|||||||
|
|
||||||
print('+')
|
print('+')
|
||||||
|
|
||||||
t = nil -- 'declare' t
|
global t; t = nil -- 'declare' t
|
||||||
function f(a,b,c) local d = 'a'; t={a,b,c,d} end
|
function f(a,b,c) local d = 'a'; t={a,b,c,d} end
|
||||||
|
|
||||||
f( -- this line change must be valid
|
f( -- this line change must be valid
|
||||||
@@ -75,7 +77,7 @@ assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a')
|
|||||||
|
|
||||||
t = nil -- delete 't'
|
t = nil -- delete 't'
|
||||||
|
|
||||||
function fat(x)
|
global function fat(x)
|
||||||
if x <= 1 then return 1
|
if x <= 1 then return 1
|
||||||
else return x*load("return fat(" .. x-1 .. ")", "")()
|
else return x*load("return fat(" .. x-1 .. ")", "")()
|
||||||
end
|
end
|
||||||
@@ -107,7 +109,7 @@ end
|
|||||||
|
|
||||||
_G.deep = nil -- "declaration" (used by 'all.lua')
|
_G.deep = nil -- "declaration" (used by 'all.lua')
|
||||||
|
|
||||||
function deep (n)
|
global function deep (n)
|
||||||
if n>0 then deep(n-1) end
|
if n>0 then deep(n-1) end
|
||||||
end
|
end
|
||||||
deep(10)
|
deep(10)
|
||||||
@@ -352,7 +354,7 @@ assert(not load(function () return true end))
|
|||||||
|
|
||||||
-- small bug
|
-- small bug
|
||||||
local t = {nil, "return ", "3"}
|
local t = {nil, "return ", "3"}
|
||||||
f, msg = load(function () return table.remove(t, 1) end)
|
local f, msg = load(function () return table.remove(t, 1) end)
|
||||||
assert(f() == nil) -- should read the empty chunk
|
assert(f() == nil) -- should read the empty chunk
|
||||||
|
|
||||||
-- another small bug (in 5.2.1)
|
-- another small bug (in 5.2.1)
|
||||||
@@ -388,7 +390,8 @@ assert(load("return _ENV", nil, nil, 123)() == 123)
|
|||||||
|
|
||||||
|
|
||||||
-- load when _ENV is not first upvalue
|
-- load when _ENV is not first upvalue
|
||||||
local x; XX = 123
|
global XX; local x
|
||||||
|
XX = 123
|
||||||
local function h ()
|
local function h ()
|
||||||
local y=x -- use 'x', so that it becomes 1st upvalue
|
local y=x -- use 'x', so that it becomes 1st upvalue
|
||||||
return XX -- global name
|
return XX -- global name
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
-- $Id: testes/closure.lua $
|
-- $Id: testes/closure.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
print "testing closures"
|
print "testing closures"
|
||||||
|
|
||||||
do -- bug in 5.4.7
|
do -- bug in 5.4.7
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
-- $Id: testes/code.lua $
|
-- $Id: testes/code.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
if T==nil then
|
if T==nil then
|
||||||
(Message or print)('\n >>> testC not active: skipping opcode tests <<<\n')
|
(Message or print)('\n >>> testC not active: skipping opcode tests <<<\n')
|
||||||
return
|
return
|
||||||
@@ -405,8 +407,8 @@ do -- tests for table access in upvalues
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- de morgan
|
-- de morgan
|
||||||
checkequal(function () local a; if not (a or b) then b=a end end,
|
checkequal(function () local a, b; if not (a or b) then b=a end end,
|
||||||
function () local a; if (not a and not b) then b=a end end)
|
function () local a, b; if (not a and not b) then b=a end end)
|
||||||
|
|
||||||
checkequal(function (l) local a; return 0 <= a and a <= l end,
|
checkequal(function (l) local a; return 0 <= a and a <= l end,
|
||||||
function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
|
function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
-- $Id: testes/files.lua $
|
-- $Id: testes/files.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
local debug = require "debug"
|
local debug = require "debug"
|
||||||
|
|
||||||
local maxint = math.maxinteger
|
local maxint = math.maxinteger
|
||||||
@@ -838,13 +840,13 @@ assert(os.date("!\0\0") == "\0\0")
|
|||||||
local x = string.rep("a", 10000)
|
local x = string.rep("a", 10000)
|
||||||
assert(os.date(x) == x)
|
assert(os.date(x) == x)
|
||||||
local t = os.time()
|
local t = os.time()
|
||||||
D = os.date("*t", t)
|
global D; D = os.date("*t", t)
|
||||||
assert(os.date(string.rep("%d", 1000), t) ==
|
assert(os.date(string.rep("%d", 1000), t) ==
|
||||||
string.rep(os.date("%d", t), 1000))
|
string.rep(os.date("%d", t), 1000))
|
||||||
assert(os.date(string.rep("%", 200)) == string.rep("%", 100))
|
assert(os.date(string.rep("%", 200)) == string.rep("%", 100))
|
||||||
|
|
||||||
local function checkDateTable (t)
|
local function checkDateTable (t)
|
||||||
_G.D = os.date("*t", t)
|
D = os.date("*t", t)
|
||||||
assert(os.time(D) == t)
|
assert(os.time(D) == t)
|
||||||
load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and
|
load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and
|
||||||
D.hour==%H and D.min==%M and D.sec==%S and
|
D.hour==%H and D.min==%M and D.sec==%S and
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
-- $Id: testes/goto.lua $
|
-- $Id: testes/goto.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global require
|
||||||
|
global print, load, assert, string, setmetatable
|
||||||
|
global collectgarbage, error
|
||||||
|
|
||||||
print("testing goto and global declarations")
|
print("testing goto and global declarations")
|
||||||
|
|
||||||
collectgarbage()
|
collectgarbage()
|
||||||
@@ -254,6 +258,8 @@ assert(testG(5) == 10)
|
|||||||
|
|
||||||
do -- test goto's around to-be-closed variable
|
do -- test goto's around to-be-closed variable
|
||||||
|
|
||||||
|
global *
|
||||||
|
|
||||||
-- set 'var' and return an object that will reset 'var' when
|
-- set 'var' and return an object that will reset 'var' when
|
||||||
-- it goes out of scope
|
-- it goes out of scope
|
||||||
local function newobj (var)
|
local function newobj (var)
|
||||||
@@ -265,16 +271,16 @@ do -- test goto's around to-be-closed variable
|
|||||||
|
|
||||||
goto L1
|
goto L1
|
||||||
|
|
||||||
::L4:: assert(not X); goto L5 -- varX dead here
|
::L4:: assert(not varX); goto L5 -- varX dead here
|
||||||
|
|
||||||
::L1::
|
::L1::
|
||||||
local varX <close> = newobj("X")
|
local varX <close> = newobj("X")
|
||||||
assert(X); goto L2 -- varX alive here
|
assert(varX); goto L2 -- varX alive here
|
||||||
|
|
||||||
::L3::
|
::L3::
|
||||||
assert(X); goto L4 -- varX alive here
|
assert(varX); goto L4 -- varX alive here
|
||||||
|
|
||||||
::L2:: assert(X); goto L3 -- varX alive here
|
::L2:: assert(varX); goto L3 -- varX alive here
|
||||||
|
|
||||||
::L5:: -- return
|
::L5:: -- return
|
||||||
end
|
end
|
||||||
@@ -285,8 +291,7 @@ foo()
|
|||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
|
|
||||||
do
|
do
|
||||||
global print, load, T<const>; global assert<const>
|
global T<const>
|
||||||
global string
|
|
||||||
|
|
||||||
local function checkerr (code, err)
|
local function checkerr (code, err)
|
||||||
local st, msg = load(code)
|
local st, msg = load(code)
|
||||||
@@ -299,6 +304,7 @@ do
|
|||||||
|
|
||||||
-- global variables cannot be to-be-closed
|
-- global variables cannot be to-be-closed
|
||||||
checkerr("global X<close>", "cannot be")
|
checkerr("global X<close>", "cannot be")
|
||||||
|
checkerr("global * <close>", "cannot be")
|
||||||
|
|
||||||
do
|
do
|
||||||
local X = 10
|
local X = 10
|
||||||
@@ -349,6 +355,12 @@ do
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
]], "%:2%:") -- correct line in error message
|
]], "%:2%:") -- correct line in error message
|
||||||
|
|
||||||
|
checkerr([[
|
||||||
|
global * <const>;
|
||||||
|
print(X) -- Ok to use
|
||||||
|
Y = 1 -- ERROR
|
||||||
|
]], "assign to const variable 'Y'")
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
print('testing scanner')
|
print('testing scanner')
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
local debug = require "debug"
|
local debug = require "debug"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
-- $Id: testes/locals.lua $
|
-- $Id: testes/locals.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
print('testing local variables and environments')
|
print('testing local variables and environments')
|
||||||
|
|
||||||
local debug = require"debug"
|
local debug = require"debug"
|
||||||
@@ -39,9 +41,11 @@ f = nil
|
|||||||
local f
|
local f
|
||||||
local x = 1
|
local x = 1
|
||||||
|
|
||||||
a = nil
|
do
|
||||||
load('local a = {}')()
|
global a; a = nil
|
||||||
assert(a == nil)
|
load('local a = {}')()
|
||||||
|
assert(a == nil)
|
||||||
|
end
|
||||||
|
|
||||||
function f (a)
|
function f (a)
|
||||||
local _1, _2, _3, _4, _5
|
local _1, _2, _3, _4, _5
|
||||||
@@ -154,7 +158,7 @@ local _ENV = (function (...) return ... end)(_G, dummy) -- {
|
|||||||
do local _ENV = {assert=assert}; assert(true) end
|
do local _ENV = {assert=assert}; assert(true) end
|
||||||
local mt = {_G = _G}
|
local mt = {_G = _G}
|
||||||
local foo,x
|
local foo,x
|
||||||
A = false -- "declare" A
|
global A; A = false -- "declare" A
|
||||||
do local _ENV = mt
|
do local _ENV = mt
|
||||||
function foo (x)
|
function foo (x)
|
||||||
A = x
|
A = x
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
-- $Id: testes/nextvar.lua $
|
-- $Id: testes/nextvar.lua $
|
||||||
-- See Copyright Notice in file lua.h
|
-- See Copyright Notice in file lua.h
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
print('testing tables, next, and for')
|
print('testing tables, next, and for')
|
||||||
|
|
||||||
local function checkerror (msg, f, ...)
|
local function checkerror (msg, f, ...)
|
||||||
@@ -345,9 +347,6 @@ end
|
|||||||
|
|
||||||
local nofind = {}
|
local nofind = {}
|
||||||
|
|
||||||
a,b,c = 1,2,3
|
|
||||||
a,b,c = nil
|
|
||||||
|
|
||||||
|
|
||||||
-- next uses always the same iteration function
|
-- next uses always the same iteration function
|
||||||
assert(next{} == next{})
|
assert(next{} == next{})
|
||||||
@@ -396,7 +395,7 @@ for i=0,10000 do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
n = {n=0}
|
local n = {n=0}
|
||||||
for i,v in pairs(a) do
|
for i,v in pairs(a) do
|
||||||
n.n = n.n+1
|
n.n = n.n+1
|
||||||
assert(i and v and a[i] == v)
|
assert(i and v and a[i] == v)
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
print('testing pattern matching')
|
print('testing pattern matching')
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
local function checkerror (msg, f, ...)
|
local function checkerror (msg, f, ...)
|
||||||
local s, err = pcall(f, ...)
|
local s, err = pcall(f, ...)
|
||||||
assert(not s and string.find(err, msg))
|
assert(not s and string.find(err, msg))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
-- ISO Latin encoding
|
-- ISO Latin encoding
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
print('testing strings and string library')
|
print('testing strings and string library')
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
-- UTF-8 file
|
-- UTF-8 file
|
||||||
|
|
||||||
|
global * <const>
|
||||||
|
|
||||||
print "testing UTF-8 library"
|
print "testing UTF-8 library"
|
||||||
|
|
||||||
local utf8 = require'utf8'
|
local utf8 = require'utf8'
|
||||||
|
|||||||
Reference in New Issue
Block a user