2020-05-19 02:03:04 +00:00
|
|
|
--[[
|
|
|
|
various intuitive assertions that
|
|
|
|
- avoid garbage generation upon success,
|
|
|
|
- build nice formatted error messages
|
|
|
|
- post one level above the call site by default
|
2020-05-29 06:20:26 +00:00
|
|
|
- return their first argument so they can be used inline
|
2020-05-19 02:03:04 +00:00
|
|
|
|
|
|
|
default call is builtin global assert
|
|
|
|
|
|
|
|
can call nop() to dummy out everything for "release mode"
|
|
|
|
(if you're worried about that sort of thing)
|
|
|
|
]]
|
|
|
|
|
|
|
|
local _assert = assert
|
|
|
|
|
|
|
|
--proxy calls to global assert
|
|
|
|
local assert = setmetatable({}, {
|
|
|
|
__call = function(self, ...)
|
|
|
|
return _assert(...)
|
2020-05-29 06:20:26 +00:00
|
|
|
end,
|
2020-05-19 02:03:04 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
local function _extra(msg)
|
|
|
|
if not msg then
|
|
|
|
return ""
|
|
|
|
end
|
2020-05-29 06:20:26 +00:00
|
|
|
return "\n\n\t(note: " .. msg .. ")"
|
2020-05-19 02:03:04 +00:00
|
|
|
end
|
|
|
|
|
2020-05-19 03:00:23 +00:00
|
|
|
--assert a value is not nil
|
2020-05-29 06:20:26 +00:00
|
|
|
--return the value, so this can be chained
|
2020-05-19 03:00:23 +00:00
|
|
|
function assert:some(v, msg, stack_level)
|
|
|
|
if v == nil then
|
|
|
|
error(("assertion failed: value is nil %s"):format(
|
|
|
|
_extra(msg)
|
|
|
|
), 2 + (stack_level or 0))
|
|
|
|
end
|
2020-05-29 06:20:26 +00:00
|
|
|
return v
|
2020-05-19 03:00:23 +00:00
|
|
|
end
|
|
|
|
|
2020-05-19 02:03:04 +00:00
|
|
|
--assert two values are equal
|
2020-05-19 03:01:56 +00:00
|
|
|
function assert:equal(a, b, msg, stack_level)
|
2020-05-19 02:03:04 +00:00
|
|
|
if a ~= b then
|
|
|
|
error(("assertion failed: %s is not equal to %s %s"):format(
|
|
|
|
tostring(a),
|
|
|
|
tostring(b),
|
|
|
|
_extra(msg)
|
|
|
|
), 2 + (stack_level or 0))
|
|
|
|
end
|
2020-05-29 06:20:26 +00:00
|
|
|
return a
|
2020-05-19 02:03:04 +00:00
|
|
|
end
|
|
|
|
|
2020-05-19 03:01:56 +00:00
|
|
|
--assert two values are not equal
|
|
|
|
function assert:not_equal(a, b, msg, stack_level)
|
|
|
|
if a == b then
|
|
|
|
error(("assertion failed: values are equal %s"):format(
|
|
|
|
_extra(msg)
|
|
|
|
), 2 + (stack_level or 0))
|
|
|
|
end
|
2020-05-29 06:20:26 +00:00
|
|
|
return a
|
2020-05-19 03:01:56 +00:00
|
|
|
end
|
|
|
|
|
2020-05-19 02:03:04 +00:00
|
|
|
--assert a value is of a certain type
|
|
|
|
function assert:type(a, t, msg, stack_level)
|
|
|
|
if type(a) ~= t then
|
|
|
|
error(("assertion failed: %s (%s) not of type %s %s"):format(
|
|
|
|
tostring(a),
|
|
|
|
type(a),
|
|
|
|
tostring(t),
|
|
|
|
_extra(msg)
|
|
|
|
), 2 + (stack_level or 0))
|
|
|
|
end
|
2020-05-29 06:20:26 +00:00
|
|
|
return a
|
2020-05-19 02:03:04 +00:00
|
|
|
end
|
|
|
|
|
2020-05-29 06:20:26 +00:00
|
|
|
--replace everything in assert with nop functions that just return their second argument, for near-zero overhead on release
|
2020-05-19 02:03:04 +00:00
|
|
|
function assert:nop()
|
2020-05-29 06:20:26 +00:00
|
|
|
local nop = function(self, a)
|
|
|
|
return a
|
|
|
|
end
|
2020-05-19 02:03:04 +00:00
|
|
|
setmetatable(self, {
|
2020-05-29 06:20:26 +00:00
|
|
|
__call = nop,
|
2020-05-19 02:03:04 +00:00
|
|
|
})
|
|
|
|
for k, v in pairs(self) do
|
2020-05-29 06:20:26 +00:00
|
|
|
self[k] = nop
|
2020-05-19 02:03:04 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return assert
|