diff options
Diffstat (limited to 'lparser.c')
-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 */ |