diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-09-07 14:39:10 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-09-07 14:39:10 -0300 |
commit | abdbe883a86bbc7fbf1d1bfc50756e1b42fc45b5 (patch) | |
tree | 051a7571c8acaf5451b5c9b7d67f1796a345c565 /lparser.c | |
parent | 4d0935ec0ffed827aade5594216fae15bed7c6b5 (diff) | |
download | lua-abdbe883a86bbc7fbf1d1bfc50756e1b42fc45b5.tar.gz lua-abdbe883a86bbc7fbf1d1bfc50756e1b42fc45b5.tar.bz2 lua-abdbe883a86bbc7fbf1d1bfc50756e1b42fc45b5.zip |
first implementation of unrestricted static scoping
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 147 |
1 files changed, 69 insertions, 78 deletions
@@ -41,6 +41,7 @@ typedef struct Constdesc { | |||
41 | typedef struct Breaklabel { | 41 | typedef struct Breaklabel { |
42 | struct Breaklabel *previous; /* chain */ | 42 | struct Breaklabel *previous; /* chain */ |
43 | int breaklist; /* list of jumps out of this loop */ | 43 | int breaklist; /* list of jumps out of this loop */ |
44 | int nactloc; /* # of active local variables outside the breakable structure */ | ||
44 | } Breaklabel; | 45 | } Breaklabel; |
45 | 46 | ||
46 | 47 | ||
@@ -163,13 +164,29 @@ static void new_localvar (LexState *ls, TString *name, int n) { | |||
163 | 164 | ||
164 | static void adjustlocalvars (LexState *ls, int nvars) { | 165 | static void adjustlocalvars (LexState *ls, int nvars) { |
165 | FuncState *fs = ls->fs; | 166 | FuncState *fs = ls->fs; |
166 | while (nvars--) | 167 | while (nvars--) { |
167 | fs->f->locvars[fs->actloc[fs->nactloc++]].startpc = fs->pc; | 168 | fs->f->locvars[fs->actloc[fs->nactloc]].startpc = fs->pc; |
169 | resetbit(fs->wasup, fs->nactloc); | ||
170 | fs->nactloc++; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | |||
175 | static void closelevel (LexState *ls, int level) { | ||
176 | FuncState *fs = ls->fs; | ||
177 | int i; | ||
178 | for (i=level; i<fs->nactloc; i++) | ||
179 | if (testbit(fs->wasup, i)) { | ||
180 | luaK_codeABC(fs, OP_CLOSE, level, 0, 0); | ||
181 | return; | ||
182 | } | ||
183 | return; /* nothing to close */ | ||
168 | } | 184 | } |
169 | 185 | ||
170 | 186 | ||
171 | static void removelocalvars (LexState *ls, int nvars) { | 187 | static void removelocalvars (LexState *ls, int nvars) { |
172 | FuncState *fs = ls->fs; | 188 | FuncState *fs = ls->fs; |
189 | closelevel(ls, fs->nactloc - nvars); | ||
173 | while (nvars--) | 190 | while (nvars--) |
174 | fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; | 191 | fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; |
175 | } | 192 | } |
@@ -180,68 +197,47 @@ static void new_localvarstr (LexState *ls, const l_char *name, int n) { | |||
180 | } | 197 | } |
181 | 198 | ||
182 | 199 | ||
183 | static int search_local (LexState *ls, TString *n, expdesc *var) { | 200 | static int indexupvalue (FuncState *fs, expdesc *v) { |
184 | FuncState *fs; | ||
185 | int level = 0; | ||
186 | for (fs=ls->fs; fs; fs=fs->prev) { | ||
187 | int i; | ||
188 | for (i=fs->nactloc-1; i >= 0; i--) { | ||
189 | if (n == fs->f->locvars[fs->actloc[i]].varname) { | ||
190 | init_exp(var, VLOCAL, i); | ||
191 | return level; | ||
192 | } | ||
193 | } | ||
194 | level++; /* `var' not found; check outer level */ | ||
195 | } | ||
196 | init_exp(var, VGLOBAL, 0); /* not found in any level; must be global */ | ||
197 | return -1; | ||
198 | } | ||
199 | |||
200 | |||
201 | static void singlevar (LexState *ls, TString *n, expdesc *var) { | ||
202 | int level = search_local(ls, n, var); | ||
203 | if (level >= 1) /* neither local (0) nor global (-1)? */ | ||
204 | luaX_syntaxerror(ls, l_s("cannot access a variable in outer function"), | ||
205 | getstr(n)); | ||
206 | else if (level == -1) /* global? */ | ||
207 | var->u.i.info = luaK_stringk(ls->fs, n); | ||
208 | } | ||
209 | |||
210 | |||
211 | static int indexupvalue (LexState *ls, expdesc *v) { | ||
212 | FuncState *fs = ls->fs; | ||
213 | int i; | 201 | int i; |
214 | for (i=0; i<fs->f->nupvalues; i++) { | 202 | for (i=0; i<fs->f->nupvalues; i++) { |
215 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) | 203 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.i.info == v->u.i.info) |
216 | return i; | 204 | return i; |
217 | } | 205 | } |
218 | /* new one */ | 206 | /* new one */ |
219 | luaX_checklimit(ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues")); | 207 | luaX_checklimit(fs->ls, fs->f->nupvalues+1, MAXUPVALUES, l_s("upvalues")); |
220 | fs->upvalues[fs->f->nupvalues] = *v; | 208 | fs->upvalues[fs->f->nupvalues] = *v; |
221 | return fs->f->nupvalues++; | 209 | return fs->f->nupvalues++; |
222 | } | 210 | } |
223 | 211 | ||
224 | 212 | ||
225 | static void codeupvalue (LexState *ls, expdesc *v, TString *n) { | 213 | static void singlevar (FuncState *fs, TString *n, expdesc *var, int baselevel) { |
226 | FuncState *fs = ls->fs; | 214 | if (fs == NULL) |
227 | int level; | 215 | init_exp(var, VGLOBAL, 0); /* not local in any level; global variable */ |
228 | level = search_local(ls, n, v); | 216 | else { /* look up at current level */ |
229 | if (level == -1) { /* global? */ | 217 | int i; |
230 | if (fs->prev == NULL) | 218 | for (i=fs->nactloc-1; i >= 0; i--) { |
231 | luaX_syntaxerror(ls, l_s("cannot access an upvalue at top level"), | 219 | if (n == fs->f->locvars[fs->actloc[i]].varname) { |
232 | getstr(n)); | 220 | if (!baselevel) |
233 | v->u.i.info = luaK_stringk(fs->prev, n); | 221 | setbit(fs->wasup, i); /* will be upvalue in some other level */ |
234 | } | 222 | init_exp(var, VLOCAL, i); |
235 | else if (level != 1) { | 223 | return; |
236 | luaX_syntaxerror(ls, | 224 | } |
237 | l_s("upvalue must be global or local to immediately outer function"), | 225 | } |
238 | getstr(n)); | 226 | /* not found at current level; try upper one */ |
227 | singlevar(fs->prev, n, var, 0); | ||
228 | if (var->k == VGLOBAL) { | ||
229 | if (baselevel) | ||
230 | var->u.i.info = luaK_stringk(fs, n); /* info points to global name */ | ||
231 | } | ||
232 | else { /* local variable in some upper level? */ | ||
233 | var->u.i.info = indexupvalue(fs, var); | ||
234 | var->k = VUPVAL; /* upvalue in this level */ | ||
235 | } | ||
239 | } | 236 | } |
240 | init_exp(v, VRELOCABLE, | ||
241 | luaK_codeABc(fs, OP_LOADUPVAL, 0, indexupvalue(ls, v))); | ||
242 | } | 237 | } |
243 | 238 | ||
244 | 239 | ||
240 | |||
245 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | 241 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
246 | FuncState *fs = ls->fs; | 242 | FuncState *fs = ls->fs; |
247 | int extra = nvars - nexps; | 243 | int extra = nvars - nexps; |
@@ -278,6 +274,7 @@ static void code_params (LexState *ls, int nparams, short dots) { | |||
278 | 274 | ||
279 | static void enterbreak (FuncState *fs, Breaklabel *bl) { | 275 | static void enterbreak (FuncState *fs, Breaklabel *bl) { |
280 | bl->breaklist = NO_JUMP; | 276 | bl->breaklist = NO_JUMP; |
277 | bl->nactloc = fs->nactloc; | ||
281 | bl->previous = fs->bl; | 278 | bl->previous = fs->bl; |
282 | fs->bl = bl; | 279 | fs->bl = bl; |
283 | } | 280 | } |
@@ -286,6 +283,7 @@ static void enterbreak (FuncState *fs, Breaklabel *bl) { | |||
286 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 283 | static void leavebreak (FuncState *fs, Breaklabel *bl) { |
287 | fs->bl = bl->previous; | 284 | fs->bl = bl->previous; |
288 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | 285 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); |
286 | lua_assert(bl->nactloc == fs->nactloc); | ||
289 | } | 287 | } |
290 | 288 | ||
291 | 289 | ||
@@ -293,16 +291,14 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | |||
293 | FuncState *fs = ls->fs; | 291 | FuncState *fs = ls->fs; |
294 | Proto *f = fs->f; | 292 | Proto *f = fs->f; |
295 | int i; | 293 | int i; |
296 | int reg = fs->freereg; | ||
297 | for (i=0; i<func->f->nupvalues; i++) | ||
298 | luaK_exp2nextreg(fs, &func->upvalues[i]); | ||
299 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, | 294 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, |
300 | MAXARG_Bc, l_s("constant table overflow")); | 295 | MAXARG_Bc, l_s("constant table overflow")); |
301 | f->p[fs->np++] = func->f; | 296 | f->p[fs->np++] = func->f; |
302 | fs->freereg = reg; /* CLOSURE will consume those values */ | 297 | init_exp(v, VRELOCABLE, luaK_codeABc(fs, OP_CLOSURE, 0, fs->np-1)); |
303 | init_exp(v, VNONRELOC, reg); | 298 | for (i=0; i<func->f->nupvalues; i++) { |
304 | luaK_reserveregs(fs, 1); | 299 | luaK_exp2nextreg(fs, &func->upvalues[i]); |
305 | luaK_codeABc(fs, OP_CLOSURE, v->u.i.info, fs->np-1); | 300 | fs->freereg--; /* CLOSURE will use these values */ |
301 | } | ||
306 | } | 302 | } |
307 | 303 | ||
308 | 304 | ||
@@ -337,9 +333,9 @@ static void close_func (LexState *ls) { | |||
337 | lua_State *L = ls->L; | 333 | lua_State *L = ls->L; |
338 | FuncState *fs = ls->fs; | 334 | FuncState *fs = ls->fs; |
339 | Proto *f = fs->f; | 335 | Proto *f = fs->f; |
336 | removelocalvars(ls, fs->nactloc); | ||
340 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ | 337 | luaK_codeABC(fs, OP_RETURN, 0, 0, 0); /* final return */ |
341 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | 338 | luaK_getlabel(fs); /* close eventual list of pending jumps */ |
342 | removelocalvars(ls, fs->nactloc); | ||
343 | lua_assert(G(L)->roottable == fs->h); | 339 | lua_assert(G(L)->roottable == fs->h); |
344 | G(L)->roottable = fs->h->next; | 340 | G(L)->roottable = fs->h->next; |
345 | luaH_free(L, fs->h); | 341 | luaH_free(L, fs->h); |
@@ -644,16 +640,18 @@ static void primaryexp (LexState *ls, expdesc *v) { | |||
644 | return; | 640 | return; |
645 | } | 641 | } |
646 | case TK_NAME: { | 642 | case TK_NAME: { |
647 | singlevar(ls, str_checkname(ls), v); | 643 | singlevar(ls->fs, str_checkname(ls), v, 1); |
648 | next(ls); | 644 | next(ls); |
649 | return; | 645 | return; |
650 | } | 646 | } |
651 | case l_c('%'): { | 647 | case l_c('%'): { /* for compatibility only */ |
652 | next(ls); /* skip `%' */ | 648 | next(ls); /* skip `%' */ |
653 | codeupvalue(ls, v, str_checkname(ls)); | 649 | singlevar(ls->fs, str_checkname(ls), v, 1); |
650 | check_condition(ls, v->k == VUPVAL, l_s("global upvalues are deprecated")); | ||
654 | next(ls); | 651 | next(ls); |
655 | break; | 652 | return; |
656 | } | 653 | } |
654 | |||
657 | default: { | 655 | default: { |
658 | luaK_error(ls, l_s("unexpected symbol")); | 656 | luaK_error(ls, l_s("unexpected symbol")); |
659 | return; | 657 | return; |
@@ -812,7 +810,7 @@ static void block (LexState *ls) { | |||
812 | */ | 810 | */ |
813 | struct LHS_assign { | 811 | struct LHS_assign { |
814 | struct LHS_assign *prev; | 812 | struct LHS_assign *prev; |
815 | expdesc v; /* variable (global, local, or indexed) */ | 813 | expdesc v; /* variable (global, local, upvalue, or indexed) */ |
816 | }; | 814 | }; |
817 | 815 | ||
818 | 816 | ||
@@ -847,9 +845,8 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
847 | 845 | ||
848 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 846 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { |
849 | expdesc e; | 847 | expdesc e; |
850 | check_condition(ls, lh->v.k == VLOCAL || lh->v.k == VGLOBAL || | 848 | check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, |
851 | lh->v.k == VINDEXED, | 849 | l_s("syntax error!!")); |
852 | l_s("syntax error")); | ||
853 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ | 850 | if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ |
854 | struct LHS_assign nv; | 851 | struct LHS_assign nv; |
855 | nv.prev = lh; | 852 | nv.prev = lh; |
@@ -1054,7 +1051,7 @@ static void localstat (LexState *ls) { | |||
1054 | static int funcname (LexState *ls, expdesc *v) { | 1051 | static int funcname (LexState *ls, expdesc *v) { |
1055 | /* funcname -> NAME {field} [`:' NAME] */ | 1052 | /* funcname -> NAME {field} [`:' NAME] */ |
1056 | int needself = 0; | 1053 | int needself = 0; |
1057 | singlevar(ls, str_checkname(ls), v); | 1054 | singlevar(ls->fs, str_checkname(ls), v, 1); |
1058 | next(ls); /* skip var name */ | 1055 | next(ls); /* skip var name */ |
1059 | while (ls->t.token == l_c('.')) { | 1056 | while (ls->t.token == l_c('.')) { |
1060 | luaY_field(ls, v); | 1057 | luaY_field(ls, v); |
@@ -1102,25 +1099,19 @@ static void retstat (LexState *ls) { | |||
1102 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) | 1099 | if (block_follow(ls->t.token) || ls->t.token == l_c(';')) |
1103 | first = nret = 0; /* return no values */ | 1100 | first = nret = 0; /* return no values */ |
1104 | else { | 1101 | else { |
1105 | int n = explist1(ls, &e); /* optional return values */ | 1102 | explist1(ls, &e); /* optional return values */ |
1106 | if (e.k == VCALL) { | 1103 | if (e.k == VCALL) { |
1107 | luaK_setcallreturns(fs, &e, LUA_MULTRET); | 1104 | luaK_setcallreturns(fs, &e, LUA_MULTRET); |
1108 | first = fs->nactloc; | 1105 | first = fs->nactloc; |
1109 | nret = NO_REG; /* return all values */ | 1106 | nret = NO_REG; /* return all values */ |
1110 | } | 1107 | } |
1111 | else { | 1108 | else { |
1112 | if (n == 1) { /* only one value? */ | 1109 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ |
1113 | luaK_exp2anyreg(fs, &e); | 1110 | first = fs->nactloc; |
1114 | first = e.u.i.info; | 1111 | nret = fs->freereg - first; /* return all `active' values */ |
1115 | nret = 1; /* return only this value */ | ||
1116 | } | ||
1117 | else { | ||
1118 | luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ | ||
1119 | first = fs->nactloc; | ||
1120 | nret = fs->freereg - first; /* return all `active' values */ | ||
1121 | } | ||
1122 | } | 1112 | } |
1123 | } | 1113 | } |
1114 | closelevel(ls, 0); | ||
1124 | luaK_codeABC(fs, OP_RETURN, first, nret, 0); | 1115 | luaK_codeABC(fs, OP_RETURN, first, nret, 0); |
1125 | fs->freereg = fs->nactloc; /* removes all temp values */ | 1116 | fs->freereg = fs->nactloc; /* removes all temp values */ |
1126 | } | 1117 | } |
@@ -1133,8 +1124,8 @@ static void breakstat (LexState *ls) { | |||
1133 | if (!bl) | 1124 | if (!bl) |
1134 | luaK_error(ls, l_s("no loop to break")); | 1125 | luaK_error(ls, l_s("no loop to break")); |
1135 | next(ls); /* skip BREAK */ | 1126 | next(ls); /* skip BREAK */ |
1127 | closelevel(ls, bl->nactloc); | ||
1136 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | 1128 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); |
1137 | /* correct stack for compiler and symbolic execution */ | ||
1138 | } | 1129 | } |
1139 | 1130 | ||
1140 | 1131 | ||