summaryrefslogtreecommitdiff
path: root/testes/bwcoercion.lua
diff options
context:
space:
mode:
Diffstat (limited to 'testes/bwcoercion.lua')
-rw-r--r--testes/bwcoercion.lua78
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 @@
1local tonumber, tointeger = tonumber, math.tointeger
2local type, getmetatable, rawget, error = type, getmetatable, rawget, error
3local strsub = string.sub
4
5local print = print
6
7_ENV = nil
8
9-- Try to convert a value to an integer, without assuming any coercion.
10local 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)
16end
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.
22local 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)
33end
34
35
36local 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
44end
45
46
47local smt = getmetatable("")
48
49smt.__band = function (x, y)
50 local x, y = checkargs(x, y, "__band")
51 return y and x & y or x
52end
53
54smt.__bor = function (x, y)
55 local x, y = checkargs(x, y, "__bor")
56 return y and x | y or x
57end
58
59smt.__bxor = function (x, y)
60 local x, y = checkargs(x, y, "__bxor")
61 return y and x ~ y or x
62end
63
64smt.__shl = function (x, y)
65 local x, y = checkargs(x, y, "__shl")
66 return y and x << y or x
67end
68
69smt.__shr = function (x, y)
70 local x, y = checkargs(x, y, "__shr")
71 return y and x >> y or x
72end
73
74smt.__bnot = function (x)
75 local x, y = checkargs(x, x, "__bnot")
76 return y and ~x or x
77end
78