aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-07-07 13:34:32 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-07-07 13:34:32 -0300
commit4dff277255e3785b76b6b52fe2a98592e6cbc834 (patch)
treee3607d2aab29b6e0dbd46ac1acc81e9c6bf08dd7
parent07db10813cb044252c18973688f63b5eac6a90a6 (diff)
downloadlua-4dff277255e3785b76b6b52fe2a98592e6cbc834.tar.gz
lua-4dff277255e3785b76b6b52fe2a98592e6cbc834.tar.bz2
lua-4dff277255e3785b76b6b52fe2a98592e6cbc834.zip
coercion string->number in arithmetic operations moved to string
library
-rw-r--r--ldebug.c5
-rw-r--r--lobject.c4
-rw-r--r--lstrlib.c88
-rw-r--r--lvm.c21
-rw-r--r--lvm.h12
5 files changed, 111 insertions, 19 deletions
diff --git a/ldebug.c b/ldebug.c
index ac0b7d54..b83b2f89 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.127 2017/06/27 11:35:31 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.128 2017/06/29 15:06:44 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -679,8 +679,7 @@ l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) {
679 679
680l_noret luaG_opinterror (lua_State *L, const TValue *p1, 680l_noret luaG_opinterror (lua_State *L, const TValue *p1,
681 const TValue *p2, const char *msg) { 681 const TValue *p2, const char *msg) {
682 lua_Number temp; 682 if (!ttisnumber(p1)) /* first operand is wrong? */
683 if (!tonumber(p1, &temp)) /* first operand is wrong? */
684 p2 = p1; /* now second is wrong */ 683 p2 = p1; /* now second is wrong */
685 luaG_typeerror(L, p2, msg); 684 luaG_typeerror(L, p2, msg);
686} 685}
diff --git a/lobject.c b/lobject.c
index 9ad833c9..21616fad 100644
--- a/lobject.c
+++ b/lobject.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.c,v 2.115 2017/05/24 13:47:11 roberto Exp roberto $ 2** $Id: lobject.c,v 2.116 2017/06/29 15:06:44 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*/
@@ -147,7 +147,7 @@ int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2,
147 setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); 147 setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
148 return 1; 148 return 1;
149 } 149 }
150 else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { 150 else if (tonumberns(p1, n1) && tonumberns(p2, n2)) {
151 setfltvalue(res, numarith(L, op, n1, n2)); 151 setfltvalue(res, numarith(L, op, n1, n2));
152 return 1; 152 return 1;
153 } 153 }
diff --git a/lstrlib.c b/lstrlib.c
index 89896fa6..c7cfa421 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.255 2017/03/14 12:40:44 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.256 2017/05/19 16:29:40 roberto Exp roberto $
3** Standard library for string operations and pattern-matching 3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -203,6 +203,88 @@ static int str_dump (lua_State *L) {
203 203
204/* 204/*
205** {====================================================== 205** {======================================================
206** METAMETHODS
207** =======================================================
208*/
209
210static int tonum (lua_State *L, int arg) {
211 if (lua_type(L, arg) == LUA_TNUMBER) { /* already a number? */
212 lua_pushvalue(L, arg);
213 return 1;
214 }
215 else { /* check whether it is a numerical string */
216 size_t len;
217 const char *s = lua_tolstring(L, arg, &len);
218 return (s != NULL && lua_stringtonumber(L, s) == len + 1);
219 }
220}
221
222
223static int arith (lua_State *L, int op, const char *mtname) {
224 if (tonum(L, 1) && tonum(L, 2))
225 lua_arith(L, op); /* result will be on the top */
226 else {
227 lua_settop(L, 2); /* back to the original arguments */
228 if (lua_type(L, 2) == LUA_TSTRING || !luaL_getmetafield(L, 2, mtname))
229 return luaL_error(L, "attempt to %s a '%s' with a '%s'", mtname + 2,
230 luaL_typename(L, -2), luaL_typename(L, -1));
231 lua_insert(L, -3); /* put metamethod before arguments */
232 lua_call(L, 2, 1); /* call metamethod */
233 }
234 return 1;
235}
236
237
238static int arith_add (lua_State *L) {
239 return arith(L, LUA_OPADD, "__add");
240}
241
242static int arith_sub (lua_State *L) {
243 return arith(L, LUA_OPSUB, "__sub");
244}
245
246static int arith_mul (lua_State *L) {
247 return arith(L, LUA_OPMUL, "__mul");
248}
249
250static int arith_mod (lua_State *L) {
251 return arith(L, LUA_OPMOD, "__mod");
252}
253
254static int arith_pow (lua_State *L) {
255 return arith(L, LUA_OPPOW, "__pow");
256}
257
258static int arith_div (lua_State *L) {
259 return arith(L, LUA_OPDIV, "__div");
260}
261
262static int arith_idiv (lua_State *L) {
263 return arith(L, LUA_OPIDIV, "__idiv");
264}
265
266static int arith_unm (lua_State *L) {
267 return arith(L, LUA_OPUNM, "__unm");
268}
269
270
271static const luaL_Reg stringmetamethods[] = {
272 {"__add", arith_add},
273 {"__sub", arith_sub},
274 {"__mul", arith_mul},
275 {"__mod", arith_mod},
276 {"__pow", arith_pow},
277 {"__div", arith_div},
278 {"__idiv", arith_idiv},
279 {"__unm", arith_unm},
280 {"__index", NULL}, /* placeholder */
281 {NULL, NULL}
282};
283
284/* }====================================================== */
285
286/*
287** {======================================================
206** PATTERN MATCHING 288** PATTERN MATCHING
207** ======================================================= 289** =======================================================
208*/ 290*/
@@ -1576,7 +1658,9 @@ static const luaL_Reg strlib[] = {
1576 1658
1577 1659
1578static void createmetatable (lua_State *L) { 1660static void createmetatable (lua_State *L) {
1579 lua_createtable(L, 0, 1); /* table to be metatable for strings */ 1661 /* table to be metatable for strings */
1662 luaL_newlibtable(L, stringmetamethods);
1663 luaL_setfuncs(L, stringmetamethods, 0);
1580 lua_pushliteral(L, ""); /* dummy string */ 1664 lua_pushliteral(L, ""); /* dummy string */
1581 lua_pushvalue(L, -2); /* copy table */ 1665 lua_pushvalue(L, -2); /* copy table */
1582 lua_setmetatable(L, -2); /* set table as metatable for strings */ 1666 lua_setmetatable(L, -2); /* set table as metatable for strings */
diff --git a/lvm.c b/lvm.c
index 8f8cc49f..18799be7 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.288 2017/06/29 15:06:44 roberto Exp roberto $ 2** $Id: lvm.c,v 2.289 2017/06/29 15:38:41 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -35,7 +35,6 @@
35#define MAXTAGLOOP 2000 35#define MAXTAGLOOP 2000
36 36
37 37
38
39/* 38/*
40** 'l_intfitsf' checks whether a given integer can be converted to a 39** 'l_intfitsf' checks whether a given integer can be converted to a
41** float without rounding. Used in comparisons. Left undefined if 40** float without rounding. Used in comparisons. Left undefined if
@@ -997,7 +996,7 @@ void luaV_execute (lua_State *L) {
997 if (ttisinteger(rb)) { 996 if (ttisinteger(rb)) {
998 setivalue(s2v(ra), intop(+, ivalue(rb), ic)); 997 setivalue(s2v(ra), intop(+, ivalue(rb), ic));
999 } 998 }
1000 else if (tonumber(rb, &nb)) { 999 else if (tonumberns(rb, nb)) {
1001 setfltvalue(s2v(ra), luai_numadd(L, nb, cast_num(ic))); 1000 setfltvalue(s2v(ra), luai_numadd(L, nb, cast_num(ic)));
1002 } 1001 }
1003 else { 1002 else {
@@ -1019,7 +1018,7 @@ void luaV_execute (lua_State *L) {
1019 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); 1018 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
1020 setivalue(s2v(ra), intop(+, ib, ic)); 1019 setivalue(s2v(ra), intop(+, ib, ic));
1021 } 1020 }
1022 else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { 1021 else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1023 setfltvalue(s2v(ra), luai_numadd(L, nb, nc)); 1022 setfltvalue(s2v(ra), luai_numadd(L, nb, nc));
1024 } 1023 }
1025 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } 1024 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
@@ -1033,7 +1032,7 @@ void luaV_execute (lua_State *L) {
1033 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); 1032 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
1034 setivalue(s2v(ra), intop(-, ib, ic)); 1033 setivalue(s2v(ra), intop(-, ib, ic));
1035 } 1034 }
1036 else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { 1035 else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1037 setfltvalue(s2v(ra), luai_numsub(L, nb, nc)); 1036 setfltvalue(s2v(ra), luai_numsub(L, nb, nc));
1038 } 1037 }
1039 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } 1038 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); }
@@ -1047,7 +1046,7 @@ void luaV_execute (lua_State *L) {
1047 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); 1046 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
1048 setivalue(s2v(ra), intop(*, ib, ic)); 1047 setivalue(s2v(ra), intop(*, ib, ic));
1049 } 1048 }
1050 else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { 1049 else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1051 setfltvalue(s2v(ra), luai_nummul(L, nb, nc)); 1050 setfltvalue(s2v(ra), luai_nummul(L, nb, nc));
1052 } 1051 }
1053 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } 1052 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); }
@@ -1057,7 +1056,7 @@ void luaV_execute (lua_State *L) {
1057 TValue *rb = RKB(i); 1056 TValue *rb = RKB(i);
1058 TValue *rc = RKC(i); 1057 TValue *rc = RKC(i);
1059 lua_Number nb; lua_Number nc; 1058 lua_Number nb; lua_Number nc;
1060 if (tonumber(rb, &nb) && tonumber(rc, &nc)) { 1059 if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1061 setfltvalue(s2v(ra), luai_numdiv(L, nb, nc)); 1060 setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
1062 } 1061 }
1063 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } 1062 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); }
@@ -1121,7 +1120,7 @@ void luaV_execute (lua_State *L) {
1121 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); 1120 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
1122 setivalue(s2v(ra), luaV_mod(L, ib, ic)); 1121 setivalue(s2v(ra), luaV_mod(L, ib, ic));
1123 } 1122 }
1124 else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { 1123 else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1125 lua_Number m; 1124 lua_Number m;
1126 luai_nummod(L, nb, nc, m); 1125 luai_nummod(L, nb, nc, m);
1127 setfltvalue(s2v(ra), m); 1126 setfltvalue(s2v(ra), m);
@@ -1137,7 +1136,7 @@ void luaV_execute (lua_State *L) {
1137 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); 1136 lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
1138 setivalue(s2v(ra), luaV_div(L, ib, ic)); 1137 setivalue(s2v(ra), luaV_div(L, ib, ic));
1139 } 1138 }
1140 else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { 1139 else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1141 setfltvalue(s2v(ra), luai_numidiv(L, nb, nc)); 1140 setfltvalue(s2v(ra), luai_numidiv(L, nb, nc));
1142 } 1141 }
1143 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } 1142 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); }
@@ -1147,7 +1146,7 @@ void luaV_execute (lua_State *L) {
1147 TValue *rb = RKB(i); 1146 TValue *rb = RKB(i);
1148 TValue *rc = RKC(i); 1147 TValue *rc = RKC(i);
1149 lua_Number nb; lua_Number nc; 1148 lua_Number nb; lua_Number nc;
1150 if (tonumber(rb, &nb) && tonumber(rc, &nc)) { 1149 if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
1151 setfltvalue(s2v(ra), luai_numpow(L, nb, nc)); 1150 setfltvalue(s2v(ra), luai_numpow(L, nb, nc));
1152 } 1151 }
1153 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } 1152 else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); }
@@ -1160,7 +1159,7 @@ void luaV_execute (lua_State *L) {
1160 lua_Integer ib = ivalue(rb); 1159 lua_Integer ib = ivalue(rb);
1161 setivalue(s2v(ra), intop(-, 0, ib)); 1160 setivalue(s2v(ra), intop(-, 0, ib));
1162 } 1161 }
1163 else if (tonumber(rb, &nb)) { 1162 else if (tonumberns(rb, nb)) {
1164 setfltvalue(s2v(ra), luai_numunm(L, nb)); 1163 setfltvalue(s2v(ra), luai_numunm(L, nb));
1165 } 1164 }
1166 else { 1165 else {
diff --git a/lvm.h b/lvm.h
index 7ac959af..6bb5818d 100644
--- a/lvm.h
+++ b/lvm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.h,v 2.44 2017/06/09 19:16:41 roberto Exp roberto $ 2** $Id: lvm.h,v 2.45 2017/06/29 15:06:44 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -37,12 +37,22 @@
37#endif 37#endif
38 38
39 39
40/* convert an object to a float (including string coercion) */
40#define tonumber(o,n) \ 41#define tonumber(o,n) \
41 (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) 42 (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n))
42 43
44
45/* convert an object to a float (without string coercion) */
46#define tonumberns(o,n) \
47 (ttisfloat(o) ? ((n) = fltvalue(o), 1) : \
48 (ttisinteger(o) ? ((n) = cast_num(ivalue(o)), 1) : 0))
49
50
51/* convert an object to an integer (including string coercion) */
43#define tointeger(o,i) \ 52#define tointeger(o,i) \
44 (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) 53 (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I))
45 54
55
46#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) 56#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2))
47 57
48#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) 58#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2)