diff options
| -rw-r--r-- | lcode.c | 35 | ||||
| -rw-r--r-- | lcode.h | 1 | ||||
| -rw-r--r-- | lparser.c | 14 | ||||
| -rw-r--r-- | lparser.h | 5 | ||||
| -rw-r--r-- | testes/code.lua | 17 |
5 files changed, 54 insertions, 18 deletions
| @@ -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 | */ |
| 564 | int luaK_stringK (FuncState *fs, TString *s) { | 563 | static 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 | */ |
| 659 | static void const2exp (FuncState *fs, TValue *v, expdesc *e) { | 658 | static 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 | */ | ||
| 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 | |||
| 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 | */ |
| 1221 | void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | 1234 | void 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 */ |
| @@ -62,7 +62,6 @@ LUAI_FUNC void luaK_fixline (FuncState *fs, int line); | |||
| 62 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); | 62 | LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); |
| 63 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); | 63 | LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); |
| 64 | LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); | 64 | LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); |
| 65 | LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); | ||
| 66 | LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); | 65 | LUAI_FUNC void luaK_int (FuncState *fs, int reg, lua_Integer n); |
| 67 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); | 66 | LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); |
| 68 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); | 67 | LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); |
| @@ -156,13 +156,15 @@ static void init_exp (expdesc *e, expkind k, int i) { | |||
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | 158 | ||
| 159 | static void codestring (LexState *ls, expdesc *e, TString *s) { | 159 | static 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 | ||
| 164 | static void codename (LexState *ls, expdesc *e) { | 166 | static 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: { |
| @@ -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 | ||
| 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 | |||
| 412 | print 'OK' | 429 | print 'OK' |
| 413 | 430 | ||
