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