diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 33 |
1 files changed, 20 insertions, 13 deletions
@@ -54,7 +54,6 @@ typedef struct BlockCnt { | |||
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. */ |
57 | lu_byte globdec; /* true if inside the scope of any global declaration */ | ||
58 | } BlockCnt; | 57 | } BlockCnt; |
59 | 58 | ||
60 | 59 | ||
@@ -399,22 +398,35 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
399 | /* | 398 | /* |
400 | ** Look for an active variable with the name 'n' in the | 399 | ** Look for an active variable with the name 'n' in the |
401 | ** function 'fs'. If found, initialize 'var' with it and return | 400 | ** function 'fs'. If found, initialize 'var' with it and return |
402 | ** its expression kind; otherwise return -1. | 401 | ** its expression kind; otherwise return -1. While searching, |
402 | ** var->u.info==-1 means that the preambular global declaration is | ||
403 | ** active (the default while there is no other global declaration); | ||
404 | ** var->u.info==-2 means there is no active collective declaration | ||
405 | ** (some previous global declaration but no collective declaration); | ||
406 | ** and var->u.info>=0 points to the inner-most (the first one found) | ||
407 | ** collective declaration, if there is one. | ||
403 | */ | 408 | */ |
404 | static int searchvar (FuncState *fs, TString *n, expdesc *var) { | 409 | static int searchvar (FuncState *fs, TString *n, expdesc *var) { |
405 | int i; | 410 | int i; |
406 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 411 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
407 | Vardesc *vd = getlocalvardesc(fs, i); | 412 | Vardesc *vd = getlocalvardesc(fs, i); |
408 | if (vd->vd.name == NULL) { /* 'global *'? */ | 413 | if (varglobal(vd)) { /* global declaration? */ |
409 | if (var->u.info == -1) { /* no previous collective declaration? */ | 414 | if (vd->vd.name == NULL) { /* collective declaration? */ |
410 | var->u.info = fs->firstlocal + i; /* will use this one as default */ | 415 | if (var->u.info < 0) /* no previous collective declaration? */ |
416 | var->u.info = fs->firstlocal + i; /* this is the first one */ | ||
417 | } | ||
418 | else { /* global name */ | ||
419 | if (eqstr(n, vd->vd.name)) { /* found? */ | ||
420 | init_exp(var, VGLOBAL, fs->firstlocal + i); | ||
421 | return VGLOBAL; | ||
422 | } | ||
423 | else if (var->u.info == -1) /* active preambular declaration? */ | ||
424 | var->u.info = -2; /* invalidate preambular declaration */ | ||
411 | } | 425 | } |
412 | } | 426 | } |
413 | else if (eqstr(n, vd->vd.name)) { /* found? */ | 427 | else if (eqstr(n, vd->vd.name)) { /* found? */ |
414 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ | 428 | if (vd->vd.kind == RDKCTC) /* compile-time constant? */ |
415 | init_exp(var, VCONST, fs->firstlocal + i); | 429 | init_exp(var, VCONST, fs->firstlocal + i); |
416 | else if (vd->vd.kind == GDKREG || vd->vd.kind == GDKCONST) | ||
417 | init_exp(var, VGLOBAL, fs->firstlocal + i); | ||
418 | else /* local variable */ | 430 | else /* local variable */ |
419 | init_var(fs, var, i); | 431 | init_var(fs, var, i); |
420 | return cast_int(var->k); | 432 | return cast_int(var->k); |
@@ -486,7 +498,7 @@ static void buildvar (LexState *ls, TString *varname, expdesc *var) { | |||
486 | expdesc key; | 498 | expdesc key; |
487 | int info = var->u.info; | 499 | int info = var->u.info; |
488 | /* global by default in the scope of a global declaration? */ | 500 | /* global by default in the scope of a global declaration? */ |
489 | if (info == -1 && fs->bl->globdec) | 501 | if (info == -2) |
490 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); | 502 | luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); |
491 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ | 503 | singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ |
492 | if (var->k == VGLOBAL) | 504 | if (var->k == VGLOBAL) |
@@ -692,10 +704,6 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
692 | bl->upval = 0; | 704 | bl->upval = 0; |
693 | /* inherit 'insidetbc' from enclosing block */ | 705 | /* inherit 'insidetbc' from enclosing block */ |
694 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); | 706 | bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); |
695 | /* inherit 'globdec' from enclosing block or enclosing function */ | ||
696 | bl->globdec = fs->bl != NULL ? fs->bl->globdec | ||
697 | : fs->prev != NULL ? fs->prev->bl->globdec | ||
698 | : 0; /* chunk's first block */ | ||
699 | bl->previous = fs->bl; /* link block in function's block list */ | 707 | bl->previous = fs->bl; /* link block in function's block list */ |
700 | fs->bl = bl; | 708 | fs->bl = bl; |
701 | lua_assert(fs->freereg == luaY_nvarstack(fs)); | 709 | lua_assert(fs->freereg == luaY_nvarstack(fs)); |
@@ -1855,7 +1863,6 @@ static void globalfunc (LexState *ls, int line) { | |||
1855 | static void globalstatfunc (LexState *ls, int line) { | 1863 | static void globalstatfunc (LexState *ls, int line) { |
1856 | /* stat -> GLOBAL globalfunc | GLOBAL globalstat */ | 1864 | /* stat -> GLOBAL globalfunc | GLOBAL globalstat */ |
1857 | luaX_next(ls); /* skip 'global' */ | 1865 | luaX_next(ls); /* skip 'global' */ |
1858 | ls->fs->bl->globdec = 1; /* in the scope of a global declaration */ | ||
1859 | if (testnext(ls, TK_FUNCTION)) | 1866 | if (testnext(ls, TK_FUNCTION)) |
1860 | globalfunc(ls, line); | 1867 | globalfunc(ls, line); |
1861 | else | 1868 | else |