diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-05-13 11:43:10 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-05-13 11:43:10 -0300 |
| commit | 3b9dd52be02fd43c598f4adb6fa7844e6a573923 (patch) | |
| tree | 8f858942f5db0e3d9d7cad503b59ee1541a60aa6 /lparser.c | |
| parent | 7dc6aae29057c9dc4588f780c7abd72a62ff4c8e (diff) | |
| download | lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.tar.gz lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.tar.bz2 lua-3b9dd52be02fd43c598f4adb6fa7844e6a573923.zip | |
Collective declaration for globals ('global *')
Diffstat (limited to '')
| -rw-r--r-- | lparser.c | 55 |
1 files changed, 36 insertions, 19 deletions
| @@ -405,7 +405,12 @@ static int searchvar (FuncState *fs, TString *n, expdesc *var) { | |||
| 405 | int i; | 405 | int i; |
| 406 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 406 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
| 407 | Vardesc *vd = getlocalvardesc(fs, i); | 407 | Vardesc *vd = getlocalvardesc(fs, i); |
| 408 | if (eqstr(n, vd->vd.name)) { /* found? */ | 408 | if (vd->vd.name == NULL) { /* 'global *'? */ |
| 409 | if (var->u.info == -1) { /* no previous collective declaration? */ | ||
| 410 | var->u.info = fs->firstlocal + i; /* will use this one as default */ | ||
| 411 | } | ||
| 412 | } | ||
| 413 | else if (eqstr(n, vd->vd.name)) { /* found? */ | ||
| 409 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ | 414 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ |
| 410 | init_exp(var, VCONST, fs->firstlocal + i); | 415 | init_exp(var, VCONST, fs->firstlocal + i); |
| 411 | else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST) | 416 | else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST) |
| @@ -449,18 +454,16 @@ static void marktobeclosed (FuncState *fs) { | |||
| 449 | ** 'var' as 'void' as a flag. | 454 | ** 'var' as 'void' as a flag. |
| 450 | */ | 455 | */ |
| 451 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 456 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { |
| 452 | int v = searchvar(fs, n, var); /* look up locals at current level */ | 457 | int v = searchvar(fs, n, var); /* look up variables at current level */ |
| 453 | if (v >= 0) { /* found? */ | 458 | if (v >= 0) { /* found? */ |
| 454 | if (v == VLOCAL && !base) | 459 | if (v == VLOCAL && !base) |
| 455 | markupval(fs, var->u.var.vidx); /* local will be used as an upval */ | 460 | markupval(fs, var->u.var.vidx); /* local will be used as an upval */ |
| 456 | } | 461 | } |
| 457 | else { /* not found as local at current level; try upvalues */ | 462 | else { /* not found at current level; try upvalues */ |
| 458 | int idx = searchupvalue(fs, n); /* try existing upvalues */ | 463 | int idx = searchupvalue(fs, n); /* try existing upvalues */ |
| 459 | if (idx < 0) { /* not found? */ | 464 | if (idx < 0) { /* not found? */ |
| 460 | if (fs->prev != NULL) /* more levels? */ | 465 | if (fs->prev != NULL) /* more levels? */ |
| 461 | singlevaraux(fs->prev, n, var, 0); /* try upper levels */ | 466 | singlevaraux(fs->prev, n, var, 0); /* try upper levels */ |
| 462 | else /* no more levels */ | ||
| 463 | init_exp(var, VGLOBAL, -1); /* global by default */ | ||
| 464 | if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ | 467 | if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ |
| 465 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ | 468 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ |
| 466 | else /* it is a global or a constant */ | 469 | else /* it is a global or a constant */ |
| @@ -477,6 +480,7 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | |||
| 477 | */ | 480 | */ |
| 478 | static void buildvar (LexState *ls, TString *varname, expdesc *var) { | 481 | static void buildvar (LexState *ls, TString *varname, expdesc *var) { |
| 479 | FuncState *fs = ls->fs; | 482 | FuncState *fs = ls->fs; |
| 483 | init_exp(var, VGLOBAL, -1); /* global by default */ | ||
| 480 | singlevaraux(fs, varname, var, 1); | 484 | singlevaraux(fs, varname, var, 1); |
| 481 | if (var->k == VGLOBAL) { /* global name? */ | 485 | if (var->k == VGLOBAL) { /* global name? */ |
| 482 | expdesc key; | 486 | expdesc key; |
| @@ -1796,20 +1800,33 @@ static void localstat (LexState *ls) { | |||
| 1796 | } | 1800 | } |
| 1797 | 1801 | ||
| 1798 | 1802 | ||
| 1803 | static lu_byte getglobalattribute (LexState *ls) { | ||
| 1804 | lu_byte kind = getvarattribute(ls); | ||
| 1805 | if (kind == RDKTOCLOSE) | ||
| 1806 | luaK_semerror(ls, "global variables cannot be to-be-closed"); | ||
| 1807 | /* adjust kind for global variable */ | ||
| 1808 | return (kind == VDKREG) ? GDKREG : GDKCONST; | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | |||
| 1799 | static void globalstat (LexState *ls) { | 1812 | static void globalstat (LexState *ls) { |
| 1800 | /* globalstat -> (GLOBAL) NAME attrib {',' NAME attrib} */ | 1813 | /* globalstat -> (GLOBAL) '*' attrib |
| 1814 | globalstat -> (GLOBAL) NAME attrib {',' NAME attrib} */ | ||
| 1801 | FuncState *fs = ls->fs; | 1815 | FuncState *fs = ls->fs; |
| 1802 | do { | 1816 | if (testnext(ls, '*')) { |
| 1803 | TString *vname = str_checkname(ls); | 1817 | lu_byte kind = getglobalattribute(ls); |
| 1804 | lu_byte kind = getvarattribute(ls); | 1818 | /* use NULL as name to represent '*' entries */ |
| 1805 | if (kind == RDKTOCLOSE) | 1819 | new_varkind(ls, NULL, kind); |
| 1806 | luaK_semerror(ls, "global variable ('%s') cannot be to-be-closed", | ||
| 1807 | getstr(vname)); | ||
| 1808 | /* adjust kind for global variable */ | ||
| 1809 | kind = (kind == VDKREG) ? GDKREG : GDKCONST; | ||
| 1810 | new_varkind(ls, vname, kind); | ||
| 1811 | fs->nactvar++; /* activate declaration */ | 1820 | fs->nactvar++; /* activate declaration */ |
| 1812 | } while (testnext(ls, ',')); | 1821 | } |
| 1822 | else { | ||
| 1823 | do { | ||
| 1824 | TString *vname = str_checkname(ls); | ||
| 1825 | lu_byte kind = getglobalattribute(ls); | ||
| 1826 | new_varkind(ls, vname, kind); | ||
| 1827 | fs->nactvar++; /* activate declaration */ | ||
| 1828 | } while (testnext(ls, ',')); | ||
| 1829 | } | ||
| 1813 | } | 1830 | } |
| 1814 | 1831 | ||
| 1815 | 1832 | ||
| @@ -1983,10 +2000,10 @@ static void statement (LexState *ls) { | |||
| 1983 | case TK_NAME: { | 2000 | case TK_NAME: { |
| 1984 | /* compatibility code to parse global keyword when "global" | 2001 | /* compatibility code to parse global keyword when "global" |
| 1985 | is not reserved */ | 2002 | is not reserved */ |
| 1986 | if (eqstr(ls->t.seminfo.ts, luaS_newliteral(ls->L, "global"))) { | 2003 | if (strcmp(getstr(ls->t.seminfo.ts), "global") == 0) { |
| 1987 | int lk = luaX_lookahead(ls); | 2004 | int lk = luaX_lookahead(ls); |
| 1988 | if (lk == TK_NAME || lk == TK_FUNCTION) { | 2005 | if (lk == TK_NAME || lk == '*' || lk == TK_FUNCTION) { |
| 1989 | /* 'global <name>' or 'global function' */ | 2006 | /* 'global <name>' or 'global *' or 'global function' */ |
| 1990 | globalstatfunc(ls, line); | 2007 | globalstatfunc(ls, line); |
| 1991 | break; | 2008 | break; |
| 1992 | } | 2009 | } |
