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) { case VNIL: setnilvalue(v); return 1; - case VK: { - TValue *k = &fs->f->k[e->u.info]; - setobj(fs->ls->L, v, k); + case VKSTR: { + setsvalue(fs->ls->L, v, e->u.strval); return 1; } default: return tonumeral(e, v); @@ -561,7 +560,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { /* ** Add a string to list of constants and return its index. */ -int luaK_stringK (FuncState *fs, TString *s) { +static int stringK (FuncState *fs, TString *s) { TValue o; setsvalue(fs->ls->L, &o, s); 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) { /* ** Convert a constant in 'v' into an expression description 'e' */ -static void const2exp (FuncState *fs, TValue *v, expdesc *e) { +static void const2exp (TValue *v, expdesc *e) { switch (ttypetag(v)) { case LUA_TNUMINT: e->k = VKINT; e->u.ival = ivalue(v); @@ -671,7 +670,7 @@ static void const2exp (FuncState *fs, TValue *v, expdesc *e) { e->k = VNIL; break; case LUA_TSHRSTR: case LUA_TLNGSTR: - e->k = VK; e->u.info = luaK_stringK(fs, tsvalue(v)); + e->k = VKSTR; e->u.strval = tsvalue(v); break; default: lua_assert(0); } @@ -696,6 +695,16 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { } +/* +** Convert a VKSTR to a VK +*/ +static void str2K (FuncState *fs, expdesc *e) { + lua_assert(e->k == VKSTR); + e->u.info = stringK(fs, e->u.strval); + e->k = VK; +} + + /* ** Fix an expression to return one result. ** If expression is not a multi-ret expression (function call or @@ -728,7 +737,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VCONST: { TValue *val = &fs->ls->dyd->actvar.arr[e->u.info].k; - const2exp(fs, val, e); + const2exp(val, e); break; } case VLOCAL: { /* already in a register */ @@ -789,6 +798,9 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); break; } + case VKSTR: { + str2K(fs, e); + } /* FALLTHROUGH */ case VK: { luaK_codek(fs, reg, e->u.info); break; @@ -949,6 +961,7 @@ static int luaK_exp2K (FuncState *fs, expdesc *e) { case VNIL: info = nilK(fs); break; case VKINT: info = luaK_intK(fs, e->u.ival); break; case VKFLT: info = luaK_numberK(fs, e->u.nval); break; + case VKSTR: info = stringK(fs, e->u.strval); break; case VK: info = e->u.info; break; default: return 0; /* not a constant */ } @@ -1083,7 +1096,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { pc = e->u.info; /* save jump position */ break; } - case VK: case VKFLT: case VKINT: case VTRUE: { + case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { pc = NO_JUMP; /* always true; do nothing */ break; } @@ -1133,7 +1146,7 @@ static void codenot (FuncState *fs, expdesc *e) { e->k = VTRUE; /* true == not nil == not false */ break; } - case VK: case VKFLT: case VKINT: case VTRUE: { + case VK: case VKFLT: case VKINT: case VKSTR: case VTRUE: { e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ break; } @@ -1219,9 +1232,11 @@ static int isSCnumber (expdesc *e, lua_Integer *i, int *isfloat) { ** values in registers. */ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + if (k->k == VKSTR) + str2K(fs, k); lua_assert(!hasjumps(t) && (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); - if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non string? */ + if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ luaK_exp2anyreg(fs, t); /* put it in a register */ if (t->k == VUPVAL) { 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); LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); LUAI_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) { } -static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s)); +static void codestring (expdesc *e, TString *s) { + e->f = e->t = NO_JUMP; + e->k = VKSTR; + e->u.strval = s; } static void codename (LexState *ls, expdesc *e) { - codestring(ls, e, str_checkname(ls)); + codestring(e, str_checkname(ls)); } @@ -445,7 +447,7 @@ static void singlevar (LexState *ls, expdesc *var) { expdesc key; singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ lua_assert(var->k != VVOID); /* this one must exist */ - codestring(ls, &key, varname); /* key is variable name */ + codestring(&key, varname); /* key is variable name */ luaK_indexed(fs, var, &key); /* env[varname] */ } } @@ -1019,7 +1021,7 @@ static void funcargs (LexState *ls, expdesc *f, int line) { break; } case TK_STRING: { /* funcargs -> STRING */ - codestring(ls, &args, ls->t.seminfo.ts); + codestring(&args, ls->t.seminfo.ts); luaX_next(ls); /* must use 'seminfo' before 'next' */ break; } @@ -1127,7 +1129,7 @@ static void simpleexp (LexState *ls, expdesc *v) { break; } case TK_STRING: { - codestring(ls, v, ls->t.seminfo.ts); + codestring(v, ls->t.seminfo.ts); break; } 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 { VFALSE, /* constant false */ VK, /* constant in 'k'; info = index of constant in 'k' */ VKFLT, /* floating constant; nval = numerical float value */ - VKINT, /* integer constant; nval = numerical integer value */ + VKINT, /* integer constant; ival = numerical integer value */ + VKSTR, /* string constant; strval = TString address; + (string is fixed by the lexer) */ VNONRELOC, /* expression has its value in a fixed register; info = result register */ VLOCAL, /* local variable; var.ridx = local register; @@ -67,6 +69,7 @@ typedef struct expdesc { union { lua_Integer ival; /* for VKINT */ lua_Number nval; /* for VKFLT */ + TString *strval; /* for VKSTR */ int info; /* for generic use */ struct { /* for indexed variables */ 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, function () return k6 and kTrue or kNil end) +do -- string constants + local function f1 () + local k = "00000000000000000000000000000000000000000000000000" + return function () + return function () return k end + end + end + + local f2 = f1() + local f3 = f2() + assert(f3() == string.rep("0", 50)) + checkK(f3, f3()) + -- string is not needed by other functions + assert(T.listk(f1)[1] == nil) + assert(T.listk(f2)[1] == nil) +end + print 'OK'