diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-05-13 11:43:10 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-05-13 11:43:10 -0300 |
commit | 3b9dd52be02fd43c598f4adb6fa7844e6a573923 (patch) | |
tree | 8f858942f5db0e3d9d7cad503b59ee1541a60aa6 | |
parent | 7dc6aae29057c9dc4588f780c7abd72a62ff4c8e (diff) | |
download | lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.tar.gz lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.tar.bz2 lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.zip |
Collective declaration for globals ('global *')
-rw-r--r-- | lparser.c | 55 | ||||
-rw-r--r-- | manual/manual.of | 76 | ||||
-rwxr-xr-x | testes/all.lua | 8 | ||||
-rw-r--r-- | testes/calls.lua | 15 | ||||
-rw-r--r-- | testes/closure.lua | 2 | ||||
-rw-r--r-- | testes/code.lua | 6 | ||||
-rw-r--r-- | testes/files.lua | 6 | ||||
-rw-r--r-- | testes/goto.lua | 24 | ||||
-rw-r--r-- | testes/literals.lua | 2 | ||||
-rw-r--r-- | testes/locals.lua | 12 | ||||
-rw-r--r-- | testes/nextvar.lua | 7 | ||||
-rw-r--r-- | testes/pm.lua | 2 | ||||
-rw-r--r-- | testes/strings.lua | 1 | ||||
-rw-r--r-- | testes/utf8.lua | 2 |
14 files changed, 155 insertions, 63 deletions
@@ -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 | */ |
451 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 456 | static 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 | */ |
478 | static void buildvar (LexState *ls, TString *varname, expdesc *var) { | 481 | static 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 | ||
1803 | static 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 | |||
1799 | static void globalstat (LexState *ls) { | 1812 | static 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 | ||
224 | All chunks start with an implicit declaration @T{global *}, | 224 | All chunks start with an implicit declaration @T{global *}, |
225 | which declares all free names as global variables; | 225 | which declares all free names as global variables; |
226 | this implicit declaration becomes void inside the scope of any other | 226 | this preambular declaration becomes void inside the scope of any other |
227 | @Rw{global} declaration, regardless of the names being declared. | 227 | @Rw{global} declaration, |
228 | as the following example illustrates: | ||
228 | @verbatim{ | 229 | @verbatim{ |
229 | X = 1 -- Ok, global by default | 230 | X = 1 -- Ok, global by default |
230 | do | 231 | do |
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 | ||
234 | end | 235 | end |
235 | X = 2 -- Ok, global by default again | 236 | X = 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{ |
1112 | and break do else elseif end | 1113 | and break do else elseif end |
1113 | false for function goto if in | 1114 | false for function global goto if |
1114 | local nil not or repeat return | 1115 | in local nil not or repeat |
1115 | then true until while | 1116 | return then true until while |
1116 | } | 1117 | } |
1117 | 1118 | ||
1118 | Lua is a case-sensitive language: | 1119 | Lua 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 | } |
1658 | If present, an initial assignment has the same semantics | 1660 | If present, an initial assignment has the same semantics |
1659 | of a multiple assignment @see{assignment}. | 1661 | of a multiple assignment @see{assignment}. |
@@ -1662,24 +1664,55 @@ Otherwise, all local variables are initialized with @nil. | |||
1662 | Each variable name may be postfixed by an attribute | 1664 | Each 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 | } |
1667 | There are two possible attributes: | 1669 | There 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} |
1670 | that is, a variable that cannot be assigned to | 1672 | that is, a variable that cannot be used as the left-hand side of an |
1671 | after its initialization; | 1673 | assignment, |
1672 | and @id{close}, which declares a to-be-closed variable @see{to-be-closed}. | 1674 | and @id{close}, which declares a to-be-closed variable @see{to-be-closed}. |
1673 | A list of variables can contain at most one to-be-closed variable. | 1675 | A list of variables can contain at most one to-be-closed variable. |
1674 | Only local variables can have the @id{close} attribute. | 1676 | Only local variables can have the @id{close} attribute. |
1675 | 1677 | ||
1678 | Lua offers also a collective declaration for global variables: | ||
1679 | @Produc{ | ||
1680 | @producname{stat}@producbody{@Rw{global} @bnfter{*} @bnfopt{attrib}} | ||
1681 | } | ||
1682 | This special form implicitly declares | ||
1683 | as globals all names not explicitly declared previously. | ||
1684 | In particular, | ||
1685 | @T{global * <const>} implicitly declares | ||
1686 | as read-only globals all names not explicitly declared previously; | ||
1687 | see the following example: | ||
1688 | @verbatim{ | ||
1689 | global X | ||
1690 | global * <const> | ||
1691 | print(math.pi) -- Ok, 'print' and 'math' are read-only | ||
1692 | X = 1 -- Ok, declared as read-write | ||
1693 | Y = 1 -- Error, Y is read-only | ||
1694 | } | ||
1695 | |||
1696 | As noted in @See{globalenv}, | ||
1697 | all chunks start with an implicit declaration @T{global *}, | ||
1698 | but this preambular declaration becomes void inside | ||
1699 | the scope of any other @Rw{global} declaration. | ||
1700 | Therefore, a program that does not use global declarations | ||
1701 | or start with @T{global *} | ||
1702 | has free read-write access to any global; | ||
1703 | a program that starts with @T{global * <const>} | ||
1704 | has free read-only access to any global; | ||
1705 | and a program that starts with any other global declaration | ||
1706 | (e.g., @T{global none}) can only refer to declared variables. | ||
1707 | |||
1676 | Note that, for global variables, | 1708 | Note that, for global variables, |
1677 | the @emph{read-only} atribute is only a syntactical restriction: | 1709 | the effect of any declaration is only syntactical: |
1678 | @verbatim{ | 1710 | @verbatim{ |
1679 | global X <const> | 1711 | global X <const>, _G |
1680 | X = 1 -- ERROR | 1712 | X = 1 -- ERROR |
1681 | _ENV.X = 1 -- Ok | 1713 | _ENV.X = 1 -- Ok |
1682 | foo() -- 'foo' can freely change the global X | 1714 | _G.print(X) -- Ok |
1715 | foo() -- 'foo' can freely change any global | ||
1683 | } | 1716 | } |
1684 | 1717 | ||
1685 | A chunk is also a block @see{chunks}, | 1718 | A chunk is also a block @see{chunks}, |
@@ -9453,7 +9486,12 @@ change between versions. | |||
9453 | @itemize{ | 9486 | @itemize{ |
9454 | 9487 | ||
9455 | @item{ | 9488 | @item{ |
9456 | The control variable in @Rw{for} loops are read only. | 9489 | The word @Rw{global} is a reserved word. |
9490 | Do not use it as a regular name. | ||
9491 | } | ||
9492 | |||
9493 | @item{ | ||
9494 | The control variable in @Rw{for} loops is read only. | ||
9457 | If you need to change it, | 9495 | If you need to change it, |
9458 | declare a local variable with the same name in the loop body. | 9496 | declare 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 | ||
5 | global * <const> | ||
6 | |||
7 | global _soft, _port, _nomsg | ||
8 | global T | ||
5 | 9 | ||
6 | local version = "Lua 5.5" | 10 | local version = "Lua 5.5" |
7 | if _VERSION ~= version then | 11 | if _VERSION ~= version then |
@@ -34,7 +38,7 @@ if usertests then | |||
34 | end | 38 | end |
35 | 39 | ||
36 | -- tests should require debug when needed | 40 | -- tests should require debug when needed |
37 | debug = nil | 41 | global debug; debug = nil |
38 | 42 | ||
39 | 43 | ||
40 | if usertests then | 44 | if usertests then |
@@ -71,7 +75,7 @@ do -- ( | |||
71 | 75 | ||
72 | -- track messages for tests not performed | 76 | -- track messages for tests not performed |
73 | local msgs = {} | 77 | local msgs = {} |
74 | function Message (m) | 78 | global 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 | ||
4 | global * <const> | ||
5 | |||
4 | print("testing functions and calls") | 6 | print("testing functions and calls") |
5 | 7 | ||
6 | local debug = require "debug" | 8 | local 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 |
25 | fact = false | 27 | global fact; fact = false |
26 | do | 28 | do |
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 | ||
64 | print('+') | 66 | print('+') |
65 | 67 | ||
66 | t = nil -- 'declare' t | 68 | global t; t = nil -- 'declare' t |
67 | function f(a,b,c) local d = 'a'; t={a,b,c,d} end | 69 | function f(a,b,c) local d = 'a'; t={a,b,c,d} end |
68 | 70 | ||
69 | f( -- this line change must be valid | 71 | 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') | |||
75 | 77 | ||
76 | t = nil -- delete 't' | 78 | t = nil -- delete 't' |
77 | 79 | ||
78 | function fat(x) | 80 | global 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 | ||
110 | function deep (n) | 112 | global function deep (n) |
111 | if n>0 then deep(n-1) end | 113 | if n>0 then deep(n-1) end |
112 | end | 114 | end |
113 | deep(10) | 115 | deep(10) |
@@ -352,7 +354,7 @@ assert(not load(function () return true end)) | |||
352 | 354 | ||
353 | -- small bug | 355 | -- small bug |
354 | local t = {nil, "return ", "3"} | 356 | local t = {nil, "return ", "3"} |
355 | f, msg = load(function () return table.remove(t, 1) end) | 357 | local f, msg = load(function () return table.remove(t, 1) end) |
356 | assert(f() == nil) -- should read the empty chunk | 358 | assert(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 |
391 | local x; XX = 123 | 393 | global XX; local x |
394 | XX = 123 | ||
392 | local function h () | 395 | local 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 | ||
4 | global * <const> | ||
5 | |||
4 | print "testing closures" | 6 | print "testing closures" |
5 | 7 | ||
6 | do -- bug in 5.4.7 | 8 | do -- 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 | ||
4 | global * <const> | ||
5 | |||
4 | if T==nil then | 6 | if 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 | |||
405 | end | 407 | end |
406 | 408 | ||
407 | -- de morgan | 409 | -- de morgan |
408 | checkequal(function () local a; if not (a or b) then b=a end end, | 410 | checkequal(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 | ||
411 | checkequal(function (l) local a; return 0 <= a and a <= l end, | 413 | checkequal(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 | ||
4 | global * <const> | ||
5 | |||
4 | local debug = require "debug" | 6 | local debug = require "debug" |
5 | 7 | ||
6 | local maxint = math.maxinteger | 8 | local maxint = math.maxinteger |
@@ -838,13 +840,13 @@ assert(os.date("!\0\0") == "\0\0") | |||
838 | local x = string.rep("a", 10000) | 840 | local x = string.rep("a", 10000) |
839 | assert(os.date(x) == x) | 841 | assert(os.date(x) == x) |
840 | local t = os.time() | 842 | local t = os.time() |
841 | D = os.date("*t", t) | 843 | global D; D = os.date("*t", t) |
842 | assert(os.date(string.rep("%d", 1000), t) == | 844 | assert(os.date(string.rep("%d", 1000), t) == |
843 | string.rep(os.date("%d", t), 1000)) | 845 | string.rep(os.date("%d", t), 1000)) |
844 | assert(os.date(string.rep("%", 200)) == string.rep("%", 100)) | 846 | assert(os.date(string.rep("%", 200)) == string.rep("%", 100)) |
845 | 847 | ||
846 | local function checkDateTable (t) | 848 | local 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 | ||
4 | global require | ||
5 | global print, load, assert, string, setmetatable | ||
6 | global collectgarbage, error | ||
7 | |||
4 | print("testing goto and global declarations") | 8 | print("testing goto and global declarations") |
5 | 9 | ||
6 | collectgarbage() | 10 | collectgarbage() |
@@ -254,6 +258,8 @@ assert(testG(5) == 10) | |||
254 | 258 | ||
255 | do -- test goto's around to-be-closed variable | 259 | do -- 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 |
280 | end | 286 | end |
@@ -285,8 +291,7 @@ foo() | |||
285 | -------------------------------------------------------------------------- | 291 | -------------------------------------------------------------------------- |
286 | 292 | ||
287 | do | 293 | do |
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 | ||
353 | end | 365 | end |
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 | ||
4 | print('testing scanner') | 4 | print('testing scanner') |
5 | 5 | ||
6 | global * <const> | ||
7 | |||
6 | local debug = require "debug" | 8 | local 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 | ||
4 | global * <const> | ||
5 | |||
4 | print('testing local variables and environments') | 6 | print('testing local variables and environments') |
5 | 7 | ||
6 | local debug = require"debug" | 8 | local debug = require"debug" |
@@ -39,9 +41,11 @@ f = nil | |||
39 | local f | 41 | local f |
40 | local x = 1 | 42 | local x = 1 |
41 | 43 | ||
42 | a = nil | 44 | do |
43 | load('local a = {}')() | 45 | global a; a = nil |
44 | assert(a == nil) | 46 | load('local a = {}')() |
47 | assert(a == nil) | ||
48 | end | ||
45 | 49 | ||
46 | function f (a) | 50 | function 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) -- { | |||
154 | do local _ENV = {assert=assert}; assert(true) end | 158 | do local _ENV = {assert=assert}; assert(true) end |
155 | local mt = {_G = _G} | 159 | local mt = {_G = _G} |
156 | local foo,x | 160 | local foo,x |
157 | A = false -- "declare" A | 161 | global A; A = false -- "declare" A |
158 | do local _ENV = mt | 162 | do 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 | ||
4 | global * <const> | ||
5 | |||
4 | print('testing tables, next, and for') | 6 | print('testing tables, next, and for') |
5 | 7 | ||
6 | local function checkerror (msg, f, ...) | 8 | local function checkerror (msg, f, ...) |
@@ -345,9 +347,6 @@ end | |||
345 | 347 | ||
346 | local nofind = {} | 348 | local nofind = {} |
347 | 349 | ||
348 | a,b,c = 1,2,3 | ||
349 | a,b,c = nil | ||
350 | |||
351 | 350 | ||
352 | -- next uses always the same iteration function | 351 | -- next uses always the same iteration function |
353 | assert(next{} == next{}) | 352 | assert(next{} == next{}) |
@@ -396,7 +395,7 @@ for i=0,10000 do | |||
396 | end | 395 | end |
397 | end | 396 | end |
398 | 397 | ||
399 | n = {n=0} | 398 | local n = {n=0} |
400 | for i,v in pairs(a) do | 399 | for 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 | ||
7 | print('testing pattern matching') | 7 | print('testing pattern matching') |
8 | 8 | ||
9 | global * <const> | ||
10 | |||
9 | local function checkerror (msg, f, ...) | 11 | local 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 | ||
6 | global * <const> | ||
6 | 7 | ||
7 | print('testing strings and string library') | 8 | print('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 | ||
6 | global * <const> | ||
7 | |||
6 | print "testing UTF-8 library" | 8 | print "testing UTF-8 library" |
7 | 9 | ||
8 | local utf8 = require'utf8' | 10 | local utf8 = require'utf8' |