aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-17 14:26:56 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-17 14:26:56 -0300
commitd6af81084df569bc8e3bd0949ad6fc0b40c8468d (patch)
tree103b92a3fd9b1164763500054f7979f51f9aa4b4
parent4846f7e3bb1397142ab0de808ae59c08db9832a6 (diff)
downloadlua-d6af81084df569bc8e3bd0949ad6fc0b40c8468d.tar.gz
lua-d6af81084df569bc8e3bd0949ad6fc0b40c8468d.tar.bz2
lua-d6af81084df569bc8e3bd0949ad6fc0b40c8468d.zip
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).
-rw-r--r--lcode.c35
-rw-r--r--lcode.h1
-rw-r--r--lparser.c14
-rw-r--r--lparser.h5
-rw-r--r--testes/code.lua17
5 files changed, 54 insertions, 18 deletions
diff --git a/lcode.c b/lcode.c
index e57ad284..40efcff3 100644
--- a/lcode.c
+++ b/lcode.c
@@ -81,9 +81,8 @@ int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) {
81 case VNIL: 81 case VNIL:
82 setnilvalue(v); 82 setnilvalue(v);
83 return 1; 83 return 1;
84 case VK: { 84 case VKSTR: {
85 TValue *k = &fs->f->k[e->u.info]; 85 setsvalue(fs->ls->L, v, e->u.strval);
86 setobj(fs->ls->L, v, k);
87 return 1; 86 return 1;
88 } 87 }
89 default: return tonumeral(e, v); 88 default: return tonumeral(e, v);
@@ -561,7 +560,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
561/* 560/*
562** Add a string to list of constants and return its index. 561** Add a string to list of constants and return its index.
563*/ 562*/
564int luaK_stringK (FuncState *fs, TString *s) { 563static int stringK (FuncState *fs, TString *s) {
565 TValue o; 564 TValue o;
566 setsvalue(fs->ls->L, &o, s); 565 setsvalue(fs->ls->L, &o, s);
567 return addk(fs, &o, &o); /* use string itself as key */ 566 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) {
656/* 655/*
657** Convert a constant in 'v' into an expression description 'e' 656** Convert a constant in 'v' into an expression description 'e'
658*/ 657*/
659static void const2exp (FuncState *fs, TValue *v, expdesc *e) { 658static void const2exp (TValue *v, expdesc *e) {
660 switch (ttypetag(v)) { 659 switch (ttypetag(v)) {
661 case LUA_TNUMINT: 660 case LUA_TNUMINT:
662 e->k = VKINT; e->u.ival = ivalue(v); 661 e->k = VKINT; e->u.ival = ivalue(v);
@@ -671,7 +670,7 @@ static void const2exp (FuncState *fs, TValue *v, expdesc *e) {
671 e->k = VNIL; 670 e->k = VNIL;
672 break; 671 break;
673 case LUA_TSHRSTR: case LUA_TLNGSTR: 672 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);
675 break; 674 break;
676 default: lua_assert(0); 675 default: lua_assert(0);
677 } 676 }
@@ -697,6 +696,16 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {
697 696
698 697
699/* 698/*
699** Convert a VKSTR to a VK
700*/
701static 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
708/*
700** Fix an expression to return one result. 709** Fix an expression to return one result.
701** If expression is not a multi-ret expression (function call or 710** If expression is not a multi-ret expression (function call or
702** vararg), it already returns one result, so nothing needs to be done. 711** vararg), it already returns one result, so nothing needs to be done.
@@ -728,7 +737,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) {
728 switch (e->k) { 737 switch (e->k) {
729 case VCONST: { 738 case VCONST: {
730 TValue *val = &fs->ls->dyd->actvar.arr[e->u.info].k; 739 TValue *val = &fs->ls->dyd->actvar.arr[e->u.info].k;
731 const2exp(fs, val, e); 740 const2exp(val, e);
732 break; 741 break;
733 } 742 }
734 case VLOCAL: { /* already in a register */ 743 case VLOCAL: { /* already in a register */
@@ -789,6 +798,9 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
789 luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); 798 luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
790 break; 799 break;
791 } 800 }
801 case VKSTR: {
802 str2K(fs, e);
803 } /* FALLTHROUGH */
792 case VK: { 804 case VK: {
793 luaK_codek(fs, reg, e->u.info); 805 luaK_codek(fs, reg, e->u.info);
794 break; 806 break;
@@ -949,6 +961,7 @@ static int luaK_exp2K (FuncState *fs, expdesc *e) {
949 case VNIL: info = nilK(fs); break; 961 case VNIL: info = nilK(fs); break;
950 case VKINT: info = luaK_intK(fs, e->u.ival); break; 962 case VKINT: info = luaK_intK(fs, e->u.ival); break;
951 case VKFLT: info = luaK_numberK(fs, e->u.nval); break; 963 case VKFLT: info = luaK_numberK(fs, e->u.nval); break;
964 case VKSTR: info = stringK(fs, e->u.strval); break;
952 case VK: info = e->u.info; break; 965 case VK: info = e->u.info; break;
953 default: return 0; /* not a constant */ 966 default: return 0; /* not a constant */
954 } 967 }
@@ -1083,7 +1096,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) {
1083 pc = e->u.info; /* save jump position */ 1096 pc = e->u.info; /* save jump position */
1084 break; 1097 break;
1085 } 1098 }
1086 case VK: case VKFLT: case VKINT: case VTRUE: { 1099 case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: {
1087 pc = NO_JUMP; /* always true; do nothing */ 1100 pc = NO_JUMP; /* always true; do nothing */
1088 break; 1101 break;
1089 } 1102 }
@@ -1133,7 +1146,7 @@ static void codenot (FuncState *fs, expdesc *e) {
1133 e->k = VTRUE; /* true == not nil == not false */ 1146 e->k = VTRUE; /* true == not nil == not false */
1134 break; 1147 break;
1135 } 1148 }
1136 case VK: case VKFLT: case VKINT: case VTRUE: { 1149 case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: {
1137 e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ 1150 e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */
1138 break; 1151 break;
1139 } 1152 }
@@ -1219,9 +1232,11 @@ static int isSCnumber (expdesc *e, lua_Integer *i, int *isfloat) {
1219** values in registers. 1232** values in registers.
1220*/ 1233*/
1221void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { 1234void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
1235 if (k->k == VKSTR)
1236 str2K(fs, k);
1222 lua_assert(!hasjumps(t) && 1237 lua_assert(!hasjumps(t) &&
1223 (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); 1238 (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'? */
1225 luaK_exp2anyreg(fs, t); /* put it in a register */ 1240 luaK_exp2anyreg(fs, t); /* put it in a register */
1226 if (t->k == VUPVAL) { 1241 if (t->k == VUPVAL) {
1227 t->u.ind.t = t->u.info; /* upvalue index */ 1242 t->u.ind.t = t->u.info; /* upvalue index */
diff --git a/lcode.h b/lcode.h
index 0c12bb64..8cecd538 100644
--- a/lcode.h
+++ b/lcode.h
@@ -62,7 +62,6 @@ LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
62LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); 62LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
63LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); 63LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
64LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); 64LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
65LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
66LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); 65LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n);
67LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); 66LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
68LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); 67LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);
diff --git a/lparser.c b/lparser.c
index ea810006..b70c609e 100644
--- a/lparser.c
+++ b/lparser.c
@@ -156,13 +156,15 @@ static void init_exp (expdesc *e, expkind k, int i) {
156} 156}
157 157
158 158
159static void codestring (LexState *ls, expdesc *e, TString *s) { 159static void codestring (expdesc *e, TString *s) {
160 init_exp(e, VK, luaK_stringK(ls->fs, s)); 160 e->f = e->t = NO_JUMP;
161 e->k = VKSTR;
162 e->u.strval = s;
161} 163}
162 164
163 165
164static void codename (LexState *ls, expdesc *e) { 166static void codename (LexState *ls, expdesc *e) {
165 codestring(ls, e, str_checkname(ls)); 167 codestring(e, str_checkname(ls));
166} 168}
167 169
168 170
@@ -445,7 +447,7 @@ static void singlevar (LexState *ls, expdesc *var) {
445 expdesc key; 447 expdesc key;
446 singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ 448 singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
447 lua_assert(var->k != VVOID); /* this one must exist */ 449 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 */
449 luaK_indexed(fs, var, &key); /* env[varname] */ 451 luaK_indexed(fs, var, &key); /* env[varname] */
450 } 452 }
451} 453}
@@ -1019,7 +1021,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
1019 break; 1021 break;
1020 } 1022 }
1021 case TK_STRING: { /* funcargs -> STRING */ 1023 case TK_STRING: { /* funcargs -> STRING */
1022 codestring(ls, &args, ls->t.seminfo.ts); 1024 codestring(&args, ls->t.seminfo.ts);
1023 luaX_next(ls); /* must use 'seminfo' before 'next' */ 1025 luaX_next(ls); /* must use 'seminfo' before 'next' */
1024 break; 1026 break;
1025 } 1027 }
@@ -1127,7 +1129,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
1127 break; 1129 break;
1128 } 1130 }
1129 case TK_STRING: { 1131 case TK_STRING: {
1130 codestring(ls, v, ls->t.seminfo.ts); 1132 codestring(v, ls->t.seminfo.ts);
1131 break; 1133 break;
1132 } 1134 }
1133 case TK_NIL: { 1135 case TK_NIL: {
diff --git a/lparser.h b/lparser.h
index d9b734bf..f528f013 100644
--- a/lparser.h
+++ b/lparser.h
@@ -30,7 +30,9 @@ typedef enum {
30 VFALSE, /* constant false */ 30 VFALSE, /* constant false */
31 VK, /* constant in 'k'; info = index of constant in 'k' */ 31 VK, /* constant in 'k'; info = index of constant in 'k' */
32 VKFLT, /* floating constant; nval = numerical float value */ 32 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) */
34 VNONRELOC, /* expression has its value in a fixed register; 36 VNONRELOC, /* expression has its value in a fixed register;
35 info = result register */ 37 info = result register */
36 VLOCAL, /* local variable; var.ridx = local register; 38 VLOCAL, /* local variable; var.ridx = local register;
@@ -67,6 +69,7 @@ typedef struct expdesc {
67 union { 69 union {
68 lua_Integer ival; /* for VKINT */ 70 lua_Integer ival; /* for VKINT */
69 lua_Number nval; /* for VKFLT */ 71 lua_Number nval; /* for VKFLT */
72 TString *strval; /* for VKSTR */
70 int info; /* for generic use */ 73 int info; /* for generic use */
71 struct { /* for indexed variables */ 74 struct { /* for indexed variables */
72 short idx; /* index (R or "long" K) */ 75 short idx; /* index (R or "long" K) */
diff --git a/testes/code.lua b/testes/code.lua
index b2702c61..b5091458 100644
--- a/testes/code.lua
+++ b/testes/code.lua
@@ -409,5 +409,22 @@ checkequal(function () return 6 and true or nil end,
409 function () return k6 and kTrue or kNil end) 409 function () return k6 and kTrue or kNil end)
410 410
411 411
412do -- 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)
427end
428
412print 'OK' 429print 'OK'
413 430