aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lparser.c33
-rw-r--r--lparser.h3
-rw-r--r--testes/db.lua6
-rw-r--r--testes/goto.lua18
4 files changed, 45 insertions, 15 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
diff --git a/lparser.h b/lparser.h
index 524df6ea..b08008ce 100644
--- a/lparser.h
+++ b/lparser.h
@@ -105,6 +105,9 @@ typedef struct expdesc {
105/* variables that live in registers */ 105/* variables that live in registers */
106#define varinreg(v) ((v)->vd.kind <= RDKTOCLOSE) 106#define varinreg(v) ((v)->vd.kind <= RDKTOCLOSE)
107 107
108/* test for global variables */
109#define varglobal(v) ((v)->vd.kind >= GDKREG)
110
108 111
109/* description of an active variable */ 112/* description of an active variable */
110typedef union Vardesc { 113typedef union Vardesc {
diff --git a/testes/db.lua b/testes/db.lua
index ae204c41..0f174f17 100644
--- a/testes/db.lua
+++ b/testes/db.lua
@@ -349,9 +349,11 @@ end, "crl")
349 349
350 350
351function f(a,b) 351function f(a,b)
352 global collectgarbage, assert, g, string 352 -- declare some globals to check that they don't interfere with 'getlocal'
353 global collectgarbage
353 collectgarbage() 354 collectgarbage()
354 local _, x = debug.getlocal(1, 1) 355 local _, x = debug.getlocal(1, 1)
356 global assert, g, string
355 local _, y = debug.getlocal(1, 2) 357 local _, y = debug.getlocal(1, 2)
356 assert(x == a and y == b) 358 assert(x == a and y == b)
357 assert(debug.setlocal(2, 3, "pera") == "AA".."AA") 359 assert(debug.setlocal(2, 3, "pera") == "AA".."AA")
@@ -387,7 +389,9 @@ function g (...)
387 f(AAAA,B) 389 f(AAAA,B)
388 assert(AAAA == "pera" and B == "manga") 390 assert(AAAA == "pera" and B == "manga")
389 do 391 do
392 global *
390 local B = 13 393 local B = 13
394 global<const> assert
391 local x,y = debug.getlocal(1,5) 395 local x,y = debug.getlocal(1,5)
392 assert(x == 'B' and y == 13) 396 assert(x == 'B' and y == 13)
393 end 397 end
diff --git a/testes/goto.lua b/testes/goto.lua
index d7730061..7e40fc4f 100644
--- a/testes/goto.lua
+++ b/testes/goto.lua
@@ -364,7 +364,23 @@ do
364 print(X) -- Ok to use 364 print(X) -- Ok to use
365 Y = 1 -- ERROR 365 Y = 1 -- ERROR
366 ]], "assign to const variable 'Y'") 366 ]], "assign to const variable 'Y'")
367 367
368 checkerr([[
369 global *;
370 Y = X -- Ok to use
371 global<const> *;
372 Y = 1 -- ERROR
373 ]], "assign to const variable 'Y'")
374
375 global *
376 Y = 10
377 assert(_ENV.Y == 10)
378 global<const> *
379 local x = Y
380 global *
381 Y = x + Y
382 assert(_ENV.Y == 20)
383
368end 384end
369 385
370print'OK' 386print'OK'