aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-05-13 11:43:10 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-05-13 11:43:10 -0300
commit3b9dd52be02fd43c598f4adb6fa7844e6a573923 (patch)
tree8f858942f5db0e3d9d7cad503b59ee1541a60aa6
parent7dc6aae29057c9dc4588f780c7abd72a62ff4c8e (diff)
downloadlua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.tar.gz
lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.tar.bz2
lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.zip
Collective declaration for globals ('global *')
-rw-r--r--lparser.c55
-rw-r--r--manual/manual.of76
-rwxr-xr-xtestes/all.lua8
-rw-r--r--testes/calls.lua15
-rw-r--r--testes/closure.lua2
-rw-r--r--testes/code.lua6
-rw-r--r--testes/files.lua6
-rw-r--r--testes/goto.lua24
-rw-r--r--testes/literals.lua2
-rw-r--r--testes/locals.lua12
-rw-r--r--testes/nextvar.lua7
-rw-r--r--testes/pm.lua2
-rw-r--r--testes/strings.lua1
-rw-r--r--testes/utf8.lua2
14 files changed, 155 insertions, 63 deletions
diff --git a/lparser.c b/lparser.c
index 93991cb0..242bb001 100644
--- a/lparser.c
+++ b/lparser.c
@@ -405,7 +405,12 @@ static int searchvar (FuncState *fs, TString *n, expdesc *var) {
405 int i; 405 int i;
406 for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { 406 for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) {
407 Vardesc *vd = getlocalvardesc(fs, i); 407 Vardesc *vd = getlocalvardesc(fs, i);
408 if (eqstr(n, vd->vd.name)) { /* found? */ 408 if (vd->vd.name == NULL) { /* 'global *'? */
409 if (var->u.info == -1) { /* no previous collective declaration? */
410 var->u.info = fs->firstlocal + i; /* will use this one as default */
411 }
412 }
413 else if (eqstr(n, vd->vd.name)) { /* found? */
409 if (vd->vd.kind == RDKCTC) /* compile-time constant? */ 414 if (vd->vd.kind == RDKCTC) /* compile-time constant? */
410 init_exp(var, VCONST, fs->firstlocal + i); 415 init_exp(var, VCONST, fs->firstlocal + i);
411 else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST) 416 else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST)
@@ -449,18 +454,16 @@ static void marktobeclosed (FuncState *fs) {
449** 'var' as 'void' as a flag. 454** 'var' as 'void' as a flag.
450*/ 455*/
451static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { 456static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
452 int v = searchvar(fs, n, var); /* look up locals at current level */ 457 int v = searchvar(fs, n, var); /* look up variables at current level */
453 if (v >= 0) { /* found? */ 458 if (v >= 0) { /* found? */
454 if (v == VLOCAL && !base) 459 if (v == VLOCAL && !base)
455 markupval(fs, var->u.var.vidx); /* local will be used as an upval */ 460 markupval(fs, var->u.var.vidx); /* local will be used as an upval */
456 } 461 }
457 else { /* not found as local at current level; try upvalues */ 462 else { /* not found at current level; try upvalues */
458 int idx = searchupvalue(fs, n); /* try existing upvalues */ 463 int idx = searchupvalue(fs, n); /* try existing upvalues */
459 if (idx < 0) { /* not found? */ 464 if (idx < 0) { /* not found? */
460 if (fs->prev != NULL) /* more levels? */ 465 if (fs->prev != NULL) /* more levels? */
461 singlevaraux(fs->prev, n, var, 0); /* try upper levels */ 466 singlevaraux(fs->prev, n, var, 0); /* try upper levels */
462 else /* no more levels */
463 init_exp(var, VGLOBAL, -1); /* global by default */
464 if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ 467 if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */
465 idx = newupvalue(fs, n, var); /* will be a new upvalue */ 468 idx = newupvalue(fs, n, var); /* will be a new upvalue */
466 else /* it is a global or a constant */ 469 else /* it is a global or a constant */
@@ -477,6 +480,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
477*/ 480*/
478static void buildvar (LexState *ls, TString *varname, expdesc *var) { 481static void buildvar (LexState *ls, TString *varname, expdesc *var) {
479 FuncState *fs = ls->fs; 482 FuncState *fs = ls->fs;
483 init_exp(var, VGLOBAL, -1); /* global by default */
480 singlevaraux(fs, varname, var, 1); 484 singlevaraux(fs, varname, var, 1);
481 if (var->k == VGLOBAL) { /* global name? */ 485 if (var->k == VGLOBAL) { /* global name? */
482 expdesc key; 486 expdesc key;
@@ -1796,20 +1800,33 @@ static void localstat (LexState *ls) {
1796} 1800}
1797 1801
1798 1802
1803static lu_byte getglobalattribute (LexState *ls) {
1804 lu_byte kind = getvarattribute(ls);
1805 if (kind == RDKTOCLOSE)
1806 luaK_semerror(ls, "global variables cannot be to-be-closed");
1807 /* adjust kind for global variable */
1808 return (kind == VDKREG) ? GDKREG : GDKCONST;
1809}
1810
1811
1799static void globalstat (LexState *ls) { 1812static void globalstat (LexState *ls) {
1800 /* globalstat -> (GLOBAL) NAME attrib {',' NAME attrib} */ 1813 /* globalstat -> (GLOBAL) '*' attrib
1814 globalstat -> (GLOBAL) NAME attrib {',' NAME attrib} */
1801 FuncState *fs = ls->fs; 1815 FuncState *fs = ls->fs;
1802 do { 1816 if (testnext(ls, '*')) {
1803 TString *vname = str_checkname(ls); 1817 lu_byte kind = getglobalattribute(ls);
1804 lu_byte kind = getvarattribute(ls); 1818 /* use NULL as name to represent '*' entries */
1805 if (kind == RDKTOCLOSE) 1819 new_varkind(ls, NULL, kind);
1806 luaK_semerror(ls, "global variable ('%s') cannot be to-be-closed",
1807 getstr(vname));
1808 /* adjust kind for global variable */
1809 kind = (kind == VDKREG) ? GDKREG : GDKCONST;
1810 new_varkind(ls, vname, kind);
1811 fs->nactvar++; /* activate declaration */ 1820 fs->nactvar++; /* activate declaration */
1812 } while (testnext(ls, ',')); 1821 }
1822 else {
1823 do {
1824 TString *vname = str_checkname(ls);
1825 lu_byte kind = getglobalattribute(ls);
1826 new_varkind(ls, vname, kind);
1827 fs->nactvar++; /* activate declaration */
1828 } while (testnext(ls, ','));
1829 }
1813} 1830}
1814 1831
1815 1832
@@ -1983,10 +2000,10 @@ static void statement (LexState *ls) {
1983 case TK_NAME: { 2000 case TK_NAME: {
1984 /* compatibility code to parse global keyword when "global" 2001 /* compatibility code to parse global keyword when "global"
1985 is not reserved */ 2002 is not reserved */
1986 if (eqstr(ls->t.seminfo.ts, luaS_newliteral(ls->L, "global"))) { 2003 if (strcmp(getstr(ls->t.seminfo.ts), "global") == 0) {
1987 int lk = luaX_lookahead(ls); 2004 int lk = luaX_lookahead(ls);
1988 if (lk == TK_NAME || lk == TK_FUNCTION) { 2005 if (lk == TK_NAME || lk == '*' || lk == TK_FUNCTION) {
1989 /* 'global <name>' or 'global function' */ 2006 /* 'global <name>' or 'global *' or 'global function' */
1990 globalstatfunc(ls, line); 2007 globalstatfunc(ls, line);
1991 break; 2008 break;
1992 } 2009 }
diff --git a/manual/manual.of b/manual/manual.of
index cc71aaad..effb95da 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -223,14 +223,15 @@ a function's formal parameter is equivalent to a local variable.)
223 223
224All chunks start with an implicit declaration @T{global *}, 224All chunks start with an implicit declaration @T{global *},
225which declares all free names as global variables; 225which declares all free names as global variables;
226this implicit declaration becomes void inside the scope of any other 226this preambular declaration becomes void inside the scope of any other
227@Rw{global} declaration, regardless of the names being declared. 227@Rw{global} declaration,
228as the following example illustrates:
228@verbatim{ 229@verbatim{
229X = 1 -- Ok, global by default 230X = 1 -- Ok, global by default
230do 231do
231 global Y -- voids implicit initial declaration 232 global Y -- voids implicit initial declaration
232 X = 1 -- ERROR, X not declared
233 Y = 1 -- Ok, Y declared as global 233 Y = 1 -- Ok, Y declared as global
234 X = 1 -- ERROR, X not declared
234end 235end
235X = 2 -- Ok, global by default again 236X = 2 -- Ok, global by default again
236} 237}
@@ -1110,9 +1111,9 @@ and cannot be used as names:
1110@index{reserved words} 1111@index{reserved words}
1111@verbatim{ 1112@verbatim{
1112and break do else elseif end 1113and break do else elseif end
1113false for function goto if in 1114false for function global goto if
1114local nil not or repeat return 1115in local nil not or repeat
1115then true until while 1116return then true until while
1116} 1117}
1117 1118
1118Lua is a case-sensitive language: 1119Lua is a case-sensitive language:
@@ -1653,7 +1654,8 @@ The declaration for locals can include an initialization:
1653@producname{stat}@producbody{@Rw{local} attnamelist @bnfopt{@bnfter{=} explist}} 1654@producname{stat}@producbody{@Rw{local} attnamelist @bnfopt{@bnfter{=} explist}}
1654@producname{stat}@producbody{@Rw{global} attnamelist} 1655@producname{stat}@producbody{@Rw{global} attnamelist}
1655@producname{attnamelist}@producbody{ 1656@producname{attnamelist}@producbody{
1656 @bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}} 1657 @bnfNter{Name} @bnfopt{attrib}
1658 @bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}}
1657} 1659}
1658If present, an initial assignment has the same semantics 1660If present, an initial assignment has the same semantics
1659of a multiple assignment @see{assignment}. 1661of a multiple assignment @see{assignment}.
@@ -1662,24 +1664,55 @@ Otherwise, all local variables are initialized with @nil.
1662Each variable name may be postfixed by an attribute 1664Each variable name may be postfixed by an attribute
1663(a name between angle brackets): 1665(a name between angle brackets):
1664@Produc{ 1666@Produc{
1665@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}} 1667@producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}}
1666} 1668}
1667There are two possible attributes: 1669There are two possible attributes:
1668@id{const}, which declares a @emph{constant} or @emph{read-only} variable, 1670@id{const}, which declares a @emph{constant} or @emph{read-only} variable,
1669@index{constant variable} 1671@index{constant variable}
1670that is, a variable that cannot be assigned to 1672that is, a variable that cannot be used as the left-hand side of an
1671after its initialization; 1673assignment,
1672and @id{close}, which declares a to-be-closed variable @see{to-be-closed}. 1674and @id{close}, which declares a to-be-closed variable @see{to-be-closed}.
1673A list of variables can contain at most one to-be-closed variable. 1675A list of variables can contain at most one to-be-closed variable.
1674Only local variables can have the @id{close} attribute. 1676Only local variables can have the @id{close} attribute.
1675 1677
1678Lua offers also a collective declaration for global variables:
1679@Produc{
1680@producname{stat}@producbody{@Rw{global} @bnfter{*} @bnfopt{attrib}}
1681}
1682This special form implicitly declares
1683as globals all names not explicitly declared previously.
1684In particular,
1685@T{global * <const>} implicitly declares
1686as read-only globals all names not explicitly declared previously;
1687see the following example:
1688@verbatim{
1689global X
1690global * <const>
1691print(math.pi) -- Ok, 'print' and 'math' are read-only
1692X = 1 -- Ok, declared as read-write
1693Y = 1 -- Error, Y is read-only
1694}
1695
1696As noted in @See{globalenv},
1697all chunks start with an implicit declaration @T{global *},
1698but this preambular declaration becomes void inside
1699the scope of any other @Rw{global} declaration.
1700Therefore, a program that does not use global declarations
1701or start with @T{global *}
1702has free read-write access to any global;
1703a program that starts with @T{global * <const>}
1704has free read-only access to any global;
1705and a program that starts with any other global declaration
1706(e.g., @T{global none}) can only refer to declared variables.
1707
1676Note that, for global variables, 1708Note that, for global variables,
1677the @emph{read-only} atribute is only a syntactical restriction: 1709the effect of any declaration is only syntactical:
1678@verbatim{ 1710@verbatim{
1679global X <const> 1711global X <const>, _G
1680X = 1 -- ERROR 1712X = 1 -- ERROR
1681_ENV.X = 1 -- Ok 1713_ENV.X = 1 -- Ok
1682foo() -- 'foo' can freely change the global X 1714_G.print(X) -- Ok
1715foo() -- 'foo' can freely change any global
1683} 1716}
1684 1717
1685A chunk is also a block @see{chunks}, 1718A chunk is also a block @see{chunks},
@@ -9453,7 +9486,12 @@ change between versions.
9453@itemize{ 9486@itemize{
9454 9487
9455@item{ 9488@item{
9456The control variable in @Rw{for} loops are read only. 9489The word @Rw{global} is a reserved word.
9490Do not use it as a regular name.
9491}
9492
9493@item{
9494The control variable in @Rw{for} loops is read only.
9457If you need to change it, 9495If you need to change it,
9458declare a local variable with the same name in the loop body. 9496declare a local variable with the same name in the loop body.
9459} 9497}
@@ -9582,12 +9620,14 @@ and @bnfNter{LiteralString}, see @See{lexical}.)
9582@OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody 9620@OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody
9583@OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist} 9621@OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist}
9584@OrNL @Rw{global} attnamelist 9622@OrNL @Rw{global} attnamelist
9623@OrNL @Rw{global} @bnfter{*} @bnfopt{attrib}
9585} 9624}
9586 9625
9587@producname{attnamelist}@producbody{ 9626@producname{attnamelist}@producbody{
9588 @bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}} 9627 @bnfNter{Name} @bnfopt{attrib}
9628 @bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}}
9589 9629
9590@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}} 9630@producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}}
9591 9631
9592@producname{retstat}@producbody{@Rw{return} 9632@producname{retstat}@producbody{@Rw{return}
9593 @bnfopt{explist} @bnfopt{@bnfter{;}}} 9633 @bnfopt{explist} @bnfopt{@bnfter{;}}}
diff --git a/testes/all.lua b/testes/all.lua
index 5c7ebfa5..499c100d 100755
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -2,6 +2,10 @@
2-- $Id: testes/all.lua $ 2-- $Id: testes/all.lua $
3-- See Copyright Notice in file lua.h 3-- See Copyright Notice in file lua.h
4 4
5global * <const>
6
7global _soft, _port, _nomsg
8global T
5 9
6local version = "Lua 5.5" 10local version = "Lua 5.5"
7if _VERSION ~= version then 11if _VERSION ~= version then
@@ -34,7 +38,7 @@ if usertests then
34end 38end
35 39
36-- tests should require debug when needed 40-- tests should require debug when needed
37debug = nil 41global debug; debug = nil
38 42
39 43
40if usertests then 44if usertests then
@@ -71,7 +75,7 @@ do -- (
71 75
72-- track messages for tests not performed 76-- track messages for tests not performed
73local msgs = {} 77local msgs = {}
74function Message (m) 78global function Message (m)
75 if not _nomsg then 79 if not _nomsg then
76 print(m) 80 print(m)
77 msgs[#msgs+1] = string.sub(m, 3, -3) 81 msgs[#msgs+1] = string.sub(m, 3, -3)
diff --git a/testes/calls.lua b/testes/calls.lua
index 942fad72..0ea1c4ab 100644
--- a/testes/calls.lua
+++ b/testes/calls.lua
@@ -1,6 +1,8 @@
1-- $Id: testes/calls.lua $ 1-- $Id: testes/calls.lua $
2-- See Copyright Notice in file lua.h 2-- See Copyright Notice in file lua.h
3 3
4global * <const>
5
4print("testing functions and calls") 6print("testing functions and calls")
5 7
6local debug = require "debug" 8local debug = require "debug"
@@ -22,7 +24,7 @@ assert(not pcall(type))
22 24
23 25
24-- testing local-function recursion 26-- testing local-function recursion
25fact = false 27global fact; fact = false
26do 28do
27 local res = 1 29 local res = 1
28 local function fact (n) 30 local function fact (n)
@@ -63,7 +65,7 @@ a.b.c:f2('k', 12); assert(a.b.c.k == 12)
63 65
64print('+') 66print('+')
65 67
66t = nil -- 'declare' t 68global t; t = nil -- 'declare' t
67function f(a,b,c) local d = 'a'; t={a,b,c,d} end 69function f(a,b,c) local d = 'a'; t={a,b,c,d} end
68 70
69f( -- this line change must be valid 71f( -- 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')
75 77
76t = nil -- delete 't' 78t = nil -- delete 't'
77 79
78function fat(x) 80global function fat(x)
79 if x <= 1 then return 1 81 if x <= 1 then return 1
80 else return x*load("return fat(" .. x-1 .. ")", "")() 82 else return x*load("return fat(" .. x-1 .. ")", "")()
81 end 83 end
@@ -107,7 +109,7 @@ end
107 109
108_G.deep = nil -- "declaration" (used by 'all.lua') 110_G.deep = nil -- "declaration" (used by 'all.lua')
109 111
110function deep (n) 112global function deep (n)
111 if n>0 then deep(n-1) end 113 if n>0 then deep(n-1) end
112end 114end
113deep(10) 115deep(10)
@@ -352,7 +354,7 @@ assert(not load(function () return true end))
352 354
353-- small bug 355-- small bug
354local t = {nil, "return ", "3"} 356local t = {nil, "return ", "3"}
355f, msg = load(function () return table.remove(t, 1) end) 357local f, msg = load(function () return table.remove(t, 1) end)
356assert(f() == nil) -- should read the empty chunk 358assert(f() == nil) -- should read the empty chunk
357 359
358-- another small bug (in 5.2.1) 360-- another small bug (in 5.2.1)
@@ -388,7 +390,8 @@ assert(load("return _ENV", nil, nil, 123)() == 123)
388 390
389 391
390-- load when _ENV is not first upvalue 392-- load when _ENV is not first upvalue
391local x; XX = 123 393global XX; local x
394XX = 123
392local function h () 395local function h ()
393 local y=x -- use 'x', so that it becomes 1st upvalue 396 local y=x -- use 'x', so that it becomes 1st upvalue
394 return XX -- global name 397 return XX -- global name
diff --git a/testes/closure.lua b/testes/closure.lua
index d3b9f621..c55d1583 100644
--- a/testes/closure.lua
+++ b/testes/closure.lua
@@ -1,6 +1,8 @@
1-- $Id: testes/closure.lua $ 1-- $Id: testes/closure.lua $
2-- See Copyright Notice in file lua.h 2-- See Copyright Notice in file lua.h
3 3
4global * <const>
5
4print "testing closures" 6print "testing closures"
5 7
6do -- bug in 5.4.7 8do -- bug in 5.4.7
diff --git a/testes/code.lua b/testes/code.lua
index 111717ce..b6ceb34c 100644
--- a/testes/code.lua
+++ b/testes/code.lua
@@ -1,6 +1,8 @@
1-- $Id: testes/code.lua $ 1-- $Id: testes/code.lua $
2-- See Copyright Notice in file lua.h 2-- See Copyright Notice in file lua.h
3 3
4global * <const>
5
4if T==nil then 6if T==nil then
5 (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n') 7 (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n')
6 return 8 return
@@ -405,8 +407,8 @@ do -- tests for table access in upvalues
405end 407end
406 408
407-- de morgan 409-- de morgan
408checkequal(function () local a; if not (a or b) then b=a end end, 410checkequal(function () local a, b; if not (a or b) then b=a end end,
409 function () local a; if (not a and not b) then b=a end end) 411 function () local a, b; if (not a and not b) then b=a end end)
410 412
411checkequal(function (l) local a; return 0 <= a and a <= l end, 413checkequal(function (l) local a; return 0 <= a and a <= l end,
412 function (l) local a; return not (not(a >= 0) or not(a <= l)) end) 414 function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
diff --git a/testes/files.lua b/testes/files.lua
index a0ae661c..c2b355fb 100644
--- a/testes/files.lua
+++ b/testes/files.lua
@@ -1,6 +1,8 @@
1-- $Id: testes/files.lua $ 1-- $Id: testes/files.lua $
2-- See Copyright Notice in file lua.h 2-- See Copyright Notice in file lua.h
3 3
4global * <const>
5
4local debug = require "debug" 6local debug = require "debug"
5 7
6local maxint = math.maxinteger 8local maxint = math.maxinteger
@@ -838,13 +840,13 @@ assert(os.date("!\0\0") == "\0\0")
838local x = string.rep("a", 10000) 840local x = string.rep("a", 10000)
839assert(os.date(x) == x) 841assert(os.date(x) == x)
840local t = os.time() 842local t = os.time()
841D = os.date("*t", t) 843global D; D = os.date("*t", t)
842assert(os.date(string.rep("%d", 1000), t) == 844assert(os.date(string.rep("%d", 1000), t) ==
843 string.rep(os.date("%d", t), 1000)) 845 string.rep(os.date("%d", t), 1000))
844assert(os.date(string.rep("%", 200)) == string.rep("%", 100)) 846assert(os.date(string.rep("%", 200)) == string.rep("%", 100))
845 847
846local function checkDateTable (t) 848local function checkDateTable (t)
847 _G.D = os.date("*t", t) 849 D = os.date("*t", t)
848 assert(os.time(D) == t) 850 assert(os.time(D) == t)
849 load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and 851 load(os.date([[assert(D.year==%Y and D.month==%m and D.day==%d and
850 D.hour==%H and D.min==%M and D.sec==%S and 852 D.hour==%H and D.min==%M and D.sec==%S and
diff --git a/testes/goto.lua b/testes/goto.lua
index 59713dd7..3f1f6e69 100644
--- a/testes/goto.lua
+++ b/testes/goto.lua
@@ -1,6 +1,10 @@
1-- $Id: testes/goto.lua $ 1-- $Id: testes/goto.lua $
2-- See Copyright Notice in file lua.h 2-- See Copyright Notice in file lua.h
3 3
4global require
5global print, load, assert, string, setmetatable
6global collectgarbage, error
7
4print("testing goto and global declarations") 8print("testing goto and global declarations")
5 9
6collectgarbage() 10collectgarbage()
@@ -254,6 +258,8 @@ assert(testG(5) == 10)
254 258
255do -- test goto's around to-be-closed variable 259do -- test goto's around to-be-closed variable
256 260
261 global *
262
257 -- set 'var' and return an object that will reset 'var' when 263 -- set 'var' and return an object that will reset 'var' when
258 -- it goes out of scope 264 -- it goes out of scope
259 local function newobj (var) 265 local function newobj (var)
@@ -265,16 +271,16 @@ do -- test goto's around to-be-closed variable
265 271
266 goto L1 272 goto L1
267 273
268 ::L4:: assert(not X); goto L5 -- varX dead here 274 ::L4:: assert(not varX); goto L5 -- varX dead here
269 275
270 ::L1:: 276 ::L1::
271 local varX <close> = newobj("X") 277 local varX <close> = newobj("X")
272 assert(X); goto L2 -- varX alive here 278 assert(varX); goto L2 -- varX alive here
273 279
274 ::L3:: 280 ::L3::
275 assert(X); goto L4 -- varX alive here 281 assert(varX); goto L4 -- varX alive here
276 282
277 ::L2:: assert(X); goto L3 -- varX alive here 283 ::L2:: assert(varX); goto L3 -- varX alive here
278 284
279 ::L5:: -- return 285 ::L5:: -- return
280end 286end
@@ -285,8 +291,7 @@ foo()
285-------------------------------------------------------------------------- 291--------------------------------------------------------------------------
286 292
287do 293do
288 global print, load, T<const>; global assert<const> 294 global T<const>
289 global string
290 295
291 local function checkerr (code, err) 296 local function checkerr (code, err)
292 local st, msg = load(code) 297 local st, msg = load(code)
@@ -299,6 +304,7 @@ do
299 304
300 -- global variables cannot be to-be-closed 305 -- global variables cannot be to-be-closed
301 checkerr("global X<close>", "cannot be") 306 checkerr("global X<close>", "cannot be")
307 checkerr("global * <close>", "cannot be")
302 308
303 do 309 do
304 local X = 10 310 local X = 10
@@ -349,6 +355,12 @@ do
349 return 355 return
350 end 356 end
351 ]], "%:2%:") -- correct line in error message 357 ]], "%:2%:") -- correct line in error message
358
359 checkerr([[
360 global * <const>;
361 print(X) -- Ok to use
362 Y = 1 -- ERROR
363 ]], "assign to const variable 'Y'")
352 364
353end 365end
354 366
diff --git a/testes/literals.lua b/testes/literals.lua
index 28995718..fecdd6d3 100644
--- a/testes/literals.lua
+++ b/testes/literals.lua
@@ -3,6 +3,8 @@
3 3
4print('testing scanner') 4print('testing scanner')
5 5
6global * <const>
7
6local debug = require "debug" 8local debug = require "debug"
7 9
8 10
diff --git a/testes/locals.lua b/testes/locals.lua
index 421595bb..99ff9edc 100644
--- a/testes/locals.lua
+++ b/testes/locals.lua
@@ -1,6 +1,8 @@
1-- $Id: testes/locals.lua $ 1-- $Id: testes/locals.lua $
2-- See Copyright Notice in file lua.h 2-- See Copyright Notice in file lua.h
3 3
4global * <const>
5
4print('testing local variables and environments') 6print('testing local variables and environments')
5 7
6local debug = require"debug" 8local debug = require"debug"
@@ -39,9 +41,11 @@ f = nil
39local f 41local f
40local x = 1 42local x = 1
41 43
42a = nil 44do
43load('local a = {}')() 45 global a; a = nil
44assert(a == nil) 46 load('local a = {}')()
47 assert(a == nil)
48end
45 49
46function f (a) 50function f (a)
47 local _1, _2, _3, _4, _5 51 local _1, _2, _3, _4, _5
@@ -154,7 +158,7 @@ local _ENV = (function (...) return ... end)(_G, dummy) -- {
154do local _ENV = {assert=assert}; assert(true) end 158do local _ENV = {assert=assert}; assert(true) end
155local mt = {_G = _G} 159local mt = {_G = _G}
156local foo,x 160local foo,x
157A = false -- "declare" A 161global A; A = false -- "declare" A
158do local _ENV = mt 162do local _ENV = mt
159 function foo (x) 163 function foo (x)
160 A = x 164 A = x
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index 679cb1e4..e5a97178 100644
--- a/testes/nextvar.lua
+++ b/testes/nextvar.lua
@@ -1,6 +1,8 @@
1-- $Id: testes/nextvar.lua $ 1-- $Id: testes/nextvar.lua $
2-- See Copyright Notice in file lua.h 2-- See Copyright Notice in file lua.h
3 3
4global * <const>
5
4print('testing tables, next, and for') 6print('testing tables, next, and for')
5 7
6local function checkerror (msg, f, ...) 8local function checkerror (msg, f, ...)
@@ -345,9 +347,6 @@ end
345 347
346local nofind = {} 348local nofind = {}
347 349
348a,b,c = 1,2,3
349a,b,c = nil
350
351 350
352-- next uses always the same iteration function 351-- next uses always the same iteration function
353assert(next{} == next{}) 352assert(next{} == next{})
@@ -396,7 +395,7 @@ for i=0,10000 do
396 end 395 end
397end 396end
398 397
399n = {n=0} 398local n = {n=0}
400for i,v in pairs(a) do 399for i,v in pairs(a) do
401 n.n = n.n+1 400 n.n = n.n+1
402 assert(i and v and a[i] == v) 401 assert(i and v and a[i] == v)
diff --git a/testes/pm.lua b/testes/pm.lua
index ab19eb5d..1700ca2c 100644
--- a/testes/pm.lua
+++ b/testes/pm.lua
@@ -6,6 +6,8 @@
6 6
7print('testing pattern matching') 7print('testing pattern matching')
8 8
9global * <const>
10
9local function checkerror (msg, f, ...) 11local function checkerror (msg, f, ...)
10 local s, err = pcall(f, ...) 12 local s, err = pcall(f, ...)
11 assert(not s and string.find(err, msg)) 13 assert(not s and string.find(err, msg))
diff --git a/testes/strings.lua b/testes/strings.lua
index ce28e4c5..455398c3 100644
--- a/testes/strings.lua
+++ b/testes/strings.lua
@@ -3,6 +3,7 @@
3 3
4-- ISO Latin encoding 4-- ISO Latin encoding
5 5
6global * <const>
6 7
7print('testing strings and string library') 8print('testing strings and string library')
8 9
diff --git a/testes/utf8.lua b/testes/utf8.lua
index d0c0184d..ec9b706f 100644
--- a/testes/utf8.lua
+++ b/testes/utf8.lua
@@ -3,6 +3,8 @@
3 3
4-- UTF-8 file 4-- UTF-8 file
5 5
6global * <const>
7
6print "testing UTF-8 library" 8print "testing UTF-8 library"
7 9
8local utf8 = require'utf8' 10local utf8 = require'utf8'