aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c55
1 files changed, 36 insertions, 19 deletions
diff --git a/lparser.c b/lparser.c
index 93991cb0..242bb001 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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*/
451static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { 456static 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*/
478static void buildvar (LexState *ls, TString *varname, expdesc *var) { 481static 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
1803static 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
1799static void globalstat (LexState *ls) { 1812static 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 }