diff options
Diffstat (limited to '')
-rw-r--r-- | lparser.c | 321 |
1 files changed, 234 insertions, 87 deletions
@@ -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 declarations 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 | ||
@@ -50,7 +50,7 @@ typedef struct BlockCnt { | |||
50 | struct BlockCnt *previous; /* chain */ | 50 | struct BlockCnt *previous; /* chain */ |
51 | int firstlabel; /* index of first label in this block */ | 51 | int firstlabel; /* index of first label in this block */ |
52 | int firstgoto; /* index of first pending goto in this block */ | 52 | int firstgoto; /* index of first pending goto in this block */ |
53 | lu_byte nactvar; /* # active locals outside the block */ | 53 | short nactvar; /* number of active declarations at block entry */ |
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. */ |
@@ -188,18 +188,16 @@ static short registerlocalvar (LexState *ls, FuncState *fs, | |||
188 | 188 | ||
189 | 189 | ||
190 | /* | 190 | /* |
191 | ** Create a new local variable with the given 'name' and given 'kind'. | 191 | ** Create a new variable with the given 'name' and given 'kind'. |
192 | ** Return its index in the function. | 192 | ** Return its index in the function. |
193 | */ | 193 | */ |
194 | static int new_localvarkind (LexState *ls, TString *name, lu_byte kind) { | 194 | static int new_varkind (LexState *ls, TString *name, lu_byte kind) { |
195 | lua_State *L = ls->L; | 195 | lua_State *L = ls->L; |
196 | FuncState *fs = ls->fs; | 196 | FuncState *fs = ls->fs; |
197 | Dyndata *dyd = ls->dyd; | 197 | Dyndata *dyd = ls->dyd; |
198 | Vardesc *var; | 198 | Vardesc *var; |
199 | luaY_checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, | ||
200 | MAXVARS, "local variables"); | ||
201 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, | 199 | luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, |
202 | dyd->actvar.size, Vardesc, SHRT_MAX, "local variables"); | 200 | dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarations"); |
203 | var = &dyd->actvar.arr[dyd->actvar.n++]; | 201 | var = &dyd->actvar.arr[dyd->actvar.n++]; |
204 | var->vd.kind = kind; /* default */ | 202 | var->vd.kind = kind; /* default */ |
205 | var->vd.name = name; | 203 | var->vd.name = name; |
@@ -211,7 +209,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. | 209 | ** Create a new local variable with the given 'name' and regular kind. |
212 | */ | 210 | */ |
213 | static int new_localvar (LexState *ls, TString *name) { | 211 | static int new_localvar (LexState *ls, TString *name) { |
214 | return new_localvarkind(ls, name, VDKREG); | 212 | return new_varkind(ls, name, VDKREG); |
215 | } | 213 | } |
216 | 214 | ||
217 | #define new_localvarliteral(ls,v) \ | 215 | #define new_localvarliteral(ls,v) \ |
@@ -238,7 +236,7 @@ static Vardesc *getlocalvardesc (FuncState *fs, int vidx) { | |||
238 | static lu_byte reglevel (FuncState *fs, int nvar) { | 236 | static lu_byte reglevel (FuncState *fs, int nvar) { |
239 | while (nvar-- > 0) { | 237 | while (nvar-- > 0) { |
240 | Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ | 238 | Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ |
241 | if (vd->vd.kind != RDKCTC) /* is in a register? */ | 239 | if (varinreg(vd)) /* is in a register? */ |
242 | return cast_byte(vd->vd.ridx + 1); | 240 | return cast_byte(vd->vd.ridx + 1); |
243 | } | 241 | } |
244 | return 0; /* no variables in registers */ | 242 | return 0; /* no variables in registers */ |
@@ -259,7 +257,7 @@ lu_byte luaY_nvarstack (FuncState *fs) { | |||
259 | */ | 257 | */ |
260 | static LocVar *localdebuginfo (FuncState *fs, int vidx) { | 258 | static LocVar *localdebuginfo (FuncState *fs, int vidx) { |
261 | Vardesc *vd = getlocalvardesc(fs, vidx); | 259 | Vardesc *vd = getlocalvardesc(fs, vidx); |
262 | if (vd->vd.kind == RDKCTC) | 260 | if (!varinreg(vd)) |
263 | return NULL; /* no debug info. for constants */ | 261 | return NULL; /* no debug info. for constants */ |
264 | else { | 262 | else { |
265 | int idx = vd->vd.pidx; | 263 | int idx = vd->vd.pidx; |
@@ -275,7 +273,7 @@ static LocVar *localdebuginfo (FuncState *fs, int vidx) { | |||
275 | static void init_var (FuncState *fs, expdesc *e, int vidx) { | 273 | static void init_var (FuncState *fs, expdesc *e, int vidx) { |
276 | e->f = e->t = NO_JUMP; | 274 | e->f = e->t = NO_JUMP; |
277 | e->k = VLOCAL; | 275 | e->k = VLOCAL; |
278 | e->u.var.vidx = cast(unsigned short, vidx); | 276 | e->u.var.vidx = cast_short(vidx); |
279 | e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; | 277 | e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; |
280 | } | 278 | } |
281 | 279 | ||
@@ -303,14 +301,18 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
303 | varname = up->name; | 301 | varname = up->name; |
304 | break; | 302 | break; |
305 | } | 303 | } |
304 | case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ | ||
305 | if (e->u.ind.ro) /* read-only? */ | ||
306 | varname = tsvalue(&fs->f->k[e->u.ind.keystr]); | ||
307 | break; | ||
308 | } | ||
306 | default: | 309 | default: |
307 | return; /* other cases cannot be read-only */ | 310 | lua_assert(e->k == VINDEXI); /* this one doesn't need any check */ |
308 | } | 311 | return; /* integer index cannot be read-only */ |
309 | if (varname) { | ||
310 | const char *msg = luaO_pushfstring(ls->L, | ||
311 | "attempt to assign to const variable '%s'", getstr(varname)); | ||
312 | luaK_semerror(ls, msg); /* error */ | ||
313 | } | 312 | } |
313 | if (varname) | ||
314 | luaK_semerror(ls, "attempt to assign to const variable '%s'", | ||
315 | getstr(varname)); | ||
314 | } | 316 | } |
315 | 317 | ||
316 | 318 | ||
@@ -326,6 +328,7 @@ static void adjustlocalvars (LexState *ls, int nvars) { | |||
326 | Vardesc *var = getlocalvardesc(fs, vidx); | 328 | Vardesc *var = getlocalvardesc(fs, vidx); |
327 | var->vd.ridx = cast_byte(reglevel++); | 329 | var->vd.ridx = cast_byte(reglevel++); |
328 | var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); | 330 | var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); |
331 | luaY_checklimit(fs, reglevel, MAXVARS, "local variables"); | ||
329 | } | 332 | } |
330 | } | 333 | } |
331 | 334 | ||
@@ -392,18 +395,38 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
392 | 395 | ||
393 | 396 | ||
394 | /* | 397 | /* |
395 | ** Look for an active local variable with the name 'n' in the | 398 | ** Look for an active variable with the name 'n' in the |
396 | ** function 'fs'. If found, initialize 'var' with it and return | 399 | ** function 'fs'. If found, initialize 'var' with it and return |
397 | ** its expression kind; otherwise return -1. | 400 | ** its expression kind; otherwise return -1. While searching, |
401 | ** var->u.info==-1 means that the preambular global declaration is | ||
402 | ** active (the default while there is no other global declaration); | ||
403 | ** var->u.info==-2 means there is no active collective declaration | ||
404 | ** (some previous global declaration but no collective declaration); | ||
405 | ** and var->u.info>=0 points to the inner-most (the first one found) | ||
406 | ** collective declaration, if there is one. | ||
398 | */ | 407 | */ |
399 | static int searchvar (FuncState *fs, TString *n, expdesc *var) { | 408 | static int searchvar (FuncState *fs, TString *n, expdesc *var) { |
400 | int i; | 409 | int i; |
401 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 410 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
402 | Vardesc *vd = getlocalvardesc(fs, i); | 411 | Vardesc *vd = getlocalvardesc(fs, i); |
403 | if (eqstr(n, vd->vd.name)) { /* found? */ | 412 | if (varglobal(vd)) { /* global declaration? */ |
413 | if (vd->vd.name == NULL) { /* collective declaration? */ | ||
414 | if (var->u.info < 0) /* no previous collective declaration? */ | ||
415 | var->u.info = fs->firstlocal + i; /* this is the first one */ | ||
416 | } | ||
417 | else { /* global name */ | ||
418 | if (eqstr(n, vd->vd.name)) { /* found? */ | ||
419 | init_exp(var, VGLOBAL, fs->firstlocal + i); | ||
420 | return VGLOBAL; | ||
421 | } | ||
422 | else if (var->u.info == -1) /* active preambular declaration? */ | ||
423 | var->u.info = -2; /* invalidate preambular declaration */ | ||
424 | } | ||
425 | } | ||
426 | else if (eqstr(n, vd->vd.name)) { /* found? */ | ||
404 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ | 427 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ |
405 | init_exp(var, VCONST, fs->firstlocal + i); | 428 | init_exp(var, VCONST, fs->firstlocal + i); |
406 | else /* real variable */ | 429 | else /* local variable */ |
407 | init_var(fs, var, i); | 430 | init_var(fs, var, i); |
408 | return cast_int(var->k); | 431 | return cast_int(var->k); |
409 | } | 432 | } |
@@ -442,48 +465,67 @@ static void marktobeclosed (FuncState *fs) { | |||
442 | ** 'var' as 'void' as a flag. | 465 | ** 'var' as 'void' as a flag. |
443 | */ | 466 | */ |
444 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 467 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { |
445 | if (fs == NULL) /* no more levels? */ | 468 | int v = searchvar(fs, n, var); /* look up variables at current level */ |
446 | init_exp(var, VVOID, 0); /* default is global */ | 469 | if (v >= 0) { /* found? */ |
447 | else { | 470 | if (v == VLOCAL && !base) |
448 | int v = searchvar(fs, n, var); /* look up locals at current level */ | 471 | markupval(fs, var->u.var.vidx); /* local will be used as an upval */ |
449 | if (v >= 0) { /* found? */ | 472 | } |
450 | if (v == VLOCAL && !base) | 473 | else { /* not found at current level; try upvalues */ |
451 | markupval(fs, var->u.var.vidx); /* local will be used as an upval */ | 474 | int idx = searchupvalue(fs, n); /* try existing upvalues */ |
452 | } | 475 | if (idx < 0) { /* not found? */ |
453 | else { /* not found as local at current level; try upvalues */ | 476 | if (fs->prev != NULL) /* more levels? */ |
454 | int idx = searchupvalue(fs, n); /* try existing upvalues */ | ||
455 | if (idx < 0) { /* not found? */ | ||
456 | singlevaraux(fs->prev, n, var, 0); /* try upper levels */ | 477 | singlevaraux(fs->prev, n, var, 0); /* try upper levels */ |
457 | if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ | 478 | if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ |
458 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ | 479 | idx = newupvalue(fs, n, var); /* will be a new upvalue */ |
459 | else /* it is a global or a constant */ | 480 | else /* it is a global or a constant */ |
460 | return; /* don't need to do anything at this level */ | 481 | return; /* don't need to do anything at this level */ |
461 | } | ||
462 | init_exp(var, VUPVAL, idx); /* new or old upvalue */ | ||
463 | } | 482 | } |
483 | init_exp(var, VUPVAL, idx); /* new or old upvalue */ | ||
464 | } | 484 | } |
465 | } | 485 | } |
466 | 486 | ||
467 | 487 | ||
488 | static void buildglobal (LexState *ls, TString *varname, expdesc *var) { | ||
489 | FuncState *fs = ls->fs; | ||
490 | expdesc key; | ||
491 | init_exp(var, VGLOBAL, -1); /* global by default */ | ||
492 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | ||
493 | if (var->k == VGLOBAL) | ||
494 | luaK_semerror(ls, "_ENV is global when accessing variable '%s'", | ||
495 | getstr(varname)); | ||
496 | luaK_exp2anyregup(fs, var); /* _ENV could be a constant */ | ||
497 | codestring(&key, varname); /* key is variable name */ | ||
498 | luaK_indexed(fs, var, &key); /* 'var' represents _ENV[varname] */ | ||
499 | } | ||
500 | |||
501 | |||
468 | /* | 502 | /* |
469 | ** Find a variable with the given name 'n', handling global variables | 503 | ** Find a variable with the given name 'n', handling global variables |
470 | ** too. | 504 | ** too. |
471 | */ | 505 | */ |
472 | static void singlevar (LexState *ls, expdesc *var) { | 506 | static void buildvar (LexState *ls, TString *varname, expdesc *var) { |
473 | TString *varname = str_checkname(ls); | ||
474 | FuncState *fs = ls->fs; | 507 | FuncState *fs = ls->fs; |
508 | init_exp(var, VGLOBAL, -1); /* global by default */ | ||
475 | singlevaraux(fs, varname, var, 1); | 509 | singlevaraux(fs, varname, var, 1); |
476 | if (var->k == VVOID) { /* global name? */ | 510 | if (var->k == VGLOBAL) { /* global name? */ |
477 | expdesc key; | 511 | int info = var->u.info; |
478 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | 512 | /* global by default in the scope of a global declaration? */ |
479 | lua_assert(var->k != VVOID); /* this one must exist */ | 513 | if (info == -2) |
480 | luaK_exp2anyregup(fs, var); /* but could be a constant */ | 514 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); |
481 | codestring(&key, varname); /* key is variable name */ | 515 | buildglobal(ls, varname, var); |
482 | luaK_indexed(fs, var, &key); /* env[varname] */ | 516 | if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST) |
517 | var->u.ind.ro = 1; /* mark variable as read-only */ | ||
518 | else /* anyway must be a global */ | ||
519 | lua_assert(info == -1 || ls->dyd->actvar.arr[info].vd.kind == GDKREG); | ||
483 | } | 520 | } |
484 | } | 521 | } |
485 | 522 | ||
486 | 523 | ||
524 | static void singlevar (LexState *ls, expdesc *var) { | ||
525 | buildvar(ls, str_checkname(ls), var); | ||
526 | } | ||
527 | |||
528 | |||
487 | /* | 529 | /* |
488 | ** Adjust the number of results from an expression list 'e' with 'nexps' | 530 | ** Adjust the number of results from an expression list 'e' with 'nexps' |
489 | ** expressions to 'nvars' values. | 531 | ** expressions to 'nvars' values. |
@@ -518,14 +560,14 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | |||
518 | 560 | ||
519 | /* | 561 | /* |
520 | ** Generates an error that a goto jumps into the scope of some | 562 | ** Generates an error that a goto jumps into the scope of some |
521 | ** local variable. | 563 | ** variable declaration. |
522 | */ | 564 | */ |
523 | static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { | 565 | static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { |
524 | TString *tsname = getlocalvardesc(ls->fs, gt->nactvar)->vd.name; | 566 | TString *tsname = getlocalvardesc(ls->fs, gt->nactvar)->vd.name; |
525 | const char *varname = getstr(tsname); | 567 | const char *varname = (tsname != NULL) ? getstr(tsname) : "*"; |
526 | const char *msg = "<goto %s> at line %d jumps into the scope of local '%s'"; | 568 | luaK_semerror(ls, |
527 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); | 569 | "<goto %s> at line %d jumps into the scope of '%s'", |
528 | luaK_semerror(ls, msg); /* raise the error */ | 570 | getstr(gt->name), gt->line, varname); /* raise the error */ |
529 | } | 571 | } |
530 | 572 | ||
531 | 573 | ||
@@ -563,7 +605,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label, int bup) { | |||
563 | 605 | ||
564 | /* | 606 | /* |
565 | ** Search for an active label with the given name, starting at | 607 | ** Search for an active label with the given name, starting at |
566 | ** index 'ilb' (so that it can searh for all labels in current block | 608 | ** index 'ilb' (so that it can search for all labels in current block |
567 | ** or all labels in current function). | 609 | ** or all labels in current function). |
568 | */ | 610 | */ |
569 | static Labeldesc *findlabel (LexState *ls, TString *name, int ilb) { | 611 | static Labeldesc *findlabel (LexState *ls, TString *name, int ilb) { |
@@ -630,7 +672,7 @@ static void createlabel (LexState *ls, TString *name, int line, int last) { | |||
630 | 672 | ||
631 | 673 | ||
632 | /* | 674 | /* |
633 | ** Traverse the pending goto's of the finishing block checking whether | 675 | ** Traverse the pending gotos of the finishing block checking whether |
634 | ** each match some label of that block. Those that do not match are | 676 | ** each match some label of that block. Those that do not match are |
635 | ** "exported" to the outer block, to be solved there. In particular, | 677 | ** "exported" to the outer block, to be solved there. In particular, |
636 | ** its 'nactvar' is updated with the level of the inner block, | 678 | ** its 'nactvar' is updated with the level of the inner block, |
@@ -666,8 +708,9 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
666 | bl->firstlabel = fs->ls->dyd->label.n; | 708 | bl->firstlabel = fs->ls->dyd->label.n; |
667 | bl->firstgoto = fs->ls->dyd->gt.n; | 709 | bl->firstgoto = fs->ls->dyd->gt.n; |
668 | bl->upval = 0; | 710 | bl->upval = 0; |
711 | /* inherit 'insidetbc' from enclosing block */ | ||
669 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); | 712 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); |
670 | bl->previous = fs->bl; | 713 | bl->previous = fs->bl; /* link block in function's block list */ |
671 | fs->bl = bl; | 714 | fs->bl = bl; |
672 | lua_assert(fs->freereg == luaY_nvarstack(fs)); | 715 | lua_assert(fs->freereg == luaY_nvarstack(fs)); |
673 | } | 716 | } |
@@ -677,11 +720,10 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
677 | ** generates an error for an undefined 'goto'. | 720 | ** generates an error for an undefined 'goto'. |
678 | */ | 721 | */ |
679 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { | 722 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { |
680 | const char *msg = "no visible label '%s' for <goto> at line %d"; | ||
681 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); | ||
682 | /* breaks are checked when created, cannot be undefined */ | 723 | /* breaks are checked when created, cannot be undefined */ |
683 | lua_assert(!eqstr(gt->name, luaS_newliteral(ls->L, "break"))); | 724 | lua_assert(!eqstr(gt->name, ls->brkn)); |
684 | luaK_semerror(ls, msg); | 725 | luaK_semerror(ls, "no visible label '%s' for <goto> at line %d", |
726 | getstr(gt->name), gt->line); | ||
685 | } | 727 | } |
686 | 728 | ||
687 | 729 | ||
@@ -695,7 +737,7 @@ static void leaveblock (FuncState *fs) { | |||
695 | removevars(fs, bl->nactvar); /* remove block locals */ | 737 | removevars(fs, bl->nactvar); /* remove block locals */ |
696 | lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ | 738 | lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ |
697 | if (bl->isloop == 2) /* has to fix pending breaks? */ | 739 | if (bl->isloop == 2) /* has to fix pending breaks? */ |
698 | createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); | 740 | createlabel(ls, ls->brkn, 0, 0); |
699 | solvegotos(fs, bl); | 741 | solvegotos(fs, bl); |
700 | if (bl->previous == NULL) { /* was it the last block? */ | 742 | if (bl->previous == NULL) { /* was it the last block? */ |
701 | if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ | 743 | if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ |
@@ -868,10 +910,8 @@ static void recfield (LexState *ls, ConsControl *cc) { | |||
868 | FuncState *fs = ls->fs; | 910 | FuncState *fs = ls->fs; |
869 | lu_byte reg = ls->fs->freereg; | 911 | lu_byte reg = ls->fs->freereg; |
870 | expdesc tab, key, val; | 912 | expdesc tab, key, val; |
871 | if (ls->t.token == TK_NAME) { | 913 | if (ls->t.token == TK_NAME) |
872 | luaY_checklimit(fs, cc->nh, INT_MAX / 2, "items in a constructor"); | ||
873 | codename(ls, &key); | 914 | codename(ls, &key); |
874 | } | ||
875 | else /* ls->t.token == '[' */ | 915 | else /* ls->t.token == '[' */ |
876 | yindex(ls, &key); | 916 | yindex(ls, &key); |
877 | cc->nh++; | 917 | cc->nh++; |
@@ -1402,6 +1442,15 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
1402 | } | 1442 | } |
1403 | } | 1443 | } |
1404 | 1444 | ||
1445 | |||
1446 | /* Create code to store the "top" register in 'var' */ | ||
1447 | static void storevartop (FuncState *fs, expdesc *var) { | ||
1448 | expdesc e; | ||
1449 | init_exp(&e, VNONRELOC, fs->freereg - 1); | ||
1450 | luaK_storevar(fs, var, &e); /* will also free the top register */ | ||
1451 | } | ||
1452 | |||
1453 | |||
1405 | /* | 1454 | /* |
1406 | ** Parse and compile a multiple assignment. The first "variable" | 1455 | ** Parse and compile a multiple assignment. The first "variable" |
1407 | ** (a 'suffixedexp') was already read by the caller. | 1456 | ** (a 'suffixedexp') was already read by the caller. |
@@ -1435,8 +1484,7 @@ static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) { | |||
1435 | return; /* avoid default */ | 1484 | return; /* avoid default */ |
1436 | } | 1485 | } |
1437 | } | 1486 | } |
1438 | init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ | 1487 | storevartop(ls->fs, &lh->v); /* default assignment */ |
1439 | luaK_storevar(ls->fs, &lh->v, &e); | ||
1440 | } | 1488 | } |
1441 | 1489 | ||
1442 | 1490 | ||
@@ -1469,7 +1517,7 @@ static void breakstat (LexState *ls, int line) { | |||
1469 | ok: | 1517 | ok: |
1470 | bl->isloop = 2; /* signal that block has pending breaks */ | 1518 | bl->isloop = 2; /* signal that block has pending breaks */ |
1471 | luaX_next(ls); /* skip break */ | 1519 | luaX_next(ls); /* skip break */ |
1472 | newgotoentry(ls, luaS_newliteral(ls->L, "break"), line); | 1520 | newgotoentry(ls, ls->brkn, line); |
1473 | } | 1521 | } |
1474 | 1522 | ||
1475 | 1523 | ||
@@ -1479,11 +1527,9 @@ static void breakstat (LexState *ls, int line) { | |||
1479 | */ | 1527 | */ |
1480 | static void checkrepeated (LexState *ls, TString *name) { | 1528 | static void checkrepeated (LexState *ls, TString *name) { |
1481 | Labeldesc *lb = findlabel(ls, name, ls->fs->firstlabel); | 1529 | Labeldesc *lb = findlabel(ls, name, ls->fs->firstlabel); |
1482 | if (l_unlikely(lb != NULL)) { /* already defined? */ | 1530 | if (l_unlikely(lb != NULL)) /* already defined? */ |
1483 | const char *msg = "label '%s' already defined on line %d"; | 1531 | luaK_semerror(ls, "label '%s' already defined on line %d", |
1484 | msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line); | 1532 | getstr(name), lb->line); /* error */ |
1485 | luaK_semerror(ls, msg); /* error */ | ||
1486 | } | ||
1487 | } | 1533 | } |
1488 | 1534 | ||
1489 | 1535 | ||
@@ -1605,7 +1651,7 @@ static void fornum (LexState *ls, TString *varname, int line) { | |||
1605 | int base = fs->freereg; | 1651 | int base = fs->freereg; |
1606 | new_localvarliteral(ls, "(for state)"); | 1652 | new_localvarliteral(ls, "(for state)"); |
1607 | new_localvarliteral(ls, "(for state)"); | 1653 | new_localvarliteral(ls, "(for state)"); |
1608 | new_localvarkind(ls, varname, RDKCONST); /* control variable */ | 1654 | new_varkind(ls, varname, RDKCONST); /* control variable */ |
1609 | checknext(ls, '='); | 1655 | checknext(ls, '='); |
1610 | exp1(ls); /* initial value */ | 1656 | exp1(ls); /* initial value */ |
1611 | checknext(ls, ','); | 1657 | checknext(ls, ','); |
@@ -1632,7 +1678,7 @@ static void forlist (LexState *ls, TString *indexname) { | |||
1632 | new_localvarliteral(ls, "(for state)"); /* iterator function */ | 1678 | new_localvarliteral(ls, "(for state)"); /* iterator function */ |
1633 | new_localvarliteral(ls, "(for state)"); /* state */ | 1679 | new_localvarliteral(ls, "(for state)"); /* state */ |
1634 | new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */ | 1680 | new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */ |
1635 | new_localvarkind(ls, indexname, RDKCONST); /* control variable */ | 1681 | new_varkind(ls, indexname, RDKCONST); /* control variable */ |
1636 | /* other declared variables */ | 1682 | /* other declared variables */ |
1637 | while (testnext(ls, ',')) { | 1683 | while (testnext(ls, ',')) { |
1638 | new_localvar(ls, str_checkname(ls)); | 1684 | new_localvar(ls, str_checkname(ls)); |
@@ -1707,8 +1753,8 @@ static void localfunc (LexState *ls) { | |||
1707 | } | 1753 | } |
1708 | 1754 | ||
1709 | 1755 | ||
1710 | static lu_byte getlocalattribute (LexState *ls) { | 1756 | static lu_byte getvarattribute (LexState *ls, lu_byte df) { |
1711 | /* ATTRIB -> ['<' Name '>'] */ | 1757 | /* attrib -> ['<' NAME '>'] */ |
1712 | if (testnext(ls, '<')) { | 1758 | if (testnext(ls, '<')) { |
1713 | TString *ts = str_checkname(ls); | 1759 | TString *ts = str_checkname(ls); |
1714 | const char *attr = getstr(ts); | 1760 | const char *attr = getstr(ts); |
@@ -1718,10 +1764,9 @@ static lu_byte getlocalattribute (LexState *ls) { | |||
1718 | else if (strcmp(attr, "close") == 0) | 1764 | else if (strcmp(attr, "close") == 0) |
1719 | return RDKTOCLOSE; /* to-be-closed variable */ | 1765 | return RDKTOCLOSE; /* to-be-closed variable */ |
1720 | else | 1766 | else |
1721 | luaK_semerror(ls, | 1767 | luaK_semerror(ls, "unknown attribute '%s'", attr); |
1722 | luaO_pushfstring(ls->L, "unknown attribute '%s'", attr)); | ||
1723 | } | 1768 | } |
1724 | return VDKREG; /* regular variable */ | 1769 | return df; /* return default value */ |
1725 | } | 1770 | } |
1726 | 1771 | ||
1727 | 1772 | ||
@@ -1734,7 +1779,7 @@ static void checktoclose (FuncState *fs, int level) { | |||
1734 | 1779 | ||
1735 | 1780 | ||
1736 | static void localstat (LexState *ls) { | 1781 | static void localstat (LexState *ls) { |
1737 | /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ | 1782 | /* stat -> LOCAL NAME attrib { ',' NAME attrib } ['=' explist] */ |
1738 | FuncState *fs = ls->fs; | 1783 | FuncState *fs = ls->fs; |
1739 | int toclose = -1; /* index of to-be-closed variable (if any) */ | 1784 | int toclose = -1; /* index of to-be-closed variable (if any) */ |
1740 | Vardesc *var; /* last variable */ | 1785 | Vardesc *var; /* last variable */ |
@@ -1742,10 +1787,12 @@ static void localstat (LexState *ls) { | |||
1742 | int nvars = 0; | 1787 | int nvars = 0; |
1743 | int nexps; | 1788 | int nexps; |
1744 | expdesc e; | 1789 | expdesc e; |
1745 | do { | 1790 | /* get prefixed attribute (if any); default is regular local variable */ |
1746 | TString *vname = str_checkname(ls); | 1791 | lu_byte defkind = getvarattribute(ls, VDKREG); |
1747 | lu_byte kind = getlocalattribute(ls); | 1792 | do { /* for each variable */ |
1748 | vidx = new_localvarkind(ls, vname, kind); | 1793 | TString *vname = str_checkname(ls); /* get its name */ |
1794 | lu_byte kind = getvarattribute(ls, defkind); /* postfixed attribute */ | ||
1795 | vidx = new_varkind(ls, vname, kind); /* predeclare it */ | ||
1749 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ | 1796 | if (kind == RDKTOCLOSE) { /* to-be-closed? */ |
1750 | if (toclose != -1) /* one already present? */ | 1797 | if (toclose != -1) /* one already present? */ |
1751 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); | 1798 | luaK_semerror(ls, "multiple to-be-closed variables in local list"); |
@@ -1753,13 +1800,13 @@ static void localstat (LexState *ls) { | |||
1753 | } | 1800 | } |
1754 | nvars++; | 1801 | nvars++; |
1755 | } while (testnext(ls, ',')); | 1802 | } while (testnext(ls, ',')); |
1756 | if (testnext(ls, '=')) | 1803 | if (testnext(ls, '=')) /* initialization? */ |
1757 | nexps = explist(ls, &e); | 1804 | nexps = explist(ls, &e); |
1758 | else { | 1805 | else { |
1759 | e.k = VVOID; | 1806 | e.k = VVOID; |
1760 | nexps = 0; | 1807 | nexps = 0; |
1761 | } | 1808 | } |
1762 | var = getlocalvardesc(fs, vidx); /* get last variable */ | 1809 | var = getlocalvardesc(fs, vidx); /* retrieve last variable */ |
1763 | if (nvars == nexps && /* no adjustments? */ | 1810 | if (nvars == nexps && /* no adjustments? */ |
1764 | var->vd.kind == RDKCONST && /* last variable is const? */ | 1811 | var->vd.kind == RDKCONST && /* last variable is const? */ |
1765 | luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ | 1812 | luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ |
@@ -1775,6 +1822,86 @@ static void localstat (LexState *ls) { | |||
1775 | } | 1822 | } |
1776 | 1823 | ||
1777 | 1824 | ||
1825 | static lu_byte getglobalattribute (LexState *ls, lu_byte df) { | ||
1826 | lu_byte kind = getvarattribute(ls, df); | ||
1827 | switch (kind) { | ||
1828 | case RDKTOCLOSE: | ||
1829 | luaK_semerror(ls, "global variables cannot be to-be-closed"); | ||
1830 | break; /* to avoid warnings */ | ||
1831 | case RDKCONST: | ||
1832 | return GDKCONST; /* adjust kind for global variable */ | ||
1833 | default: | ||
1834 | return kind; | ||
1835 | } | ||
1836 | } | ||
1837 | |||
1838 | |||
1839 | static void globalnames (LexState *ls, lu_byte defkind) { | ||
1840 | FuncState *fs = ls->fs; | ||
1841 | int nvars = 0; | ||
1842 | int lastidx; /* index of last registered variable */ | ||
1843 | do { /* for each name */ | ||
1844 | TString *vname = str_checkname(ls); | ||
1845 | lu_byte kind = getglobalattribute(ls, defkind); | ||
1846 | lastidx = new_varkind(ls, vname, kind); | ||
1847 | nvars++; | ||
1848 | } while (testnext(ls, ',')); | ||
1849 | if (testnext(ls, '=')) { /* initialization? */ | ||
1850 | expdesc e; | ||
1851 | int i; | ||
1852 | int nexps = explist(ls, &e); /* read list of expressions */ | ||
1853 | adjust_assign(ls, nvars, nexps, &e); | ||
1854 | for (i = 0; i < nvars; i++) { /* for each variable */ | ||
1855 | expdesc var; | ||
1856 | TString *varname = getlocalvardesc(fs, lastidx - i)->vd.name; | ||
1857 | buildglobal(ls, varname, &var); /* create global variable in 'var' */ | ||
1858 | storevartop(fs, &var); | ||
1859 | } | ||
1860 | } | ||
1861 | fs->nactvar = cast_short(fs->nactvar + nvars); /* activate declaration */ | ||
1862 | } | ||
1863 | |||
1864 | |||
1865 | static void globalstat (LexState *ls) { | ||
1866 | /* globalstat -> (GLOBAL) attrib '*' | ||
1867 | globalstat -> (GLOBAL) attrib NAME attrib {',' NAME attrib} */ | ||
1868 | FuncState *fs = ls->fs; | ||
1869 | /* get prefixed attribute (if any); default is regular global variable */ | ||
1870 | lu_byte defkind = getglobalattribute(ls, GDKREG); | ||
1871 | if (!testnext(ls, '*')) | ||
1872 | globalnames(ls, defkind); | ||
1873 | else { | ||
1874 | /* use NULL as name to represent '*' entries */ | ||
1875 | new_varkind(ls, NULL, defkind); | ||
1876 | fs->nactvar++; /* activate declaration */ | ||
1877 | } | ||
1878 | } | ||
1879 | |||
1880 | |||
1881 | static void globalfunc (LexState *ls, int line) { | ||
1882 | /* globalfunc -> (GLOBAL FUNCTION) NAME body */ | ||
1883 | expdesc var, b; | ||
1884 | FuncState *fs = ls->fs; | ||
1885 | TString *fname = str_checkname(ls); | ||
1886 | new_varkind(ls, fname, GDKREG); /* declare global variable */ | ||
1887 | fs->nactvar++; /* enter its scope */ | ||
1888 | buildglobal(ls, fname, &var); | ||
1889 | body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */ | ||
1890 | luaK_storevar(fs, &var, &b); | ||
1891 | luaK_fixline(fs, line); /* definition "happens" in the first line */ | ||
1892 | } | ||
1893 | |||
1894 | |||
1895 | static void globalstatfunc (LexState *ls, int line) { | ||
1896 | /* stat -> GLOBAL globalfunc | GLOBAL globalstat */ | ||
1897 | luaX_next(ls); /* skip 'global' */ | ||
1898 | if (testnext(ls, TK_FUNCTION)) | ||
1899 | globalfunc(ls, line); | ||
1900 | else | ||
1901 | globalstat(ls); | ||
1902 | } | ||
1903 | |||
1904 | |||
1778 | static int funcname (LexState *ls, expdesc *v) { | 1905 | static int funcname (LexState *ls, expdesc *v) { |
1779 | /* funcname -> NAME {fieldsel} [':' NAME] */ | 1906 | /* funcname -> NAME {fieldsel} [':' NAME] */ |
1780 | int ismethod = 0; | 1907 | int ismethod = 0; |
@@ -1795,8 +1922,8 @@ static void funcstat (LexState *ls, int line) { | |||
1795 | expdesc v, b; | 1922 | expdesc v, b; |
1796 | luaX_next(ls); /* skip FUNCTION */ | 1923 | luaX_next(ls); /* skip FUNCTION */ |
1797 | ismethod = funcname(ls, &v); | 1924 | ismethod = funcname(ls, &v); |
1798 | body(ls, &b, ismethod, line); | ||
1799 | check_readonly(ls, &v); | 1925 | check_readonly(ls, &v); |
1926 | body(ls, &b, ismethod, line); | ||
1800 | luaK_storevar(ls->fs, &v, &b); | 1927 | luaK_storevar(ls->fs, &v, &b); |
1801 | luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ | 1928 | luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ |
1802 | } | 1929 | } |
@@ -1894,6 +2021,10 @@ static void statement (LexState *ls) { | |||
1894 | localstat(ls); | 2021 | localstat(ls); |
1895 | break; | 2022 | break; |
1896 | } | 2023 | } |
2024 | case TK_GLOBAL: { /* stat -> globalstatfunc */ | ||
2025 | globalstatfunc(ls, line); | ||
2026 | break; | ||
2027 | } | ||
1897 | case TK_DBCOLON: { /* stat -> label */ | 2028 | case TK_DBCOLON: { /* stat -> label */ |
1898 | luaX_next(ls); /* skip double colon */ | 2029 | luaX_next(ls); /* skip double colon */ |
1899 | labelstat(ls, str_checkname(ls), line); | 2030 | labelstat(ls, str_checkname(ls), line); |
@@ -1913,6 +2044,22 @@ static void statement (LexState *ls) { | |||
1913 | gotostat(ls, line); | 2044 | gotostat(ls, line); |
1914 | break; | 2045 | break; |
1915 | } | 2046 | } |
2047 | #if defined(LUA_COMPAT_GLOBAL) | ||
2048 | case TK_NAME: { | ||
2049 | /* compatibility code to parse global keyword when "global" | ||
2050 | is not reserved */ | ||
2051 | if (ls->t.seminfo.ts == ls->glbn) { /* current = "global"? */ | ||
2052 | int lk = luaX_lookahead(ls); | ||
2053 | if (lk == '<' || lk == TK_NAME || lk == '*' || lk == TK_FUNCTION) { | ||
2054 | /* 'global <attrib>' or 'global name' or 'global *' or | ||
2055 | 'global function' */ | ||
2056 | globalstatfunc(ls, line); | ||
2057 | break; | ||
2058 | } | ||
2059 | } /* else... */ | ||
2060 | } | ||
2061 | #endif | ||
2062 | /* FALLTHROUGH */ | ||
1916 | default: { /* stat -> func | assignment */ | 2063 | default: { /* stat -> func | assignment */ |
1917 | exprstat(ls); | 2064 | exprstat(ls); |
1918 | break; | 2065 | break; |