diff options
| -rw-r--r-- | lcode.c | 2 | ||||
| -rw-r--r-- | lparser.c | 41 | ||||
| -rw-r--r-- | testes/goto.lua | 22 |
3 files changed, 52 insertions, 13 deletions
| @@ -1242,7 +1242,7 @@ static void codenot (FuncState *fs, expdesc *e) { | |||
| 1242 | ** Check whether expression 'e' is a short literal string | 1242 | ** Check whether expression 'e' is a short literal string |
| 1243 | */ | 1243 | */ |
| 1244 | static int isKstr (FuncState *fs, expdesc *e) { | 1244 | static int isKstr (FuncState *fs, expdesc *e) { |
| 1245 | return (e->k == VK && !hasjumps(e) && e->u.info <= MAXARG_B && | 1245 | return (e->k == VK && !hasjumps(e) && e->u.info <= MAXINDEXRK && |
| 1246 | ttisshrstring(&fs->f->k[e->u.info])); | 1246 | ttisshrstring(&fs->f->k[e->u.info])); |
| 1247 | } | 1247 | } |
| 1248 | 1248 | ||
| @@ -1875,6 +1875,33 @@ static lu_byte getglobalattribute (LexState *ls, lu_byte df) { | |||
| 1875 | } | 1875 | } |
| 1876 | 1876 | ||
| 1877 | 1877 | ||
| 1878 | /* | ||
| 1879 | ** Recursively traverse list of globals to be initalized. When | ||
| 1880 | ** going, generate table description for the global. In the end, | ||
| 1881 | ** after all indices have been generated, read list of initializing | ||
| 1882 | ** expressions. When returning, generate the assignment of the value on | ||
| 1883 | ** the stack to the corresponding table description. 'n' is the variable | ||
| 1884 | ** being handled, range [0, nvars - 1]. | ||
| 1885 | */ | ||
| 1886 | static void initglobal (LexState *ls, int nvars, int firstidx, int n) { | ||
| 1887 | if (n == nvars) { /* traversed all variables? */ | ||
| 1888 | expdesc e; | ||
| 1889 | int nexps = explist(ls, &e); /* read list of expressions */ | ||
| 1890 | adjust_assign(ls, nvars, nexps, &e); | ||
| 1891 | } | ||
| 1892 | else { /* handle variable 'n' */ | ||
| 1893 | FuncState *fs = ls->fs; | ||
| 1894 | expdesc var; | ||
| 1895 | TString *varname = getlocalvardesc(fs, firstidx + n)->vd.name; | ||
| 1896 | buildglobal(ls, varname, &var); /* create global variable in 'var' */ | ||
| 1897 | enterlevel(ls); /* control recursion depth */ | ||
| 1898 | initglobal(ls, nvars, firstidx, n + 1); | ||
| 1899 | leavelevel(ls); | ||
| 1900 | storevartop(fs, &var); | ||
| 1901 | } | ||
| 1902 | } | ||
| 1903 | |||
| 1904 | |||
| 1878 | static void globalnames (LexState *ls, lu_byte defkind) { | 1905 | static void globalnames (LexState *ls, lu_byte defkind) { |
| 1879 | FuncState *fs = ls->fs; | 1906 | FuncState *fs = ls->fs; |
| 1880 | int nvars = 0; | 1907 | int nvars = 0; |
| @@ -1885,18 +1912,8 @@ static void globalnames (LexState *ls, lu_byte defkind) { | |||
| 1885 | lastidx = new_varkind(ls, vname, kind); | 1912 | lastidx = new_varkind(ls, vname, kind); |
| 1886 | nvars++; | 1913 | nvars++; |
| 1887 | } while (testnext(ls, ',')); | 1914 | } while (testnext(ls, ',')); |
| 1888 | if (testnext(ls, '=')) { /* initialization? */ | 1915 | if (testnext(ls, '=')) /* initialization? */ |
| 1889 | expdesc e; | 1916 | initglobal(ls, nvars, lastidx - nvars + 1, 0); |
| 1890 | int i; | ||
| 1891 | int nexps = explist(ls, &e); /* read list of expressions */ | ||
| 1892 | adjust_assign(ls, nvars, nexps, &e); | ||
| 1893 | for (i = 0; i < nvars; i++) { /* for each variable */ | ||
| 1894 | expdesc var; | ||
| 1895 | TString *varname = getlocalvardesc(fs, lastidx - i)->vd.name; | ||
| 1896 | buildglobal(ls, varname, &var); /* create global variable in 'var' */ | ||
| 1897 | storevartop(fs, &var); | ||
| 1898 | } | ||
| 1899 | } | ||
| 1900 | fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */ | 1917 | fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */ |
| 1901 | } | 1918 | } |
| 1902 | 1919 | ||
diff --git a/testes/goto.lua b/testes/goto.lua index 3310314d..a692a623 100644 --- a/testes/goto.lua +++ b/testes/goto.lua | |||
| @@ -432,5 +432,27 @@ do print "testing initialization in global declarations" | |||
| 432 | _ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals | 432 | _ENV.a, _ENV.b, _ENV.c, _ENV.d = nil -- erase these globals |
| 433 | end | 433 | end |
| 434 | 434 | ||
| 435 | do | ||
| 436 | global table, string | ||
| 437 | -- global initialization when names don't fit in K | ||
| 438 | |||
| 439 | -- to fill constant table | ||
| 440 | local code = {} | ||
| 441 | for i = 1, 300 do code[i] = "'" .. i .. "'" end | ||
| 442 | code = table.concat(code, ",") | ||
| 443 | code = string.format([[ | ||
| 444 | return function (_ENV) | ||
| 445 | local dummy = {%s} -- fill initial positions in constant table, | ||
| 446 | -- so that initialization must use registers for global names | ||
| 447 | global a, b, c = 10, 20, 30 | ||
| 448 | end]], code) | ||
| 449 | |||
| 450 | local fun = assert(load(code))() | ||
| 451 | |||
| 452 | local env = {} | ||
| 453 | fun(env) | ||
| 454 | assert(env.a == 10 and env.b == 20 and env.c == 30) | ||
| 455 | end | ||
| 456 | |||
| 435 | print'OK' | 457 | print'OK' |
| 436 | 458 | ||
