diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-08 12:50:23 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-08 12:50:23 -0200 |
commit | 26679ea35bf261f2b5edc2fb2f5cc4df483fd50d (patch) | |
tree | 94c99ed74251cdf3e10a7e52560c3a7a78053ad1 /lvm.c | |
parent | c3e5946fb2b7b5781d9bca9d303967abe6263482 (diff) | |
download | lua-26679ea35bf261f2b5edc2fb2f5cc4df483fd50d.tar.gz lua-26679ea35bf261f2b5edc2fb2f5cc4df483fd50d.tar.bz2 lua-26679ea35bf261f2b5edc2fb2f5cc4df483fd50d.zip |
new function 'luaV_flttointeger' to convert floats to integers (without
string coercions) + string operands to bitwise operations handled
by string metamethods
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 60 |
1 files changed, 35 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.306 2017/11/07 13:25:26 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.307 2017/11/07 17:20:42 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 | */ |
@@ -74,7 +74,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { | |||
74 | *n = cast_num(ivalue(obj)); | 74 | *n = cast_num(ivalue(obj)); |
75 | return 1; | 75 | return 1; |
76 | } | 76 | } |
77 | else if (cvt2num(obj) && /* string convertible to number? */ | 77 | else if (cvt2num(obj) && /* string coercible to number? */ |
78 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { | 78 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { |
79 | *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ | 79 | *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ |
80 | return 1; | 80 | return 1; |
@@ -85,15 +85,15 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { | |||
85 | 85 | ||
86 | 86 | ||
87 | /* | 87 | /* |
88 | ** try to convert a value to an integer, rounding according to 'mode': | 88 | ** try to convert a float to an integer, rounding according to 'mode': |
89 | ** mode == 0: accepts only integral values | 89 | ** mode == 0: accepts only integral values |
90 | ** mode == 1: takes the floor of the number | 90 | ** mode == 1: takes the floor of the number |
91 | ** mode == 2: takes the ceil of the number | 91 | ** mode == 2: takes the ceil of the number |
92 | */ | 92 | */ |
93 | int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | 93 | int luaV_flttointeger (const TValue *obj, lua_Integer *p, int mode) { |
94 | TValue v; | 94 | if (!ttisfloat(obj)) |
95 | again: | 95 | return 0; |
96 | if (ttisfloat(obj)) { | 96 | else { |
97 | lua_Number n = fltvalue(obj); | 97 | lua_Number n = fltvalue(obj); |
98 | lua_Number f = l_floor(n); | 98 | lua_Number f = l_floor(n); |
99 | if (n != f) { /* not an integral value? */ | 99 | if (n != f) { /* not an integral value? */ |
@@ -103,16 +103,23 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | |||
103 | } | 103 | } |
104 | return lua_numbertointeger(f, p); | 104 | return lua_numbertointeger(f, p); |
105 | } | 105 | } |
106 | else if (ttisinteger(obj)) { | 106 | } |
107 | |||
108 | |||
109 | /* | ||
110 | ** try to convert a value to an integer. ("Fast track" is handled | ||
111 | ** by macro 'tointeger'.) | ||
112 | */ | ||
113 | int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | ||
114 | TValue v; | ||
115 | if (cvt2num(obj) && luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) | ||
116 | obj = &v; /* change string to its corresponding number */ | ||
117 | if (ttisinteger(obj)) { | ||
107 | *p = ivalue(obj); | 118 | *p = ivalue(obj); |
108 | return 1; | 119 | return 1; |
109 | } | 120 | } |
110 | else if (cvt2num(obj) && | 121 | else |
111 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { | 122 | return luaV_flttointeger(obj, p, mode); |
112 | obj = &v; | ||
113 | goto again; /* convert result from 'luaO_str2num' to an integer */ | ||
114 | } | ||
115 | return 0; /* conversion failed */ | ||
116 | } | 123 | } |
117 | 124 | ||
118 | 125 | ||
@@ -120,9 +127,9 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | |||
120 | ** Try to convert a 'for' limit to an integer, preserving the semantics | 127 | ** Try to convert a 'for' limit to an integer, preserving the semantics |
121 | ** of the loop. (The following explanation assumes a non-negative step; | 128 | ** of the loop. (The following explanation assumes a non-negative step; |
122 | ** it is valid for negative steps mutatis mutandis.) | 129 | ** it is valid for negative steps mutatis mutandis.) |
123 | ** If the limit can be converted to an integer, rounding down, that is | 130 | ** If the limit is an integer or can be converted to an integer, |
124 | ** it. | 131 | ** rounding down, that is it. |
125 | ** Otherwise, check whether the limit can be converted to a number. If | 132 | ** Otherwise, check whether the limit can be converted to a float. If |
126 | ** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, | 133 | ** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, |
127 | ** which means no limit. If the number is too negative, the loop | 134 | ** which means no limit. If the number is too negative, the loop |
128 | ** should not run, because any initial integer value is larger than the | 135 | ** should not run, because any initial integer value is larger than the |
@@ -133,7 +140,10 @@ int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { | |||
133 | static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, | 140 | static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, |
134 | int *stopnow) { | 141 | int *stopnow) { |
135 | *stopnow = 0; /* usually, let loops run */ | 142 | *stopnow = 0; /* usually, let loops run */ |
136 | if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ | 143 | if (ttisinteger(obj)) |
144 | *p = ivalue(obj); | ||
145 | else if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { | ||
146 | /* not coercible to in integer */ | ||
137 | lua_Number n; /* try to convert to float */ | 147 | lua_Number n; /* try to convert to float */ |
138 | if (!tonumber(obj, &n)) /* cannot convert to float? */ | 148 | if (!tonumber(obj, &n)) /* cannot convert to float? */ |
139 | return 0; /* not a number */ | 149 | return 0; /* not a number */ |
@@ -411,7 +421,7 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | |||
411 | return 0; /* only numbers can be equal with different variants */ | 421 | return 0; /* only numbers can be equal with different variants */ |
412 | else { /* two numbers with different variants */ | 422 | else { /* two numbers with different variants */ |
413 | lua_Integer i1, i2; /* compare them as integers */ | 423 | lua_Integer i1, i2; /* compare them as integers */ |
414 | return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); | 424 | return (tointegerns(t1, &i1) && tointegerns(t2, &i2) && i1 == i2); |
415 | } | 425 | } |
416 | } | 426 | } |
417 | /* values have same type and same variant */ | 427 | /* values have same type and same variant */ |
@@ -1144,7 +1154,7 @@ void luaV_execute (lua_State *L) { | |||
1144 | TValue *rb = vRB(i); | 1154 | TValue *rb = vRB(i); |
1145 | TValue *rc = vRC(i); | 1155 | TValue *rc = vRC(i); |
1146 | lua_Integer ib; lua_Integer ic; | 1156 | lua_Integer ib; lua_Integer ic; |
1147 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1157 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1148 | setivalue(s2v(ra), intop(&, ib, ic)); | 1158 | setivalue(s2v(ra), intop(&, ib, ic)); |
1149 | } | 1159 | } |
1150 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } | 1160 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } |
@@ -1154,7 +1164,7 @@ void luaV_execute (lua_State *L) { | |||
1154 | TValue *rb = vRB(i); | 1164 | TValue *rb = vRB(i); |
1155 | TValue *rc = vRC(i); | 1165 | TValue *rc = vRC(i); |
1156 | lua_Integer ib; lua_Integer ic; | 1166 | lua_Integer ib; lua_Integer ic; |
1157 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1167 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1158 | setivalue(s2v(ra), intop(|, ib, ic)); | 1168 | setivalue(s2v(ra), intop(|, ib, ic)); |
1159 | } | 1169 | } |
1160 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } | 1170 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } |
@@ -1164,7 +1174,7 @@ void luaV_execute (lua_State *L) { | |||
1164 | TValue *rb = vRB(i); | 1174 | TValue *rb = vRB(i); |
1165 | TValue *rc = vRC(i); | 1175 | TValue *rc = vRC(i); |
1166 | lua_Integer ib; lua_Integer ic; | 1176 | lua_Integer ib; lua_Integer ic; |
1167 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1177 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1168 | setivalue(s2v(ra), intop(^, ib, ic)); | 1178 | setivalue(s2v(ra), intop(^, ib, ic)); |
1169 | } | 1179 | } |
1170 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } | 1180 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } |
@@ -1174,7 +1184,7 @@ void luaV_execute (lua_State *L) { | |||
1174 | TValue *rb = vRB(i); | 1184 | TValue *rb = vRB(i); |
1175 | TValue *rc = vRC(i); | 1185 | TValue *rc = vRC(i); |
1176 | lua_Integer ib; lua_Integer ic; | 1186 | lua_Integer ib; lua_Integer ic; |
1177 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1187 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1178 | setivalue(s2v(ra), luaV_shiftl(ib, ic)); | 1188 | setivalue(s2v(ra), luaV_shiftl(ib, ic)); |
1179 | } | 1189 | } |
1180 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } | 1190 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } |
@@ -1184,7 +1194,7 @@ void luaV_execute (lua_State *L) { | |||
1184 | TValue *rb = vRB(i); | 1194 | TValue *rb = vRB(i); |
1185 | TValue *rc = vRC(i); | 1195 | TValue *rc = vRC(i); |
1186 | lua_Integer ib; lua_Integer ic; | 1196 | lua_Integer ib; lua_Integer ic; |
1187 | if (tointeger(rb, &ib) && tointeger(rc, &ic)) { | 1197 | if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) { |
1188 | setivalue(s2v(ra), luaV_shiftl(ib, -ic)); | 1198 | setivalue(s2v(ra), luaV_shiftl(ib, -ic)); |
1189 | } | 1199 | } |
1190 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } | 1200 | else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } |
@@ -1248,7 +1258,7 @@ void luaV_execute (lua_State *L) { | |||
1248 | vmcase(OP_BNOT) { | 1258 | vmcase(OP_BNOT) { |
1249 | TValue *rb = vRB(i); | 1259 | TValue *rb = vRB(i); |
1250 | lua_Integer ib; | 1260 | lua_Integer ib; |
1251 | if (tointeger(rb, &ib)) { | 1261 | if (tointegerns(rb, &ib)) { |
1252 | setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); | 1262 | setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib)); |
1253 | } | 1263 | } |
1254 | else { | 1264 | else { |