Skip to content

Commit d6af810

Browse files
committed
New kind of expression VKSTR
String literal expressions have their own kind VKSTR, instead of the generic VK. This allows strings to "cross" functions without entering their constant tables (e.g., if they are used only by some nested function).
1 parent 4846f7e commit d6af810

5 files changed

Lines changed: 54 additions & 18 deletions

File tree

lcode.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,8 @@ int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) {
8181
case VNIL:
8282
setnilvalue(v);
8383
return 1;
84-
case VK: {
85-
TValue *k = &fs->f->k[e->u.info];
86-
setobj(fs->ls->L, v, k);
84+
case VKSTR: {
85+
setsvalue(fs->ls->L, v, e->u.strval);
8786
return 1;
8887
}
8988
default: return tonumeral(e, v);
@@ -561,7 +560,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
561560
/*
562561
** Add a string to list of constants and return its index.
563562
*/
564-
int luaK_stringK (FuncState *fs, TString *s) {
563+
static int stringK (FuncState *fs, TString *s) {
565564
TValue o;
566565
setsvalue(fs->ls->L, &o, s);
567566
return addk(fs, &o, &o); /* use string itself as key */
@@ -656,7 +655,7 @@ static void luaK_float (FuncState *fs, int reg, lua_Number f) {
656655
/*
657656
** Convert a constant in 'v' into an expression description 'e'
658657
*/
659-
static void const2exp (FuncState *fs, TValue *v, expdesc *e) {
658+
static void const2exp (TValue *v, expdesc *e) {
660659
switch (ttypetag(v)) {
661660
case LUA_TNUMINT:
662661
e->k = VKINT; e->u.ival = ivalue(v);
@@ -671,7 +670,7 @@ static void const2exp (FuncState *fs, TValue *v, expdesc *e) {
671670
e->k = VNIL;
672671
break;
673672
case LUA_TSHRSTR: case LUA_TLNGSTR:
674-
e->k = VK; e->u.info = luaK_stringK(fs, tsvalue(v));
673+
e->k = VKSTR; e->u.strval = tsvalue(v);
675674
break;
676675
default: lua_assert(0);
677676
}
@@ -696,6 +695,16 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
696695
}
697696

698697

698+
/*
699+
** Convert a VKSTR to a VK
700+
*/
701+
static void str2K (FuncState *fs, expdesc *e) {
702+
lua_assert(e->k == VKSTR);
703+
e->u.info = stringK(fs, e->u.strval);
704+
e->k = VK;
705+
}
706+
707+
699708
/*
700709
** Fix an expression to return one result.
701710
** If expression is not a multi-ret expression (function call or
@@ -728,7 +737,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
728737
switch (e->k) {
729738
case VCONST: {
730739
TValue *val = &fs->ls->dyd->actvar.arr[e->u.info].k;
731-
const2exp(fs, val, e);
740+
const2exp(val, e);
732741
break;
733742
}
734743
case VLOCAL: { /* already in a register */
@@ -789,6 +798,9 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
789798
luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
790799
break;
791800
}
801+
case VKSTR: {
802+
str2K(fs, e);
803+
} /* FALLTHROUGH */
792804
case VK: {
793805
luaK_codek(fs, reg, e->u.info);
794806
break;
@@ -949,6 +961,7 @@ static int luaK_exp2K (FuncState *fs, expdesc *e) {
949961
case VNIL: info = nilK(fs); break;
950962
case VKINT: info = luaK_intK(fs, e->u.ival); break;
951963
case VKFLT: info = luaK_numberK(fs, e->u.nval); break;
964+
case VKSTR: info = stringK(fs, e->u.strval); break;
952965
case VK: info = e->u.info; break;
953966
default: return 0; /* not a constant */
954967
}
@@ -1083,7 +1096,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
10831096
pc = e->u.info; /* save jump position */
10841097
break;
10851098
}
1086-
case VK: case VKFLT: case VKINT: case VTRUE: {
1099+
case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: {
10871100
pc = NO_JUMP; /* always true; do nothing */
10881101
break;
10891102
}
@@ -1133,7 +1146,7 @@ static void codenot (FuncState *fs, expdesc *e) {
11331146
e->k = VTRUE; /* true == not nil == not false */
11341147
break;
11351148
}
1136-
case VK: case VKFLT: case VKINT: case VTRUE: {
1149+
case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: {
11371150
e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */
11381151
break;
11391152
}
@@ -1219,9 +1232,11 @@ static int isSCnumber (expdesc *e, lua_Integer *i, int *isfloat) {
12191232
** values in registers.
12201233
*/
12211234
void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
1235+
if (k->k == VKSTR)
1236+
str2K(fs, k);
12221237
lua_assert(!hasjumps(t) &&
12231238
(t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL));
1224-
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */
1239+
if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */
12251240
luaK_exp2anyreg(fs, t); /* put it in a register */
12261241
if (t->k == VUPVAL) {
12271242
t->u.ind.t = t->u.info; /* upvalue index */

lcode.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
6262
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
6363
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
6464
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
65-
LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
6665
LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n);
6766
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
6867
LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);

lparser.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,15 @@ static void init_exp (expdesc *e, expkind k, int i) {
156156
}
157157

158158

159-
static void codestring (LexState *ls, expdesc *e, TString *s) {
160-
init_exp(e, VK, luaK_stringK(ls->fs, s));
159+
static void codestring (expdesc *e, TString *s) {
160+
e->f = e->t = NO_JUMP;
161+
e->k = VKSTR;
162+
e->u.strval = s;
161163
}
162164

163165

164166
static void codename (LexState *ls, expdesc *e) {
165-
codestring(ls, e, str_checkname(ls));
167+
codestring(e, str_checkname(ls));
166168
}
167169

168170

@@ -445,7 +447,7 @@ static void singlevar (LexState *ls, expdesc *var) {
445447
expdesc key;
446448
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
447449
lua_assert(var->k != VVOID); /* this one must exist */
448-
codestring(ls, &key, varname); /* key is variable name */
450+
codestring(&key, varname); /* key is variable name */
449451
luaK_indexed(fs, var, &key); /* env[varname] */
450452
}
451453
}
@@ -1019,7 +1021,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
10191021
break;
10201022
}
10211023
case TK_STRING: { /* funcargs -> STRING */
1022-
codestring(ls, &args, ls->t.seminfo.ts);
1024+
codestring(&args, ls->t.seminfo.ts);
10231025
luaX_next(ls); /* must use 'seminfo' before 'next' */
10241026
break;
10251027
}
@@ -1127,7 +1129,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
11271129
break;
11281130
}
11291131
case TK_STRING: {
1130-
codestring(ls, v, ls->t.seminfo.ts);
1132+
codestring(v, ls->t.seminfo.ts);
11311133
break;
11321134
}
11331135
case TK_NIL: {

lparser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ typedef enum {
3030
VFALSE, /* constant false */
3131
VK, /* constant in 'k'; info = index of constant in 'k' */
3232
VKFLT, /* floating constant; nval = numerical float value */
33-
VKINT, /* integer constant; nval = numerical integer value */
33+
VKINT, /* integer constant; ival = numerical integer value */
34+
VKSTR, /* string constant; strval = TString address;
35+
(string is fixed by the lexer) */
3436
VNONRELOC, /* expression has its value in a fixed register;
3537
info = result register */
3638
VLOCAL, /* local variable; var.ridx = local register;
@@ -67,6 +69,7 @@ typedef struct expdesc {
6769
union {
6870
lua_Integer ival; /* for VKINT */
6971
lua_Number nval; /* for VKFLT */
72+
TString *strval; /* for VKSTR */
7073
int info; /* for generic use */
7174
struct { /* for indexed variables */
7275
short idx; /* index (R or "long" K) */

testes/code.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,5 +409,22 @@ checkequal(function () return 6 and true or nil end,
409409
function () return k6 and kTrue or kNil end)
410410

411411

412+
do -- string constants
413+
local function f1 ()
414+
local <const> k = "00000000000000000000000000000000000000000000000000"
415+
return function ()
416+
return function () return k end
417+
end
418+
end
419+
420+
local f2 = f1()
421+
local f3 = f2()
422+
assert(f3() == string.rep("0", 50))
423+
checkK(f3, f3())
424+
-- string is not needed by other functions
425+
assert(T.listk(f1)[1] == nil)
426+
assert(T.listk(f2)[1] == nil)
427+
end
428+
412429
print 'OK'
413430

0 commit comments

Comments
 (0)