diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-14 15:01:52 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-14 15:01:52 -0300 |
commit | 7ff21273d66541ac19ad817f90e8bcea5790f355 (patch) | |
tree | 9798243bbc84da7f0ea3aa7316ba42b06b947e63 | |
parent | 207dad86065acf4b6168bea1f13e88b7306a7440 (diff) | |
download | lua-7ff21273d66541ac19ad817f90e8bcea5790f355.tar.gz lua-7ff21273d66541ac19ad817f90e8bcea5790f355.tar.bz2 lua-7ff21273d66541ac19ad817f90e8bcea5790f355.zip |
implementation of `global' statement
-rw-r--r-- | llimits.h | 8 | ||||
-rw-r--r-- | lparser.c | 269 | ||||
-rw-r--r-- | lparser.h | 36 | ||||
-rw-r--r-- | ltests.c | 4 |
4 files changed, 211 insertions, 106 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: llimits.h,v 1.38 2002/03/05 16:22:54 roberto Exp roberto $ | 2 | ** $Id: llimits.h,v 1.39 2002/03/07 18:11:51 roberto Exp roberto $ |
3 | ** Limits, basic types, and some other `installation-dependent' definitions | 3 | ** Limits, basic types, and some other `installation-dependent' definitions |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -96,9 +96,9 @@ typedef unsigned long Instruction; | |||
96 | #define MAXSTACK 250 | 96 | #define MAXSTACK 250 |
97 | 97 | ||
98 | 98 | ||
99 | /* maximum number of local variables */ | 99 | /* maximum number of variables declared in a function */ |
100 | #ifndef MAXLOCALS | 100 | #ifndef MAXVARS |
101 | #define MAXLOCALS 200 /* arbitrary limit (<MAXSTACK) */ | 101 | #define MAXVARS 200 /* arbitrary limit (<MAXSTACK) */ |
102 | #endif | 102 | #endif |
103 | 103 | ||
104 | 104 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.167 2002/02/14 21:46:58 roberto Exp $ | 2 | ** $Id: lparser.c,v 1.168 2002/03/08 19:10:32 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -24,14 +24,17 @@ | |||
24 | 24 | ||
25 | 25 | ||
26 | /* | 26 | /* |
27 | ** nodes for break list (list of active breakable loops) | 27 | ** nodes for block list (list of active blocks) |
28 | */ | 28 | */ |
29 | typedef struct Breaklabel { | 29 | typedef struct BlockCnt { |
30 | struct Breaklabel *previous; /* chain */ | 30 | struct BlockCnt *previous; /* chain */ |
31 | int breaklist; /* list of jumps out of this loop */ | 31 | int breaklist; /* list of jumps out of this loop */ |
32 | int nactloc; /* # of active local variables outside the breakable structure */ | 32 | int nactloc; /* # active local variables outside the breakable structure */ |
33 | } Breaklabel; | 33 | int nactvar; |
34 | 34 | int defaultglob; | |
35 | int upval; /* true if some variable in the block is an upvalue */ | ||
36 | int isbreakable; /* true if `block' is a loop */ | ||
37 | } BlockCnt; | ||
35 | 38 | ||
36 | 39 | ||
37 | 40 | ||
@@ -77,9 +80,7 @@ static void check (LexState *ls, int c) { | |||
77 | } | 80 | } |
78 | 81 | ||
79 | 82 | ||
80 | static void check_condition (LexState *ls, int c, const char *msg) { | 83 | #define check_condition(ls,c,msg) { if (!(c)) luaK_error(ls, msg); } |
81 | if (!c) luaK_error(ls, msg); | ||
82 | } | ||
83 | 84 | ||
84 | 85 | ||
85 | static int optional (LexState *ls, int c) { | 86 | static int optional (LexState *ls, int c) { |
@@ -143,41 +144,51 @@ static int luaI_registerlocalvar (LexState *ls, TString *varname) { | |||
143 | } | 144 | } |
144 | 145 | ||
145 | 146 | ||
146 | static void new_localvar (LexState *ls, TString *name, int n) { | 147 | static vardesc *new_var (LexState *ls, int n) { |
147 | FuncState *fs = ls->fs; | 148 | FuncState *fs = ls->fs; |
148 | luaX_checklimit(ls, fs->nactloc+n+1, MAXLOCALS, "local variables"); | 149 | luaX_checklimit(ls, fs->nactvar+n+1, MAXVARS, "variables"); |
149 | fs->actloc[fs->nactloc+n] = luaI_registerlocalvar(ls, name); | 150 | return &fs->actvar[fs->nactvar+n]; |
151 | } | ||
152 | |||
153 | |||
154 | static void new_localvar (LexState *ls, TString *name, int n) { | ||
155 | vardesc *v = new_var(ls, n); | ||
156 | v->k = VLOCAL; | ||
157 | v->i = luaI_registerlocalvar(ls, name); | ||
158 | v->level = ls->fs->nactloc + n; | ||
150 | } | 159 | } |
151 | 160 | ||
152 | 161 | ||
153 | static void adjustlocalvars (LexState *ls, int nvars) { | 162 | static void adjustlocalvars (LexState *ls, int nvars) { |
154 | FuncState *fs = ls->fs; | 163 | FuncState *fs = ls->fs; |
155 | while (nvars--) { | 164 | while (nvars--) { |
156 | fs->f->locvars[fs->actloc[fs->nactloc]].startpc = fs->pc; | 165 | lua_assert(fs->actvar[fs->nactvar].k == VLOCAL); |
157 | resetbit(fs->wasup, fs->nactloc); | 166 | fs->f->locvars[fs->actvar[fs->nactvar].i].startpc = fs->pc; |
167 | fs->nactvar++; | ||
158 | fs->nactloc++; | 168 | fs->nactloc++; |
159 | } | 169 | } |
160 | } | 170 | } |
161 | 171 | ||
162 | 172 | ||
163 | static void closelevel (LexState *ls, int level) { | 173 | static void adjustglobalvars (LexState *ls, int nvars, int level) { |
164 | FuncState *fs = ls->fs; | 174 | FuncState *fs = ls->fs; |
165 | int i; | 175 | while (nvars--) { |
166 | for (i=level; i<fs->nactloc; i++) | 176 | fs->actvar[fs->nactvar].k = VGLOBAL; |
167 | if (testbit(fs->wasup, i)) { | 177 | fs->actvar[fs->nactvar].level = level; |
168 | luaK_codeABC(fs, OP_CLOSE, level, 0, 0); | 178 | fs->nactvar++; |
169 | return; | 179 | } |
170 | } | ||
171 | return; /* nothing to close */ | ||
172 | } | 180 | } |
173 | 181 | ||
174 | 182 | ||
175 | static void removelocalvars (LexState *ls, int nvars, int toclose) { | 183 | static void removevars (LexState *ls, int tolevel) { |
176 | FuncState *fs = ls->fs; | 184 | FuncState *fs = ls->fs; |
177 | if (toclose) | 185 | while (fs->nactvar > tolevel) { |
178 | closelevel(ls, fs->nactloc - nvars); | 186 | fs->nactvar--; |
179 | while (nvars--) | 187 | if (fs->actvar[fs->nactvar].k == VLOCAL) { |
180 | fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; | 188 | fs->nactloc--; |
189 | fs->f->locvars[fs->actvar[fs->nactvar].i].endpc = fs->pc; | ||
190 | } | ||
191 | } | ||
181 | } | 192 | } |
182 | 193 | ||
183 | 194 | ||
@@ -186,6 +197,12 @@ static void new_localvarstr (LexState *ls, const char *name, int n) { | |||
186 | } | 197 | } |
187 | 198 | ||
188 | 199 | ||
200 | static void create_local (LexState *ls, const char *name) { | ||
201 | new_localvarstr(ls, name, 0); | ||
202 | adjustlocalvars(ls, 1); | ||
203 | } | ||
204 | |||
205 | |||
189 | static int indexupvalue (FuncState *fs, expdesc *v) { | 206 | static int indexupvalue (FuncState *fs, expdesc *v) { |
190 | int i; | 207 | int i; |
191 | for (i=0; i<fs->f->nupvalues; i++) { | 208 | for (i=0; i<fs->f->nupvalues; i++) { |
@@ -199,28 +216,72 @@ static int indexupvalue (FuncState *fs, expdesc *v) { | |||
199 | } | 216 | } |
200 | 217 | ||
201 | 218 | ||
202 | static void singlevar (FuncState *fs, TString *n, expdesc *var, int baselevel) { | 219 | static vardesc *searchvar (FuncState *fs, TString *n) { |
203 | if (fs == NULL) | 220 | int i; |
204 | init_exp(var, VGLOBAL, 0); /* not local in any level; global variable */ | 221 | for (i=fs->nactvar-1; i >= 0; i--) { |
205 | else { /* look up at current level */ | 222 | vardesc *v = &fs->actvar[i]; |
206 | int i; | 223 | if (v->k == VLOCAL ? n == fs->f->locvars[v->i].varname |
207 | for (i=fs->nactloc-1; i >= 0; i--) { | 224 | : n == tsvalue(&fs->f->k[v->i])) |
208 | if (n == fs->f->locvars[fs->actloc[i]].varname) { | 225 | return v; |
209 | if (!baselevel) | 226 | } |
210 | setbit(fs->wasup, i); /* will be upvalue in some other level */ | 227 | return NULL; /* not found */ |
211 | init_exp(var, VLOCAL, i); | 228 | } |
212 | return; | 229 | |
230 | |||
231 | static void markupval (FuncState *fs, int level) { | ||
232 | BlockCnt *bl = fs->bl; | ||
233 | while (bl && bl->nactloc > level) bl = bl->previous; | ||
234 | if (bl) bl->upval = 1; | ||
235 | } | ||
236 | |||
237 | |||
238 | static int singlevar_aux (FuncState *fs, TString *n, expdesc *var, int nd) { | ||
239 | if (fs == NULL) { /* no more levels? */ | ||
240 | init_exp(var, VGLOBAL, NO_REG); /* default is free global */ | ||
241 | return VNIL; /* not found */ | ||
242 | } | ||
243 | else { | ||
244 | vardesc *v = searchvar(fs, n); /* look up at current level */ | ||
245 | if (v) { | ||
246 | if (v->level == NO_REG) { /* free global? */ | ||
247 | lua_assert(v->k == VGLOBAL); | ||
248 | init_exp(var, VGLOBAL, NO_REG); | ||
213 | } | 249 | } |
250 | else | ||
251 | init_exp(var, VLOCAL, v->level); | ||
252 | return v->k; | ||
214 | } | 253 | } |
215 | /* not found at current level; try upper one */ | 254 | else { /* not found at current level; try upper one */ |
216 | singlevar(fs->prev, n, var, 0); | 255 | int k = singlevar_aux(fs->prev, n, var, nd && fs->defaultglob == NO_REG); |
217 | if (var->k == VGLOBAL) { | 256 | if (var->k == VGLOBAL) { |
218 | if (baselevel) | 257 | if (k == VNIL && nd && fs->defaultglob != NO_REG) { |
219 | var->info = luaK_stringK(fs, n); /* info points to global name */ | 258 | init_exp(var, VLOCAL, fs->defaultglob); |
259 | k = VGLOBAL; /* now there is a declaration */ | ||
260 | } | ||
261 | } | ||
262 | else { /* LOCAL or UPVAL */ | ||
263 | if (var->k == VLOCAL) | ||
264 | markupval(fs->prev, var->info); /* local will be used as an upval */ | ||
265 | var->info = indexupvalue(fs, var); | ||
266 | var->k = VUPVAL; /* upvalue in this level */ | ||
267 | } | ||
268 | return k; | ||
220 | } | 269 | } |
221 | else { /* local variable in some upper level? */ | 270 | } |
222 | var->info = indexupvalue(fs, var); | 271 | } |
223 | var->k = VUPVAL; /* upvalue in this level */ | 272 | |
273 | |||
274 | static void singlevar (FuncState *fs, TString *n, expdesc *var) { | ||
275 | int k = singlevar_aux(fs, n, var, 1); | ||
276 | if (k == VNIL || k == VGLOBAL) { /* global? */ | ||
277 | if (var->k == VGLOBAL) /* free global? */ | ||
278 | var->info = luaK_stringK(fs, n); | ||
279 | else { /* `indexed' global */ | ||
280 | expdesc e; | ||
281 | codestring(fs->ls, &e, n); | ||
282 | luaK_exp2anyreg(fs, var); | ||
283 | var->aux = luaK_exp2RK(fs, &e); | ||
284 | var->k = VINDEXED; | ||
224 | } | 285 | } |
225 | } | 286 | } |
226 | } | 287 | } |
@@ -250,29 +311,38 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
250 | static void code_params (LexState *ls, int nparams, int dots) { | 311 | static void code_params (LexState *ls, int nparams, int dots) { |
251 | FuncState *fs = ls->fs; | 312 | FuncState *fs = ls->fs; |
252 | adjustlocalvars(ls, nparams); | 313 | adjustlocalvars(ls, nparams); |
253 | luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); | 314 | luaX_checklimit(ls, fs->nactvar, MAXPARAMS, "parameters"); |
254 | fs->f->numparams = cast(lu_byte, fs->nactloc); | 315 | fs->f->numparams = cast(lu_byte, fs->nactloc); |
255 | fs->f->is_vararg = cast(lu_byte, dots); | 316 | fs->f->is_vararg = cast(lu_byte, dots); |
256 | if (dots) { | 317 | if (dots) |
257 | new_localvarstr(ls, "arg", 0); | 318 | create_local(ls, "arg"); |
258 | adjustlocalvars(ls, 1); | ||
259 | } | ||
260 | luaK_reserveregs(fs, fs->nactloc); /* reserve register for parameters */ | 319 | luaK_reserveregs(fs, fs->nactloc); /* reserve register for parameters */ |
261 | } | 320 | } |
262 | 321 | ||
263 | 322 | ||
264 | static void enterbreak (FuncState *fs, Breaklabel *bl) { | 323 | static void enterblock (FuncState *fs, BlockCnt *bl, int isbreakable) { |
265 | bl->breaklist = NO_JUMP; | 324 | bl->breaklist = NO_JUMP; |
325 | bl->isbreakable = isbreakable; | ||
266 | bl->nactloc = fs->nactloc; | 326 | bl->nactloc = fs->nactloc; |
327 | bl->nactvar = fs->nactvar; | ||
328 | bl->defaultglob = fs->defaultglob; | ||
329 | bl->upval = 0; | ||
267 | bl->previous = fs->bl; | 330 | bl->previous = fs->bl; |
268 | fs->bl = bl; | 331 | fs->bl = bl; |
269 | } | 332 | } |
270 | 333 | ||
271 | 334 | ||
272 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | 335 | static void leaveblock (FuncState *fs) { |
336 | BlockCnt *bl = fs->bl; | ||
273 | fs->bl = bl->previous; | 337 | fs->bl = bl->previous; |
274 | luaK_patchtohere(fs, bl->breaklist); | 338 | removevars(fs->ls, bl->nactvar); |
339 | if (bl->upval) | ||
340 | luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0); | ||
275 | lua_assert(bl->nactloc == fs->nactloc); | 341 | lua_assert(bl->nactloc == fs->nactloc); |
342 | lua_assert(bl->nactvar == fs->nactvar); | ||
343 | fs->defaultglob = bl->defaultglob; | ||
344 | fs->freereg = bl->nactloc; /* free registers used by locals */ | ||
345 | luaK_patchtohere(fs, bl->breaklist); | ||
276 | } | 346 | } |
277 | 347 | ||
278 | 348 | ||
@@ -308,7 +378,9 @@ static void open_func (LexState *ls, FuncState *fs) { | |||
308 | fs->nlineinfo = 0; | 378 | fs->nlineinfo = 0; |
309 | fs->nlocvars = 0; | 379 | fs->nlocvars = 0; |
310 | fs->nactloc = 0; | 380 | fs->nactloc = 0; |
381 | fs->nactvar = 0; | ||
311 | fs->lastline = 0; | 382 | fs->lastline = 0; |
383 | fs->defaultglob = NO_REG; /* default is free globals */ | ||
312 | fs->bl = NULL; | 384 | fs->bl = NULL; |
313 | f->code = NULL; | 385 | f->code = NULL; |
314 | f->source = ls->source; | 386 | f->source = ls->source; |
@@ -322,7 +394,7 @@ static void close_func (LexState *ls) { | |||
322 | lua_State *L = ls->L; | 394 | lua_State *L = ls->L; |
323 | FuncState *fs = ls->fs; | 395 | FuncState *fs = ls->fs; |
324 | Proto *f = fs->f; | 396 | Proto *f = fs->f; |
325 | removelocalvars(ls, fs->nactloc, 0); | 397 | removevars(ls, 0); |
326 | luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ | 398 | luaK_codeABC(fs, OP_RETURN, 0, 1, 0); /* final return */ |
327 | luaK_getlabel(fs); /* close eventual list of pending jumps */ | 399 | luaK_getlabel(fs); /* close eventual list of pending jumps */ |
328 | lua_assert(G(L)->roottable == fs->h); | 400 | lua_assert(G(L)->roottable == fs->h); |
@@ -352,8 +424,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { | |||
352 | open_func(&lexstate, &funcstate); | 424 | open_func(&lexstate, &funcstate); |
353 | next(&lexstate); /* read first token */ | 425 | next(&lexstate); /* read first token */ |
354 | chunk(&lexstate); | 426 | chunk(&lexstate); |
355 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), | 427 | check_condition(&lexstate, (lexstate.t.token == TK_EOS), "<eof> expected"); |
356 | "<eof> expected"); | ||
357 | close_func(&lexstate); | 428 | close_func(&lexstate); |
358 | lua_assert(funcstate.prev == NULL); | 429 | lua_assert(funcstate.prev == NULL); |
359 | lua_assert(funcstate.f->nupvalues == 0); | 430 | lua_assert(funcstate.f->nupvalues == 0); |
@@ -593,13 +664,13 @@ static void prefixexp (LexState *ls, expdesc *v) { | |||
593 | return; | 664 | return; |
594 | } | 665 | } |
595 | case TK_NAME: { | 666 | case TK_NAME: { |
596 | singlevar(ls->fs, str_checkname(ls), v, 1); | 667 | singlevar(ls->fs, str_checkname(ls), v); |
597 | next(ls); | 668 | next(ls); |
598 | return; | 669 | return; |
599 | } | 670 | } |
600 | case '%': { /* for compatibility only */ | 671 | case '%': { /* for compatibility only */ |
601 | next(ls); /* skip `%' */ | 672 | next(ls); /* skip `%' */ |
602 | singlevar(ls->fs, str_checkname(ls), v, 1); | 673 | singlevar(ls->fs, str_checkname(ls), v); |
603 | check_condition(ls, v->k == VUPVAL, "global upvalues are obsolete"); | 674 | check_condition(ls, v->k == VUPVAL, "global upvalues are obsolete"); |
604 | next(ls); | 675 | next(ls); |
605 | return; | 676 | return; |
@@ -797,10 +868,11 @@ static int block_follow (int token) { | |||
797 | static void block (LexState *ls) { | 868 | static void block (LexState *ls) { |
798 | /* block -> chunk */ | 869 | /* block -> chunk */ |
799 | FuncState *fs = ls->fs; | 870 | FuncState *fs = ls->fs; |
800 | int nactloc = fs->nactloc; | 871 | BlockCnt bl; |
872 | enterblock(fs, &bl, 0); | ||
801 | chunk(ls); | 873 | chunk(ls); |
802 | removelocalvars(ls, fs->nactloc - nactloc, 1); | 874 | lua_assert(bl.breaklist == NO_JUMP); |
803 | fs->freereg = nactloc; /* free registers used by locals */ | 875 | leaveblock(fs); |
804 | } | 876 | } |
805 | 877 | ||
806 | 878 | ||
@@ -887,8 +959,8 @@ static void whilestat (LexState *ls, int line) { | |||
887 | FuncState *fs = ls->fs; | 959 | FuncState *fs = ls->fs; |
888 | int while_init = luaK_getlabel(fs); | 960 | int while_init = luaK_getlabel(fs); |
889 | expdesc v; | 961 | expdesc v; |
890 | Breaklabel bl; | 962 | BlockCnt bl; |
891 | enterbreak(fs, &bl); | 963 | enterblock(fs, &bl, 1); |
892 | next(ls); | 964 | next(ls); |
893 | cond(ls, &v); | 965 | cond(ls, &v); |
894 | check(ls, TK_DO); | 966 | check(ls, TK_DO); |
@@ -896,7 +968,7 @@ static void whilestat (LexState *ls, int line) { | |||
896 | luaK_patchlist(fs, luaK_jump(fs), while_init); | 968 | luaK_patchlist(fs, luaK_jump(fs), while_init); |
897 | luaK_patchtohere(fs, v.f); | 969 | luaK_patchtohere(fs, v.f); |
898 | check_match(ls, TK_END, TK_WHILE, line); | 970 | check_match(ls, TK_END, TK_WHILE, line); |
899 | leavebreak(fs, &bl); | 971 | leaveblock(fs); |
900 | } | 972 | } |
901 | 973 | ||
902 | 974 | ||
@@ -905,14 +977,14 @@ static void repeatstat (LexState *ls, int line) { | |||
905 | FuncState *fs = ls->fs; | 977 | FuncState *fs = ls->fs; |
906 | int repeat_init = luaK_getlabel(fs); | 978 | int repeat_init = luaK_getlabel(fs); |
907 | expdesc v; | 979 | expdesc v; |
908 | Breaklabel bl; | 980 | BlockCnt bl; |
909 | enterbreak(fs, &bl); | 981 | enterblock(fs, &bl, 1); |
910 | next(ls); | 982 | next(ls); |
911 | block(ls); | 983 | block(ls); |
912 | check_match(ls, TK_UNTIL, TK_REPEAT, line); | 984 | check_match(ls, TK_UNTIL, TK_REPEAT, line); |
913 | cond(ls, &v); | 985 | cond(ls, &v); |
914 | luaK_patchlist(fs, v.f, repeat_init); | 986 | luaK_patchlist(fs, v.f, repeat_init); |
915 | leavebreak(fs, &bl); | 987 | leaveblock(fs); |
916 | } | 988 | } |
917 | 989 | ||
918 | 990 | ||
@@ -949,7 +1021,6 @@ static void fornum (LexState *ls, TString *varname) { | |||
949 | block(ls); | 1021 | block(ls); |
950 | luaK_patchtohere(fs, prep-1); | 1022 | luaK_patchtohere(fs, prep-1); |
951 | luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep); | 1023 | luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep); |
952 | removelocalvars(ls, 3, 1); | ||
953 | } | 1024 | } |
954 | 1025 | ||
955 | 1026 | ||
@@ -977,7 +1048,6 @@ static void forlist (LexState *ls, TString *indexname) { | |||
977 | block(ls); | 1048 | block(ls); |
978 | luaK_patchlist(fs, luaK_jump(fs), prep-1); | 1049 | luaK_patchlist(fs, luaK_jump(fs), prep-1); |
979 | luaK_patchtohere(fs, prep); | 1050 | luaK_patchtohere(fs, prep); |
980 | removelocalvars(ls, nvars+1, 1); | ||
981 | } | 1051 | } |
982 | 1052 | ||
983 | 1053 | ||
@@ -985,8 +1055,8 @@ static void forstat (LexState *ls, int line) { | |||
985 | /* forstat -> fornum | forlist */ | 1055 | /* forstat -> fornum | forlist */ |
986 | FuncState *fs = ls->fs; | 1056 | FuncState *fs = ls->fs; |
987 | TString *varname; | 1057 | TString *varname; |
988 | Breaklabel bl; | 1058 | BlockCnt bl; |
989 | enterbreak(fs, &bl); | 1059 | enterblock(fs, &bl, 1); |
990 | next(ls); /* skip `for' */ | 1060 | next(ls); /* skip `for' */ |
991 | varname = str_checkname(ls); /* first variable name */ | 1061 | varname = str_checkname(ls); /* first variable name */ |
992 | next(ls); /* skip var name */ | 1062 | next(ls); /* skip var name */ |
@@ -996,7 +1066,7 @@ static void forstat (LexState *ls, int line) { | |||
996 | default: luaK_error(ls, "`=' or `in' expected"); | 1066 | default: luaK_error(ls, "`=' or `in' expected"); |
997 | } | 1067 | } |
998 | check_match(ls, TK_END, TK_FOR, line); | 1068 | check_match(ls, TK_END, TK_FOR, line); |
999 | leavebreak(fs, &bl); | 1069 | leaveblock(fs); |
1000 | } | 1070 | } |
1001 | 1071 | ||
1002 | 1072 | ||
@@ -1054,10 +1124,37 @@ static void localstat (LexState *ls) { | |||
1054 | } | 1124 | } |
1055 | 1125 | ||
1056 | 1126 | ||
1127 | static void globalstat (LexState *ls) { | ||
1128 | /* stat -> GLOBAL NAME {`,' NAME} [IN exp] | GLOBAL IN exp */ | ||
1129 | FuncState *fs = ls->fs; | ||
1130 | next(ls); /* skip GLOBAL */ | ||
1131 | if (optional(ls, TK_IN)) { /* default declaration? */ | ||
1132 | exp1(ls); | ||
1133 | fs->defaultglob = fs->freereg - 1; | ||
1134 | create_local(ls, "(global table)"); | ||
1135 | } | ||
1136 | else { | ||
1137 | int nvars = 0; | ||
1138 | do { | ||
1139 | vardesc *v = new_var(ls, nvars++); | ||
1140 | v->i = luaK_stringK(ls->fs, str_checkname(ls)); | ||
1141 | next(ls); /* skip name */ | ||
1142 | } while (optional(ls, ',')); | ||
1143 | if (!optional(ls, TK_IN)) | ||
1144 | adjustglobalvars(ls, nvars, NO_REG); /* free globals */ | ||
1145 | else { | ||
1146 | exp1(ls); | ||
1147 | adjustglobalvars(ls, nvars, ls->fs->freereg - 1); | ||
1148 | create_local(ls, "(global table)"); | ||
1149 | } | ||
1150 | } | ||
1151 | } | ||
1152 | |||
1153 | |||
1057 | static int funcname (LexState *ls, expdesc *v) { | 1154 | static int funcname (LexState *ls, expdesc *v) { |
1058 | /* funcname -> NAME {field} [`:' NAME] */ | 1155 | /* funcname -> NAME {field} [`:' NAME] */ |
1059 | int needself = 0; | 1156 | int needself = 0; |
1060 | singlevar(ls->fs, str_checkname(ls), v, 1); | 1157 | singlevar(ls->fs, str_checkname(ls), v); |
1061 | next(ls); /* skip var name */ | 1158 | next(ls); /* skip var name */ |
1062 | while (ls->t.token == '.') { | 1159 | while (ls->t.token == '.') { |
1063 | luaY_field(ls, v); | 1160 | luaY_field(ls, v); |
@@ -1125,11 +1222,17 @@ static void retstat (LexState *ls) { | |||
1125 | static void breakstat (LexState *ls) { | 1222 | static void breakstat (LexState *ls) { |
1126 | /* stat -> BREAK [NAME] */ | 1223 | /* stat -> BREAK [NAME] */ |
1127 | FuncState *fs = ls->fs; | 1224 | FuncState *fs = ls->fs; |
1128 | Breaklabel *bl = fs->bl; | 1225 | BlockCnt *bl = fs->bl; |
1226 | int upval = 0; | ||
1227 | next(ls); /* skip BREAK */ | ||
1228 | while (bl && !bl->isbreakable) { | ||
1229 | upval |= bl->upval; | ||
1230 | bl = bl->previous; | ||
1231 | } | ||
1129 | if (!bl) | 1232 | if (!bl) |
1130 | luaK_error(ls, "no loop to break"); | 1233 | luaK_error(ls, "no loop to break"); |
1131 | next(ls); /* skip BREAK */ | 1234 | if (upval) |
1132 | closelevel(ls, bl->nactloc); | 1235 | luaK_codeABC(fs, OP_CLOSE, bl->nactloc, 0, 0); |
1133 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | 1236 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); |
1134 | } | 1237 | } |
1135 | 1238 | ||
@@ -1167,6 +1270,10 @@ static int statement (LexState *ls) { | |||
1167 | localstat(ls); | 1270 | localstat(ls); |
1168 | return 0; | 1271 | return 0; |
1169 | } | 1272 | } |
1273 | case TK_GLOBAL: { /* stat -> globalstat */ | ||
1274 | globalstat(ls); | ||
1275 | return 0; | ||
1276 | } | ||
1170 | case TK_RETURN: { /* stat -> retstat */ | 1277 | case TK_RETURN: { /* stat -> retstat */ |
1171 | retstat(ls); | 1278 | retstat(ls); |
1172 | return 1; /* must be last statement */ | 1279 | return 1; /* must be last statement */ |
@@ -1207,10 +1314,8 @@ static void body (LexState *ls, expdesc *e, int needself, int line) { | |||
1207 | open_func(ls, &new_fs); | 1314 | open_func(ls, &new_fs); |
1208 | new_fs.f->lineDefined = line; | 1315 | new_fs.f->lineDefined = line; |
1209 | check(ls, '('); | 1316 | check(ls, '('); |
1210 | if (needself) { | 1317 | if (needself) |
1211 | new_localvarstr(ls, "self", 0); | 1318 | create_local(ls, "self"); |
1212 | adjustlocalvars(ls, 1); | ||
1213 | } | ||
1214 | parlist(ls); | 1319 | parlist(ls); |
1215 | check(ls, ')'); | 1320 | check(ls, ')'); |
1216 | chunk(ls); | 1321 | chunk(ls); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ | 2 | ** $Id: lparser.h,v 1.39 2002/02/08 22:42:41 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -13,18 +13,6 @@ | |||
13 | #include "lzio.h" | 13 | #include "lzio.h" |
14 | 14 | ||
15 | 15 | ||
16 | |||
17 | /* small implementation of bit arrays */ | ||
18 | |||
19 | #define BPW (CHAR_BIT*sizeof(unsigned int)) /* bits per word */ | ||
20 | |||
21 | #define words2bits(b) (((b)-1)/BPW + 1) | ||
22 | |||
23 | #define setbit(a, b) ((a)[(b)/BPW] |= (1 << (b)%BPW)) | ||
24 | #define resetbit(a, b) ((a)[(b)/BPW] &= ~((1 << (b)%BPW))) | ||
25 | #define testbit(a, b) ((a)[(b)/BPW] & (1 << (b)%BPW)) | ||
26 | |||
27 | |||
28 | /* | 16 | /* |
29 | ** Expression descriptor | 17 | ** Expression descriptor |
30 | */ | 18 | */ |
@@ -37,7 +25,7 @@ typedef enum { | |||
37 | VK, /* info = index of constant in `k' */ | 25 | VK, /* info = index of constant in `k' */ |
38 | VLOCAL, /* info = local register */ | 26 | VLOCAL, /* info = local register */ |
39 | VUPVAL, /* info = index of upvalue in `upvalues' */ | 27 | VUPVAL, /* info = index of upvalue in `upvalues' */ |
40 | VGLOBAL, /* info = index of global name in `k' */ | 28 | VGLOBAL, /* info = index of table; aux = index of global name in `k' */ |
41 | VINDEXED, /* info = table register; aux = index register (or `k') */ | 29 | VINDEXED, /* info = table register; aux = index register (or `k') */ |
42 | VRELOCABLE, /* info = instruction pc */ | 30 | VRELOCABLE, /* info = instruction pc */ |
43 | VNONRELOC, /* info = result register */ | 31 | VNONRELOC, /* info = result register */ |
@@ -53,6 +41,18 @@ typedef struct expdesc { | |||
53 | } expdesc; | 41 | } expdesc; |
54 | 42 | ||
55 | 43 | ||
44 | /* describe declared variables */ | ||
45 | typedef struct vardesc { | ||
46 | int i; /* if local, its index in `locvars'; | ||
47 | if global, its name index in `k' */ | ||
48 | lu_byte k; | ||
49 | lu_byte level; /* if local, stack level; | ||
50 | if global, corresponding local (NO_REG for free globals) */ | ||
51 | } vardesc; | ||
52 | |||
53 | |||
54 | struct BlockCnt; /* defined in lparser.c */ | ||
55 | |||
56 | /* state needed to generate code for a given function */ | 56 | /* state needed to generate code for a given function */ |
57 | typedef struct FuncState { | 57 | typedef struct FuncState { |
58 | Proto *f; /* current function header */ | 58 | Proto *f; /* current function header */ |
@@ -60,21 +60,21 @@ typedef struct FuncState { | |||
60 | struct FuncState *prev; /* enclosing function */ | 60 | struct FuncState *prev; /* enclosing function */ |
61 | struct LexState *ls; /* lexical state */ | 61 | struct LexState *ls; /* lexical state */ |
62 | struct lua_State *L; /* copy of the Lua state */ | 62 | struct lua_State *L; /* copy of the Lua state */ |
63 | struct Breaklabel *bl; /* chain of breakable blocks */ | 63 | struct BlockCnt *bl; /* chain of current blocks */ |
64 | int pc; /* next position to code (equivalent to `ncode') */ | 64 | int pc; /* next position to code (equivalent to `ncode') */ |
65 | int lasttarget; /* `pc' of last `jump target' */ | 65 | int lasttarget; /* `pc' of last `jump target' */ |
66 | int jlt; /* list of jumps to `lasttarget' */ | 66 | int jlt; /* list of jumps to `lasttarget' */ |
67 | int freereg; /* first free register */ | 67 | int freereg; /* first free register */ |
68 | int defaultglob; /* where to look for non-declared globals */ | ||
68 | int nk; /* number of elements in `k' */ | 69 | int nk; /* number of elements in `k' */ |
69 | int np; /* number of elements in `p' */ | 70 | int np; /* number of elements in `p' */ |
70 | int nlineinfo; /* number of elements in `lineinfo' */ | 71 | int nlineinfo; /* number of elements in `lineinfo' */ |
71 | int nlocvars; /* number of elements in `locvars' */ | 72 | int nlocvars; /* number of elements in `locvars' */ |
72 | int nactloc; /* number of active local variables */ | 73 | int nactloc; /* number of active local variables */ |
74 | int nactvar; /* number of elements in array `actvar' */ | ||
73 | int lastline; /* line where last `lineinfo' was generated */ | 75 | int lastline; /* line where last `lineinfo' was generated */ |
74 | expdesc upvalues[MAXUPVALUES]; /* upvalues */ | 76 | expdesc upvalues[MAXUPVALUES]; /* upvalues */ |
75 | int actloc[MAXLOCALS]; /* local-variable stack (indices to locvars) */ | 77 | vardesc actvar[MAXVARS]; /* declared-variable stack */ |
76 | unsigned int wasup[words2bits(MAXLOCALS)]; /* bit array to mark whether a | ||
77 | local variable was used as upvalue at some level */ | ||
78 | } FuncState; | 78 | } FuncState; |
79 | 79 | ||
80 | 80 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 1.110 2002/03/04 15:26:56 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.111 2002/03/04 21:29:41 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -219,7 +219,7 @@ static int get_limits (lua_State *L) { | |||
219 | lua_newtable(L); | 219 | lua_newtable(L); |
220 | setnameval(L, "BITS_INT", BITS_INT); | 220 | setnameval(L, "BITS_INT", BITS_INT); |
221 | setnameval(L, "LFPF", LFIELDS_PER_FLUSH); | 221 | setnameval(L, "LFPF", LFIELDS_PER_FLUSH); |
222 | setnameval(L, "MAXLOCALS", MAXLOCALS); | 222 | setnameval(L, "MAXVARS", MAXVARS); |
223 | setnameval(L, "MAXPARAMS", MAXPARAMS); | 223 | setnameval(L, "MAXPARAMS", MAXPARAMS); |
224 | setnameval(L, "MAXSTACK", MAXSTACK); | 224 | setnameval(L, "MAXSTACK", MAXSTACK); |
225 | setnameval(L, "MAXUPVALUES", MAXUPVALUES); | 225 | setnameval(L, "MAXUPVALUES", MAXUPVALUES); |