Module std.debug
Additions to the core debug module.
The module table returned by std.debug
also contains all of the entries
from the core debug table. An hygienic way to import this module, then, is
simply to override the core debug
locally:
local debug = require "std.debug"
The behaviour of the functions in this module are controlled by the value
of the global _DEBUG
. Not setting _DEBUG
prior to requiring any of
stdlib's modules is equivalent to having _DEBUG = true
.
The first line of Lua code in production quality projects that use stdlib should be either:
_DEBUG = false
or alternatively, if you need to be careful not to damage the global environment:
local init = require "std.debug_init" init._DEBUG = false
This mitigates almost all of the overhead of argument typechecking in stdlib API functions.
Functions
DEPRECATED (version, name[, extramsg], fn) | Provide a deprecated function definition according to _DEBUG.deprecate. |
DEPRECATIONMSG (version, name[, extramsg], level) | Format a deprecation warning message. |
argcheck (name, i, expected, actual[, level=2]) | Check the type of an argument against expected types. |
argerror (name, i[, extramsg[, level=1]]) | Raise a bad argument error. |
argscheck (decl, inner) | Wrap a function definition with argument type and arity checking. |
debug () | Equivalent to calling debug.say (1, ...) |
extramsg_mismatch (expected, actual[, index]) | Format a type mismatch error. |
parsetypes (types) | Compact permutation list into a list of valid types at each argument. |
say ([n=1], ...) | Print a debugging message to io.stderr . |
trace (event) | Trace function calls. |
Tables
_DEBUG | Control std.debug function behaviour. |
Fields
extramsg_toomany | Format a too many things error. |
getfenv | Extend debug.getfenv to unwrap functables correctly. |
resulterror | Raise a bad result error. |
setfenv | Extend debug.setfenv to unwrap functables correctly. |
typesplit | Split a typespec string into a table of normalized type names. |
Functions
Methods- DEPRECATED (version, name[, extramsg], fn)
-
Provide a deprecated function definition according to _DEBUG.deprecate.
You can check whether your covered code uses deprecated functions by
setting
_DEBUG.deprecate
totrue
before loading any stdlib modules, or silence deprecation warnings by setting_DEBUG.deprecate = false
.Parameters:
- version string first deprecation release version
- name string function name for automatic warning message
- extramsg string additional warning text (optional)
- fn func deprecated function
Returns:
-
a function to show the warning on first call, and hand off to fn
Usage:
M.op = DEPRECATED ("41", "'std.functional.op'", std.operator)
- DEPRECATIONMSG (version, name[, extramsg], level)
-
Format a deprecation warning message.
Parameters:
- version string first deprecation release version
- name string function name for automatic warning message
- extramsg string additional warning text (optional)
- level int call stack level to blame for the error
Returns:
-
string
deprecation warning message, or empty string
Usage:
io.stderr:write (DEPRECATIONMSG ("42", "multi-argument 'module.fname'", 2))
- argcheck (name, i, expected, actual[, level=2])
-
Check the type of an argument against expected types.
Equivalent to luaL_argcheck in the Lua C API.
Call
argerror
if there is a type mismatch.Argument
actual
must match one of the types from inexpected
, each of which can be the name of a primitive Lua type, a stdlib object type, or one of the special options below:#table accept any non-empty table any accept any non-nil argument type file accept an open file object function accept a function, or object with a __call metamethod int accept an integer valued number list accept a table where all keys are a contiguous 1-based integer range #list accept any non-empty list object accept any std.Object derived type :foo accept only the exact string ":foo", works for any :-prefixed string
The
:foo
format allows for type-checking of self-documenting boolean-like constant string parameters predicated onnil
versus:option
instead offalse
versustrue
. Or you could support both:argcheck ("table.copy", 2, "boolean|:nometa|nil", nometa)
A very common pattern is to have a list of possible types including "nil" when the argument is optional. Rather than writing long-hand as above, prepend a question mark to the list of types and omit the explicit "nil" entry:
argcheck ("table.copy", 2, "?boolean|:nometa", predicate)
Normally, you should not need to use the
level
parameter, as the default is to blame the caller of the function usingargcheck
in error messages; which is almost certainly what you want.Parameters:
- name string function to blame in error message
- i int argument number to blame in error message
- expected string specification for acceptable argument types
- actual argument passed
- level int call stack level to blame for the error (default 2)
Usage:
local function case (with, branches) argcheck ("std.functional.case", 2, "#table", branches) ...
- argerror (name, i[, extramsg[, level=1]])
-
Raise a bad argument error.
Equivalent to luaL_argerror in the Lua C API. This function does not
return. The
level
argument behaves just like the coreerror
function.Parameters:
- name string function to callout in error message
- i int argument number
- extramsg string additional text to append to message inside parentheses (optional)
- level int call stack level to blame for the error (default 1)
See also:
Usage:
local function slurp (file) local h, err = input_handle (file) if h == nil then argerror ("std.io.slurp", 1, err, 2) end ...
- argscheck (decl, inner)
-
Wrap a function definition with argument type and arity checking. In addition to checking that each argument type matches the corresponding element in the types table with
argcheck
, if the final element of types ends with an ellipsis, remaining unchecked arguments are checked against that type:format = argscheck ("string.format (string, ?any...)", string.format)
A colon in the function name indicates that the argument type list does not have a type for
self
:format = argscheck ("string:format (?any...)", string.format)
If an argument can be omitted entirely, then put its type specification in square brackets:
insert = argscheck ("table.insert (table, [int], ?any)", table.insert)
Similarly return types can be checked with the same list syntax as arguments:
len = argscheck ("string.len (string) => int", string.len)
Additionally, variant return type lists can be listed like this:
open = argscheck ("io.open (string, ?string) => file or nil, string", io.open)
Parameters:
- decl string function type declaration string
- inner func function to wrap with argument checking
Usage:
local case = argscheck ("std.functional.case (?any, #table) => [any...]", function (with, branches) ... end)
- debug ()
-
Equivalent to calling
debug.say (1, ...)
See also:
Usage:
local debug = require "std.debug" debug "oh noes!"
- extramsg_mismatch (expected, actual[, index])
-
Format a type mismatch error.
Parameters:
- expected string a pipe delimited list of matchable types
- actual the actual argument to match with
- index number erroring container element index (optional)
Returns:
See also:
Usage:
if fmt ~= nil and type (fmt) ~= "string" then argerror ("format", 1, extramsg_mismatch ("?string", fmt)) end
- parsetypes (types)
-
Compact permutation list into a list of valid types at each argument.
Eliminate bracketed types by combining all valid types at each position
for all permutations of typelist.
Parameters:
- types list a normalized list of type names
Returns:
-
list
valid types for each positional parameter
- say ([n=1], ...)
-
Print a debugging message to
io.stderr
. Display arguments passed throughstd.tostring
and separated by tab characters when_DEBUG
istrue
and n is 1 or less; or_DEBUG.level
is a number greater than or equal to n. If_DEBUG
is false or nil, nothing is written.Parameters:
- n int debugging level, smaller is higher priority (default 1)
- ... objects to print (as for print)
Usage:
local _DEBUG = require "std.debug_init"._DEBUG _DEBUG.level = 3 say (2, "_DEBUG table contents:", _DEBUG)
- trace (event)
-
Trace function calls.
Use as debug.sethook (trace, "cr"), which is done automatically
when
_DEBUG.call
is set. Based on test/trace-calls.lua from the Lua distribution.Parameters:
- event string event causing the call
Usage:
_DEBUG = { call = true } local debug = require "std.debug"
Tables
- _DEBUG
-
Control std.debug function behaviour.
To declare debugging state, set _DEBUG either to
false
to disable all runtime debugging; to any "truthy" value (equivalent to enabling everything except call, or as documented below.Fields:
- argcheck boolean honor argcheck and argscheck calls (default true)
- call boolean do call trace debugging (default false)
- deprecate
if
false
, deprecated APIs are defined, and do not issue deprecation warnings when used; ifnil
issue a deprecation warning each time a deprecated api is used; any other value causes deprecated APIs not to be defined at all (default nil) - level int debugging level (default 1)
Usage:
_DEBUG = { argcheck = false, level = 9 }
Fields
- extramsg_toomany
-
Format a too many things error.
- bad string the thing there are too many of
- expected int maximum number of bad things expected
- actual int actual number of bad things that triggered the error
See also:
Usage:
if maxn (argt) > 7 then argerror ("sevenses", 8, extramsg_toomany ("argument", 7, maxn (argt))) end
- getfenv
-
Extend
debug.getfenv
to unwrap functables correctly.- fn int, function or functable target function, or stack level
- resulterror
-
Raise a bad result error.
Like argerror for bad results. This function does not
return. The
level
argument behaves just like the coreerror
function.- name string function to callout in error message
- i int argument number
- extramsg string additional text to append to message inside parentheses (optional)
- level int call stack level to blame for the error (default 1)
Usage:
local function slurp (file) local h, err = input_handle (file) if h == nil then argerror ("std.io.slurp", 1, err, 2) end ...
- setfenv
-
Extend
debug.setfenv
to unwrap functables correctly.- fn function or functable target function
- env table new function environment
- typesplit
- Split a typespec string into a table of normalized type names.