Skip to content

Commit 4cd1f4a

Browse files
committed
Towards "to closed" local variables
Start of the implementation of "scoped variables" or "to be closed" variables, local variables whose '__close' (or themselves) are called when they go out of scope. This commit implements the syntax, the opcode, and the creation of the corresponding upvalue, but it still does not call the finalizations when the variable goes out of scope (the most important part). Currently, the syntax is 'local scoped name = exp', but that will probably change.
1 parent b114c7d commit 4cd1f4a

15 files changed

Lines changed: 81 additions & 22 deletions

File tree

lcode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1673,13 +1673,13 @@ void luaK_finish (FuncState *fs) {
16731673
lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc));
16741674
switch (GET_OPCODE(*pc)) {
16751675
case OP_RETURN0: case OP_RETURN1: {
1676-
if (p->sizep == 0 && !p->is_vararg)
1676+
if (!(fs->needclose || p->is_vararg))
16771677
break; /* no extra work */
16781678
/* else use OP_RETURN to do the extra work */
16791679
SET_OPCODE(*pc, OP_RETURN);
16801680
} /* FALLTHROUGH */
16811681
case OP_RETURN: case OP_TAILCALL: {
1682-
if (p->sizep > 0 || p->is_vararg) {
1682+
if (fs->needclose || p->is_vararg) {
16831683
SETARG_C(*pc, p->is_vararg ? p->numparams + 1 : 0);
16841684
SETARG_k(*pc, 1); /* signal that there is extra work */
16851685
}

ldo.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ struct lua_longjmp {
9191
static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
9292
switch (errcode) {
9393
case LUA_ERRMEM: { /* memory error? */
94-
TString *memerrmsg = luaS_newliteral(L, MEMERRMSG);
95-
setsvalue2s(L, oldtop, memerrmsg); /* reuse preregistered msg. */
94+
setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
9695
break;
9796
}
9897
case LUA_ERRERR: {

lgc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ static void reallymarkobject (global_State *g, GCObject *o) {
293293
gray2black(o);
294294
break;
295295
}
296-
case LUA_TUPVAL: {
296+
case LUA_TUPVAL:
297+
case LUA_TUPVALTBC: {
297298
UpVal *uv = gco2upv(o);
298299
if (!upisopen(uv)) /* open upvalues are kept gray */
299300
gray2black(o);
@@ -760,6 +761,7 @@ static void freeobj (lua_State *L, GCObject *o) {
760761
luaF_freeproto(L, gco2p(o));
761762
break;
762763
case LUA_TUPVAL:
764+
case LUA_TUPVALTBC:
763765
freeupval(L, gco2upv(o));
764766
break;
765767
case LUA_TLCL:

ljumptab.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ static void *disptab[] = {
7474
&&L_OP_LEN,
7575
&&L_OP_CONCAT,
7676
&&L_OP_CLOSE,
77+
&&L_OP_TBC,
7778
&&L_OP_JMP,
7879
&&L_OP_EQ,
7980
&&L_OP_LT,

lobject.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,10 @@ typedef struct UpVal {
588588
} UpVal;
589589

590590

591+
/* variant for "To Be Closed" upvalues */
592+
#define LUA_TUPVALTBC (LUA_TUPVAL | (1 << 4))
593+
594+
591595
#define ClosureHeader \
592596
CommonHeader; lu_byte nupvalues; GCObject *gclist
593597

lopcodes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
6868
,opmode(0, 0, 0, 1, iABC) /* OP_LEN */
6969
,opmode(0, 0, 0, 1, iABC) /* OP_CONCAT */
7070
,opmode(0, 0, 0, 0, iABC) /* OP_CLOSE */
71+
,opmode(0, 0, 0, 0, iABC) /* OP_TBC */
7172
,opmode(0, 0, 0, 0, isJ) /* OP_JMP */
7273
,opmode(0, 0, 1, 0, iABC) /* OP_EQ */
7374
,opmode(0, 0, 1, 0, iABC) /* OP_LT */

lopcodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ OP_LEN,/* A B R(A) := length of R(B) */
251251
OP_CONCAT,/* A B R(A) := R(A).. ... ..R(A + B - 1) */
252252

253253
OP_CLOSE,/* A close all upvalues >= R(A) */
254+
OP_TBC,/* A mark variable A "to be closed" */
254255
OP_JMP,/* k sJ pc += sJ (k is used in code generation) */
255256
OP_EQ,/* A B if ((R(A) == R(B)) ~= k) then pc++ */
256257
OP_LT,/* A B if ((R(A) < R(B)) ~= k) then pc++ */

lopnames.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ static const char *const opnames[] = {
5959
"LEN",
6060
"CONCAT",
6161
"CLOSE",
62+
"TBC",
6263
"JMP",
6364
"EQ",
6465
"LT",

lparser.c

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ static void markupval (FuncState *fs, int level) {
255255
while (bl->nactvar > level)
256256
bl = bl->previous;
257257
bl->upval = 1;
258+
fs->needclose = 1;
258259
}
259260

260261

@@ -547,6 +548,7 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
547548
fs->nups = 0;
548549
fs->nlocvars = 0;
549550
fs->nactvar = 0;
551+
fs->needclose = 0;
550552
fs->firstlocal = ls->dyd->actvar.n;
551553
fs->bl = NULL;
552554
f->source = ls->source;
@@ -1509,15 +1511,16 @@ static void localfunc (LexState *ls) {
15091511
}
15101512

15111513

1512-
static void localstat (LexState *ls) {
1514+
static void commonlocalstat (LexState *ls, TString *firstvar) {
15131515
/* stat -> LOCAL NAME {',' NAME} ['=' explist] */
1514-
int nvars = 0;
1516+
int nvars = 1;
15151517
int nexps;
15161518
expdesc e;
1517-
do {
1519+
new_localvar(ls, firstvar);
1520+
while (testnext(ls, ',')) {
15181521
new_localvar(ls, str_checkname(ls));
15191522
nvars++;
1520-
} while (testnext(ls, ','));
1523+
}
15211524
if (testnext(ls, '='))
15221525
nexps = explist(ls, &e);
15231526
else {
@@ -1529,6 +1532,29 @@ static void localstat (LexState *ls) {
15291532
}
15301533

15311534

1535+
static void scopedlocalstat (LexState *ls) {
1536+
FuncState *fs = ls->fs;
1537+
new_localvar(ls, str_checkname(ls));
1538+
checknext(ls, '=');
1539+
luaK_codeABC(fs, OP_TBC, fs->nactvar, 0, 0);
1540+
markupval(fs, fs->nactvar);
1541+
exp1(ls, 0);
1542+
adjustlocalvars(ls, 1);
1543+
}
1544+
1545+
1546+
static void localstat (LexState *ls) {
1547+
/* stat -> LOCAL NAME {',' NAME} ['=' explist]
1548+
| LOCAL SCOPED NAME '=' exp */
1549+
TString *firstvar = str_checkname(ls);
1550+
if (ls->t.token == TK_NAME &&
1551+
eqshrstr(firstvar, luaS_newliteral(ls->L, "scoped")))
1552+
scopedlocalstat(ls);
1553+
else
1554+
commonlocalstat(ls, firstvar);
1555+
}
1556+
1557+
15321558
static int funcname (LexState *ls, expdesc *v) {
15331559
/* funcname -> NAME {fieldsel} [':' NAME] */
15341560
int ismethod = 0;

lparser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ typedef struct FuncState {
133133
lu_byte nups; /* number of upvalues */
134134
lu_byte freereg; /* first free register */
135135
lu_byte iwthabs; /* instructions issued since last absolute line info */
136+
lu_byte needclose; /* function needs to close upvalues when returning */
136137
} FuncState;
137138

138139

0 commit comments

Comments
 (0)