Include offending type in precondition failure msg
Output the type that was incorrect to make it more obvious what the user is doing wrong without them adding logging. To avoid string building during lots of vector math, introduced a private precond module that only builds the strings when an error occurs. It uses error() to put the resulting error message at the caller to cpml. Before: lua: ~/cpml/modules/vec2.lua:52: new: Wrong argument type for x (<number> expected) lua: ~/cpml/modules/vec2.lua:424: __add: Wrong argument type for right hand operand. (<cpml.vec2> expected) example stack traceback: [C]: in function 'assert' ~/cpml/modules/vec2.lua:424: in metamethod '__add' test_cpml.lua:32: in main chunk [C]: in ? After: lua: test_cpml.lua:31: new: Wrong argument type for x: string (<number> expected) lua: test_cpml.lua:32: __add: Wrong argument type 'string' for right hand operand. (<cpml.vec2> expected) example stack traceback: [C]: in function 'error' ~/cpml/modules/_private_precond.lua:13: in function 'modules._private_precond.assert' ~/cpml/modules/vec2.lua:425: in metamethod '__add' test_cpml.lua:32: in main chunk [C]: in ? The tracebacks are longer, but the initial error is at the location of the mistake and the output includes the input type.
This commit is contained in:
parent
c50d292cb6
commit
c26cc1a508
17
modules/_private_precond.lua
Normal file
17
modules/_private_precond.lua
Normal file
@ -0,0 +1,17 @@
|
||||
-- Preconditions for cpml functions.
|
||||
local precond = {}
|
||||
|
||||
|
||||
function precond.typeof(t, expected, msg)
|
||||
if type(t) ~= expected then
|
||||
error(("%s: %s (<%s> expected)"):format(msg, type(t), expected), 3)
|
||||
end
|
||||
end
|
||||
|
||||
function precond.assert(cond, msg, ...)
|
||||
if not cond then
|
||||
error(msg:format(...), 3)
|
||||
end
|
||||
end
|
||||
|
||||
return precond
|
@ -3,6 +3,7 @@
|
||||
|
||||
local modules = (...):gsub('%.[^%.]+$', '') .. "."
|
||||
local utils = require(modules .. "utils")
|
||||
local precond = require(modules .. "_private_precond")
|
||||
local color = {}
|
||||
local color_mt = {}
|
||||
|
||||
@ -103,20 +104,20 @@ end
|
||||
function color.new(r, g, b, a)
|
||||
-- number, number, number, number
|
||||
if r and g and b and a then
|
||||
assert(type(r) == "number", "new: Wrong argument type for r (<number> expected)")
|
||||
assert(type(g) == "number", "new: Wrong argument type for g (<number> expected)")
|
||||
assert(type(b) == "number", "new: Wrong argument type for b (<number> expected)")
|
||||
assert(type(a) == "number", "new: Wrong argument type for a (<number> expected)")
|
||||
precond.typeof(r, "number", "new: Wrong argument type for r")
|
||||
precond.typeof(g, "number", "new: Wrong argument type for g")
|
||||
precond.typeof(b, "number", "new: Wrong argument type for b")
|
||||
precond.typeof(a, "number", "new: Wrong argument type for a")
|
||||
|
||||
return new(r, g, b, a)
|
||||
|
||||
-- {r, g, b, a}
|
||||
elseif type(r) == "table" then
|
||||
local rr, gg, bb, aa = r[1], r[2], r[3], r[4]
|
||||
assert(type(rr) == "number", "new: Wrong argument type for r (<number> expected)")
|
||||
assert(type(gg) == "number", "new: Wrong argument type for g (<number> expected)")
|
||||
assert(type(bb) == "number", "new: Wrong argument type for b (<number> expected)")
|
||||
assert(type(aa) == "number", "new: Wrong argument type for a (<number> expected)")
|
||||
precond.typeof(rr, "number", "new: Wrong argument type for r")
|
||||
precond.typeof(gg, "number", "new: Wrong argument type for g")
|
||||
precond.typeof(bb, "number", "new: Wrong argument type for b")
|
||||
precond.typeof(aa, "number", "new: Wrong argument type for a")
|
||||
|
||||
return new(rr, gg, bb, aa)
|
||||
end
|
||||
|
@ -6,6 +6,7 @@ local vec2 = require(modules .. "vec2")
|
||||
local vec3 = require(modules .. "vec3")
|
||||
local quat = require(modules .. "quat")
|
||||
local utils = require(modules .. "utils")
|
||||
local precond = require(modules .. "_private_precond")
|
||||
local private = require(modules .. "_private_utils")
|
||||
local sqrt = math.sqrt
|
||||
local cos = math.cos
|
||||
@ -861,7 +862,7 @@ function mat4_mt.__eq(a, b)
|
||||
end
|
||||
|
||||
function mat4_mt.__mul(a, b)
|
||||
assert(mat4.is_mat4(a), "__mul: Wrong argument type for left hand operand. (<cpml.mat4> expected)")
|
||||
precond.assert(mat4.is_mat4(a), "__mul: Wrong argument type '%s' for left hand operand. (<cpml.mat4> expected)", type(a))
|
||||
|
||||
if vec3.is_vec3(b) then
|
||||
return vec3(mat4.mul_vec4({}, a, { b.x, b.y, b.z, 1 }))
|
||||
|
@ -4,6 +4,7 @@
|
||||
local modules = (...):gsub('%.[^%.]+$', '') .. "."
|
||||
local constants = require(modules .. "constants")
|
||||
local vec3 = require(modules .. "vec3")
|
||||
local precond = require(modules .. "_private_precond")
|
||||
local private = require(modules .. "_private_utils")
|
||||
local DOT_THRESHOLD = constants.DOT_THRESHOLD
|
||||
local DBL_EPSILON = constants.DBL_EPSILON
|
||||
@ -58,20 +59,20 @@ quat.zero = new(0, 0, 0, 0)
|
||||
function quat.new(x, y, z, w)
|
||||
-- number, number, number, number
|
||||
if x and y and z and w then
|
||||
assert(type(x) == "number", "new: Wrong argument type for x (<number> expected)")
|
||||
assert(type(y) == "number", "new: Wrong argument type for y (<number> expected)")
|
||||
assert(type(z) == "number", "new: Wrong argument type for z (<number> expected)")
|
||||
assert(type(w) == "number", "new: Wrong argument type for w (<number> expected)")
|
||||
precond.typeof(x, "number", "new: Wrong argument type for x")
|
||||
precond.typeof(y, "number", "new: Wrong argument type for y")
|
||||
precond.typeof(z, "number", "new: Wrong argument type for z")
|
||||
precond.typeof(w, "number", "new: Wrong argument type for w")
|
||||
|
||||
return new(x, y, z, w)
|
||||
|
||||
-- {x, y, z, w} or {x=x, y=y, z=z, w=w}
|
||||
elseif type(x) == "table" then
|
||||
local xx, yy, zz, ww = x.x or x[1], x.y or x[2], x.z or x[3], x.w or x[4]
|
||||
assert(type(xx) == "number", "new: Wrong argument type for x (<number> expected)")
|
||||
assert(type(yy) == "number", "new: Wrong argument type for y (<number> expected)")
|
||||
assert(type(zz) == "number", "new: Wrong argument type for z (<number> expected)")
|
||||
assert(type(ww) == "number", "new: Wrong argument type for w (<number> expected)")
|
||||
precond.typeof(xx, "number", "new: Wrong argument type for x")
|
||||
precond.typeof(yy, "number", "new: Wrong argument type for y")
|
||||
precond.typeof(zz, "number", "new: Wrong argument type for z")
|
||||
precond.typeof(ww, "number", "new: Wrong argument type for w")
|
||||
|
||||
return new(xx, yy, zz, ww)
|
||||
end
|
||||
@ -456,19 +457,19 @@ function quat_mt.__eq(a,b)
|
||||
end
|
||||
|
||||
function quat_mt.__add(a, b)
|
||||
assert(quat.is_quat(a), "__add: Wrong argument type for left hand operand. (<cpml.quat> expected)")
|
||||
assert(quat.is_quat(b), "__add: Wrong argument type for right hand operand. (<cpml.quat> expected)")
|
||||
precond.assert(quat.is_quat(a), "__add: Wrong argument type '%s' for left hand operand. (<cpml.quat> expected)", type(a))
|
||||
precond.assert(quat.is_quat(b), "__add: Wrong argument type '%s' for right hand operand. (<cpml.quat> expected)", type(b))
|
||||
return a:add(b)
|
||||
end
|
||||
|
||||
function quat_mt.__sub(a, b)
|
||||
assert(quat.is_quat(a), "__sub: Wrong argument type for left hand operand. (<cpml.quat> expected)")
|
||||
assert(quat.is_quat(b), "__sub: Wrong argument type for right hand operand. (<cpml.quat> expected)")
|
||||
precond.assert(quat.is_quat(a), "__sub: Wrong argument type '%s' for left hand operand. (<cpml.quat> expected)", type(a))
|
||||
precond.assert(quat.is_quat(b), "__sub: Wrong argument type '%s' for right hand operand. (<cpml.quat> expected)", type(b))
|
||||
return a:sub(b)
|
||||
end
|
||||
|
||||
function quat_mt.__mul(a, b)
|
||||
assert(quat.is_quat(a), "__mul: Wrong argument type for left hand operand. (<cpml.quat> expected)")
|
||||
precond.assert(quat.is_quat(a), "__mul: Wrong argument type '%s' for left hand operand. (<cpml.quat> expected)", type(a))
|
||||
assert(quat.is_quat(b) or vec3.is_vec3(b) or type(b) == "number", "__mul: Wrong argument type for right hand operand. (<cpml.quat> or <cpml.vec3> or <number> expected)")
|
||||
|
||||
if quat.is_quat(b) then
|
||||
@ -483,8 +484,8 @@ function quat_mt.__mul(a, b)
|
||||
end
|
||||
|
||||
function quat_mt.__pow(a, n)
|
||||
assert(quat.is_quat(a), "__pow: Wrong argument type for left hand operand. (<cpml.quat> expected)")
|
||||
assert(type(n) == "number", "__pow: Wrong argument type for right hand operand. (<number> expected)")
|
||||
precond.assert(quat.is_quat(a), "__pow: Wrong argument type '%s' for left hand operand. (<cpml.quat> expected)", type(a))
|
||||
precond.typeof(n, "number", "__pow: Wrong argument type for right hand operand.")
|
||||
return a:pow(n)
|
||||
end
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
local modules = (...):gsub('%.[^%.]+$', '') .. "."
|
||||
local vec3 = require(modules .. "vec3")
|
||||
local precond = require(modules .. "_private_precond")
|
||||
local private = require(modules .. "_private_utils")
|
||||
local acos = math.acos
|
||||
local atan2 = math.atan2
|
||||
@ -49,16 +50,16 @@ vec2.zero = new(0, 0)
|
||||
function vec2.new(x, y)
|
||||
-- number, number
|
||||
if x and y then
|
||||
assert(type(x) == "number", "new: Wrong argument type for x (<number> expected)")
|
||||
assert(type(y) == "number", "new: Wrong argument type for y (<number> expected)")
|
||||
precond.typeof(x, "number", "new: Wrong argument type for x")
|
||||
precond.typeof(y, "number", "new: Wrong argument type for y")
|
||||
|
||||
return new(x, y)
|
||||
|
||||
-- {x, y} or {x=x, y=y}
|
||||
elseif type(x) == "table" or type(x) == "cdata" then -- table in vanilla lua, cdata in luajit
|
||||
local xx, yy = x.x or x[1], x.y or x[2]
|
||||
assert(type(xx) == "number", "new: Wrong argument type for x (<number> expected)")
|
||||
assert(type(yy) == "number", "new: Wrong argument type for y (<number> expected)")
|
||||
precond.typeof(xx, "number", "new: Wrong argument type for x")
|
||||
precond.typeof(yy, "number", "new: Wrong argument type for y")
|
||||
|
||||
return new(xx, yy)
|
||||
|
||||
@ -401,19 +402,19 @@ function vec2_mt.__eq(a, b)
|
||||
end
|
||||
|
||||
function vec2_mt.__add(a, b)
|
||||
assert(vec2.is_vec2(a), "__add: Wrong argument type for left hand operand. (<cpml.vec2> expected)")
|
||||
assert(vec2.is_vec2(b), "__add: Wrong argument type for right hand operand. (<cpml.vec2> expected)")
|
||||
precond.assert(vec2.is_vec2(a), "__add: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
|
||||
precond.assert(vec2.is_vec2(b), "__add: Wrong argument type '%s' for right hand operand. (<cpml.vec2> expected)", type(b))
|
||||
return a:add(b)
|
||||
end
|
||||
|
||||
function vec2_mt.__sub(a, b)
|
||||
assert(vec2.is_vec2(a), "__add: Wrong argument type for left hand operand. (<cpml.vec2> expected)")
|
||||
assert(vec2.is_vec2(b), "__add: Wrong argument type for right hand operand. (<cpml.vec2> expected)")
|
||||
precond.assert(vec2.is_vec2(a), "__add: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
|
||||
precond.assert(vec2.is_vec2(b), "__add: Wrong argument type '%s' for right hand operand. (<cpml.vec2> expected)", type(b))
|
||||
return a:sub(b)
|
||||
end
|
||||
|
||||
function vec2_mt.__mul(a, b)
|
||||
assert(vec2.is_vec2(a), "__mul: Wrong argument type for left hand operand. (<cpml.vec2> expected)")
|
||||
precond.assert(vec2.is_vec2(a), "__mul: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
|
||||
assert(vec2.is_vec2(b) or type(b) == "number", "__mul: Wrong argument type for right hand operand. (<cpml.vec2> or <number> expected)")
|
||||
|
||||
if vec2.is_vec2(b) then
|
||||
@ -424,7 +425,7 @@ function vec2_mt.__mul(a, b)
|
||||
end
|
||||
|
||||
function vec2_mt.__div(a, b)
|
||||
assert(vec2.is_vec2(a), "__div: Wrong argument type for left hand operand. (<cpml.vec2> expected)")
|
||||
precond.assert(vec2.is_vec2(a), "__div: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
|
||||
assert(vec2.is_vec2(b) or type(b) == "number", "__div: Wrong argument type for right hand operand. (<cpml.vec2> or <number> expected)")
|
||||
|
||||
if vec2.is_vec2(b) then
|
||||
|
@ -2,6 +2,7 @@
|
||||
-- @module vec3
|
||||
|
||||
local modules = (...):gsub('%.[^%.]+$', '') .. "."
|
||||
local precond = require(modules .. "_private_precond")
|
||||
local private = require(modules .. "_private_utils")
|
||||
local sqrt = math.sqrt
|
||||
local cos = math.cos
|
||||
@ -50,18 +51,18 @@ vec3.zero = new(0, 0, 0)
|
||||
function vec3.new(x, y, z)
|
||||
-- number, number, number
|
||||
if x and y and z then
|
||||
assert(type(x) == "number", "new: Wrong argument type for x (<number> expected)")
|
||||
assert(type(y) == "number", "new: Wrong argument type for y (<number> expected)")
|
||||
assert(type(z) == "number", "new: Wrong argument type for z (<number> expected)")
|
||||
precond.typeof(x, "number", "new: Wrong argument type for x")
|
||||
precond.typeof(y, "number", "new: Wrong argument type for y")
|
||||
precond.typeof(z, "number", "new: Wrong argument type for z")
|
||||
|
||||
return new(x, y, z)
|
||||
|
||||
-- {x, y, z} or {x=x, y=y, z=z}
|
||||
elseif type(x) == "table" or type(x) == "cdata" then -- table in vanilla lua, cdata in luajit
|
||||
local xx, yy, zz = x.x or x[1], x.y or x[2], x.z or x[3]
|
||||
assert(type(xx) == "number", "new: Wrong argument type for x (<number> expected)")
|
||||
assert(type(yy) == "number", "new: Wrong argument type for y (<number> expected)")
|
||||
assert(type(zz) == "number", "new: Wrong argument type for z (<number> expected)")
|
||||
precond.typeof(xx, "number", "new: Wrong argument type for x")
|
||||
precond.typeof(yy, "number", "new: Wrong argument type for y")
|
||||
precond.typeof(zz, "number", "new: Wrong argument type for z")
|
||||
|
||||
return new(xx, yy, zz)
|
||||
|
||||
@ -374,20 +375,20 @@ function vec3_mt.__eq(a, b)
|
||||
end
|
||||
|
||||
function vec3_mt.__add(a, b)
|
||||
assert(vec3.is_vec3(a), "__add: Wrong argument type for left hand operand. (<cpml.vec3> expected)")
|
||||
assert(vec3.is_vec3(b), "__add: Wrong argument type for right hand operand. (<cpml.vec3> expected)")
|
||||
precond.assert(vec3.is_vec3(a), "__add: Wrong argument type '%s' for left hand operand. (<cpml.vec3> expected)", type(a))
|
||||
precond.assert(vec3.is_vec3(b), "__add: Wrong argument type '%s' for right hand operand. (<cpml.vec3> expected)", type(b))
|
||||
return a:add(b)
|
||||
end
|
||||
|
||||
function vec3_mt.__sub(a, b)
|
||||
assert(vec3.is_vec3(a), "__sub: Wrong argument type for left hand operand. (<cpml.vec3> expected)")
|
||||
assert(vec3.is_vec3(b), "__sub: Wrong argument type for right hand operand. (<cpml.vec3> expected)")
|
||||
precond.assert(vec3.is_vec3(a), "__sub: Wrong argument type '%s' for left hand operand. (<cpml.vec3> expected)", type(a))
|
||||
precond.assert(vec3.is_vec3(b), "__sub: Wrong argument type '%s' for right hand operand. (<cpml.vec3> expected)", type(b))
|
||||
return a:sub(b)
|
||||
end
|
||||
|
||||
function vec3_mt.__mul(a, b)
|
||||
assert(vec3.is_vec3(a), "__mul: Wrong argument type for left hand operand. (<cpml.vec3> expected)")
|
||||
assert(vec3.is_vec3(b) or type(b) == "number", "__mul: Wrong argument type for right hand operand. (<cpml.vec3> or <number> expected)")
|
||||
precond.assert(vec3.is_vec3(a), "__mul: Wrong argument type '%s' for left hand operand. (<cpml.vec3> expected)", type(a))
|
||||
precond.assert(vec3.is_vec3(b) or type(b) == "number", "__mul: Wrong argument type '%s' for right hand operand. (<cpml.vec3> or <number> expected)", type(b))
|
||||
|
||||
if vec3.is_vec3(b) then
|
||||
return a:mul(b)
|
||||
@ -397,8 +398,8 @@ function vec3_mt.__mul(a, b)
|
||||
end
|
||||
|
||||
function vec3_mt.__div(a, b)
|
||||
assert(vec3.is_vec3(a), "__div: Wrong argument type for left hand operand. (<cpml.vec3> expected)")
|
||||
assert(vec3.is_vec3(b) or type(b) == "number", "__div: Wrong argument type for right hand operand. (<cpml.vec3> or <number> expected)")
|
||||
precond.assert(vec3.is_vec3(a), "__div: Wrong argument type '%s' for left hand operand. (<cpml.vec3> expected)", type(a))
|
||||
precond.assert(vec3.is_vec3(b) or type(b) == "number", "__div: Wrong argument type '%s' for right hand operand. (<cpml.vec3> or <number> expected)", type(b))
|
||||
|
||||
if vec3.is_vec3(b) then
|
||||
return a:div(b)
|
||||
|
Loading…
x
Reference in New Issue
Block a user