diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-09 12:33:01 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-09 12:33:01 -0300 |
| commit | 7c519dfbd0c68b952f0849e01deaa3750e1f8153 (patch) | |
| tree | dde3ddbba310877db725df37a0d9f2cbe4e2a8f9 /testes/bwcoercion.lua | |
| parent | f59e6a93c0ad38a27a420e51abf8f13d962446b5 (diff) | |
| download | lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.gz lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.bz2 lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.zip | |
Added manual and tests for version 5.4-w2
Diffstat (limited to 'testes/bwcoercion.lua')
| -rw-r--r-- | testes/bwcoercion.lua | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/testes/bwcoercion.lua b/testes/bwcoercion.lua new file mode 100644 index 00000000..cd735ab0 --- /dev/null +++ b/testes/bwcoercion.lua | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | local tonumber, tointeger = tonumber, math.tointeger | ||
| 2 | local type, getmetatable, rawget, error = type, getmetatable, rawget, error | ||
| 3 | local strsub = string.sub | ||
| 4 | |||
| 5 | local print = print | ||
| 6 | |||
| 7 | _ENV = nil | ||
| 8 | |||
| 9 | -- Try to convert a value to an integer, without assuming any coercion. | ||
| 10 | local function toint (x) | ||
| 11 | x = tonumber(x) -- handle numerical strings | ||
| 12 | if not x then | ||
| 13 | return false -- not coercible to a number | ||
| 14 | end | ||
| 15 | return tointeger(x) | ||
| 16 | end | ||
| 17 | |||
| 18 | |||
| 19 | -- If operation fails, maybe second operand has a metamethod that should | ||
| 20 | -- have been called if not for this string metamethod, so try to | ||
| 21 | -- call it. | ||
| 22 | local function trymt (x, y, mtname) | ||
| 23 | if type(y) ~= "string" then -- avoid recalling original metamethod | ||
| 24 | local mt = getmetatable(y) | ||
| 25 | local mm = mt and rawget(mt, mtname) | ||
| 26 | if mm then | ||
| 27 | return mm(x, y) | ||
| 28 | end | ||
| 29 | end | ||
| 30 | -- if any test fails, there is no other metamethod to be called | ||
| 31 | error("attempt to '" .. strsub(mtname, 3) .. | ||
| 32 | "' a " .. type(x) .. " with a " .. type(y), 4) | ||
| 33 | end | ||
| 34 | |||
| 35 | |||
| 36 | local function checkargs (x, y, mtname) | ||
| 37 | local xi = toint(x) | ||
| 38 | local yi = toint(y) | ||
| 39 | if xi and yi then | ||
| 40 | return xi, yi | ||
| 41 | else | ||
| 42 | return trymt(x, y, mtname), nil | ||
| 43 | end | ||
| 44 | end | ||
| 45 | |||
| 46 | |||
| 47 | local smt = getmetatable("") | ||
| 48 | |||
| 49 | smt.__band = function (x, y) | ||
| 50 | local x, y = checkargs(x, y, "__band") | ||
| 51 | return y and x & y or x | ||
| 52 | end | ||
| 53 | |||
| 54 | smt.__bor = function (x, y) | ||
| 55 | local x, y = checkargs(x, y, "__bor") | ||
| 56 | return y and x | y or x | ||
| 57 | end | ||
| 58 | |||
| 59 | smt.__bxor = function (x, y) | ||
| 60 | local x, y = checkargs(x, y, "__bxor") | ||
| 61 | return y and x ~ y or x | ||
| 62 | end | ||
| 63 | |||
| 64 | smt.__shl = function (x, y) | ||
| 65 | local x, y = checkargs(x, y, "__shl") | ||
| 66 | return y and x << y or x | ||
| 67 | end | ||
| 68 | |||
| 69 | smt.__shr = function (x, y) | ||
| 70 | local x, y = checkargs(x, y, "__shr") | ||
| 71 | return y and x >> y or x | ||
| 72 | end | ||
| 73 | |||
| 74 | smt.__bnot = function (x) | ||
| 75 | local x, y = checkargs(x, x, "__bnot") | ||
| 76 | return y and ~x or x | ||
| 77 | end | ||
| 78 | |||
