diff options
Diffstat (limited to 'lcode.c')
-rw-r--r-- | lcode.c | 47 |
1 files changed, 31 insertions, 16 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.66 2013/04/26 13:07:53 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.67 2013/04/29 16:57:48 roberto Exp roberto $ |
3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -29,8 +29,18 @@ | |||
29 | #define hasjumps(e) ((e)->t != (e)->f) | 29 | #define hasjumps(e) ((e)->t != (e)->f) |
30 | 30 | ||
31 | 31 | ||
32 | static int isnumeral(expdesc *e) { | 32 | static int tonumeral(expdesc *e, TValue *v) { |
33 | return (e->k == VKFLT && e->t == NO_JUMP && e->f == NO_JUMP); | 33 | if (e->t != NO_JUMP || e->f != NO_JUMP) |
34 | return 0; /* not a numeral */ | ||
35 | switch (e->k) { | ||
36 | case VKINT: | ||
37 | if (v) setivalue(v, e->u.ival); | ||
38 | return 1; | ||
39 | case VKFLT: | ||
40 | if (v) setnvalue(v, e->u.nval); | ||
41 | return 1; | ||
42 | default: return 0; | ||
43 | } | ||
34 | } | 44 | } |
35 | 45 | ||
36 | 46 | ||
@@ -730,21 +740,28 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | |||
730 | 740 | ||
731 | 741 | ||
732 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | 742 | static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { |
733 | lua_Number r; | 743 | TValue v1, v2, res; |
734 | if (!isnumeral(e1) || !isnumeral(e2)) return 0; | 744 | lua_Integer i2; |
735 | if ((op == OP_DIV || op == OP_IDIV || op == OP_MOD) && e2->u.nval == 0) | 745 | if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2)) |
736 | return 0; /* do not attempt to divide by 0 */ | 746 | return 0; |
737 | r = luaO_numarith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); | 747 | if ((op == OP_IDIV || op == OP_MOD) && tointeger(&v2, &i2) && i2 == 0) |
738 | e1->u.nval = r; | 748 | return 0; /* avoid division by 0 at compile time */ |
749 | luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res); | ||
750 | if (ttisinteger(&res)) { | ||
751 | e1->k = VKINT; | ||
752 | e1->u.ival = ivalue(&res); | ||
753 | } | ||
754 | else { | ||
755 | e1->k = VKFLT; | ||
756 | e1->u.nval = fltvalue(&res); | ||
757 | } | ||
739 | return 1; | 758 | return 1; |
740 | } | 759 | } |
741 | 760 | ||
742 | 761 | ||
743 | static void codearith (FuncState *fs, OpCode op, | 762 | static void codearith (FuncState *fs, OpCode op, |
744 | expdesc *e1, expdesc *e2, int line) { | 763 | expdesc *e1, expdesc *e2, int line) { |
745 | if (constfolding(op, e1, e2)) | 764 | if (!constfolding(op, e1, e2)) { /* could not fold operation? */ |
746 | return; | ||
747 | else { | ||
748 | int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; | 765 | int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; |
749 | int o1 = luaK_exp2RK(fs, e1); | 766 | int o1 = luaK_exp2RK(fs, e1); |
750 | if (o1 > o2) { | 767 | if (o1 > o2) { |
@@ -783,9 +800,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { | |||
783 | e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0; | 800 | e2.t = e2.f = NO_JUMP; e2.k = VKFLT; e2.u.nval = 0; |
784 | switch (op) { | 801 | switch (op) { |
785 | case OPR_MINUS: { | 802 | case OPR_MINUS: { |
786 | if (isnumeral(e)) /* minus constant? */ | 803 | if (!constfolding(OP_UNM, e, e)) { /* cannot fold it? */ |
787 | e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ | ||
788 | else { | ||
789 | luaK_exp2anyreg(fs, e); | 804 | luaK_exp2anyreg(fs, e); |
790 | codearith(fs, OP_UNM, e, &e2, line); | 805 | codearith(fs, OP_UNM, e, &e2, line); |
791 | } | 806 | } |
@@ -819,7 +834,7 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { | |||
819 | case OPR_ADD: case OPR_SUB: | 834 | case OPR_ADD: case OPR_SUB: |
820 | case OPR_MUL: case OPR_DIV: case OPR_IDIV: | 835 | case OPR_MUL: case OPR_DIV: case OPR_IDIV: |
821 | case OPR_MOD: case OPR_POW: { | 836 | case OPR_MOD: case OPR_POW: { |
822 | if (!isnumeral(v)) luaK_exp2RK(fs, v); | 837 | if (!tonumeral(v, NULL)) luaK_exp2RK(fs, v); |
823 | break; | 838 | break; |
824 | } | 839 | } |
825 | default: { | 840 | default: { |