diff options
-rw-r--r-- | lparser.c | 33 | ||||
-rw-r--r-- | lparser.h | 3 | ||||
-rw-r--r-- | testes/db.lua | 6 | ||||
-rw-r--r-- | testes/goto.lua | 18 |
4 files changed, 45 insertions, 15 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 |
@@ -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 */ |
110 | typedef union Vardesc { | 113 | typedef 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 | ||
351 | function f(a,b) | 351 | function 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 | |||
368 | end | 384 | end |
369 | 385 | ||
370 | print'OK' | 386 | print'OK' |