mirror of
https://github.com/lua/lua
synced 2024-11-29 16:13:17 +03:00
79 lines
1.7 KiB
Lua
79 lines
1.7 KiB
Lua
local tonumber, tointeger = tonumber, math.tointeger
|
|
local type, getmetatable, rawget, error = type, getmetatable, rawget, error
|
|
local strsub = string.sub
|
|
|
|
local print = print
|
|
|
|
_ENV = nil
|
|
|
|
-- Try to convert a value to an integer, without assuming any coercion.
|
|
local function toint (x)
|
|
x = tonumber(x) -- handle numerical strings
|
|
if not x then
|
|
return false -- not coercible to a number
|
|
end
|
|
return tointeger(x)
|
|
end
|
|
|
|
|
|
-- If operation fails, maybe second operand has a metamethod that should
|
|
-- have been called if not for this string metamethod, so try to
|
|
-- call it.
|
|
local function trymt (x, y, mtname)
|
|
if type(y) ~= "string" then -- avoid recalling original metamethod
|
|
local mt = getmetatable(y)
|
|
local mm = mt and rawget(mt, mtname)
|
|
if mm then
|
|
return mm(x, y)
|
|
end
|
|
end
|
|
-- if any test fails, there is no other metamethod to be called
|
|
error("attempt to '" .. strsub(mtname, 3) ..
|
|
"' a " .. type(x) .. " with a " .. type(y), 4)
|
|
end
|
|
|
|
|
|
local function checkargs (x, y, mtname)
|
|
local xi = toint(x)
|
|
local yi = toint(y)
|
|
if xi and yi then
|
|
return xi, yi
|
|
else
|
|
return trymt(x, y, mtname), nil
|
|
end
|
|
end
|
|
|
|
|
|
local smt = getmetatable("")
|
|
|
|
smt.__band = function (x, y)
|
|
local x, y = checkargs(x, y, "__band")
|
|
return y and x & y or x
|
|
end
|
|
|
|
smt.__bor = function (x, y)
|
|
local x, y = checkargs(x, y, "__bor")
|
|
return y and x | y or x
|
|
end
|
|
|
|
smt.__bxor = function (x, y)
|
|
local x, y = checkargs(x, y, "__bxor")
|
|
return y and x ~ y or x
|
|
end
|
|
|
|
smt.__shl = function (x, y)
|
|
local x, y = checkargs(x, y, "__shl")
|
|
return y and x << y or x
|
|
end
|
|
|
|
smt.__shr = function (x, y)
|
|
local x, y = checkargs(x, y, "__shr")
|
|
return y and x >> y or x
|
|
end
|
|
|
|
smt.__bnot = function (x)
|
|
local x, y = checkargs(x, x, "__bnot")
|
|
return y and ~x or x
|
|
end
|
|
|