Collective declaration for globals ('global *') · lua/lua@3b9dd52 · GitHub
Skip to content

Commit 3b9dd52

Browse files
committed
Collective declaration for globals ('global *')
1 parent 7dc6aae commit 3b9dd52

14 files changed

Lines changed: 155 additions & 63 deletions

File tree

‎lparser.c‎

Lines changed: 36 additions & 19 deletions

‎manual/manual.of‎

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -223,14 +223,15 @@ a function's formal parameter is equivalent to a local variable.)
223223

224224
All chunks start with an implicit declaration @T{global *},
225225
which declares all free names as global variables;
226-
this implicit declaration becomes void inside the scope of any other
227-
@Rw{global} declaration, regardless of the names being declared.
226+
this preambular declaration becomes void inside the scope of any other
227+
@Rw{global} declaration,
228+
as the following example illustrates:
228229
@verbatim{
229230
X = 1 -- Ok, global by default
230231
do
231232
global Y -- voids implicit initial declaration
232-
X = 1 -- ERROR, X not declared
233233
Y = 1 -- Ok, Y declared as global
234+
X = 1 -- ERROR, X not declared
234235
end
235236
X = 2 -- Ok, global by default again
236237
}
@@ -1110,9 +1111,9 @@ and cannot be used as names:
11101111
@index{reserved words}
11111112
@verbatim{
11121113
and break do else elseif end
1113-
false for function goto if in
1114-
local nil not or repeat return
1115-
then true until while
1114+
false for function global goto if
1115+
in local nil not or repeat
1116+
return then true until while
11161117
}
11171118

11181119
Lua is a case-sensitive language:
@@ -1653,7 +1654,8 @@ The declaration for locals can include an initialization:
16531654
@producname{stat}@producbody{@Rw{local} attnamelist @bnfopt{@bnfter{=} explist}}
16541655
@producname{stat}@producbody{@Rw{global} attnamelist}
16551656
@producname{attnamelist}@producbody{
1656-
@bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}}
1657+
@bnfNter{Name} @bnfopt{attrib}
1658+
@bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}}
16571659
}
16581660
If present, an initial assignment has the same semantics
16591661
of a multiple assignment @see{assignment}.
@@ -1662,24 +1664,55 @@ Otherwise, all local variables are initialized with @nil.
16621664
Each variable name may be postfixed by an attribute
16631665
(a name between angle brackets):
16641666
@Produc{
1665-
@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}}
1667+
@producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}}
16661668
}
16671669
There are two possible attributes:
16681670
@id{const}, which declares a @emph{constant} or @emph{read-only} variable,
16691671
@index{constant variable}
1670-
that is, a variable that cannot be assigned to
1671-
after its initialization;
1672+
that is, a variable that cannot be used as the left-hand side of an
1673+
assignment,
16721674
and @id{close}, which declares a to-be-closed variable @see{to-be-closed}.
16731675
A list of variables can contain at most one to-be-closed variable.
16741676
Only local variables can have the @id{close} attribute.
16751677

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+
16761708
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:
16781710
@verbatim{
1679-
global X <const>
1680-
X = 1 -- ERROR
1681-
_ENV.X = 1 -- Ok
1682-
foo() -- 'foo' can freely change the global X
1711+
global X <const>, _G
1712+
X = 1 -- ERROR
1713+
_ENV.X = 1 -- Ok
1714+
_G.print(X) -- Ok
1715+
foo() -- 'foo' can freely change any global
16831716
}
16841717

16851718
A chunk is also a block @see{chunks},
@@ -9453,7 +9486,12 @@ change between versions.
94539486
@itemize{
94549487

94559488
@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.
94579495
If you need to change it,
94589496
declare a local variable with the same name in the loop body.
94599497
}
@@ -9582,12 +9620,14 @@ and @bnfNter{LiteralString}, see @See{lexical}.)
95829620
@OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody
95839621
@OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist}
95849622
@OrNL @Rw{global} attnamelist
9623+
@OrNL @Rw{global} @bnfter{*} @bnfopt{attrib}
95859624
}
95869625

95879626
@producname{attnamelist}@producbody{
9588-
@bnfNter{Name} attrib @bnfrep{@bnfter{,} @bnfNter{Name} attrib}}
9627+
@bnfNter{Name} @bnfopt{attrib}
9628+
@bnfrep{@bnfter{,} @bnfNter{Name} @bnfopt{attrib}}}
95899629

9590-
@producname{attrib}@producbody{@bnfopt{@bnfter{<} @bnfNter{Name} @bnfter{>}}}
9630+
@producname{attrib}@producbody{@bnfter{<} @bnfNter{Name} @bnfter{>}}
95919631

95929632
@producname{retstat}@producbody{@Rw{return}
95939633
@bnfopt{explist} @bnfopt{@bnfter{;}}}

‎testes/all.lua‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
-- $Id: testes/all.lua $
33
-- See Copyright Notice in file lua.h
44

5+
global * <const>
6+
7+
global _soft, _port, _nomsg
8+
global T
59

610
local version = "Lua 5.5"
711
if _VERSION ~= version then
@@ -34,7 +38,7 @@ if usertests then
3438
end
3539

3640
-- tests should require debug when needed
37-
debug = nil
41+
global debug; debug = nil
3842

3943

4044
if usertests then
@@ -71,7 +75,7 @@ do -- (
7175

7276
-- track messages for tests not performed
7377
local msgs = {}
74-
function Message (m)
78+
global function Message (m)
7579
if not _nomsg then
7680
print(m)
7781
msgs[#msgs+1] = string.sub(m, 3, -3)

‎testes/calls.lua‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
-- $Id: testes/calls.lua $
22
-- See Copyright Notice in file lua.h
33

4+
global * <const>
5+
46
print("testing functions and calls")
57

68
local debug = require "debug"
@@ -22,7 +24,7 @@ assert(not pcall(type))
2224

2325

2426
-- testing local-function recursion
25-
fact = false
27+
global fact; fact = false
2628
do
2729
local res = 1
2830
local function fact (n)
@@ -63,7 +65,7 @@ a.b.c:f2('k', 12); assert(a.b.c.k == 12)
6365

6466
print('+')
6567

66-
t = nil -- 'declare' t
68+
global t; t = nil -- 'declare' t
6769
function f(a,b,c) local d = 'a'; t={a,b,c,d} end
6870

6971
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')
7577

7678
t = nil -- delete 't'
7779

78-
function fat(x)
80+
global function fat(x)
7981
if x <= 1 then return 1
8082
else return x*load("return fat(" .. x-1 .. ")", "")()
8183
end
@@ -107,7 +109,7 @@ end
107109

108110
_G.deep = nil -- "declaration" (used by 'all.lua')
109111

110-
function deep (n)
112+
global function deep (n)
111113
if n>0 then deep(n-1) end
112114
end
113115
deep(10)
@@ -352,7 +354,7 @@ assert(not load(function () return true end))
352354

353355
-- small bug
354356
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)
356358
assert(f() == nil) -- should read the empty chunk
357359

358360
-- another small bug (in 5.2.1)
@@ -388,7 +390,8 @@ assert(load("return _ENV", nil, nil, 123)() == 123)
388390

389391

390392
-- load when _ENV is not first upvalue
391-
local x; XX = 123
393+
global XX; local x
394+
XX = 123
392395
local function h ()
393396
local y=x -- use 'x', so that it becomes 1st upvalue
394397
return XX -- global name

‎testes/closure.lua‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
-- $Id: testes/closure.lua $
22
-- See Copyright Notice in file lua.h
33

4+
global * <const>
5+
46
print "testing closures"
57

68
do -- bug in 5.4.7

‎testes/code.lua‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
-- $Id: testes/code.lua $
22
-- See Copyright Notice in file lua.h
33

4+
global * <const>
5+
46
if T==nil then
57
(Message or print)('\n >>> testC not active: skipping opcode tests <<<\n')
68
return
@@ -405,8 +407,8 @@ do -- tests for table access in upvalues
405407
end
406408

407409
-- de morgan
408-
checkequal(function () local a; 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)
410+
checkequal(function () local a, b; if not (a or b) then b=a end end,
411+
function () local a, b; if (not a and not b) then b=a end end)
410412

411413
checkequal(function (l) local a; return 0 <= a and a <= l end,
412414
function (l) local a; return not (not(a >= 0) or not(a <= l)) end)

‎testes/files.lua‎

Lines changed: 4 additions & 2 deletions

0 commit comments

Comments
 (0)