aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-05-05 16:24:59 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-05-05 16:24:59 -0300
commitbe8120906304a8658fab998587b969e0e42f5650 (patch)
tree81cf2d38522b10468d09763fc25d261486008197 /lparser.c
parente05590591410a5e007a1e3f1691f6c1cf9d8fe45 (diff)
downloadlua-be8120906304a8658fab998587b969e0e42f5650.tar.gz
lua-be8120906304a8658fab998587b969e0e42f5650.tar.bz2
lua-be8120906304a8658fab998587b969e0e42f5650.zip
First implementation of global declarations
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c111
1 files changed, 78 insertions, 33 deletions
diff --git a/lparser.c b/lparser.c
index e7e05f48..1c5fdca6 100644
--- a/lparser.c
+++ b/lparser.c
@@ -30,8 +30,8 @@
30 30
31 31
32 32
33/* maximum number of local variables per function (must be smaller 33/* maximum number of variable declarationss per function (must be
34 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
37 37
@@ -54,6 +54,7 @@ typedef struct BlockCnt {
54 lu_byte upval; /* true if some variable in the block is an upvalue */ 54 lu_byte upval; /* true if some variable in the block is an upvalue */
55 lu_byte isloop; /* 1 if 'block' is a loop; 2 if it has pending breaks */ 55 lu_byte isloop; /* 1 if 'block' is a loop; 2 if it has pending breaks */
56 lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ 56 lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */
57 lu_byte globdec; /* true if inside the scope of any global declaration */
57} BlockCnt; 58} BlockCnt;
58 59
59 60
@@ -188,10 +189,10 @@ static short registerlocalvar (LexState *ls, FuncState *fs,
188 189
189 190
190/* 191/*
191** Create a new local variable with the given 'name' and given 'kind'. 192** Create a new variable with the given 'name' and given 'kind'.
192** Return its index in the function. 193** Return its index in the function.
193*/ 194*/
194static int new_localvarkind (LexState *ls, TString *name, lu_byte kind) { 195static int new_varkind (LexState *ls, TString *name, lu_byte kind) {
195 lua_State *L = ls->L; 196 lua_State *L = ls->L;
196 FuncState *fs = ls->fs; 197 FuncState *fs = ls->fs;
197 Dyndata *dyd = ls->dyd; 198 Dyndata *dyd = ls->dyd;
@@ -211,7 +212,7 @@ static int new_localvarkind (LexState *ls, TString *name, lu_byte kind) {
211** Create a new local variable with the given 'name' and regular kind. 212** Create a new local variable with the given 'name' and regular kind.
212*/ 213*/
213static int new_localvar (LexState *ls, TString *name) { 214static int new_localvar (LexState *ls, TString *name) {
214 return new_localvarkind(ls, name, VDKREG); 215 return new_varkind(ls, name, VDKREG);
215} 216}
216 217
217#define new_localvarliteral(ls,v) \ 218#define new_localvarliteral(ls,v) \
@@ -238,7 +239,7 @@ static Vardesc *getlocalvardesc (FuncState *fs, int vidx) {
238static lu_byte reglevel (FuncState *fs, int nvar) { 239static lu_byte reglevel (FuncState *fs, int nvar) {
239 while (nvar-- > 0) { 240 while (nvar-- > 0) {
240 Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ 241 Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */
241 if (vd->vd.kind != RDKCTC) /* is in a register? */ 242 if (varinreg(vd)) /* is in a register? */
242 return cast_byte(vd->vd.ridx + 1); 243 return cast_byte(vd->vd.ridx + 1);
243 } 244 }
244 return 0; /* no variables in registers */ 245 return 0; /* no variables in registers */
@@ -259,7 +260,7 @@ lu_byte luaY_nvarstack (FuncState *fs) {
259*/ 260*/
260static LocVar *localdebuginfo (FuncState *fs, int vidx) { 261static LocVar *localdebuginfo (FuncState *fs, int vidx) {
261 Vardesc *vd = getlocalvardesc(fs, vidx); 262 Vardesc *vd = getlocalvardesc(fs, vidx);
262 if (vd->vd.kind == RDKCTC) 263 if (!varinreg(vd))
263 return NULL; /* no debug info. for constants */ 264 return NULL; /* no debug info. for constants */
264 else { 265 else {
265 int idx = vd->vd.pidx; 266 int idx = vd->vd.pidx;
@@ -401,7 +402,9 @@ static int searchvar (FuncState *fs, TString *n, expdesc *var) {
401 if (eqstr(n, vd->vd.name)) { /* found? */ 402 if (eqstr(n, vd->vd.name)) { /* found? */
402 if (vd->vd.kind == RDKCTC) /* compile-time constant? */ 403 if (vd->vd.kind == RDKCTC) /* compile-time constant? */
403 init_exp(var, VCONST, fs->firstlocal + i); 404 init_exp(var, VCONST, fs->firstlocal + i);
404 else /* real variable */ 405 else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST)
406 init_exp(var, VGLOBAL, i);
407 else /* local variable */
405 init_var(fs, var, i); 408 init_var(fs, var, i);
406 return cast_int(var->k); 409 return cast_int(var->k);
407 } 410 }
@@ -440,25 +443,24 @@ static void marktobeclosed (FuncState *fs) {
440** 'var' as 'void' as a flag. 443** 'var' as 'void' as a flag.
441*/ 444*/
442static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { 445static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
443 if (fs == NULL) /* no more levels? */ 446 int v = searchvar(fs, n, var); /* look up locals at current level */
444 init_exp(var, VVOID, 0); /* default is global */ 447 if (v >= 0) { /* found? */
445 else { 448 if (v == VLOCAL && !base)
446 int v = searchvar(fs, n, var); /* look up locals at current level */ 449 markupval(fs, var->u.var.vidx); /* local will be used as an upval */
447 if (v >= 0) { /* found? */ 450 }
448 if (v == VLOCAL && !base) 451 else { /* not found as local at current level; try upvalues */
449 markupval(fs, var->u.var.vidx); /* local will be used as an upval */ 452 int idx = searchupvalue(fs, n); /* try existing upvalues */
450 } 453 if (idx < 0) { /* not found? */
451 else { /* not found as local at current level; try upvalues */ 454 if (fs->prev != NULL) /* more levels? */
452 int idx = searchupvalue(fs, n); /* try existing upvalues */
453 if (idx < 0) { /* not found? */
454 singlevaraux(fs->prev, n, var, 0); /* try upper levels */ 455 singlevaraux(fs->prev, n, var, 0); /* try upper levels */
455 if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ 456 else /* no more levels */
456 idx = newupvalue(fs, n, var); /* will be a new upvalue */ 457 init_exp(var, VGLOBAL, -1); /* global by default */
457 else /* it is a global or a constant */ 458 if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */
458 return; /* don't need to do anything at this level */ 459 idx = newupvalue(fs, n, var); /* will be a new upvalue */
459 } 460 else /* it is a global or a constant */
460 init_exp(var, VUPVAL, idx); /* new or old upvalue */ 461 return; /* don't need to do anything at this level */
461 } 462 }
463 init_exp(var, VUPVAL, idx); /* new or old upvalue */
462 } 464 }
463} 465}
464 466
@@ -471,10 +473,15 @@ static void singlevar (LexState *ls, expdesc *var) {
471 TString *varname = str_checkname(ls); 473 TString *varname = str_checkname(ls);
472 FuncState *fs = ls->fs; 474 FuncState *fs = ls->fs;
473 singlevaraux(fs, varname, var, 1); 475 singlevaraux(fs, varname, var, 1);
474 if (var->k == VVOID) { /* global name? */ 476 if (var->k == VGLOBAL) { /* global name? */
475 expdesc key; 477 expdesc key;
478 /* global by default in the scope of a global declaration? */
479 if (var->u.info == -1 && fs->bl->globdec)
480 luaK_semerror(ls, "variable '%s' not declared", getstr(varname));
476 singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ 481 singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
477 lua_assert(var->k != VVOID); /* this one must exist */ 482 if (var->k == VGLOBAL)
483 luaK_semerror(ls, "_ENV is global when accessing variable '%s'",
484 getstr(varname));
478 luaK_exp2anyregup(fs, var); /* but could be a constant */ 485 luaK_exp2anyregup(fs, var); /* but could be a constant */
479 codestring(&key, varname); /* key is variable name */ 486 codestring(&key, varname); /* key is variable name */
480 luaK_indexed(fs, var, &key); /* env[varname] */ 487 luaK_indexed(fs, var, &key); /* env[varname] */
@@ -664,8 +671,13 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
664 bl->firstlabel = fs->ls->dyd->label.n; 671 bl->firstlabel = fs->ls->dyd->label.n;
665 bl->firstgoto = fs->ls->dyd->gt.n; 672 bl->firstgoto = fs->ls->dyd->gt.n;
666 bl->upval = 0; 673 bl->upval = 0;
674 /* inherit 'insidetbc' from enclosing block */
667 bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); 675 bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc);
668 bl->previous = fs->bl; 676 /* inherit 'globdec' from enclosing block or enclosing function */
677 bl->globdec = fs->bl != NULL ? fs->bl->globdec
678 : fs->prev != NULL ? fs->prev->bl->globdec
679 : 0; /* chunk's first block */
680 bl->previous = fs->bl; /* link block in function's block list */
669 fs->bl = bl; 681 fs->bl = bl;
670 lua_assert(fs->freereg == luaY_nvarstack(fs)); 682 lua_assert(fs->freereg == luaY_nvarstack(fs));
671} 683}
@@ -1600,7 +1612,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1600 int base = fs->freereg; 1612 int base = fs->freereg;
1601 new_localvarliteral(ls, "(for state)"); 1613 new_localvarliteral(ls, "(for state)");
1602 new_localvarliteral(ls, "(for state)"); 1614 new_localvarliteral(ls, "(for state)");
1603 new_localvarkind(ls, varname, RDKCONST); /* control variable */ 1615 new_varkind(ls, varname, RDKCONST); /* control variable */
1604 checknext(ls, '='); 1616 checknext(ls, '=');
1605 exp1(ls); /* initial value */ 1617 exp1(ls); /* initial value */
1606 checknext(ls, ','); 1618 checknext(ls, ',');
@@ -1627,7 +1639,7 @@ static void forlist (LexState *ls, TString *indexname) {
1627 new_localvarliteral(ls, "(for state)"); /* iterator function */ 1639 new_localvarliteral(ls, "(for state)"); /* iterator function */
1628 new_localvarliteral(ls, "(for state)"); /* state */ 1640 new_localvarliteral(ls, "(for state)"); /* state */
1629 new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */ 1641 new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */
1630 new_localvarkind(ls, indexname, RDKCONST); /* control variable */ 1642 new_varkind(ls, indexname, RDKCONST); /* control variable */
1631 /* other declared variables */ 1643 /* other declared variables */
1632 while (testnext(ls, ',')) { 1644 while (testnext(ls, ',')) {
1633 new_localvar(ls, str_checkname(ls)); 1645 new_localvar(ls, str_checkname(ls));
@@ -1702,7 +1714,7 @@ static void localfunc (LexState *ls) {
1702} 1714}
1703 1715
1704 1716
1705static lu_byte getlocalattribute (LexState *ls) { 1717static lu_byte getvarattribute (LexState *ls) {
1706 /* ATTRIB -> ['<' Name '>'] */ 1718 /* ATTRIB -> ['<' Name '>'] */
1707 if (testnext(ls, '<')) { 1719 if (testnext(ls, '<')) {
1708 TString *ts = str_checkname(ls); 1720 TString *ts = str_checkname(ls);
@@ -1738,8 +1750,8 @@ static void localstat (LexState *ls) {
1738 expdesc e; 1750 expdesc e;
1739 do { 1751 do {
1740 TString *vname = str_checkname(ls); 1752 TString *vname = str_checkname(ls);
1741 lu_byte kind = getlocalattribute(ls); 1753 lu_byte kind = getvarattribute(ls);
1742 vidx = new_localvarkind(ls, vname, kind); 1754 vidx = new_varkind(ls, vname, kind);
1743 if (kind == RDKTOCLOSE) { /* to-be-closed? */ 1755 if (kind == RDKTOCLOSE) { /* to-be-closed? */
1744 if (toclose != -1) /* one already present? */ 1756 if (toclose != -1) /* one already present? */
1745 luaK_semerror(ls, "multiple to-be-closed variables in local list"); 1757 luaK_semerror(ls, "multiple to-be-closed variables in local list");
@@ -1769,6 +1781,24 @@ static void localstat (LexState *ls) {
1769} 1781}
1770 1782
1771 1783
1784static void globalstat (LexState *ls) {
1785 FuncState *fs = ls->fs;
1786 luaX_next(ls); /* skip 'global' */
1787 do {
1788 TString *vname = str_checkname(ls);
1789 lu_byte kind = getvarattribute(ls);
1790 if (kind == RDKTOCLOSE)
1791 luaK_semerror(ls, "global variable ('%s') cannot be to-be-closed",
1792 getstr(vname));
1793 /* adjust kind for global variable */
1794 kind = (kind == VDKREG) ? GDKREG : GDKCONST;
1795 new_varkind(ls, vname, kind);
1796 fs->nactvar++; /* activate declaration */
1797 } while (testnext(ls, ','));
1798 fs->bl->globdec = 1; /* code is in the scope of a global declaration */
1799}
1800
1801
1772static int funcname (LexState *ls, expdesc *v) { 1802static int funcname (LexState *ls, expdesc *v) {
1773 /* funcname -> NAME {fieldsel} [':' NAME] */ 1803 /* funcname -> NAME {fieldsel} [':' NAME] */
1774 int ismethod = 0; 1804 int ismethod = 0;
@@ -1888,6 +1918,10 @@ static void statement (LexState *ls) {
1888 localstat(ls); 1918 localstat(ls);
1889 break; 1919 break;
1890 } 1920 }
1921 case TK_GLOBAL: { /* stat -> globalstat */
1922 globalstat(ls);
1923 break;
1924 }
1891 case TK_DBCOLON: { /* stat -> label */ 1925 case TK_DBCOLON: { /* stat -> label */
1892 luaX_next(ls); /* skip double colon */ 1926 luaX_next(ls); /* skip double colon */
1893 labelstat(ls, str_checkname(ls), line); 1927 labelstat(ls, str_checkname(ls), line);
@@ -1907,6 +1941,17 @@ static void statement (LexState *ls) {
1907 gotostat(ls, line); 1941 gotostat(ls, line);
1908 break; 1942 break;
1909 } 1943 }
1944 case TK_NAME: {
1945 /* compatibility code to parse global keyword when "global"
1946 is not reserved */
1947 if (eqstr(ls->t.seminfo.ts, luaS_newliteral(ls->L, "global"))) {
1948 int lk = luaX_lookahead(ls);
1949 if (lk == TK_NAME) { /* 'global name'? */
1950 globalstat(ls);
1951 break;
1952 }
1953 } /* else... */
1954 } /* FALLTHROUGH */
1910 default: { /* stat -> func | assignment */ 1955 default: { /* stat -> func | assignment */
1911 exprstat(ls); 1956 exprstat(ls);
1912 break; 1957 break;