diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-12-21 12:04:59 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2022-12-21 12:04:59 -0300 |
commit | b2f7b3b79f3117885b265575f6c5dbf934757797 (patch) | |
tree | ad7ac30fb9a05e1e6635110f03c45b9cd41190c8 /lparser.c | |
parent | 540d8052265776451bb9f0ab4dee4ec860563cbe (diff) | |
download | lua-b2f7b3b79f3117885b265575f6c5dbf934757797.tar.gz lua-b2f7b3b79f3117885b265575f6c5dbf934757797.tar.bz2 lua-b2f7b3b79f3117885b265575f6c5dbf934757797.zip |
Control variables in for loops are read only
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 30 |
1 files changed, 19 insertions, 11 deletions
@@ -187,10 +187,10 @@ static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) { | |||
187 | 187 | ||
188 | 188 | ||
189 | /* | 189 | /* |
190 | ** Create a new local variable with the given 'name'. Return its index | 190 | ** Create a new local variable with the given 'name' and given 'kind'. |
191 | ** in the function. | 191 | ** Return its index in the function. |
192 | */ | 192 | */ |
193 | static int new_localvar (LexState *ls, TString *name) { | 193 | static int new_localvarkind (LexState *ls, TString *name, int kind) { |
194 | lua_State *L = ls->L; | 194 | lua_State *L = ls->L; |
195 | FuncState *fs = ls->fs; | 195 | FuncState *fs = ls->fs; |
196 | Dyndata *dyd = ls->dyd; | 196 | Dyndata *dyd = ls->dyd; |
@@ -200,11 +200,19 @@ static int new_localvar (LexState *ls, TString *name) { | |||
200 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, | 200 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, |
201 | dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); | 201 | dyd->actvar.size, Vardesc, USHRT_MAX, "local variables"); |
202 | var = &dyd->actvar.arr[dyd->actvar.n++]; | 202 | var = &dyd->actvar.arr[dyd->actvar.n++]; |
203 | var->vd.kind = VDKREG; /* default */ | 203 | var->vd.kind = kind; /* default */ |
204 | var->vd.name = name; | 204 | var->vd.name = name; |
205 | return dyd->actvar.n - 1 - fs->firstlocal; | 205 | return dyd->actvar.n - 1 - fs->firstlocal; |
206 | } | 206 | } |
207 | 207 | ||
208 | |||
209 | /* | ||
210 | ** Create a new local variable with the given 'name' and regular kind. | ||
211 | */ | ||
212 | static int new_localvar (LexState *ls, TString *name) { | ||
213 | return new_localvarkind(ls, name, VDKREG); | ||
214 | } | ||
215 | |||
208 | #define new_localvarliteral(ls,v) \ | 216 | #define new_localvarliteral(ls,v) \ |
209 | new_localvar(ls, \ | 217 | new_localvar(ls, \ |
210 | luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); | 218 | luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); |
@@ -1573,7 +1581,7 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1573 | new_localvarliteral(ls, "(for state)"); | 1581 | new_localvarliteral(ls, "(for state)"); |
1574 | new_localvarliteral(ls, "(for state)"); | 1582 | new_localvarliteral(ls, "(for state)"); |
1575 | new_localvarliteral(ls, "(for state)"); | 1583 | new_localvarliteral(ls, "(for state)"); |
1576 | new_localvar(ls, varname); | 1584 | new_localvarkind(ls, varname, RDKCONST); /* control variable */ |
1577 | checknext(ls, '='); | 1585 | checknext(ls, '='); |
1578 | exp1(ls); /* initial value */ | 1586 | exp1(ls); /* initial value */ |
1579 | checknext(ls, ','); | 1587 | checknext(ls, ','); |
@@ -1601,8 +1609,8 @@ static void forlist (LexState *ls, TString *indexname) { | |||
1601 | new_localvarliteral(ls, "(for state)"); | 1609 | new_localvarliteral(ls, "(for state)"); |
1602 | new_localvarliteral(ls, "(for state)"); | 1610 | new_localvarliteral(ls, "(for state)"); |
1603 | new_localvarliteral(ls, "(for state)"); | 1611 | new_localvarliteral(ls, "(for state)"); |
1604 | /* create declared variables */ | 1612 | new_localvarkind(ls, indexname, RDKCONST); /* control variable */ |
1605 | new_localvar(ls, indexname); | 1613 | /* other declared variables */ |
1606 | while (testnext(ls, ',')) { | 1614 | while (testnext(ls, ',')) { |
1607 | new_localvar(ls, str_checkname(ls)); | 1615 | new_localvar(ls, str_checkname(ls)); |
1608 | nvars++; | 1616 | nvars++; |
@@ -1728,14 +1736,14 @@ static void localstat (LexState *ls) { | |||
1728 | FuncState *fs = ls->fs; | 1736 | FuncState *fs = ls->fs; |
1729 | int toclose = -1; /* index of to-be-closed variable (if any) */ | 1737 | int toclose = -1; /* index of to-be-closed variable (if any) */ |
1730 | Vardesc *var; /* last variable */ | 1738 | Vardesc *var; /* last variable */ |
1731 | int vidx, kind; /* index and kind of last variable */ | 1739 | int vidx; /* index of last variable */ |
1732 | int nvars = 0; | 1740 | int nvars = 0; |
1733 | int nexps; | 1741 | int nexps; |
1734 | expdesc e; | 1742 | expdesc e; |
1735 | do { | 1743 | do { |
1736 | vidx = new_localvar(ls, str_checkname(ls)); | 1744 | TString *vname = str_checkname(ls); |
1737 | kind = getlocalattribute(ls); | 1745 | int kind = getlocalattribute(ls); |
1738 | getlocalvardesc(fs, vidx)->vd.kind = kind; | 1746 | vidx = new_localvarkind(ls, vname, kind); |
1739 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ | 1747 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ |
1740 | if (toclose != -1) /* one already present? */ | 1748 | if (toclose != -1) /* one already present? */ |
1741 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); | 1749 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); |