diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 56 |
1 files changed, 55 insertions, 1 deletions
@@ -68,6 +68,30 @@ static int tonumeral (const expdesc *e, TValue *v) { | |||
68 | 68 | ||
69 | 69 | ||
70 | /* | 70 | /* |
71 | ** If expression is a constant, fills 'v' with its value | ||
72 | ** and returns 1. Otherwise, returns 0. | ||
73 | */ | ||
74 | int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) { | ||
75 | if (hasjumps(e)) | ||
76 | return 0; /* not a constant */ | ||
77 | switch (e->k) { | ||
78 | case VFALSE: case VTRUE: | ||
79 | setbvalue(v, e->k == VTRUE); | ||
80 | return 1; | ||
81 | case VNIL: | ||
82 | setnilvalue(v); | ||
83 | return 1; | ||
84 | case VK: { | ||
85 | TValue *k = &fs->f->k[e->u.info]; | ||
86 | setobj(fs->ls->L, v, k); | ||
87 | return 1; | ||
88 | } | ||
89 | default: return tonumeral(e, v); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | |||
94 | /* | ||
71 | ** Return the previous instruction of the current code. If there | 95 | ** Return the previous instruction of the current code. If there |
72 | ** may be a jump target between the current instruction and the | 96 | ** may be a jump target between the current instruction and the |
73 | ** previous one, return an invalid instruction (to avoid wrong | 97 | ** previous one, return an invalid instruction (to avoid wrong |
@@ -630,6 +654,31 @@ static void luaK_float (FuncState *fs, int reg, lua_Number f) { | |||
630 | 654 | ||
631 | 655 | ||
632 | /* | 656 | /* |
657 | ** Convert a constant in 'v' into an expression description 'e' | ||
658 | */ | ||
659 | static void const2exp (FuncState *fs, TValue *v, expdesc *e) { | ||
660 | switch (ttypetag(v)) { | ||
661 | case LUA_TNUMINT: | ||
662 | e->k = VKINT; e->u.ival = ivalue(v); | ||
663 | break; | ||
664 | case LUA_TNUMFLT: | ||
665 | e->k = VKFLT; e->u.nval = fltvalue(v); | ||
666 | break; | ||
667 | case LUA_TBOOLEAN: | ||
668 | e->k = bvalue(v) ? VTRUE : VFALSE; | ||
669 | break; | ||
670 | case LUA_TNIL: | ||
671 | e->k = VNIL; | ||
672 | break; | ||
673 | case LUA_TSHRSTR: case LUA_TLNGSTR: | ||
674 | e->k = VK; e->u.info = luaK_stringK(fs, tsvalue(v)); | ||
675 | break; | ||
676 | default: lua_assert(0); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | |||
681 | /* | ||
633 | ** Fix an expression to return the number of results 'nresults'. | 682 | ** Fix an expression to return the number of results 'nresults'. |
634 | ** Either 'e' is a multi-ret expression (function call or vararg) | 683 | ** Either 'e' is a multi-ret expression (function call or vararg) |
635 | ** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). | 684 | ** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). |
@@ -677,6 +726,11 @@ void luaK_setoneret (FuncState *fs, expdesc *e) { | |||
677 | */ | 726 | */ |
678 | void luaK_dischargevars (FuncState *fs, expdesc *e) { | 727 | void luaK_dischargevars (FuncState *fs, expdesc *e) { |
679 | switch (e->k) { | 728 | switch (e->k) { |
729 | case VCONST: { | ||
730 | TValue *val = &fs->ls->dyd->actvar.arr[e->u.info].k; | ||
731 | const2exp(fs, val, e); | ||
732 | break; | ||
733 | } | ||
680 | case VLOCAL: { /* already in a register */ | 734 | case VLOCAL: { /* already in a register */ |
681 | e->u.info = e->u.var.sidx; | 735 | e->u.info = e->u.var.sidx; |
682 | e->k = VNONRELOC; /* becomes a non-relocatable value */ | 736 | e->k = VNONRELOC; /* becomes a non-relocatable value */ |
@@ -1074,7 +1128,6 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) { | |||
1074 | ** Code 'not e', doing constant folding. | 1128 | ** Code 'not e', doing constant folding. |
1075 | */ | 1129 | */ |
1076 | static void codenot (FuncState *fs, expdesc *e) { | 1130 | static void codenot (FuncState *fs, expdesc *e) { |
1077 | luaK_dischargevars(fs, e); | ||
1078 | switch (e->k) { | 1131 | switch (e->k) { |
1079 | case VNIL: case VFALSE: { | 1132 | case VNIL: case VFALSE: { |
1080 | e->k = VTRUE; /* true == not nil == not false */ | 1133 | e->k = VTRUE; /* true == not nil == not false */ |
@@ -1447,6 +1500,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { | |||
1447 | */ | 1500 | */ |
1448 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { | 1501 | void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { |
1449 | static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; | 1502 | static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; |
1503 | luaK_dischargevars(fs, e); | ||
1450 | switch (op) { | 1504 | switch (op) { |
1451 | case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ | 1505 | case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ |
1452 | if (constfolding(fs, op + LUA_OPUNM, e, &ef)) | 1506 | if (constfolding(fs, op + LUA_OPUNM, e, &ef)) |