aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/lparser.c b/lparser.c
index c134b7a8..e868e887 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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*/
404static int searchvar (FuncState *fs, TString *n, expdesc *var) { 409static 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) {
1855static void globalstatfunc (LexState *ls, int line) { 1863static 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