diff options
| -rw-r--r-- | lapi.c | 15 | ||||
| -rw-r--r-- | lcode.c | 47 | ||||
| -rw-r--r-- | lobject.c | 47 | ||||
| -rw-r--r-- | lobject.h | 5 |
4 files changed, 83 insertions, 31 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.177 2013/04/26 19:51:17 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.178 2013/04/29 17:12:50 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -297,9 +297,6 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { | |||
| 297 | 297 | ||
| 298 | 298 | ||
| 299 | LUA_API void lua_arith (lua_State *L, int op) { | 299 | LUA_API void lua_arith (lua_State *L, int op) { |
| 300 | StkId o1; /* 1st operand */ | ||
| 301 | StkId o2; /* 2nd operand */ | ||
| 302 | lua_Number n1, n2; | ||
| 303 | lua_lock(L); | 300 | lua_lock(L); |
| 304 | if (op != LUA_OPUNM) /* all other operations expect two operands */ | 301 | if (op != LUA_OPUNM) /* all other operations expect two operands */ |
| 305 | api_checknelems(L, 2); | 302 | api_checknelems(L, 2); |
| @@ -308,13 +305,9 @@ LUA_API void lua_arith (lua_State *L, int op) { | |||
| 308 | setobjs2s(L, L->top, L->top - 1); | 305 | setobjs2s(L, L->top, L->top - 1); |
| 309 | L->top++; | 306 | L->top++; |
| 310 | } | 307 | } |
| 311 | o1 = L->top - 2; | 308 | /* first operand at top - 2, second at top - 1; result go to top - 2 */ |
| 312 | o2 = L->top - 1; | 309 | luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); |
| 313 | if (tonumber(o1, &n1) && tonumber(o2, &n2)) { | 310 | L->top--; /* remove second operand */ |
| 314 | setnvalue(o1, luaO_numarith(op, n1, n2)); | ||
| 315 | } | ||
| 316 | else luaT_trybinTM(L, o1, o2, o1, cast(TMS, op - LUA_OPADD + TM_ADD)); | ||
| 317 | L->top--; | ||
| 318 | lua_unlock(L); | 311 | lua_unlock(L); |
| 319 | } | 312 | } |
| 320 | 313 | ||
| @@ -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: { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.c,v 2.60 2013/04/25 13:53:13 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.61 2013/04/29 16:57:28 roberto Exp roberto $ |
| 3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -70,7 +70,21 @@ int luaO_ceillog2 (unsigned int x) { | |||
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | 72 | ||
| 73 | lua_Number luaO_numarith (int op, lua_Number v1, lua_Number v2) { | 73 | static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, |
| 74 | lua_Integer v2) { | ||
| 75 | switch (op) { | ||
| 76 | case LUA_OPADD: return intop(+, v1, v2); | ||
| 77 | case LUA_OPSUB:return intop(-, v1, v2); | ||
| 78 | case LUA_OPMUL:return intop(*, v1, v2); | ||
| 79 | case LUA_OPMOD: return luaV_mod(L, v1, v2); | ||
| 80 | case LUA_OPPOW: return luaV_pow(v1, v2); | ||
| 81 | case LUA_OPUNM: return -v1; | ||
| 82 | default: lua_assert(0); return 0; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | |||
| 87 | static lua_Number numarith (int op, lua_Number v1, lua_Number v2) { | ||
| 74 | switch (op) { | 88 | switch (op) { |
| 75 | case LUA_OPADD: return luai_numadd(NULL, v1, v2); | 89 | case LUA_OPADD: return luai_numadd(NULL, v1, v2); |
| 76 | case LUA_OPSUB: return luai_numsub(NULL, v1, v2); | 90 | case LUA_OPSUB: return luai_numsub(NULL, v1, v2); |
| @@ -84,6 +98,35 @@ lua_Number luaO_numarith (int op, lua_Number v1, lua_Number v2) { | |||
| 84 | } | 98 | } |
| 85 | 99 | ||
| 86 | 100 | ||
| 101 | void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, | ||
| 102 | TValue *res) { | ||
| 103 | if (op == LUA_OPIDIV) { /* operates only on integers */ | ||
| 104 | lua_Integer i1; lua_Integer i2; | ||
| 105 | if (tointeger(p1, &i1) && tointeger(p2, &i2)) { | ||
| 106 | setivalue(res, luaV_div(L, i1, i2)); | ||
| 107 | return; | ||
| 108 | } | ||
| 109 | /* else go to the end */ | ||
| 110 | } | ||
| 111 | else { /* other operations */ | ||
| 112 | lua_Number n1; lua_Number n2; | ||
| 113 | if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV && | ||
| 114 | (op != LUA_OPPOW || ivalue(p2) >= 0)) { | ||
| 115 | setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); | ||
| 116 | return; | ||
| 117 | } | ||
| 118 | else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { | ||
| 119 | setnvalue(res, numarith(op, n1, n2)); | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | /* else go to the end */ | ||
| 123 | } | ||
| 124 | /* could not perform raw operation; try metmethod */ | ||
| 125 | lua_assert(L != NULL); /* cannot fail when folding (compile time) */ | ||
| 126 | luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD)); | ||
| 127 | } | ||
| 128 | |||
| 129 | |||
| 87 | int luaO_hexavalue (int c) { | 130 | int luaO_hexavalue (int c) { |
| 88 | if (lisdigit(c)) return c - '0'; | 131 | if (lisdigit(c)) return c - '0'; |
| 89 | else return ltolower(c) - 'a' + 10; | 132 | else return ltolower(c) - 'a' + 10; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.74 2013/04/16 18:46:28 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.75 2013/04/29 16:57:28 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -496,7 +496,8 @@ LUAI_DDEC const TValue luaO_nilobject_; | |||
| 496 | LUAI_FUNC int luaO_int2fb (unsigned int x); | 496 | LUAI_FUNC int luaO_int2fb (unsigned int x); |
| 497 | LUAI_FUNC int luaO_fb2int (int x); | 497 | LUAI_FUNC int luaO_fb2int (int x); |
| 498 | LUAI_FUNC int luaO_ceillog2 (unsigned int x); | 498 | LUAI_FUNC int luaO_ceillog2 (unsigned int x); |
| 499 | LUAI_FUNC lua_Number luaO_numarith (int op, lua_Number v1, lua_Number v2); | 499 | LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, |
| 500 | const TValue *p2, TValue *res); | ||
| 500 | LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); | 501 | LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); |
| 501 | LUAI_FUNC int luaO_str2int (const char *s, lua_Integer *result); | 502 | LUAI_FUNC int luaO_str2int (const char *s, lua_Integer *result); |
| 502 | LUAI_FUNC int luaO_hexavalue (int c); | 503 | LUAI_FUNC int luaO_hexavalue (int c); |
