diff options
| -rw-r--r-- | lparser.c | 49 | ||||
| -rw-r--r-- | manual/manual.of | 15 | ||||
| -rw-r--r-- | testes/errors.lua | 8 | ||||
| -rw-r--r-- | testes/goto.lua | 23 |
4 files changed, 82 insertions, 13 deletions
| @@ -477,8 +477,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | |||
| 477 | ** Find a variable with the given name 'n', handling global variables | 477 | ** Find a variable with the given name 'n', handling global variables |
| 478 | ** too. | 478 | ** too. |
| 479 | */ | 479 | */ |
| 480 | static void singlevar (LexState *ls, expdesc *var) { | 480 | static void buildvar (LexState *ls, TString *varname, expdesc *var) { |
| 481 | TString *varname = str_checkname(ls); | ||
| 482 | FuncState *fs = ls->fs; | 481 | FuncState *fs = ls->fs; |
| 483 | singlevaraux(fs, varname, var, 1); | 482 | singlevaraux(fs, varname, var, 1); |
| 484 | if (var->k == VGLOBAL) { /* global name? */ | 483 | if (var->k == VGLOBAL) { /* global name? */ |
| @@ -501,6 +500,11 @@ static void singlevar (LexState *ls, expdesc *var) { | |||
| 501 | } | 500 | } |
| 502 | 501 | ||
| 503 | 502 | ||
| 503 | static void singlevar (LexState *ls, expdesc *var) { | ||
| 504 | buildvar(ls, str_checkname(ls), var); | ||
| 505 | } | ||
| 506 | |||
| 507 | |||
| 504 | /* | 508 | /* |
| 505 | ** Adjust the number of results from an expression list 'e' with 'nexps' | 509 | ** Adjust the number of results from an expression list 'e' with 'nexps' |
| 506 | ** expressions to 'nvars' values. | 510 | ** expressions to 'nvars' values. |
| @@ -1727,7 +1731,7 @@ static void localfunc (LexState *ls) { | |||
| 1727 | 1731 | ||
| 1728 | 1732 | ||
| 1729 | static lu_byte getvarattribute (LexState *ls) { | 1733 | static lu_byte getvarattribute (LexState *ls) { |
| 1730 | /* ATTRIB -> ['<' Name '>'] */ | 1734 | /* attrib -> ['<' NAME '>'] */ |
| 1731 | if (testnext(ls, '<')) { | 1735 | if (testnext(ls, '<')) { |
| 1732 | TString *ts = str_checkname(ls); | 1736 | TString *ts = str_checkname(ls); |
| 1733 | const char *attr = getstr(ts); | 1737 | const char *attr = getstr(ts); |
| @@ -1752,7 +1756,7 @@ static void checktoclose (FuncState *fs, int level) { | |||
| 1752 | 1756 | ||
| 1753 | 1757 | ||
| 1754 | static void localstat (LexState *ls) { | 1758 | static void localstat (LexState *ls) { |
| 1755 | /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ | 1759 | /* stat -> LOCAL NAME attrib { ',' NAME attrib } ['=' explist] */ |
| 1756 | FuncState *fs = ls->fs; | 1760 | FuncState *fs = ls->fs; |
| 1757 | int toclose = -1; /* index of to-be-closed variable (if any) */ | 1761 | int toclose = -1; /* index of to-be-closed variable (if any) */ |
| 1758 | Vardesc *var; /* last variable */ | 1762 | Vardesc *var; /* last variable */ |
| @@ -1794,8 +1798,8 @@ static void localstat (LexState *ls) { | |||
| 1794 | 1798 | ||
| 1795 | 1799 | ||
| 1796 | static void globalstat (LexState *ls) { | 1800 | static void globalstat (LexState *ls) { |
| 1801 | /* globalstat -> (GLOBAL) NAME attrib {',' NAME attrib} */ | ||
| 1797 | FuncState *fs = ls->fs; | 1802 | FuncState *fs = ls->fs; |
| 1798 | luaX_next(ls); /* skip 'global' */ | ||
| 1799 | do { | 1803 | do { |
| 1800 | TString *vname = str_checkname(ls); | 1804 | TString *vname = str_checkname(ls); |
| 1801 | lu_byte kind = getvarattribute(ls); | 1805 | lu_byte kind = getvarattribute(ls); |
| @@ -1807,7 +1811,31 @@ static void globalstat (LexState *ls) { | |||
| 1807 | new_varkind(ls, vname, kind); | 1811 | new_varkind(ls, vname, kind); |
| 1808 | fs->nactvar++; /* activate declaration */ | 1812 | fs->nactvar++; /* activate declaration */ |
| 1809 | } while (testnext(ls, ',')); | 1813 | } while (testnext(ls, ',')); |
| 1810 | fs->bl->globdec = 1; /* code is in the scope of a global declaration */ | 1814 | } |
| 1815 | |||
| 1816 | |||
| 1817 | static void globalfunc (LexState *ls, int line) { | ||
| 1818 | /* globalfunc -> (GLOBAL FUNCTION) NAME body */ | ||
| 1819 | expdesc var, b; | ||
| 1820 | FuncState *fs = ls->fs; | ||
| 1821 | TString *fname = str_checkname(ls); | ||
| 1822 | new_varkind(ls, fname, GDKREG); /* declare global variable */ | ||
| 1823 | fs->nactvar++; /* enter its scope */ | ||
| 1824 | buildvar(ls, fname, &var); | ||
| 1825 | body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */ | ||
| 1826 | luaK_storevar(fs, &var, &b); | ||
| 1827 | luaK_fixline(fs, line); /* definition "happens" in the first line */ | ||
| 1828 | } | ||
| 1829 | |||
| 1830 | |||
| 1831 | static void globalstatfunc (LexState *ls, int line) { | ||
| 1832 | /* stat -> GLOBAL globalfunc | GLOBAL globalstat */ | ||
| 1833 | luaX_next(ls); /* skip 'global' */ | ||
| 1834 | ls->fs->bl->globdec = 1; /* in the scope of a global declaration */ | ||
| 1835 | if (testnext(ls, TK_FUNCTION)) | ||
| 1836 | globalfunc(ls, line); | ||
| 1837 | else | ||
| 1838 | globalstat(ls); | ||
| 1811 | } | 1839 | } |
| 1812 | 1840 | ||
| 1813 | 1841 | ||
| @@ -1930,8 +1958,8 @@ static void statement (LexState *ls) { | |||
| 1930 | localstat(ls); | 1958 | localstat(ls); |
| 1931 | break; | 1959 | break; |
| 1932 | } | 1960 | } |
| 1933 | case TK_GLOBAL: { /* stat -> globalstat */ | 1961 | case TK_GLOBAL: { /* stat -> globalstatfunc */ |
| 1934 | globalstat(ls); | 1962 | globalstatfunc(ls, line); |
| 1935 | break; | 1963 | break; |
| 1936 | } | 1964 | } |
| 1937 | case TK_DBCOLON: { /* stat -> label */ | 1965 | case TK_DBCOLON: { /* stat -> label */ |
| @@ -1958,8 +1986,9 @@ static void statement (LexState *ls) { | |||
| 1958 | is not reserved */ | 1986 | is not reserved */ |
| 1959 | if (eqstr(ls->t.seminfo.ts, luaS_newliteral(ls->L, "global"))) { | 1987 | if (eqstr(ls->t.seminfo.ts, luaS_newliteral(ls->L, "global"))) { |
| 1960 | int lk = luaX_lookahead(ls); | 1988 | int lk = luaX_lookahead(ls); |
| 1961 | if (lk == TK_NAME) { /* 'global name'? */ | 1989 | if (lk == TK_NAME || lk == TK_FUNCTION) { |
| 1962 | globalstat(ls); | 1990 | /* 'global <name>' or 'global function' */ |
| 1991 | globalstatfunc(ls, line); | ||
| 1963 | break; | 1992 | break; |
| 1964 | } | 1993 | } |
| 1965 | } /* else... */ | 1994 | } /* else... */ |
diff --git a/manual/manual.of b/manual/manual.of index ace5d375..cc71aaad 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -2229,6 +2229,7 @@ The following syntactic sugar simplifies function definitions: | |||
| 2229 | @Produc{ | 2229 | @Produc{ |
| 2230 | @producname{stat}@producbody{@Rw{function} funcname funcbody} | 2230 | @producname{stat}@producbody{@Rw{function} funcname funcbody} |
| 2231 | @producname{stat}@producbody{@Rw{local} @Rw{function} @bnfNter{Name} funcbody} | 2231 | @producname{stat}@producbody{@Rw{local} @Rw{function} @bnfNter{Name} funcbody} |
| 2232 | @producname{stat}@producbody{@Rw{global} @Rw{function} @bnfNter{Name} funcbody} | ||
| 2232 | @producname{funcname}@producbody{@bnfNter{Name} @bnfrep{@bnfter{.} @bnfNter{Name}} @bnfopt{@bnfter{:} @bnfNter{Name}}} | 2233 | @producname{funcname}@producbody{@bnfNter{Name} @bnfrep{@bnfter{.} @bnfNter{Name}} @bnfopt{@bnfter{:} @bnfNter{Name}}} |
| 2233 | } | 2234 | } |
| 2234 | The statement | 2235 | The statement |
| @@ -2247,6 +2248,7 @@ translates to | |||
| 2247 | @verbatim{ | 2248 | @verbatim{ |
| 2248 | t.a.b.c.f = function () @rep{body} end | 2249 | t.a.b.c.f = function () @rep{body} end |
| 2249 | } | 2250 | } |
| 2251 | |||
| 2250 | The statement | 2252 | The statement |
| 2251 | @verbatim{ | 2253 | @verbatim{ |
| 2252 | local function f () @rep{body} end | 2254 | local function f () @rep{body} end |
| @@ -2260,7 +2262,15 @@ not to | |||
| 2260 | local f = function () @rep{body} end | 2262 | local f = function () @rep{body} end |
| 2261 | } | 2263 | } |
| 2262 | (This only makes a difference when the body of the function | 2264 | (This only makes a difference when the body of the function |
| 2263 | contains references to @id{f}.) | 2265 | contains recursive references to @id{f}.) |
| 2266 | Similarly, the statement | ||
| 2267 | @verbatim{ | ||
| 2268 | global function f () @rep{body} end | ||
| 2269 | } | ||
| 2270 | translates to | ||
| 2271 | @verbatim{ | ||
| 2272 | global f; f = function () @rep{body} end | ||
| 2273 | } | ||
| 2264 | 2274 | ||
| 2265 | A function definition is an executable expression, | 2275 | A function definition is an executable expression, |
| 2266 | whose value has type @emph{function}. | 2276 | whose value has type @emph{function}. |
| @@ -2323,7 +2333,7 @@ then the function returns with no results. | |||
| 2323 | @index{multiple return} | 2333 | @index{multiple return} |
| 2324 | There is a system-dependent limit on the number of values | 2334 | There is a system-dependent limit on the number of values |
| 2325 | that a function may return. | 2335 | that a function may return. |
| 2326 | This limit is guaranteed to be greater than 1000. | 2336 | This limit is guaranteed to be at least 1000. |
| 2327 | 2337 | ||
| 2328 | The @emphx{colon} syntax | 2338 | The @emphx{colon} syntax |
| 2329 | is used to emulate @def{methods}, | 2339 | is used to emulate @def{methods}, |
| @@ -9569,6 +9579,7 @@ and @bnfNter{LiteralString}, see @See{lexical}.) | |||
| 9569 | @OrNL @Rw{for} namelist @Rw{in} explist @Rw{do} block @Rw{end} | 9579 | @OrNL @Rw{for} namelist @Rw{in} explist @Rw{do} block @Rw{end} |
| 9570 | @OrNL @Rw{function} funcname funcbody | 9580 | @OrNL @Rw{function} funcname funcbody |
| 9571 | @OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody | 9581 | @OrNL @Rw{local} @Rw{function} @bnfNter{Name} funcbody |
| 9582 | @OrNL @Rw{global} @Rw{function} @bnfNter{Name} funcbody | ||
| 9572 | @OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist} | 9583 | @OrNL @Rw{local} attnamelist @bnfopt{@bnfter{=} explist} |
| 9573 | @OrNL @Rw{global} attnamelist | 9584 | @OrNL @Rw{global} attnamelist |
| 9574 | } | 9585 | } |
diff --git a/testes/errors.lua b/testes/errors.lua index c80051fc..6c76a99a 100644 --- a/testes/errors.lua +++ b/testes/errors.lua | |||
| @@ -489,6 +489,14 @@ if not b then | |||
| 489 | end | 489 | end |
| 490 | end]], 5) | 490 | end]], 5) |
| 491 | 491 | ||
| 492 | lineerror([[ | ||
| 493 | _ENV = 1 | ||
| 494 | global function foo () | ||
| 495 | local a = 10 | ||
| 496 | return a | ||
| 497 | end | ||
| 498 | ]], 2) | ||
| 499 | |||
| 492 | 500 | ||
| 493 | -- bug in 5.4.0 | 501 | -- bug in 5.4.0 |
| 494 | lineerror([[ | 502 | lineerror([[ |
diff --git a/testes/goto.lua b/testes/goto.lua index fdfddb85..b41399ff 100644 --- a/testes/goto.lua +++ b/testes/goto.lua | |||
| @@ -293,8 +293,9 @@ do | |||
| 293 | assert(not st and string.find(msg, err)) | 293 | assert(not st and string.find(msg, err)) |
| 294 | end | 294 | end |
| 295 | 295 | ||
| 296 | -- globals must be declared after a global declaration | 296 | -- globals must be declared, after a global declaration |
| 297 | checkerr("global none; X = 1", "variable 'X'") | 297 | checkerr("global none; X = 1", "variable 'X'") |
| 298 | checkerr("global none; function XX() end", "variable 'XX'") | ||
| 298 | 299 | ||
| 299 | -- global variables cannot be to-be-closed | 300 | -- global variables cannot be to-be-closed |
| 300 | checkerr("global X<close>", "cannot be") | 301 | checkerr("global X<close>", "cannot be") |
| @@ -321,6 +322,26 @@ do | |||
| 321 | -- "global" reserved, cannot be used as a variable | 322 | -- "global" reserved, cannot be used as a variable |
| 322 | assert(not load("global = 1; return global")) | 323 | assert(not load("global = 1; return global")) |
| 323 | end | 324 | end |
| 325 | |||
| 326 | local foo = 20 | ||
| 327 | do | ||
| 328 | global function foo (x) | ||
| 329 | if x == 0 then return 1 else return 2 * foo(x - 1) end | ||
| 330 | end | ||
| 331 | assert(foo == _ENV.foo and foo(4) == 16) | ||
| 332 | end | ||
| 333 | assert(_ENV.foo(4) == 16) | ||
| 334 | assert(foo == 20) -- local one is in context here | ||
| 335 | |||
| 336 | do | ||
| 337 | global foo; | ||
| 338 | function foo (x) return end -- Ok after declaration | ||
| 339 | end | ||
| 340 | |||
| 341 | checkerr([[ | ||
| 342 | global foo <const>; | ||
| 343 | function foo (x) return end -- ERROR: foo is read-only | ||
| 344 | ]], "assign to const variable 'foo'") | ||
| 324 | 345 | ||
| 325 | end | 346 | end |
| 326 | 347 | ||
