aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-03 14:18:07 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-03 14:18:07 -0300
commit4d46289331395a845c5de1f6c0e0fe873c50db4f (patch)
tree96649174d3c13830549ad026af0133e0b789d411 /lparser.c
parent8eca21c2e85625390a2a3b08c231e75e315980b0 (diff)
downloadlua-4d46289331395a845c5de1f6c0e0fe873c50db4f.tar.gz
lua-4d46289331395a845c5de1f6c0e0fe873c50db4f.tar.bz2
lua-4d46289331395a845c5de1f6c0e0fe873c50db4f.zip
Local attributes can be used in list of local variables
The syntax for local attributes ('const'/'toclose') was unified with the regular syntax for local variables, so that we can have variables with attributes in local definitions with multiple names; for instance: local <toclose> f, <const> err = io.open(fname) This new syntax does not implement constant propagation, yet. This commit also has some small improvements to the manual.
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c90
1 files changed, 41 insertions, 49 deletions
diff --git a/lparser.c b/lparser.c
index 875f7d04..52486e08 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1656,13 +1656,50 @@ static void localfunc (LexState *ls) {
1656} 1656}
1657 1657
1658 1658
1659static void commonlocalstat (LexState *ls) { 1659static int getlocalattribute (LexState *ls) {
1660 /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ 1660 /* ATTRIB -> ['<' Name '>'] */
1661 if (testnext(ls, '<')) {
1662 const char *attr = getstr(str_checkname(ls));
1663 checknext(ls, '>');
1664 if (strcmp(attr, "const") == 0)
1665 return 1; /* read-only variable */
1666 else if (strcmp(attr, "toclose") == 0)
1667 return 2; /* to-be-closed variable */
1668 else
1669 luaK_semerror(ls,
1670 luaO_pushfstring(ls->L, "unknown attribute '%s'", attr));
1671 }
1672 return 0;
1673}
1674
1675
1676static void checktoclose (LexState *ls, int toclose) {
1677 if (toclose != -1) { /* is there a to-be-closed variable? */
1678 FuncState *fs = ls->fs;
1679 markupval(fs, fs->nactvar + toclose + 1);
1680 fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
1681 luaK_codeABC(fs, OP_TBC, fs->nactvar + toclose, 0, 0);
1682 }
1683}
1684
1685
1686static void localstat (LexState *ls) {
1687 /* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */
1688 int toclose = -1; /* index of to-be-closed variable (if any) */
1661 int nvars = 0; 1689 int nvars = 0;
1662 int nexps; 1690 int nexps;
1663 expdesc e; 1691 expdesc e;
1664 do { 1692 do {
1665 new_localvar(ls, str_checkname(ls)); 1693 int kind = getlocalattribute(ls);
1694 Vardesc *var = new_localvar(ls, str_checkname(ls));
1695 if (kind != 0) { /* is there an attribute? */
1696 var->ro = 1; /* all attributes make variable read-only */
1697 if (kind == 2) { /* to-be-closed? */
1698 if (toclose != -1) /* one already present? */
1699 luaK_semerror(ls, "multiple to-be-closed variables in local list");
1700 toclose = nvars;
1701 }
1702 }
1666 nvars++; 1703 nvars++;
1667 } while (testnext(ls, ',')); 1704 } while (testnext(ls, ','));
1668 if (testnext(ls, '=')) 1705 if (testnext(ls, '='))
@@ -1672,56 +1709,11 @@ static void commonlocalstat (LexState *ls) {
1672 nexps = 0; 1709 nexps = 0;
1673 } 1710 }
1674 adjust_assign(ls, nvars, nexps, &e); 1711 adjust_assign(ls, nvars, nexps, &e);
1712 checktoclose(ls, toclose);
1675 adjustlocalvars(ls, nvars); 1713 adjustlocalvars(ls, nvars);
1676} 1714}
1677 1715
1678 1716
1679static void tocloselocalstat (LexState *ls, Vardesc *var) {
1680 FuncState *fs = ls->fs;
1681 var->ro = 1; /* to-be-closed variables are always read-only */
1682 markupval(fs, fs->nactvar + 1);
1683 fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */
1684 luaK_codeABC(fs, OP_TBC, fs->nactvar, 0, 0);
1685}
1686
1687
1688static void checkattrib (LexState *ls, TString *attr, Vardesc *var) {
1689 if (strcmp(getstr(attr), "const") == 0)
1690 var->ro = 1; /* set variable as read-only */
1691 else if (strcmp(getstr(attr), "toclose") == 0)
1692 tocloselocalstat(ls, var);
1693 else
1694 luaK_semerror(ls,
1695 luaO_pushfstring(ls->L, "unknown attribute '%s'", getstr(attr)));
1696}
1697
1698
1699static void attriblocalstat (LexState *ls) {
1700 FuncState *fs = ls->fs;
1701 Vardesc *var;
1702 expdesc e;
1703 TString *attr = str_checkname(ls);
1704 testnext(ls, '>');
1705 var = new_localvar(ls, str_checkname(ls));
1706 checknext(ls, '=');
1707 expr(ls, &e);
1708 checkattrib(ls, attr, var);
1709 luaK_tonumeral(fs, &e, &var->val);
1710 luaK_exp2nextreg(fs, &e);
1711 adjustlocalvars(ls, 1);
1712}
1713
1714
1715static void localstat (LexState *ls) {
1716 /* stat -> LOCAL NAME {',' NAME} ['=' explist]
1717 | LOCAL *toclose NAME '=' exp */
1718 if (testnext(ls, '<'))
1719 attriblocalstat(ls);
1720 else
1721 commonlocalstat(ls);
1722}
1723
1724
1725static int funcname (LexState *ls, expdesc *v) { 1717static int funcname (LexState *ls, expdesc *v) {
1726 /* funcname -> NAME {fieldsel} [':' NAME] */ 1718 /* funcname -> NAME {fieldsel} [':' NAME] */
1727 int ismethod = 0; 1719 int ismethod = 0;