diff options
| -rw-r--r-- | lparser.c | 81 | ||||
| -rw-r--r-- | manual/manual.of | 18 | ||||
| -rw-r--r-- | testes/bwcoercion.lua | 2 | ||||
| -rw-r--r-- | testes/calls.lua | 4 | ||||
| -rw-r--r-- | testes/files.lua | 4 | ||||
| -rw-r--r-- | testes/goto.lua | 23 | ||||
| -rw-r--r-- | testes/tracegc.lua | 2 |
7 files changed, 96 insertions, 38 deletions
| @@ -30,7 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | /* maximum number of variable declarationss per function (must be | 33 | /* maximum number of variable declarations per function (must be |
| 34 | smaller than 250, due to the bytecode format) */ | 34 | smaller than 250, due to the bytecode format) */ |
| 35 | #define MAXVARS 200 | 35 | #define MAXVARS 200 |
| 36 | 36 | ||
| @@ -197,7 +197,7 @@ static int new_varkind (LexState *ls, TString *name, lu_byte kind) { | |||
| 197 | Dyndata *dyd = ls->dyd; | 197 | Dyndata *dyd = ls->dyd; |
| 198 | Vardesc *var; | 198 | Vardesc *var; |
| 199 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, | 199 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, |
| 200 | dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarationss"); | 200 | dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarations"); |
| 201 | var = &dyd->actvar.arr[dyd->actvar.n++]; | 201 | var = &dyd->actvar.arr[dyd->actvar.n++]; |
| 202 | var->vd.kind = kind; /* default */ | 202 | var->vd.kind = kind; /* default */ |
| 203 | var->vd.name = name; | 203 | var->vd.name = name; |
| @@ -485,6 +485,20 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | |||
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | 487 | ||
| 488 | static void buildglobal (LexState *ls, TString *varname, expdesc *var) { | ||
| 489 | FuncState *fs = ls->fs; | ||
| 490 | expdesc key; | ||
| 491 | init_exp(var, VGLOBAL, -1); /* global by default */ | ||
| 492 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | ||
| 493 | if (var->k == VGLOBAL) | ||
| 494 | luaK_semerror(ls, "_ENV is global when accessing variable '%s'", | ||
| 495 | getstr(varname)); | ||
| 496 | luaK_exp2anyregup(fs, var); /* _ENV could be a constant */ | ||
| 497 | codestring(&key, varname); /* key is variable name */ | ||
| 498 | luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */ | ||
| 499 | } | ||
| 500 | |||
| 501 | |||
| 488 | /* | 502 | /* |
| 489 | ** Find a variable with the given name 'n', handling global variables | 503 | ** Find a variable with the given name 'n', handling global variables |
| 490 | ** too. | 504 | ** too. |
| @@ -494,18 +508,11 @@ static void buildvar (LexState *ls, TString *varname, expdesc *var) { | |||
| 494 | init_exp(var, VGLOBAL, -1); /* global by default */ | 508 | init_exp(var, VGLOBAL, -1); /* global by default */ |
| 495 | singlevaraux(fs, varname, var, 1); | 509 | singlevaraux(fs, varname, var, 1); |
| 496 | if (var->k == VGLOBAL) { /* global name? */ | 510 | if (var->k == VGLOBAL) { /* global name? */ |
| 497 | expdesc key; | ||
| 498 | int info = var->u.info; | 511 | int info = var->u.info; |
| 499 | /* global by default in the scope of a global declaration? */ | 512 | /* global by default in the scope of a global declaration? */ |
| 500 | if (info == -2) | 513 | if (info == -2) |
| 501 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); | 514 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); |
| 502 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | 515 | buildglobal(ls, varname, var); |
| 503 | if (var->k == VGLOBAL) | ||
| 504 | luaK_semerror(ls, "_ENV is global when accessing variable '%s'", | ||
| 505 | getstr(varname)); | ||
| 506 | luaK_exp2anyregup(fs, var); /* but could be a constant */ | ||
| 507 | codestring(&key, varname); /* key is variable name */ | ||
| 508 | luaK_indexed(fs, var, &key); /* env[varname] */ | ||
| 509 | if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST) | 516 | if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST) |
| 510 | var->u.ind.ro = 1; /* mark variable as read-only */ | 517 | var->u.ind.ro = 1; /* mark variable as read-only */ |
| 511 | else /* anyway must be a global */ | 518 | else /* anyway must be a global */ |
| @@ -665,7 +672,7 @@ static void createlabel (LexState *ls, TString *name, int line, int last) { | |||
| 665 | 672 | ||
| 666 | 673 | ||
| 667 | /* | 674 | /* |
| 668 | ** Traverse the pending goto's of the finishing block checking whether | 675 | ** Traverse the pending gotos of the finishing block checking whether |
| 669 | ** each match some label of that block. Those that do not match are | 676 | ** each match some label of that block. Those that do not match are |
| 670 | ** "exported" to the outer block, to be solved there. In particular, | 677 | ** "exported" to the outer block, to be solved there. In particular, |
| 671 | ** its 'nactvar' is updated with the level of the inner block, | 678 | ** its 'nactvar' is updated with the level of the inner block, |
| @@ -1435,6 +1442,15 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
| 1435 | } | 1442 | } |
| 1436 | } | 1443 | } |
| 1437 | 1444 | ||
| 1445 | |||
| 1446 | /* Create code to store the "top" register in 'var' */ | ||
| 1447 | static void storevartop (FuncState *fs, expdesc *var) { | ||
| 1448 | expdesc e; | ||
| 1449 | init_exp(&e, VNONRELOC, fs->freereg - 1); | ||
| 1450 | luaK_storevar(fs, var, &e); /* will also free the top register */ | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | |||
| 1438 | /* | 1454 | /* |
| 1439 | ** Parse and compile a multiple assignment. The first "variable" | 1455 | ** Parse and compile a multiple assignment. The first "variable" |
| 1440 | ** (a 'suffixedexp') was already read by the caller. | 1456 | ** (a 'suffixedexp') was already read by the caller. |
| @@ -1468,8 +1484,7 @@ static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) { | |||
| 1468 | return; /* avoid default */ | 1484 | return; /* avoid default */ |
| 1469 | } | 1485 | } |
| 1470 | } | 1486 | } |
| 1471 | init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ | 1487 | storevartop(ls->fs, &lh->v); /* default assignment */ |
| 1472 | luaK_storevar(ls->fs, &lh->v, &e); | ||
| 1473 | } | 1488 | } |
| 1474 | 1489 | ||
| 1475 | 1490 | ||
| @@ -1821,25 +1836,45 @@ static lu_byte getglobalattribute (LexState *ls, lu_byte df) { | |||
| 1821 | } | 1836 | } |
| 1822 | 1837 | ||
| 1823 | 1838 | ||
| 1839 | static void globalnames (LexState *ls, lu_byte defkind) { | ||
| 1840 | FuncState *fs = ls->fs; | ||
| 1841 | int nvars = 0; | ||
| 1842 | int lastidx; /* index of last registered variable */ | ||
| 1843 | do { /* for each name */ | ||
| 1844 | TString *vname = str_checkname(ls); | ||
| 1845 | lu_byte kind = getglobalattribute(ls, defkind); | ||
| 1846 | lastidx = new_varkind(ls, vname, kind); | ||
| 1847 | nvars++; | ||
| 1848 | } while (testnext(ls, ',')); | ||
| 1849 | if (testnext(ls, '=')) { /* initialization? */ | ||
| 1850 | expdesc e; | ||
| 1851 | int i; | ||
| 1852 | int nexps = explist(ls, &e); /* read list of expressions */ | ||
| 1853 | adjust_assign(ls, nvars, nexps, &e); | ||
| 1854 | for (i = 0; i < nvars; i++) { /* for each variable */ | ||
| 1855 | expdesc var; | ||
| 1856 | TString *varname = getlocalvardesc(fs, lastidx - i)->vd.name; | ||
| 1857 | buildglobal(ls, varname, &var); /* create global variable in 'var' */ | ||
| 1858 | storevartop(fs, &var); | ||
| 1859 | } | ||
| 1860 | } | ||
| 1861 | fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */ | ||
| 1862 | } | ||
| 1863 | |||
| 1864 | |||
| 1824 | static void globalstat (LexState *ls) { | 1865 | static void globalstat (LexState *ls) { |
| 1825 | /* globalstat -> (GLOBAL) attrib '*' | 1866 | /* globalstat -> (GLOBAL) attrib '*' |
| 1826 | globalstat -> (GLOBAL) attrib NAME attrib {',' NAME attrib} */ | 1867 | globalstat -> (GLOBAL) attrib NAME attrib {',' NAME attrib} */ |
| 1827 | FuncState *fs = ls->fs; | 1868 | FuncState *fs = ls->fs; |
| 1828 | /* get prefixed attribute (if any); default is regular global variable */ | 1869 | /* get prefixed attribute (if any); default is regular global variable */ |
| 1829 | lu_byte defkind = getglobalattribute(ls, GDKREG); | 1870 | lu_byte defkind = getglobalattribute(ls, GDKREG); |
| 1830 | if (testnext(ls, '*')) { | 1871 | if (!testnext(ls, '*')) |
| 1872 | globalnames(ls, defkind); | ||
| 1873 | else { | ||
| 1831 | /* use NULL as name to represent '*' entries */ | 1874 | /* use NULL as name to represent '*' entries */ |
| 1832 | new_varkind(ls, NULL, defkind); | 1875 | new_varkind(ls, NULL, defkind); |
| 1833 | fs->nactvar++; /* activate declaration */ | 1876 | fs->nactvar++; /* activate declaration */ |
| 1834 | } | 1877 | } |
| 1835 | else { | ||
| 1836 | do { /* list of names */ | ||
| 1837 | TString *vname = str_checkname(ls); | ||
| 1838 | lu_byte kind = getglobalattribute(ls, defkind); | ||
| 1839 | new_varkind(ls, vname, kind); | ||
| 1840 | fs->nactvar++; /* activate declaration */ | ||
| 1841 | } while (testnext(ls, ',')); | ||
| 1842 | } | ||
| 1843 | } | 1878 | } |
| 1844 | 1879 | ||
| 1845 | 1880 | ||
| @@ -1850,7 +1885,7 @@ static void globalfunc (LexState *ls, int line) { | |||
| 1850 | TString *fname = str_checkname(ls); | 1885 | TString *fname = str_checkname(ls); |
| 1851 | new_varkind(ls, fname, GDKREG); /* declare global variable */ | 1886 | new_varkind(ls, fname, GDKREG); /* declare global variable */ |
| 1852 | fs->nactvar++; /* enter its scope */ | 1887 | fs->nactvar++; /* enter its scope */ |
| 1853 | buildvar(ls, fname, &var); | 1888 | buildglobal(ls, fname, &var); |
| 1854 | body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */ | 1889 | body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */ |
| 1855 | luaK_storevar(fs, &var, &b); | 1890 | luaK_storevar(fs, &var, &b); |
| 1856 | luaK_fixline(fs, line); /* definition "happens" in the first line */ | 1891 | luaK_fixline(fs, line); /* definition "happens" in the first line */ |
diff --git a/manual/manual.of b/manual/manual.of index bcc8173b..8f90f942 100644 --- a/manual/manual.of +++ b/manual/manual.of | |||
| @@ -229,7 +229,7 @@ as the following example illustrates: | |||
| 229 | @verbatim{ | 229 | @verbatim{ |
| 230 | X = 1 -- Ok, global by default | 230 | X = 1 -- Ok, global by default |
| 231 | do | 231 | do |
| 232 | global Y -- voids implicit initial declaration | 232 | global Y -- voids the implicit initial declaration |
| 233 | Y = 1 -- Ok, Y declared as global | 233 | Y = 1 -- Ok, Y declared as global |
| 234 | X = 1 -- ERROR, X not declared | 234 | X = 1 -- ERROR, X not declared |
| 235 | end | 235 | end |
| @@ -269,7 +269,7 @@ print(x) --> 10 (the global one) | |||
| 269 | 269 | ||
| 270 | Notice that, in a declaration like @T{local x = x}, | 270 | Notice that, in a declaration like @T{local x = x}, |
| 271 | the new @id{x} being declared is not in scope yet, | 271 | the new @id{x} being declared is not in scope yet, |
| 272 | and so the @id{x} in the left-hand side refers to the outside variable. | 272 | and so the @id{x} in the right-hand side refers to the outside variable. |
| 273 | 273 | ||
| 274 | Because of the @x{lexical scoping} rules, | 274 | Because of the @x{lexical scoping} rules, |
| 275 | local variables can be freely accessed by functions | 275 | local variables can be freely accessed by functions |
| @@ -1651,11 +1651,12 @@ Function calls are explained in @See{functioncall}. | |||
| 1651 | 1651 | ||
| 1652 | @sect3{localvar| @title{Variable Declarations} | 1652 | @sect3{localvar| @title{Variable Declarations} |
| 1653 | Local and global variables can be declared anywhere inside a block. | 1653 | Local and global variables can be declared anywhere inside a block. |
| 1654 | The declaration for locals can include an initialization: | 1654 | The declaration can include an initialization: |
| 1655 | @Produc{ | 1655 | @Produc{ |
| 1656 | @producname{stat}@producbody{@Rw{local} | 1656 | @producname{stat}@producbody{@Rw{local} |
| 1657 | attnamelist @bnfopt{@bnfter{=} explist}} | 1657 | attnamelist @bnfopt{@bnfter{=} explist}} |
| 1658 | @producname{stat}@producbody{@Rw{global} attnamelist} | 1658 | @producname{stat}@producbody{@Rw{global} |
| 1659 | attnamelist @bnfopt{@bnfter{=} explist}} | ||
| 1659 | } | 1660 | } |
| 1660 | If present, an initial assignment has the same semantics | 1661 | If present, an initial assignment has the same semantics |
| 1661 | of a multiple assignment @see{assignment}. | 1662 | of a multiple assignment @see{assignment}. |
| @@ -1712,7 +1713,8 @@ and a program that starts with any other global declaration | |||
| 1712 | (e.g., @T{global none}) can only refer to declared variables. | 1713 | (e.g., @T{global none}) can only refer to declared variables. |
| 1713 | 1714 | ||
| 1714 | Note that, for global variables, | 1715 | Note that, for global variables, |
| 1715 | the effect of any declaration is only syntactical: | 1716 | the effect of any declaration is only syntactical |
| 1717 | (except for the optional assignment): | ||
| 1716 | @verbatim{ | 1718 | @verbatim{ |
| 1717 | global X <const>, _G | 1719 | global X <const>, _G |
| 1718 | X = 1 -- ERROR | 1720 | X = 1 -- ERROR |
| @@ -3924,8 +3926,8 @@ This macro may evaluate its arguments more than once. | |||
| 3924 | 3926 | ||
| 3925 | } | 3927 | } |
| 3926 | 3928 | ||
| 3927 | @APIEntry{unsigned (lua_numbertocstring) (lua_State *L, int idx, | 3929 | @APIEntry{unsigned lua_numbertocstring (lua_State *L, int idx, |
| 3928 | char *buff);| | 3930 | char *buff);| |
| 3929 | @apii{0,0,-} | 3931 | @apii{0,0,-} |
| 3930 | 3932 | ||
| 3931 | Converts the number at acceptable index @id{idx} to a string | 3933 | Converts the number at acceptable index @id{idx} to a string |
| @@ -4050,7 +4052,7 @@ This function is equivalent to @Lid{lua_pushcclosure} with no upvalues. | |||
| 4050 | 4052 | ||
| 4051 | } | 4053 | } |
| 4052 | 4054 | ||
| 4053 | @APIEntry{const char *(lua_pushexternalstring) (lua_State *L, | 4055 | @APIEntry{const char *lua_pushexternalstring (lua_State *L, |
| 4054 | const char *s, size_t len, lua_Alloc falloc, void *ud);| | 4056 | const char *s, size_t len, lua_Alloc falloc, void *ud);| |
| 4055 | @apii{0,1,m} | 4057 | @apii{0,1,m} |
| 4056 | 4058 | ||
diff --git a/testes/bwcoercion.lua b/testes/bwcoercion.lua index cd735ab0..0544944d 100644 --- a/testes/bwcoercion.lua +++ b/testes/bwcoercion.lua | |||
| @@ -4,7 +4,7 @@ local strsub = string.sub | |||
| 4 | 4 | ||
| 5 | local print = print | 5 | local print = print |
| 6 | 6 | ||
| 7 | _ENV = nil | 7 | global none |
| 8 | 8 | ||
| 9 | -- Try to convert a value to an integer, without assuming any coercion. | 9 | -- Try to convert a value to an integer, without assuming any coercion. |
| 10 | local function toint (x) | 10 | local function toint (x) |
diff --git a/testes/calls.lua b/testes/calls.lua index 21441701..0dacb85a 100644 --- a/testes/calls.lua +++ b/testes/calls.lua | |||
| @@ -24,7 +24,7 @@ assert(not pcall(type)) | |||
| 24 | 24 | ||
| 25 | 25 | ||
| 26 | -- testing local-function recursion | 26 | -- testing local-function recursion |
| 27 | global fact; fact = false | 27 | global fact = false |
| 28 | do | 28 | do |
| 29 | local res = 1 | 29 | local res = 1 |
| 30 | local function fact (n) | 30 | local function fact (n) |
| @@ -65,7 +65,7 @@ a.b.c:f2('k', 12); assert(a.b.c.k == 12) | |||
| 65 | 65 | ||
| 66 | print('+') | 66 | print('+') |
| 67 | 67 | ||
| 68 | global t; t = nil -- 'declare' t | 68 | global t = nil -- 'declare' t |
| 69 | 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 |
| 70 | 70 | ||
| 71 | f( -- this line change must be valid | 71 | f( -- this line change must be valid |
diff --git a/testes/files.lua b/testes/files.lua index d4e327b7..7146ac7c 100644 --- a/testes/files.lua +++ b/testes/files.lua | |||
| @@ -715,7 +715,7 @@ do | |||
| 715 | end | 715 | end |
| 716 | 716 | ||
| 717 | 717 | ||
| 718 | if T and T.nonblock then | 718 | if T and T.nonblock and not _port then |
| 719 | print("testing failed write") | 719 | print("testing failed write") |
| 720 | 720 | ||
| 721 | -- unable to write anything to /dev/full | 721 | -- unable to write anything to /dev/full |
| @@ -840,7 +840,7 @@ assert(os.date("!\0\0") == "\0\0") | |||
| 840 | local x = string.rep("a", 10000) | 840 | local x = string.rep("a", 10000) |
| 841 | assert(os.date(x) == x) | 841 | assert(os.date(x) == x) |
| 842 | local t = os.time() | 842 | local t = os.time() |
| 843 | global D; D = os.date("*t", t) | 843 | global D = os.date("*t", t) |
| 844 | assert(os.date(string.rep("%d", 1000), t) == | 844 | assert(os.date(string.rep("%d", 1000), t) == |
| 845 | string.rep(os.date("%d", t), 1000)) | 845 | string.rep(os.date("%d", t), 1000)) |
| 846 | assert(os.date(string.rep("%", 200)) == string.rep("%", 100)) | 846 | assert(os.date(string.rep("%", 200)) == string.rep("%", 100)) |
diff --git a/testes/goto.lua b/testes/goto.lua index 3519e75d..3310314d 100644 --- a/testes/goto.lua +++ b/testes/goto.lua | |||
| @@ -380,7 +380,7 @@ do | |||
| 380 | global * | 380 | global * |
| 381 | Y = x + Y | 381 | Y = x + Y |
| 382 | assert(_ENV.Y == 20) | 382 | assert(_ENV.Y == 20) |
| 383 | 383 | Y = nil | |
| 384 | end | 384 | end |
| 385 | 385 | ||
| 386 | 386 | ||
| @@ -411,5 +411,26 @@ do -- mixing lots of global/local declarations | |||
| 411 | _ENV.x200 = nil | 411 | _ENV.x200 = nil |
| 412 | end | 412 | end |
| 413 | 413 | ||
| 414 | do print "testing initialization in global declarations" | ||
| 415 | global<const> a, b, c = 10, 20, 30 | ||
| 416 | assert(_ENV.a == 10 and b == 20 and c == 30) | ||
| 417 | |||
| 418 | global<const> a, b, c = 10 | ||
| 419 | assert(_ENV.a == 10 and b == nil and c == nil) | ||
| 420 | |||
| 421 | global table | ||
| 422 | global a, b, c, d = table.unpack{1, 2, 3, 6, 5} | ||
| 423 | assert(_ENV.a == 1 and b == 2 and c == 3 and d == 6) | ||
| 424 | |||
| 425 | local a, b = 100, 200 | ||
| 426 | do | ||
| 427 | global a, b = a, b | ||
| 428 | end | ||
| 429 | assert(_ENV.a == 100 and _ENV.b == 200) | ||
| 430 | |||
| 431 | |||
| 432 | _ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals | ||
| 433 | end | ||
| 434 | |||
| 414 | print'OK' | 435 | print'OK' |
| 415 | 436 | ||
diff --git a/testes/tracegc.lua b/testes/tracegc.lua index 9c5c1b3f..a8c929df 100644 --- a/testes/tracegc.lua +++ b/testes/tracegc.lua | |||
| @@ -6,7 +6,7 @@ local M = {} | |||
| 6 | local setmetatable, stderr, collectgarbage = | 6 | local setmetatable, stderr, collectgarbage = |
| 7 | setmetatable, io.stderr, collectgarbage | 7 | setmetatable, io.stderr, collectgarbage |
| 8 | 8 | ||
| 9 | _ENV = nil | 9 | global none |
| 10 | 10 | ||
| 11 | local active = false | 11 | local active = false |
| 12 | 12 | ||
