diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-07-08 13:33:57 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-07-08 13:33:57 -0300 |
| commit | 942c10a5e33811a08a290ec15031c950a6d17c99 (patch) | |
| tree | 114395a69857609bdd6c220f85476812f0fd5fb1 /lparser.c | |
| parent | 848568790826b7e201f84682185b5b605c473016 (diff) | |
| download | lua-942c10a5e33811a08a290ec15031c950a6d17c99.tar.gz lua-942c10a5e33811a08a290ec15031c950a6d17c99.tar.bz2 lua-942c10a5e33811a08a290ec15031c950a6d17c99.zip | |
Optional initialization for global declarations
Diffstat (limited to '')
| -rw-r--r-- | lparser.c | 81 |
1 files changed, 58 insertions, 23 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 */ |
