Module std.normalize
Normalize API differences between supported Lua implementations.
Respecting the values set in the std._debug settings module, inject
deterministic identically behaving cross-implementation low-level
functions into the callers environment.
Writing Lua libraries that target several Lua implementations can be a frustrating exercise in working around lots of small differences in APIs and semantics they share (or rename, or omit). normalize provides the means to simply access deterministic implementations of those APIs that have the the same semantics across all supported host Lua implementations. Each function is as thin and fast an implementation as is possible within that host Lua environment, evaluating to the Lua C implementation with no overhead where host semantics allow.
The core of this module is to transparently set the environment up with a single API (as opposed to requiring caching functions from a module table into module locals):
local _ENV = require 'std.normalize' { 'package', 'std.prototype', strict = 'std.strict', }
It is not yet complete, and in contrast to the kepler project lua-compat libraries, neither does it attempt to provide you with as nearly compatible an API as is possible relative to some specific Lua implementation - rather it provides a variation of the "lowest common denominator" that can be implemented relatively efficiently in the supported Lua implementations, all in pure Lua.
At the moment, only the functionality used by stdlib is implemented.
Functions
| argerror (name, i[, extramsg[, level=1]]) | Raise a bad argument error. |
| callable (x) | Return x if it can be called, otherwise nil. |
| getfenv ([fn=1]) | Get a function or functor environment. |
| getmetafield (x, n) | Return the named field of the metatable of an object, if any. |
| getmetamethod (x, n) | Return named metamethod, if callable, otherwise nil. |
| ipairs (t) | Iterate over elements of a sequence, until the first nil value. |
| iscallable (x) | Whether x can be called. |
| len (x) | Deterministic, functional version of core Lua # operator. |
| load (ld, source[, mode[, env]]) | Load a string or a function, just like Lua 5.2+. |
| pack (...) | Return a list of given arguments, with field n set to the length. |
| pairs (t) | Like Lua pairs iterator, but respect __pairs even in Lua 5.1. |
| rawlen (x) | Length of a string or table object without using any metamethod. |
| setfenv (fn, env) | Set a function or functor environment. |
| str (x) | Return a compact stringified representation of argument. |
| unpack (t[, i=1[, j=len(t)]]) | Either table.unpack in newer-, or unpack in older Lua implementations. |
| xpcall (f, errh, ...) | Support arguments to a protected function call, even on Lua 5.1. |
| bit32.arshift (x, disp) | Shift right, filling the left with the sign bit. |
| bit32.band (...) | Bitwise and. |
| bit32.bnot (x) | Bitwise not. |
| bit32.bor (...) | Bitwise or. |
| bit32.btest (...) | Whether the bitwise and of the values is not zero. |
| bit32.bxor (...) | Bitwise exclusive or. |
| bit32.extract (n, field[, width=1]) | Extract bits of a value. |
| bit32.lrotate (x, disp) | Rotate left. |
| bit32.lshift (x, disp) | Shift left, filling the right with zeros. |
| bit32.replace (n, v, field[, width=1]) | Replace bits of a value. |
| bit32.rrotate (x, disp) | Rotate right. |
| bit32.rshift (x, disp) | Shift right, filling the left with zeros. |
| math.tointeger (x) | Convert to an integer and return if possible, otherwise nil. |
| math.type (x) | Return 'integer', 'float' or nil according to argument type. |
| os.exit (status) | Exit the program. |
| package.searchpath (name, path[, sep='.'[, rep=`package.dirsep`]]) | Searches for a named file in a given path. |
| string.format (fmt, ...) | Return a formatted string, converting any %s argument with tostring. |
| string.render (x, vfns[, roots]) | Low-level recursive data to string rendering. |
| table.maxn (t) | Return the largest positive numerical key of a table. |
| table.keys (t) | Return an unordered list of all keys in a table. |
| table.merge (t[, u={}]) | Destructively merge keys and values from one table into another. |
Tables
| package | Package module constants for package.config substrings. |
Metamethods
| __call (env[, level=1]) | Normalize caller's lexical environment. |
| __index (name) | Lazy loading of normalize modules. |
Types
| RenderFns | Table of functions for string.render. |
| RenderElem (x) | Type of function for uniquely stringifying rendered element. |
| RenderTerm (x) | Type of predicate function for terminal elements. |
| RenderSort (keys) | Type of function for sorting keys of a recursively rendered element. |
| RenderOpen (x) | Type of function to get string for before first element. |
| RenderClose (x) | Type of function te get string for after last element. |
| RenderPair (x, kp, vp, k, v, kstr, vstr, seqp) | Type of function to render a key value pair. |
| RenderSep (x, kp, vp, kn, vn, seqp) | Type of function to render a separator between pairs. |
Functions
- 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
levelargument behaves just like the coreerrorfunction.Parameters:
- name string function to callout in error message
- i integer argument number
- extramsg
string
additional text to append to message inside
(optional)parentheses - level integer 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 ...
- callable (x)
-
Return x if it can be called, otherwise
nil. A function can be called, and so can a table, or other object, with a__callmetamethod in its metatable, a functor. Unlike the__callmetamethod, which takes the functor as its first argument, the object that this returns can be called with just the arguments that it is for.Parameters:
- x an object or primitive
Returns:
-
x if x can be called, otherwise
nilSee also:
Usage:
(callable(functor) or function() end)(args, ...)
- getfenv ([fn=1])
-
Get a function or functor environment.
This version of getfenv works on all supported Lua versions, and knows how to unwrap functors: a table with a function valued
callfield acts on that function, and any other functor acts on its__callmetamethod.Parameters:
- fn
function or int
stack level, C or Lua function or
(default 1)functor to act on
Returns:
-
table
the execution environment of fn
Usage:
callers_environment = getfenv(1)
- fn
function or int
- getmetafield (x, n)
-
Return the named field of the metatable of an object, if any.
Unlike
getmetatable(x)[n], or(getmetatable(x) or {})[n], this does not raise an error for an object that has no metatable, or whose__metatablefield, whichgetmetatablereturns, is not a table.Parameters:
- x item to act on
- n string name of field to look up
Returns:
the value of field n of the metatable of x, or
nilif it has noneSee also:
Usage:
local kind = getmetafield(x, '_type') or type(x)
- getmetamethod (x, n)
-
Return named metamethod, if callable, otherwise
nil.Parameters:
- x item to act on
- n string name of metamethod to look up
Returns:
-
function or nil
metamethod function, or
nilif nometamethodUsage:
normalize = getmetamethod(require 'std.normalize', '__call')
- ipairs (t)
-
Iterate over elements of a sequence, until the first
nilvalue.Returns successive key-value pairs with integer keys starting at 1, up to the index returned by the
__lenmetamethod if any, or else up to last non-nilvalue.Unlike Lua 5.1, any
__indexmetamethod is respected.Unlike Lua 5.2+, any
__ipairsmetamethod is ignored!Parameters:
- t table table to iterate on
Returns:
- function iterator function
- table t the table being iterated over
- int the previous iteration index
Usage:
t, u = {}, {} for i, v in ipairs {1, 2, nil, 4} do t[i] = v end assert(len(t) == 2) for i, v in ipairs(pack(1, 2, nil, 4)) do u[i] = v end assert(len(u) == 4) - iscallable (x)
-
Whether x can be called.
Parameters:
- x an object or primitive
Returns:
-
boolean
trueif x is a function or a functor,otherwise `false`See also:
Usage:
if iscallable(handler) then handler(event) end
- len (x)
-
Deterministic, functional version of core Lua
#operator.Respects
__lenmetamethod (like Lua 5.2+). Otherwise, always return one less than the lowest integer index with anilvalue in x, where the#operator implementation might return the size of the array part of a table. A__tostringmetamethod is ignored.Parameters:
- x item to act on
Returns:
-
int
the length of x
Usage:
x = {1, 2, 3, nil, 5} --> 5 3 print(#x, len(x)) - load (ld, source[, mode[, env]])
-
Load a string or a function, just like Lua 5.2+.
Parameters:
- ld
string or function
chunk to load, or a functor or string-like
object that stands for one - source string name of the source of ld, or a string-like object
- mode
string
't'or'bt'to allow only text, or either kind
(optional)of chunk, and so Lua byte code, which is not portable between hosts. A mode that does not allow text is an error. Lua 5.1 checks that a string *ld* is text for `'t'`, but can't read ahead in a function - env
table
the environment for the chunk, in place of
(optional)the global one; in Lua 5.1 it must be a table, and is set with `setfenv`
Returns:
-
function
a Lua function to execute ld in global scope,
or in *env* if one is givenUsage:
assert(load 'print "woo"')() assert(load('return x', 'chunk', 't', {x = 'woo'}))()
- ld
string or function
- pack (...)
-
Return a list of given arguments, with field
nset to the length.The returned table also has a
__lenmetamethod that returnsn, soipairsandunpackbehave sanely when there arenilvalued elements.Parameters:
- ... tuple to act on
Returns:
-
table
packed list of ... values, with field
nset tonumber of tuple elements (including any explicit `nil` elements)See also:
Usage:
--> 5 len(pack(nil, 2, 5, nil, nil))
- pairs (t)
-
Like Lua
pairsiterator, but respect__pairseven in Lua 5.1.Parameters:
- t table table to act on
Returns:
- function iterator function
- table t, the table being iterated over
- the previous iteration key
Usage:
for k, v in pairs {'a', b='c', foo=42} do process(k, v) end
- rawlen (x)
-
Length of a string or table object without using any metamethod.
Parameters:
Returns:
-
int
raw length of x
Usage:
--> 0 rawlen(setmetatable({}, {__len=function() return 42}))
- setfenv (fn, env)
-
Set a function or functor environment.
This version of setfenv works on all supported Lua versions, and knows how to unwrap functors, like getfenv. Lua 5.2 and later have no global environment to set with level 0, so it is an error in all of them.
Parameters:
- fn
function or int
stack level, C or Lua function or functor
to act on - env table new execution environment for fn
Returns:
-
function
function acted upon
Usage:
function clearenv(fn) return setfenv(fn, {}) end
- fn
function or int
- str (x)
-
Return a compact stringified representation of argument.
A string argument has its control characters (
\a\b\t\n\v\f\r) written as C-like escape sequences, so usetostringto get a string exactly as it is.Parameters:
- x item to act on
Returns:
-
string
compact string representing x
Usage:
-- {baz,5,foo=bar} print(str{foo='bar','baz', 5})
- unpack (t[, i=1[, j=len(t)]])
-
Either
table.unpackin newer-, orunpackin older Lua implementations.Parameters:
- t table table to act on
- i integer first index to unpack (default 1)
- j integer last index to unpack (default len(t))
Returns:
-
... values of numeric indices of t
See also:
Usage:
local a, b, c = unpack(pack(nil, 2, nil)) assert(a == nil and b == 2 and c == nil)
- xpcall (f, errh, ...)
-
Support arguments to a protected function call, even on Lua 5.1.
Parameters:
- f function protect this function call
- errh
function
error object handler callback if f raises
an error - ... arguments to pass to f
Returns:
-
... all return values from f follow
Or
-
boolean
falsewhenf(...)raised an error - string error message
Or
-
boolean
truewhenf(...)succeededUsage:
-- Use errh to get a backtrack after curses exits abnormally xpcall(main, errh, arg, opt)
- bit32.arshift (x, disp)
-
Shift right, filling the left with the sign bit.
Parameters:
- x integer value to shift, as an unsigned 32-bit integer
- disp integer number of bits to shift, left if negative
Returns:
-
integer
the shifted value
Usage:
--> 0xFFFFFFFE arshift(0xFFFFFFFC, 1)
- bit32.band (...)
-
Bitwise and.
Parameters:
- ... integer values, as unsigned 32-bit integers
Returns:
-
integer
the bits that are set in every value
Usage:
--> 0x0F band(0xFF, 0x0F)
- bit32.bnot (x)
-
Bitwise not.
Parameters:
- x integer value, as an unsigned 32-bit integer
Returns:
-
integer
x with every bit of the 32 flipped
Usage:
--> 0xFFFFFF00 bnot(0xFF)
- bit32.bor (...)
-
Bitwise or.
Parameters:
- ... integer values, as unsigned 32-bit integers
Returns:
-
integer
the bits that are set in any value
Usage:
--> 0xFF bor(0xF0, 0x0F)
- bit32.btest (...)
-
Whether the bitwise and of the values is not zero.
Parameters:
- ... integer values, as unsigned 32-bit integers
Returns:
-
boolean
trueif some bit is set in every valueUsage:
--> true btest(0x03, 0x02)
- bit32.bxor (...)
-
Bitwise exclusive or.
Parameters:
- ... integer values, as unsigned 32-bit integers
Returns:
-
integer
the bits that are set in an odd number of values
Usage:
--> 0xF0 bxor(0xFF, 0x0F)
- bit32.extract (n, field[, width=1])
-
Extract bits of a value.
Parameters:
- n integer value to read, as an unsigned 32-bit integer
- field integer the lowest bit to read, from 0
- width integer the number of bits to read (default 1)
Returns:
-
integer
the bits, as the low bits of the result
Raises:
if the bits are not all among the 32Usage:
--> 0x0A extract(0xAB, 4, 4)
- bit32.lrotate (x, disp)
-
Rotate left.
Parameters:
- x integer value to rotate, as an unsigned 32-bit integer
- disp integer number of bits to rotate, right if negative
Returns:
-
integer
the rotated value
Usage:
--> 0x00000001 lrotate(0x80000000, 1)
- bit32.lshift (x, disp)
-
Shift left, filling the right with zeros.
Parameters:
- x integer value to shift, as an unsigned 32-bit integer
- disp integer number of bits to shift, right if negative
Returns:
-
integer
the shifted value
Usage:
--> 0xF0 lshift(0x0F, 4)
- bit32.replace (n, v, field[, width=1])
-
Replace bits of a value.
Parameters:
- n integer value to change, as an unsigned 32-bit integer
- v integer the bits to put in, as the low bits of v
- field integer the lowest bit to replace, from 0
- width integer the number of bits to replace (default 1)
Returns:
-
integer
n with the bits replaced
Raises:
if the bits are not all among the 32Usage:
--> 0xFF replace(0x0F, 0x0F, 4, 4)
- bit32.rrotate (x, disp)
-
Rotate right.
Parameters:
- x integer value to rotate, as an unsigned 32-bit integer
- disp integer number of bits to rotate, left if negative
Returns:
-
integer
the rotated value
Usage:
--> 0x80000000 rrotate(0x00000001, 1)
- bit32.rshift (x, disp)
-
Shift right, filling the left with zeros.
Parameters:
- x integer value to shift, as an unsigned 32-bit integer
- disp integer number of bits to shift, left if negative
Returns:
-
integer
the shifted value
Usage:
--> 0x0F rshift(0xF0, 4)
- math.tointeger (x)
-
Convert to an integer and return if possible, otherwise
nil.Parameters:
- x object to act on
Returns:
-
integer
x converted to an integer if possible
Or
nilotherwise - math.type (x)
-
Return 'integer', 'float' or
nilaccording to argument type.To ensure the same behaviour on all host Lua implementations, this function returns 'float' for integer-equivalent floating values, even on Lua 5.3.
Parameters:
- x object to act on
Returns:
-
string
'integer', if x is a whole number
Or
-
string
'float', for other numbers
Or
nilotherwise - os.exit (status)
-
Exit the program.
Parameters:
- status bool or number[opt=true] report back to parent process
Usage:
exit(len(records.processed) > 0)
- package.searchpath (name, path[, sep='.'[, rep=`package.dirsep`]])
-
Searches for a named file in a given path.
For each
package.pathsepdelimited template in the given path, search for an readable file made by first substituting for sep withpackage.dirsep, and then replacing anypackage.pathmarkwith the result. The first such file, if any is returned.Parameters:
- name string name of search file
- path
string
package.pathsepdelimited list of full path templates - sep string name component separator (default '.')
- rep string sep replacement in template (default `package.dirsep`)
Returns:
-
string
first template substitution that names a file
that can be opened in read modeOr
-
nil - string error message listing all failed paths
- string.format (fmt, ...)
-
Return a formatted string, converting any
%sargument withtostring. Lua 5.1 only accepts strings and numbers for%s, so wrap it there to match the later Luas; elsewhere this isstring.format.Parameters:
- fmt string a format string
- ... values to substitute into fmt
Returns:
-
string
fmt with each conversion replaced by an argument
- string.render (x, vfns[, roots])
-
Low-level recursive data to string rendering.
Parameters:
- x data to be renedered
- vfns RenderFns table of virtual functions to control rendering
- roots table used internally for cycle detection (optional)
Returns:
-
string
a text recursive rendering of x using vfns
Usage:
function printarray(x) return render(x, arrayvfns) end
- table.maxn (t)
-
Return the largest positive numerical key of a table.
This was
table.maxnin Lua 5.1, and is not in the later releases.Parameters:
- t table table to operate on
Returns:
-
number
the largest positive number that is a key of t,
or `0` if there is noneUsage:
--> 5 maxn{'a', [5]='e', x=9}
- table.keys (t)
-
Return an unordered list of all keys in a table.
Parameters:
- t table table to operate on
Returns:
-
table
an unorderd list of keys in t
Usage:
--> {'key2', 1, 42, 2, 'key1'} keys{'a', 'b', key1=1, key2=2, [42]=3}
- table.merge (t[, u={}])
-
Destructively merge keys and values from one table into another.
Parameters:
- t table take fields from this table
- u table and copy them into here, unless they are set already (default {})
Returns:
-
table
u
Usage:
--> {'a', 'b', d='d'} merge({'a', 'b'}, {'c', d='d'})
Tables
- package
-
Package module constants for
package.configsubstrings. Every other field, such aspathandloaded, is read from and written to the corepackagetable, except thatloadedholds the normalized core modules.Fields:
- dirsep string directory separator in path elements
- execdir string replaced by the executable's directory in a path
- igmark
string
ignore everything before this when building
`luaopen_` function name - pathmark string mark substitution points in a path template
- pathsep string element separator in a path template
Metamethods
- __call (env[, level=1])
-
Normalize caller's lexical environment.
Using 'std.strict' when available and selected, otherwise a (Lua 5.1 compatible) function to set the given environment.
With an empty table argument, the core (not-table) normalize functions are loaded into the callers environment. For consistent behaviour between supported host Lua implementations, the result must always be assigned back to
_ENV. Additional core modules must be named to be loaded at all (i.e. no 'debug' table unless it is explicitly listed in the argument table).Additionally, external modules are loaded using
require, with.separators in the module name translated to nested tables in the module environment. For example 'std.prototype' in the usage below will add to the environment table the equivalent of:local prototype = require 'std.prototype'Alternatively, you can assign a loaded module symbol to a specific environment table symbol with
key=valuesyntax. For example the the 'math.tointeger' from the usage below is equivalent to:local int = require 'std.normalize.math'.tointegerCompare this to loading the non-normalized implementation from the host Lua with a table entry such as:
int = require 'math'.tointeger,Finally, explicit string assignment to ALLCAPS keys are not loaded from modules at all, but behave as a constant string assignment:
INT = 'math.tointeger',Parameters:
- env table environment table
- level
int
stack level for
setfenv, 1 means set
(default 1)caller's environment
Returns:
-
table
env with this module's functions merge id. Assign
back to `_ENV`Usage:
local _ENV = require 'std.normalize' { 'string', 'std.prototype', int = 'math.tointeger', }
- __index (name)
-
Lazy loading of normalize modules.
Don't load everything on initial startup, wait until first attempt
to access a submodule, and then load it on demand.
Parameters:
- name string submodule name
Returns:
-
table or nil
the submodule that was loaded to satisfy the missing
`name`, otherwise `nil` if nothing was foundUsage:
local version = require 'std.normalize'.version
Types
- RenderFns
-
Table of functions for string.render.
Fields:
- elem RenderElem return unique string representation of an element
- term
RenderTerm
return true for elements that should not be
recursed - sort RenderSort return list of keys in order to be rendered
- open RenderOpen return a string for before first element of a table
- close RenderClose return a string for after last element of a table
- pair
RenderPair
return a string rendering of a key value pair
element - sep RenderSep return a string to render between elements
See also:
Usage:
arrayvfns = { elem = tostring, term = function(x) return type(x) ~= 'table' or getmetamethod(x, '__tostring') end, sort = function(keys) local r = {} for i = 1, #keys do if type(keys[i]) == 'number' then r[#r + 1] = keys[i] end end return r end, open = function(_) return '[' end, close = function(_) return ']' end, pair = function(x, kp, vp, k, v, kstr, vstr, seqp) return seqp and vstr or '' end, sep = function(x, kp, vp, kn, vn, seqp) return seqp and kp ~= nil and kn ~= nil and ', ' or '' end, ) - RenderElem (x)
-
Type of function for uniquely stringifying rendered element.
Parameters:
- x element to operate on
Returns:
-
string
stringified x
- RenderTerm (x)
-
Type of predicate function for terminal elements.
Parameters:
- x element to operate on
Returns:
-
bool
true for terminal elements that should be rendered
immediately - RenderSort (keys)
-
Type of function for sorting keys of a recursively rendered element.
Parameters:
- keys
table
list of table keys, it's okay to mutate and return
this parameter
Returns:
-
table
sorted list of keys for pairs to be rendered
- keys
table
- RenderOpen (x)
-
Type of function to get string for before first element.
Parameters:
- x element to operate on
Returns:
-
string
string to render before first element
- RenderClose (x)
-
Type of function te get string for after last element.
Parameters:
- x element to operate on
Returns:
-
string
string to render after last element
- RenderPair (x, kp, vp, k, v, kstr, vstr, seqp)
-
Type of function to render a key value pair.
Parameters:
- x complete table elmeent being operated on
- kp unstringified previous pair key
- vp unstringified previous pair value
- k unstringified pair key to render
- v unstringified pair value to render
- kstr already stringified pair key to render
- vstr already stringified pair value to render
- seqp
true if all keys so far have been a contiguous range of
integers
Returns:
-
string
stringified rendering of pair kstr and vstr
- RenderSep (x, kp, vp, kn, vn, seqp)
-
Type of function to render a separator between pairs.
Parameters:
- x complet table element being operated on
- kp unstringified previous pair key
- vp unstringified previous pair value
- kn unstringified next pair key
- vn unstringified next pair value
- seqp
true if all keys so far have been a contiguous range of
integers
Returns:
-
string
stringified rendering of separator between previous and
next pairs