summaryrefslogtreecommitdiff
path: root/Data/BuiltIn/Libraries/lua-stdlib/lib/std
diff options
context:
space:
mode:
Diffstat (limited to 'Data/BuiltIn/Libraries/lua-stdlib/lib/std')
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/_base.lua204
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/debug.lua156
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/init.lua389
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/io.lua322
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/math.lua92
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/package.lua263
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/string.lua505
-rw-r--r--Data/BuiltIn/Libraries/lua-stdlib/lib/std/table.lua439
8 files changed, 2370 insertions, 0 deletions
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/_base.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/_base.lua
new file mode 100644
index 0000000..0c623d4
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/_base.lua
@@ -0,0 +1,204 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ Prevent dependency loops with key function implementations.
+
+ A few key functions are used in several stdlib modules; we implement those
+ functions in this internal module to prevent dependency loops in the first
+ instance, and to minimise coupling between modules where the use of one of
+ these functions might otherwise load a whole selection of other supporting
+ modules unnecessarily.
+
+ Although the implementations are here for logistical reasons, we re-export
+ them from their respective logical modules so that the api is not affected
+ as far as client code is concerned. The functions in this file do not make
+ use of `argcheck` or similar, because we know that they are only called by
+ other stdlib functions which have already performed the necessary checking
+ and neither do we want to slow everything down by recheckng those argument
+ types here.
+
+ This implies that when re-exporting from another module when argument type
+ checking is in force, we must export a wrapper function that can check the
+ user's arguments fully at the API boundary.
+]]
+
+
+local _ENV = require 'std.normalize' {
+ concat = 'table.concat',
+ dirsep = 'package.dirsep',
+ find = 'string.find',
+ gsub = 'string.gsub',
+ insert = 'table.insert',
+ min = 'math.min',
+ shallow_copy = 'table.merge',
+ sort = 'table.sort',
+ sub = 'string.sub',
+ table_maxn = table.maxn,
+ wrap = 'coroutine.wrap',
+ yield = 'coroutine.yield',
+}
+
+
+
+--[[ ============================ ]]--
+--[[ Enhanced Core Lua functions. ]]--
+--[[ ============================ ]]--
+
+
+-- These come as early as possible, because we want the rest of the code
+-- in this file to use these versions over the core Lua implementation
+-- (which have slightly varying semantics between releases).
+
+
+local maxn = table_maxn or function(t)
+ local n = 0
+ for k in pairs(t) do
+ if type(k) == 'number' and k > n then
+ n = k
+ end
+ end
+ return n
+end
+
+
+
+--[[ ============================ ]]--
+--[[ Shared Stdlib API functions. ]]--
+--[[ ============================ ]]--
+
+
+-- No need to recurse because functables are second class citizens in
+-- Lua:
+-- func = function() print 'called' end
+-- func() --> 'called'
+-- functable=setmetatable({}, {__call=func})
+-- functable() --> 'called'
+-- nested=setmetatable({}, {__call=functable})
+-- nested()
+-- --> stdin:1: attempt to call a table value(global 'd')
+-- --> stack traceback:
+-- --> stdin:1: in main chunk
+-- --> [C]: in ?
+local function callable(x)
+ if type(x) == 'function' then
+ return x
+ end
+ return (getmetatable(x) or {}).__call
+end
+
+
+local function catfile(...)
+ return concat({...}, dirsep)
+end
+
+
+local function compare(l, m)
+ local lenl, lenm = len(l), len(m)
+ for i = 1, min(lenl, lenm) do
+ local li, mi = tonumber(l[i]), tonumber(m[i])
+ if li == nil or mi == nil then
+ li, mi = l[i], m[i]
+ end
+ if li < mi then
+ return -1
+ elseif li > mi then
+ return 1
+ end
+ end
+ if lenl < lenm then
+ return -1
+ elseif lenl > lenm then
+ return 1
+ end
+ return 0
+end
+
+
+local function escape_pattern(s)
+ return (gsub(s, '[%^%$%(%)%%%.%[%]%*%+%-%?]', '%%%0'))
+end
+
+
+local function invert(t)
+ local i = {}
+ for k, v in pairs(t) do
+ i[v] = k
+ end
+ return i
+end
+
+
+local function leaves(it, tr)
+ local function visit(n)
+ if type(n) == 'table' then
+ for _, v in it(n) do
+ visit(v)
+ end
+ else
+ yield(n)
+ end
+ end
+ return wrap(visit), tr
+end
+
+
+local function split(s, sep)
+ local r, patt = {}
+ if sep == '' then
+ patt = '(.)'
+ insert(r, '')
+ else
+ patt = '(.-)' ..(sep or '%s+')
+ end
+ local b, slen = 0, len(s)
+ while b <= slen do
+ local e, n, m = find(s, patt, b + 1)
+ insert(r, m or sub(s, b + 1, slen))
+ b = n or slen + 1
+ end
+ return r
+end
+
+
+--[[ ============= ]]--
+--[[ Internal API. ]]--
+--[[ ============= ]]--
+
+
+-- For efficient use within stdlib, these functions have no type-checking.
+-- In debug mode, type-checking wrappers are re-exported from the public-
+-- facing modules as necessary.
+--
+-- Also, to provide some sanity, we mirror the subtable layout of stdlib
+-- public API here too, which means everything looks relatively normal
+-- when importing the functions into stdlib implementation modules.
+return {
+ io = {
+ catfile = catfile,
+ },
+
+ list = {
+ compare = compare,
+ },
+
+ object = {
+ Module = Module,
+ mapfields = mapfields,
+ },
+
+ string = {
+ escape_pattern = escape_pattern,
+ split = split,
+ },
+
+ table = {
+ invert = invert,
+ maxn = maxn,
+ },
+
+ tree = {
+ leaves = leaves,
+ },
+}
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/debug.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/debug.lua
new file mode 100644
index 0000000..cab29ff
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/debug.lua
@@ -0,0 +1,156 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ 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'
+
+ @corelibrary std.debug
+]]
+
+
+local _ENV = require 'std.normalize' {
+ 'debug',
+ _debug = require 'std._debug',
+ concat = 'table.concat',
+ huge = 'math.huge',
+ max = 'math.max',
+ merge = 'table.merge',
+ stderr = 'io.stderr',
+}
+
+
+
+--[[ =============== ]]--
+--[[ Implementation. ]]--
+--[[ =============== ]]--
+
+
+local function say(n, ...)
+ local level, argt = n, {...}
+ if type(n) ~= 'number' then
+ level, argt = 1, {n, ...}
+ end
+ if _debug.level ~= huge and
+ ((type(_debug.level) == 'number' and _debug.level >= level) or level <= 1)
+ then
+ local t = {}
+ for k, v in pairs(argt) do
+ t[k] = str(v)
+ end
+ stderr:write(concat(t, '\t') .. '\n')
+ end
+end
+
+
+local level = 0
+
+local function trace(event)
+ local t = debug.getinfo(3)
+ local s = ' >>> '
+ for i = 1, level do
+ s = s .. ' '
+ end
+ if t ~= nil and t.currentline >= 0 then
+ s = s .. t.short_src .. ':' .. t.currentline .. ' '
+ end
+ t = debug.getinfo(2)
+ if event == 'call' then
+ level = level + 1
+ else
+ level = max(level - 1, 0)
+ end
+ if t.what == 'main' then
+ if event == 'call' then
+ s = s .. 'begin ' .. t.short_src
+ else
+ s = s .. 'end ' .. t.short_src
+ end
+ elseif t.what == 'Lua' then
+ s = s .. event .. ' ' ..(t.name or '(Lua)') .. ' <' ..
+ t.linedefined .. ':' .. t.short_src .. '>'
+ else
+ s = s .. event .. ' ' ..(t.name or '(C)') .. ' [' .. t.what .. ']'
+ end
+ stderr:write(s .. '\n')
+end
+
+-- Set hooks according to _debug
+if _debug.call then
+ debug.sethook(trace, 'cr')
+end
+
+
+
+local M = {
+ --- Function Environments
+ -- @section environments
+
+ --- Extend `debug.getfenv` to unwrap functables correctly.
+ -- @function getfenv
+ -- @tparam int|function|functable fn target function, or stack level
+ -- @treturn table environment of *fn*
+ getfenv = getfenv,
+
+ --- Extend `debug.setfenv` to unwrap functables correctly.
+ -- @function setfenv
+ -- @tparam function|functable fn target function
+ -- @tparam table env new function environment
+ -- @treturn function *fn*
+ setfenv = setfenv,
+
+
+ --- Functions
+ -- @section functions
+
+ --- Print a debugging message to `io.stderr`.
+ -- Display arguments passed through `std.tostring` and separated by tab
+ -- characters when `std._debug` hinting is `true` and *n* is 1 or less;
+ -- or `std._debug.level` is a number greater than or equal to *n*. If
+ -- `std._debug` hinting is false or nil, nothing is written.
+ -- @function say
+ -- @int[opt=1] n debugging level, smaller is higher priority
+ -- @param ... objects to print(as for print)
+ -- @usage
+ -- local _debug = require 'std._debug'
+ -- _debug.level = 3
+ -- say(2, '_debug status level:', _debug.level)
+ say = say,
+
+ --- Trace function calls.
+ -- Use as debug.sethook(trace, 'cr'), which is done automatically
+ -- when `std._debug.call` is set.
+ -- Based on test/trace-calls.lua from the Lua distribution.
+ -- @function trace
+ -- @string event event causing the call
+ -- @usage
+ -- local _debug = require 'std._debug'
+ -- _debug.call = true
+ -- local debug = require 'std.debug'
+ trace = trace,
+}
+
+
+--- Metamethods
+-- @section metamethods
+
+--- Equivalent to calling `debug.say(1, ...)`
+-- @function __call
+-- @see say
+-- @usage
+-- local debug = require 'std.debug'
+-- debug 'oh noes!'
+local metatable = {
+ __call = function(self, ...)
+ M.say(1, ...)
+ end,
+}
+
+
+return setmetatable(merge(debug, M), metatable)
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/init.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/init.lua
new file mode 100644
index 0000000..732d41f
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/init.lua
@@ -0,0 +1,389 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ Enhanced Lua core functions, and others.
+
+ After requiring this module, simply referencing symbols in the submodule
+ hierarchy will load the necessary modules on demand. There are no
+ changes to any global symbols, or monkey patching of core module tables
+ and metatables.
+
+ @todo Write a style guide(indenting/wrapping, capitalisation,
+ function and variable names); library functions should call
+ error, not die; OO vs non-OO(a thorny problem).
+ @todo pre-compile.
+ @corefunction std
+]]
+
+
+local _ = require 'std._base'
+
+local argscheck = _.typecheck and _.typecheck.argscheck
+local compare = _.list.compare
+local maxn = _.table.maxn
+local split = _.string.split
+
+_ = nil
+
+
+local _ENV = require 'std.normalize' {
+ format = 'string.format',
+ match = 'string.match',
+}
+
+
+
+--[[ =============== ]]--
+--[[ Implementation. ]]--
+--[[ =============== ]]--
+
+
+local M
+
+
+local function _assert(expect, fmt, arg1, ...)
+ local msg =(arg1 ~= nil) and format(fmt, arg1, ...) or fmt or ''
+ return expect or error(msg, 2)
+end
+
+
+local function elems(t)
+ -- capture pairs iterator initial state
+ local fn, istate, ctrl = pairs(t)
+ return function(state, _)
+ local v
+ ctrl, v = fn(state, ctrl)
+ if ctrl then
+ return v
+ end
+ end, istate, true -- wrapped initial state
+end
+
+
+local function eval(s)
+ return load('return ' .. s)()
+end
+
+
+local function ielems(t)
+ -- capture pairs iterator initial state
+ local fn, istate, ctrl = ipairs(t)
+ return function(state, _)
+ local v
+ ctrl, v = fn(state, ctrl)
+ if ctrl then
+ return v
+ end
+ end, istate, true -- wrapped initial state
+end
+
+
+local function npairs(t)
+ local m = getmetamethod(t, '__len')
+ local i, n = 0, m and m(t) or maxn(t)
+ return function(t)
+ i = i + 1
+ if i <= n then
+ return i, t[i]
+ end
+ end,
+ t, i
+end
+
+
+local function ripairs(t)
+ local oob = 1
+ while t[oob] ~= nil do
+ oob = oob + 1
+ end
+
+ return function(t, n)
+ n = n - 1
+ if n > 0 then
+ return n, t[n]
+ end
+ end, t, oob
+end
+
+
+local function rnpairs(t)
+ local m = getmetamethod(t, '__len')
+ local oob =(m and m(t) or maxn(t)) + 1
+
+ return function(t, n)
+ n = n - 1
+ if n > 0 then
+ return n, t[n]
+ end
+ end, t, oob
+end
+
+
+local vconvert = setmetatable({
+ string = function(x)
+ return split(x, '%.')
+ end,
+ number = function(x)
+ return {x}
+ end,
+ table = function(x)
+ return x
+ end,
+}, {
+ __call = function(self, x)
+ local fn = self[type(x)] or function()
+ return 0
+ end
+ return fn(x)
+ end,
+})
+
+
+local function vcompare(a, b)
+ return compare(vconvert(a), vconvert(b))
+end
+
+
+local function _require(module, min, too_big, pattern)
+ pattern = pattern or '([%.%d]+)%D*$'
+
+ local s, m = '', require(module)
+ if type(m) == 'table' then
+ s = tostring(m.version or m._VERSION or '')
+ end
+ local v = match(s, pattern) or 0
+ if min then
+ _assert(vcompare(v, min) >= 0, "require '" .. module ..
+ "' with at least version " .. min .. ', but found version ' .. v)
+ end
+ if too_big then
+ _assert(vcompare(v, too_big) < 0, "require '" .. module ..
+ "' with version less than " .. too_big .. ', but found version ' .. v)
+ end
+ return m
+end
+
+
+
+--[[ ================= ]]--
+--[[ Public Interface. ]]--
+--[[ ================= ]]--
+
+
+local function X(decl, fn)
+ return argscheck and argscheck('std.' .. decl, fn) or fn
+end
+
+M = {
+ --- Release version string.
+ -- @field version
+
+
+ --- Core Functions
+ -- @section corefuncs
+
+ --- Enhance core `assert` to also allow formatted arguments.
+ -- @function assert
+ -- @param expect expression, expected to be *truthy*
+ -- @string[opt=''] f format string
+ -- @param[opt] ... arguments to format
+ -- @return value of *expect*, if *truthy*
+ -- @usage
+ -- std.assert(expect == nil, '100% unexpected!')
+ -- std.assert(expect == 'expect', '%s the unexpected!', expect)
+ assert = X('assert(?any, ?string, [any...])', _assert),
+
+ --- Evaluate a string as Lua code.
+ -- @function eval
+ -- @string s string of Lua code
+ -- @return result of evaluating `s`
+ -- @usage
+ -- --> 2
+ -- std.eval 'math.min(2, 10)'
+ eval = X('eval(string)', eval),
+
+ --- Return named metamethod, if any, otherwise `nil`.
+ -- The value found at the given key in the metatable of *x* must be a
+ -- function or have its own `__call` metamethod to qualify as a
+ -- callable. Any other value found at key *n* will cause this function
+ -- to return `nil`.
+ -- @function getmetamethod
+ -- @param x item to act on
+ -- @string n name of metamethod to lookup
+ -- @treturn callable|nil callable metamethod, or `nil` if no metamethod
+ -- @usage
+ -- clone = std.getmetamethod(std.object.prototype, '__call')
+ getmetamethod = X('getmetamethod(?any, string)', getmetamethod),
+
+
+ --- Module Functions
+ -- @section modulefuncs
+
+ --- Enhance core `require` to assert version number compatibility.
+ -- By default match against the last substring of(dot-delimited)
+ -- digits in the module version string.
+ -- @function require
+ -- @string module module to require
+ -- @string[opt] min lowest acceptable version
+ -- @string[opt] too_big lowest version that is too big
+ -- @string[opt] pattern to match version in `module.version` or
+ -- `module._VERSION`(default: `'([%.%d]+)%D*$'`)
+ -- @usage
+ -- -- posix.version == 'posix library for Lua 5.2 / 32'
+ -- posix = require('posix', '29')
+ require = X('require(string, ?string, ?string, ?string)', _require),
+
+ --- Iterator Functions
+ -- @section iteratorfuncs
+
+ --- An iterator over all values of a table.
+ -- If *t* has a `__pairs` metamethod, use that to iterate.
+ -- @function elems
+ -- @tparam table t a table
+ -- @treturn function iterator function
+ -- @treturn table *t*, the table being iterated over
+ -- @return *key*, the previous iteration key
+ -- @see ielems
+ -- @see pairs
+ -- @usage
+ -- --> foo
+ -- --> bar
+ -- --> baz
+ -- --> 5
+ -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5})
+ elems = X('elems(table)', elems),
+
+ --- An iterator over the integer keyed elements of a table.
+ --
+ -- If *t* has a `__len` metamethod, iterate up to the index it
+ -- returns, otherwise up to the first `nil`.
+ --
+ -- This function does **not** support the Lua 5.2 `__ipairs` metamethod.
+ -- @function ielems
+ -- @tparam table t a table
+ -- @treturn function iterator function
+ -- @treturn table *t*, the table being iterated over
+ -- @treturn int *index*, the previous iteration index
+ -- @see elems
+ -- @see ipairs
+ -- @usage
+ -- --> foo
+ -- --> bar
+ -- std.functional.map(print, std.ielems, {'foo', 'bar', [4]='baz', d=5})
+ ielems = X('ielems(table)', ielems),
+
+ --- An iterator over integer keyed pairs of a sequence.
+ --
+ -- Like Lua 5.1 and 5.3, this iterator returns successive key-value
+ -- pairs with integer keys starting at 1, up to the first `nil` valued
+ -- pair.
+ --
+ -- If there is a `_len` metamethod, keep iterating up to and including
+ -- that element, regardless of any intervening `nil` values.
+ --
+ -- This function does **not** support the Lua 5.2 `__ipairs` metamethod.
+ -- @function ipairs
+ -- @tparam table t a table
+ -- @treturn function iterator function
+ -- @treturn table *t*, the table being iterated over
+ -- @treturn int *index*, the previous iteration index
+ -- @see ielems
+ -- @see npairs
+ -- @see pairs
+ -- @usage
+ -- --> 1 foo
+ -- --> 2 bar
+ -- std.functional.map(print, std.ipairs, {'foo', 'bar', [4]='baz', d=5})
+ ipairs = X('ipairs(table)', ipairs),
+
+ --- Ordered iterator for integer keyed values.
+ -- Like ipairs, but does not stop until the __len or maxn of *t*.
+ -- @function npairs
+ -- @tparam table t a table
+ -- @treturn function iterator function
+ -- @treturn table t
+ -- @see ipairs
+ -- @see rnpairs
+ -- @usage
+ -- --> 1 foo
+ -- --> 2 bar
+ -- --> 3 nil
+ -- --> 4 baz
+ -- std.functional.map(print, std.npairs, {'foo', 'bar', [4]='baz', d=5})
+ npairs = X('npairs(table)', npairs),
+
+ --- Enhance core `pairs` to respect `__pairs` even in Lua 5.1.
+ -- @function pairs
+ -- @tparam table t a table
+ -- @treturn function iterator function
+ -- @treturn table *t*, the table being iterated over
+ -- @return *key*, the previous iteration key
+ -- @see elems
+ -- @see ipairs
+ -- @usage
+ -- --> 1 foo
+ -- --> 2 bar
+ -- --> 4 baz
+ -- --> d 5
+ -- std.functional.map(print, std.pairs, {'foo', 'bar', [4]='baz', d=5})
+ pairs = X('pairs(table)', pairs),
+
+ --- An iterator like ipairs, but in reverse.
+ -- Apart from the order of the elements returned, this function follows
+ -- the same rules as @{ipairs} for determining first and last elements.
+ -- @function ripairs
+ -- @tparam table t any table
+ -- @treturn function iterator function
+ -- @treturn table *t*
+ -- @treturn number `#t + 1`
+ -- @see ipairs
+ -- @see rnpairs
+ -- @usage
+ -- --> 2 bar
+ -- --> 1 foo
+ -- std.functional.map(print, std.ripairs, {'foo', 'bar', [4]='baz', d=5})
+ ripairs = X('ripairs(table)', ripairs),
+
+ --- An iterator like npairs, but in reverse.
+ -- Apart from the order of the elements returned, this function follows
+ -- the same rules as @{npairs} for determining first and last elements.
+ -- @function rnpairs
+ -- @tparam table t a table
+ -- @treturn function iterator function
+ -- @treturn table t
+ -- @see npairs
+ -- @see ripairs
+ -- @usage
+ -- --> 4 baz
+ -- --> 3 nil
+ -- --> 2 bar
+ -- --> 1 foo
+ -- std.functional.map(print, std.rnpairs, {'foo', 'bar', [4]='baz', d=5})
+ rnpairs = X('rnpairs(table)', rnpairs),
+}
+
+
+--- Metamethods
+-- @section Metamethods
+
+return setmetatable(M, {
+ --- Lazy loading of stdlib modules.
+ -- Don't load everything on initial startup, wait until first attempt
+ -- to access a submodule, and then load it on demand.
+ -- @function __index
+ -- @string name submodule name
+ -- @treturn table|nil the submodule that was loaded to satisfy the missing
+ -- `name`, otherwise `nil` if nothing was found
+ -- @usage
+ -- local std = require 'std'
+ -- local Object = std.object.prototype
+ __index = function(self, name)
+ local ok, t = pcall(require, 'std.' .. name)
+ if ok then
+ rawset(self, name, t)
+ return t
+ end
+ end,
+})
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/io.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/io.lua
new file mode 100644
index 0000000..1a2b79f
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/io.lua
@@ -0,0 +1,322 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ Additions to the core io module.
+
+ The module table returned by `std.io` also contains all of the entries from
+ the core `io` module table. An hygienic way to import this module, then,
+ is simply to override core `io` locally:
+
+ local io = require 'std.io'
+
+ @corelibrary std.io
+]]
+
+
+local _ = require 'std._base'
+
+local argscheck = _.typecheck and _.typecheck.argscheck
+local catfile = _.io.catfile
+local leaves = _.tree.leaves
+local split = _.string.split
+
+_ = nil
+
+
+local _ENV = require 'std.normalize' {
+ 'io',
+ _G = _G, -- FIXME: don't use the host _G as an API!
+ concat = 'table.concat',
+ dirsep = 'package.dirsep',
+ format = 'string.format',
+ gsub = 'string.gsub',
+ input = 'io.input',
+ insert = 'table.insert',
+ io_type = 'io.type',
+ merge = 'table.merge',
+ open = 'io.open',
+ output = 'io.output',
+ popen = 'io.popen',
+ stderr = 'io.stderr',
+ stdin = 'io.stdin',
+ write = 'io.write',
+}
+
+
+--[[ =============== ]]--
+--[[ Implementation. ]]--
+--[[ =============== ]]--
+
+
+local M
+
+
+local function input_handle(h)
+ if h == nil then
+ return input()
+ elseif type(h) == 'string' then
+ return open(h)
+ end
+ return h
+end
+
+
+local function slurp(file)
+ local h, err = input_handle(file)
+ if h == nil then
+ argerror('std.io.slurp', 1, err, 2)
+ end
+
+ if h then
+ local s = h:read('*a')
+ h:close()
+ return s
+ end
+end
+
+
+local function readlines(file)
+ local h, err = input_handle(file)
+ if h == nil then
+ argerror('std.io.readlines', 1, err, 2)
+ end
+
+ local l = {}
+ for line in h:lines() do
+ l[#l + 1] = line
+ end
+ h:close()
+ return l
+end
+
+
+local function writelines(h, ...)
+ if io_type(h) ~= 'file' then
+ write(h, '\n')
+ h = output()
+ end
+ for v in leaves(ipairs, {...}) do
+ h:write(v, '\n')
+ end
+end
+
+
+local function process_files(fn)
+ -- N.B. 'arg' below refers to the global array of command-line args
+ if len(arg) == 0 then
+ insert(arg, '-')
+ end
+ for i, v in ipairs(arg) do
+ if v == '-' then
+ input(stdin)
+ else
+ input(v)
+ end
+ fn(v, i)
+ end
+end
+
+
+local function warnfmt(msg, ...)
+ local prefix = ''
+ local prog = rawget(_G, 'prog') or {}
+ local opts = rawget(_G, 'opts') or {}
+ if prog.name then
+ prefix = prog.name .. ':'
+ if prog.line then
+ prefix = prefix .. str(prog.line) .. ':'
+ end
+ elseif prog.file then
+ prefix = prog.file .. ':'
+ if prog.line then
+ prefix = prefix .. str(prog.line) .. ':'
+ end
+ elseif opts.program then
+ prefix = opts.program .. ':'
+ if opts.line then
+ prefix = prefix .. str(opts.line) .. ':'
+ end
+ end
+ if #prefix > 0 then
+ prefix = prefix .. ' '
+ end
+ return prefix .. format(msg, ...)
+end
+
+
+local function warn(msg, ...)
+ writelines(stderr, warnfmt(msg, ...))
+end
+
+
+
+--[[ ================= ]]--
+--[[ Public Interface. ]]--
+--[[ ================= ]]--
+
+
+local function X(decl, fn)
+ return argscheck and argscheck('std.io.' .. decl, fn) or fn
+end
+
+
+M = {
+ --- Diagnostic functions
+ -- @section diagnosticfuncs
+
+ --- Die with error.
+ -- This function uses the same rules to build a message prefix
+ -- as @{warn}.
+ -- @function die
+ -- @string msg format string
+ -- @param ... additional arguments to plug format string specifiers
+ -- @see warn
+ -- @usage
+ -- die('oh noes!(%s)', tostring(obj))
+ die = X('die(string, [any...])', function(...)
+ error(warnfmt(...), 0)
+ end),
+
+ --- Give warning with the name of program and file(if any).
+ -- If there is a global `prog` table, prefix the message with
+ -- `prog.name` or `prog.file`, and `prog.line` if any. Otherwise
+ -- if there is a global `opts` table, prefix the message with
+ -- `opts.program` and `opts.line` if any.
+ -- @function warn
+ -- @string msg format string
+ -- @param ... additional arguments to plug format string specifiers
+ -- @see die
+ -- @usage
+ -- local OptionParser = require 'std.optparse'
+ -- local parser = OptionParser 'eg 0\nUsage: eg\n'
+ -- _G.arg, _G.opts = parser:parse(_G.arg)
+ -- if not _G.opts.keep_going then
+ -- require 'std.io'.warn 'oh noes!'
+ -- end
+ warn = X('warn(string, [any...])', warn),
+
+
+ --- Path Functions
+ -- @section pathfuncs
+
+ --- Concatenate directory names into a path.
+ -- @function catdir
+ -- @string ... path components
+ -- @return path without trailing separator
+ -- @see catfile
+ -- @usage
+ -- dirpath = catdir('', 'absolute', 'directory')
+ catdir = X('catdir(string...)', function(...)
+ return(gsub(concat({...}, dirsep), '^$', dirsep))
+ end),
+
+ --- Concatenate one or more directories and a filename into a path.
+ -- @function catfile
+ -- @string ... path components
+ -- @treturn string path
+ -- @see catdir
+ -- @see splitdir
+ -- @usage
+ -- filepath = catfile('relative', 'path', 'filename')
+ catfile = X('catfile(string...)', catfile),
+
+ --- Remove the last dirsep delimited element from a path.
+ -- @function dirname
+ -- @string path file path
+ -- @treturn string a new path with the last dirsep and following
+ -- truncated
+ -- @usage
+ -- dir = dirname '/base/subdir/filename'
+ dirname = X('dirname(string)', function(path)
+ return(gsub(path, catfile('', '[^', ']*$'), ''))
+ end),
+
+ --- Split a directory path into components.
+ -- Empty components are retained: the root directory becomes `{'', ''}`.
+ -- @function splitdir
+ -- @param path path
+ -- @return list of path components
+ -- @see catdir
+ -- @usage
+ -- dir_components = splitdir(filepath)
+ splitdir = X('splitdir(string)', function(path)
+ return split(path, dirsep)
+ end),
+
+
+ --- IO Functions
+ -- @section iofuncs
+
+ --- Process files specified on the command-line.
+ -- Each filename is made the default input source with `io.input`, and
+ -- then the filename and argument number are passed to the callback
+ -- function. In list of filenames, `-` means `io.stdin`. If no
+ -- filenames were given, behave as if a single `-` was passed.
+ -- @todo Make the file list an argument to the function.
+ -- @function process_files
+ -- @tparam fileprocessor fn function called for each file argument
+ -- @usage
+ -- #! /usr/bin/env lua
+ -- -- minimal cat command
+ -- local io = require 'std.io'
+ -- io.process_files(function() io.write(io.slurp()) end)
+ process_files = X('process_files(function)', process_files),
+
+ --- Read a file or file handle into a list of lines.
+ -- The lines in the returned list are not `\n` terminated.
+ -- @function readlines
+ -- @tparam[opt=io.input()] file|string file file handle or name;
+ -- if file is a file handle, that file is closed after reading
+ -- @treturn list lines
+ -- @usage
+ -- list = readlines '/etc/passwd'
+ readlines = X('readlines(?file|string)', readlines),
+
+ --- Perform a shell command and return its output.
+ -- @function shell
+ -- @string c command
+ -- @treturn string output, or nil if error
+ -- @see os.execute
+ -- @usage
+ -- users = shell [[cat /etc/passwd | awk -F: '{print $1;}']]
+ shell = X('shell(string)', function(c) return slurp(popen(c)) end),
+
+ --- Slurp a file handle.
+ -- @function slurp
+ -- @tparam[opt=io.input()] file|string file file handle or name;
+ -- if file is a file handle, that file is closed after reading
+ -- @return contents of file or handle, or nil if error
+ -- @see process_files
+ -- @usage
+ -- contents = slurp(filename)
+ slurp = X('slurp(?file|string)', slurp),
+
+ --- Write values adding a newline after each.
+ -- @function writelines
+ -- @tparam[opt=io.output()] file h open writable file handle;
+ -- the file is **not** closed after writing
+ -- @tparam string|number ... values to write(as for write)
+ -- @usage
+ -- writelines(io.stdout, 'first line', 'next line')
+ writelines = X('writelines(?file|string|number, [string|number...])', writelines),
+}
+
+
+return merge(io, M)
+
+
+
+--- Types
+-- @section Types
+
+--- Signature of @{process_files} callback function.
+-- @function fileprocessor
+-- @string filename filename
+-- @int i argument number of *filename*
+-- @usage
+-- local fileprocessor = function(filename, i)
+-- io.write(tostring(i) .. ':\n===\n' .. io.slurp(filename) .. '\n')
+-- end
+-- io.process_files(fileprocessor)
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/math.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/math.lua
new file mode 100644
index 0000000..d955862
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/math.lua
@@ -0,0 +1,92 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ Additions to the core math module.
+
+ The module table returned by `std.math` also contains all of the entries from
+ the core math table. An hygienic way to import this module, then, is simply
+ to override the core `math` locally:
+
+ local math = require 'std.math'
+
+ @corelibrary std.math
+]]
+
+
+local _ = require 'std._base'
+
+local argscheck = _.typecheck and _.typecheck.argscheck
+
+_ = nil
+
+
+local _ENV = require 'std.normalize' {
+ 'math',
+ merge = 'table.merge',
+}
+
+
+
+--[[ ================= ]]--
+--[[ Implementatation. ]]--
+--[[ ================= ]]--
+
+
+local M
+
+
+local _floor = math.floor
+
+local function floor(n, p)
+ if(p or 0) == 0 then
+ return _floor(n)
+ end
+ local e = 10 ^ p
+ return _floor(n * e) / e
+end
+
+
+local function round(n, p)
+ local e = 10 ^(p or 0)
+ return _floor(n * e + 0.5) / e
+end
+
+
+
+--[[ ================= ]]--
+--[[ Public Interface. ]]--
+--[[ ================= ]]--
+
+
+local function X(decl, fn)
+ return argscheck and argscheck('std.math.' .. decl, fn) or fn
+end
+
+
+M = {
+ --- Core Functions
+ -- @section corefuncs
+
+ --- Extend `math.floor` to take the number of decimal places.
+ -- @function floor
+ -- @number n number
+ -- @int[opt=0] p number of decimal places to truncate to
+ -- @treturn number `n` truncated to `p` decimal places
+ -- @usage
+ -- tenths = floor(magnitude, 1)
+ floor = X('floor(number, ?int)', floor),
+
+ --- Round a number to a given number of decimal places.
+ -- @function round
+ -- @number n number
+ -- @int[opt=0] p number of decimal places to round to
+ -- @treturn number `n` rounded to `p` decimal places
+ -- @usage
+ -- roughly = round(exactly, 2)
+ round = X('round(number, ?int)', round),
+}
+
+
+return merge(math, M)
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/package.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/package.lua
new file mode 100644
index 0000000..e3e8243
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/package.lua
@@ -0,0 +1,263 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ Additions to the core package module.
+
+ The module table returned by `std.package` also contains all of the entries
+ from the core `package` table. An hygienic way to import this module, then, is
+ simply to override core `package` locally:
+
+ local package = require 'std.package'
+
+ Manage `package.path` with normalization, duplicate removal,
+ insertion & removal of elements and automatic folding of '/' and '?'
+ onto `package.dirsep` and `package.pathmark`, for easy addition of
+ new paths. For example, instead of all this:
+
+ lib = std.io.catfile('.', 'lib', package.pathmark .. '.lua')
+ paths = std.string.split(package.path, package.pathsep)
+ for i, path in ipairs(paths) do
+ -- ... lots of normalization code...
+ end
+ i = 1
+ while i <= #paths do
+ if paths[i] == lib then
+ table.remove(paths, i)
+ else
+ i = i + 1
+ end
+ end
+ table.insert(paths, 1, lib)
+ package.path = table.concat(paths, package.pathsep)
+
+ You can now write just:
+
+ package.path = package.normalize('./lib/?.lua', package.path)
+
+ @corelibrary std.package
+]]
+
+
+local _ = require 'std._base'
+
+local argscheck = _.typecheck and _.typecheck.argscheck
+local catfile = _.io.catfile
+local escape_pattern = _.string.escape_pattern
+local invert = _.table.invert
+local split = _.string.split
+
+_ = nil
+
+local _ENV = require 'std.normalize' {
+ 'package',
+ concat = 'table.concat',
+ dirsep = 'package.dirsep',
+ gsub = 'string.gsub',
+ merge = 'table.merge',
+ pathmark = 'package.pathmark',
+ pathsep = 'package.pathsep',
+ string_find = 'string.find',
+ table_insert = 'table.insert',
+ table_remove = 'table.remove',
+}
+
+
+
+--[[ =============== ]]--
+--[[ Implementation. ]]--
+--[[ =============== ]]--
+
+
+--- Make named constants for `package.config`
+-- (undocumented in 5.1; see luaconf.h for C equivalents).
+-- @table package
+-- @string dirsep directory separator
+-- @string pathsep path separator
+-- @string pathmark string that marks substitution points in a path template
+-- @string execdir(Windows only) replaced by the executable's directory in a path
+-- @string igmark Mark to ignore all before it when building `luaopen_` function name.
+
+
+local function pathsub(path)
+ return gsub(path, '%%?.', function(capture)
+ if capture == '?' then
+ return pathmark
+ elseif capture == '/' then
+ return dirsep
+ else
+ return gsub(capture, '^%%', '', 1)
+ end
+ end)
+end
+
+
+local function find(pathstrings, patt, init, plain)
+ local paths = split(pathstrings, pathsep)
+ if plain then
+ patt = escape_pattern(patt)
+ end
+ init = init or 1
+ if init < 0 then
+ init = #paths - init
+ end
+ for i = init, #paths do
+ if string_find(paths[i], patt) then
+ return i, paths[i]
+ end
+ end
+end
+
+
+local function normalize(...)
+ local i, paths, pathstrings = 1, {}, concat({...}, pathsep)
+ for _, path in ipairs(split(pathstrings, pathsep)) do
+ path = gsub(pathsub(path), catfile('^[^', ']'), catfile('.', '%0'))
+ path = gsub(path, catfile('', '%.', ''), dirsep)
+ path = gsub(path, catfile('', '%.$'), '')
+ path = gsub(path, catfile('^%.', '%..', ''), catfile('..', ''))
+ path = gsub(path, catfile('', '$'), '')
+
+ -- Carefully remove redundant /foo/../ matches.
+ repeat
+ local again = false
+ path = gsub(path, catfile('', '([^', ']+)', '%.%.', ''),
+ function(dir1)
+ if dir1 == '..' then -- don't remove /../../
+ return catfile('', '..', '..', '')
+ else
+ again = true
+ return dirsep
+ end
+ end)
+ path = gsub(path, catfile('', '([^', ']+)', '%.%.$'),
+ function(dir1)
+ if dir1 == '..' then -- don't remove /../..
+ return catfile('', '..', '..')
+ else
+ again = true
+ return ''
+ end
+ end)
+ until again == false
+
+ -- Build an inverted table of elements to eliminate duplicates after
+ -- normalization.
+ if not paths[path] then
+ paths[path], i = i, i + 1
+ end
+ end
+ return concat(invert(paths), pathsep)
+end
+
+
+local function insert(pathstrings, ...)
+ local paths = split(pathstrings, pathsep)
+ table_insert(paths, ...)
+ return normalize(unpack(paths, 1, len(paths)))
+end
+
+
+local function mappath(pathstrings, callback, ...)
+ for _, path in ipairs(split(pathstrings, pathsep)) do
+ local r = callback(path, ...)
+ if r ~= nil then
+ return r
+ end
+ end
+end
+
+
+local function remove(pathstrings, pos)
+ local paths = split(pathstrings, pathsep)
+ table_remove(paths, pos)
+ return concat(paths, pathsep)
+end
+
+
+
+--[[ ================= ]]--
+--[[ Public Interface. ]]--
+--[[ ================= ]]--
+
+
+local function X(decl, fn)
+ return argscheck and argscheck('std.package.' .. decl, fn) or fn
+end
+
+
+local M = {
+ --- Look for a path segment match of *patt* in *pathstrings*.
+ -- @function find
+ -- @string pathstrings `pathsep` delimited path elements
+ -- @string patt a Lua pattern to search for in *pathstrings*
+ -- @int[opt=1] init element(not byte index!) to start search at.
+ -- Negative numbers begin counting backwards from the last element
+ -- @bool[opt=false] plain unless false, treat *patt* as a plain
+ -- string, not a pattern. Note that if *plain* is given, then *init*
+ -- must be given as well.
+ -- @return the matching element number(not byte index!) and full text
+ -- of the matching element, if any; otherwise nil
+ -- @usage
+ -- i, s = find(package.path, '^[^' .. package.dirsep .. '/]')
+ find = X('find(string, string, ?int, ?boolean|:plain)', find),
+
+ --- Insert a new element into a `package.path` like string of paths.
+ -- @function insert
+ -- @string pathstrings a `package.path` like string
+ -- @int[opt=n+1] pos element index at which to insert *value*, where `n` is
+ -- the number of elements prior to insertion
+ -- @string value new path element to insert
+ -- @treturn string a new string with the new element inserted
+ -- @usage
+ -- package.path = insert(package.path, 1, install_dir .. '/?.lua')
+ insert = X('insert(string, [int], string)', insert),
+
+ --- Call a function with each element of a path string.
+ -- @function mappath
+ -- @string pathstrings a `package.path` like string
+ -- @tparam mappathcb callback function to call for each element
+ -- @param ... additional arguments passed to *callback*
+ -- @return nil, or first non-nil returned by *callback*
+ -- @usage
+ -- mappath(package.path, searcherfn, transformfn)
+ mappath = X('mappath(string, function, [any...])', mappath),
+
+ --- Normalize a path list.
+ -- Removing redundant `.` and `..` directories, and keep only the first
+ -- instance of duplicate elements. Each argument can contain any number
+ -- of `pathsep` delimited elements; wherein characters are subject to
+ -- `/` and `?` normalization, converting `/` to `dirsep` and `?` to
+ -- `pathmark`(unless immediately preceded by a `%` character).
+ -- @function normalize
+ -- @param ... path elements
+ -- @treturn string a single normalized `pathsep` delimited paths string
+ -- @usage
+ -- package.path = normalize(user_paths, sys_paths, package.path)
+ normalize = X('normalize(string...)', normalize),
+
+ --- Remove any element from a `package.path` like string of paths.
+ -- @function remove
+ -- @string pathstrings a `package.path` like string
+ -- @int[opt=n] pos element index from which to remove an item, where `n`
+ -- is the number of elements prior to removal
+ -- @treturn string a new string with given element removed
+ -- @usage
+ -- package.path = remove(package.path)
+ remove = X('remove(string, ?int)', remove),
+}
+
+
+return merge(package, M)
+
+
+--- Types
+-- @section Types
+
+--- Function signature of a callback for @{mappath}.
+-- @function mappathcb
+-- @string element an element from a `pathsep` delimited string of
+-- paths
+-- @param ... additional arguments propagated from @{mappath}
+-- @return non-nil to break, otherwise continue with the next element
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/string.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/string.lua
new file mode 100644
index 0000000..6ad9014
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/string.lua
@@ -0,0 +1,505 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ Additions to the core string module.
+
+ The module table returned by `std.string` also contains all of the entries
+ from the core string table. An hygienic way to import this module, then, is
+ simply to override the core `string` locally:
+
+ local string = require 'std.string'
+
+ @corelibrary std.string
+]]
+
+
+local _ = require 'std._base'
+
+local argscheck = _.typecheck and _.std.typecheck.argscheck
+local escape_pattern = _.string.escape_pattern
+local split = _.string.split
+
+_ = nil
+
+
+local _ENV = require 'std.normalize' {
+ 'string',
+ abs = 'math.abs',
+ concat = 'table.concat',
+ find = 'string.find',
+ floor = 'math.floor',
+ format = 'string.format',
+ gsub = 'string.gsub',
+ insert = 'table.insert',
+ match = 'string.match',
+ merge = 'table.merge',
+ render = 'string.render',
+ sort = 'table.sort',
+ sub = 'string.sub',
+ upper = 'string.upper',
+}
+
+
+
+--[[ =============== ]]--
+--[[ Implementation. ]]--
+--[[ =============== ]]--
+
+
+local M
+
+
+local function toqstring(x, xstr)
+ if type(x) ~= 'string' then
+ return xstr
+ end
+ return format('%q', x)
+end
+
+
+local concatvfns = {
+ elem = tostring,
+ term = function(x)
+ return type(x) ~= 'table' or getmetamethod(x, '__tostring')
+ end,
+ sort = function(keys)
+ return keys
+ end,
+ open = function(x) return '{' end,
+ close = function(x) return '}' end,
+ pair = function(x, kp, vp, k, v, kstr, vstr, seqp)
+ return toqstring(k, kstr) .. '=' .. toqstring(v, vstr)
+ end,
+ sep = function(x, kp, vp, kn, vn, seqp)
+ return kp ~= nil and kn ~= nil and ',' or ''
+ end,
+}
+
+
+local function __concat(s, o)
+ -- Don't use normalize.str here, because we don't want ASCII escape rendering.
+ return render(s, concatvfns) .. render(o, concatvfns)
+end
+
+
+local function __index(s, i)
+ if type(i) == 'number' then
+ return sub(s, i, i)
+ else
+ -- Fall back to module metamethods
+ return M[i]
+ end
+end
+
+
+local _format = string.format
+
+local function format(f, arg1, ...)
+ return(arg1 ~= nil) and _format(f, arg1, ...) or f
+end
+
+
+local function tpack(from, to, ...)
+ return from, to, {...}
+end
+
+local function tfind(s, ...)
+ return tpack(find(s, ...))
+end
+
+
+local function finds(s, p, i, ...)
+ i = i or 1
+ local l = {}
+ local from, to, r
+ repeat
+ from, to, r = tfind(s, p, i, ...)
+ if from ~= nil then
+ insert(l, {from, to, capt=r})
+ i = to + 1
+ end
+ until not from
+ return l
+end
+
+
+local function caps(s)
+ return(gsub(s, '(%w)([%w]*)', function(l, ls)
+ return upper(l) .. ls
+ end))
+end
+
+
+local function escape_shell(s)
+ return(gsub(s, '([ %(%)%\\%[%]\'"])', '\\%1'))
+end
+
+
+local function ordinal_suffix(n)
+ n = abs(n) % 100
+ local d = n % 10
+ if d == 1 and n ~= 11 then
+ return 'st'
+ elseif d == 2 and n ~= 12 then
+ return 'nd'
+ elseif d == 3 and n ~= 13 then
+ return 'rd'
+ else
+ return 'th'
+ end
+end
+
+
+local function pad(s, w, p)
+ p = string.rep(p or ' ', abs(w))
+ if w < 0 then
+ return string.sub(p .. s, w)
+ end
+ return string.sub(s .. p, 1, w)
+end
+
+
+local function wrap(s, w, ind, ind1)
+ w = w or 78
+ ind = ind or 0
+ ind1 = ind1 or ind
+ assert(ind1 < w and ind < w,
+ 'the indents must be less than the line width')
+ local r = {string.rep(' ', ind1)}
+ local i, lstart, lens = 1, ind1, len(s)
+ while i <= lens do
+ local j = i + w - lstart
+ while len(s[j]) > 0 and s[j] ~= ' ' and j > i do
+ j = j - 1
+ end
+ local ni = j + 1
+ while s[j] == ' ' do
+ j = j - 1
+ end
+ insert(r, sub(s, i, j))
+ i = ni
+ if i < lens then
+ insert(r, '\n' .. string.rep(' ', ind))
+ lstart = ind
+ end
+ end
+ return concat(r)
+end
+
+
+local function numbertosi(n)
+ local SIprefix = {
+ [-8]='y', [-7]='z', [-6]='a', [-5]='f',
+ [-4]='p', [-3]='n', [-2]='mu', [-1]='m',
+ [0]='', [1]='k', [2]='M', [3]='G',
+ [4]='T', [5]='P', [6]='E', [7]='Z',
+ [8]='Y'
+ }
+ local t = _format('% #.2e', n)
+ local _, _, m, e = find(t, '.(.%...)e(.+)')
+ local man, exp = tonumber(m), tonumber(e)
+ local siexp = floor(exp / 3)
+ local shift = exp - siexp * 3
+ local s = SIprefix[siexp] or 'e' .. tostring(siexp)
+ man = man *(10 ^ shift)
+ return _format('%0.f', man) .. s
+end
+
+
+-- Ordor numbers first then asciibetically.
+local function keycmp(a, b)
+ if type(a) == 'number' then
+ return type(b) ~= 'number' or a < b
+ end
+ return type(b) ~= 'number' and tostring(a) < tostring(b)
+end
+
+
+local render_fallbacks = {
+ __index = concatvfns,
+}
+
+
+local function prettytostring(x, indent, spacing)
+ indent = indent or '\t'
+ spacing = spacing or ''
+ return render(x, setmetatable({
+ elem = function(x)
+ if type(x) ~= 'string' then
+ return tostring(x)
+ end
+ return format('%q', x)
+ end,
+
+ sort = function(keylist)
+ sort(keylist, keycmp)
+ return keylist
+ end,
+
+ open = function()
+ local s = spacing .. '{'
+ spacing = spacing .. indent
+ return s
+ end,
+
+ close = function()
+ spacing = string.gsub(spacing, indent .. '$', '')
+ return spacing .. '}'
+ end,
+
+ pair = function(x, _, _, k, v, kstr, vstr)
+ local type_k = type(k)
+ local s = spacing
+ if type_k ~= 'string' or match(k, '[^%w_]') then
+ s = s .. '['
+ if type_k == 'table' then
+ s = s .. '\n'
+ end
+ s = s .. kstr
+ if type_k == 'table' then
+ s = s .. '\n'
+ end
+ s = s .. ']'
+ else
+ s = s .. k
+ end
+ s = s .. ' ='
+ if type(v) == 'table' then
+ s = s .. '\n'
+ else
+ s = s .. ' '
+ end
+ s = s .. vstr
+ return s
+ end,
+
+ sep = function(_, k)
+ local s = '\n'
+ if k then
+ s = ',' .. s
+ end
+ return s
+ end,
+ }, render_fallbacks))
+end
+
+
+local function trim(s, r)
+ r = r or '%s+'
+ return (gsub(gsub(s, '^' .. r, ''), r .. '$', ''))
+end
+
+
+
+--[[ ================= ]]--
+--[[ Public Interface. ]]--
+--[[ ================= ]]--
+
+
+local function X(decl, fn)
+ return argscheck and argscheck('std.string.' .. decl, fn) or fn
+end
+
+M = {
+ --- Metamethods
+ -- @section metamethods
+
+ --- String concatenation operation.
+ -- @function __concat
+ -- @string s initial string
+ -- @param o object to stringify and concatenate
+ -- @return s .. tostring(o)
+ -- @usage
+ -- local string = setmetatable('', require 'std.string')
+ -- concatenated = 'foo' .. {'bar'}
+ __concat = __concat,
+
+ --- String subscript operation.
+ -- @function __index
+ -- @string s string
+ -- @tparam int|string i index or method name
+ -- @return `sub(s, i, i)` if i is a number, otherwise
+ -- fall back to a `std.string` metamethod(if any).
+ -- @usage
+ -- getmetatable('').__index = require 'std.string'.__index
+ -- third =('12345')[3]
+ __index = __index,
+
+
+ --- Core Functions
+ -- @section corefuncs
+
+ --- Capitalise each word in a string.
+ -- @function caps
+ -- @string s any string
+ -- @treturn string *s* with each word capitalized
+ -- @usage
+ -- userfullname = caps(input_string)
+ caps = X('caps(string)', caps),
+
+ --- Remove any final newline from a string.
+ -- @function chomp
+ -- @string s any string
+ -- @treturn string *s* with any single trailing newline removed
+ -- @usage
+ -- line = chomp(line)
+ chomp = X('chomp(string)', function(s)
+ return(gsub(s, '\n$', ''))
+ end),
+
+ --- Escape a string to be used as a pattern.
+ -- @function escape_pattern
+ -- @string s any string
+ -- @treturn string *s* with active pattern characters escaped
+ -- @usage
+ -- substr = match(inputstr, escape_pattern(literal))
+ escape_pattern = X('escape_pattern(string)', escape_pattern),
+
+ --- Escape a string to be used as a shell token.
+ -- Quotes spaces, parentheses, brackets, quotes, apostrophes and
+ -- whitespace.
+ -- @function escape_shell
+ -- @string s any string
+ -- @treturn string *s* with active shell characters escaped
+ -- @usage
+ -- os.execute('echo ' .. escape_shell(outputstr))
+ escape_shell = X('escape_shell(string)', escape_shell),
+
+ --- Repeatedly `string.find` until target string is exhausted.
+ -- @function finds
+ -- @string s target string
+ -- @string pattern pattern to match in *s*
+ -- @int[opt=1] init start position
+ -- @bool[opt] plain inhibit magic characters
+ -- @return list of `{from, to; capt={captures}}`
+ -- @see std.string.tfind
+ -- @usage
+ -- for t in std.elems(finds('the target string', '%S+')) do
+ -- print(tostring(t.capt))
+ -- end
+ finds = X('finds(string, string, ?int, ?boolean|:plain)', finds),
+
+ --- Extend to work better with one argument.
+ -- If only one argument is passed, no formatting is attempted.
+ -- @function format
+ -- @string f format string
+ -- @param[opt] ... arguments to format
+ -- @return formatted string
+ -- @usage
+ -- print(format '100% stdlib!')
+ format = X('format(string, [any...])', format),
+
+ --- Remove leading matter from a string.
+ -- @function ltrim
+ -- @string s any string
+ -- @string[opt='%s+'] r leading pattern
+ -- @treturn string *s* with leading *r* stripped
+ -- @usage
+ -- print('got: ' .. ltrim(userinput))
+ ltrim = X('ltrim(string, ?string)', function(s, r)
+ return (gsub(s, '^' ..(r or '%s+'), ''))
+ end),
+
+ --- Write a number using SI suffixes.
+ -- The number is always written to 3 s.f.
+ -- @function numbertosi
+ -- @tparam number|string n any numeric value
+ -- @treturn string *n* simplifed using largest available SI suffix.
+ -- @usage
+ -- print(numbertosi(bitspersecond) .. 'bps')
+ numbertosi = X('numbertosi(number|string)', numbertosi),
+
+ --- Return the English suffix for an ordinal.
+ -- @function ordinal_suffix
+ -- @tparam int|string n any integer value
+ -- @treturn string English suffix for *n*
+ -- @usage
+ -- local now = os.date '*t'
+ -- print('%d%s day of the week', now.day, ordinal_suffix(now.day))
+ ordinal_suffix = X('ordinal_suffix(int|string)', ordinal_suffix),
+
+ --- Justify a string.
+ -- When the string is longer than w, it is truncated(left or right
+ -- according to the sign of w).
+ -- @function pad
+ -- @string s a string to justify
+ -- @int w width to justify to(-ve means right-justify; +ve means
+ -- left-justify)
+ -- @string[opt=' '] p string to pad with
+ -- @treturn string *s* justified to *w* characters wide
+ -- @usage
+ -- print(pad(trim(outputstr, 78)) .. '\n')
+ pad = X('pad(string, int, ?string)', pad),
+
+ --- Pretty-print a table, or other object.
+ -- @function prettytostring
+ -- @param x object to convert to string
+ -- @string[opt='\t'] indent indent between levels
+ -- @string[opt=''] spacing space before every line
+ -- @treturn string pretty string rendering of *x*
+ -- @usage
+ -- print(prettytostring(std, ' '))
+ prettytostring = X('prettytostring(?any, ?string, ?string)', prettytostring),
+
+ --- Remove trailing matter from a string.
+ -- @function rtrim
+ -- @string s any string
+ -- @string[opt='%s+'] r trailing pattern
+ -- @treturn string *s* with trailing *r* stripped
+ -- @usage
+ -- print('got: ' .. rtrim(userinput))
+ rtrim = X('rtrim(string, ?string)', function(s, r)
+ return (gsub(s, (r or '%s+') .. '$', ''))
+ end),
+
+ --- Split a string at a given separator.
+ -- Separator is a Lua pattern, so you have to escape active characters,
+ -- `^$()%.[]*+-?` with a `%` prefix to match a literal character in *s*.
+ -- @function split
+ -- @string s to split
+ -- @string[opt='%s+'] sep separator pattern
+ -- @return list of strings
+ -- @usage
+ -- words = split 'a very short sentence'
+ split = X('split(string, ?string)', split),
+
+ --- Do `string.find`, returning a table of captures.
+ -- @function tfind
+ -- @string s target string
+ -- @string pattern pattern to match in *s*
+ -- @int[opt=1] init start position
+ -- @bool[opt] plain inhibit magic characters
+ -- @treturn int start of match
+ -- @treturn int end of match
+ -- @treturn table list of captured strings
+ -- @see std.string.finds
+ -- @usage
+ -- b, e, captures = tfind('the target string', '%s', 10)
+ tfind = X('tfind(string, string, ?int, ?boolean|:plain)', tfind),
+
+ --- Remove leading and trailing matter from a string.
+ -- @function trim
+ -- @string s any string
+ -- @string[opt='%s+'] r trailing pattern
+ -- @treturn string *s* with leading and trailing *r* stripped
+ -- @usage
+ -- print('got: ' .. trim(userinput))
+ trim = X('trim(string, ?string)', trim),
+
+ --- Wrap a string into a paragraph.
+ -- @function wrap
+ -- @string s a paragraph of text
+ -- @int[opt=78] w width to wrap to
+ -- @int[opt=0] ind indent
+ -- @int[opt=ind] ind1 indent of first line
+ -- @treturn string *s* wrapped to *w* columns
+ -- @usage
+ -- print(wrap(copyright, 72, 4))
+ wrap = X('wrap(string, ?int, ?int, ?int)', wrap),
+}
+
+
+return merge(string, M)
+
diff --git a/Data/BuiltIn/Libraries/lua-stdlib/lib/std/table.lua b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/table.lua
new file mode 100644
index 0000000..7bda608
--- /dev/null
+++ b/Data/BuiltIn/Libraries/lua-stdlib/lib/std/table.lua
@@ -0,0 +1,439 @@
+--[[
+ General Lua Libraries for Lua 5.1, 5.2 & 5.3
+ Copyright (C) 2002-2018 stdlib authors
+]]
+--[[--
+ Extensions to the core table module.
+
+ The module table returned by `std.table` also contains all of the entries from
+ the core table module. An hygienic way to import this module, then, is simply
+ to override the core `table` locally:
+
+ local table = require 'std.table'
+
+ @corelibrary std.table
+]]
+
+
+local _ = require 'std._base'
+
+local argscheck = _.typecheck and _.typecheck.argscheck
+local invert = _.table.invert
+local maxn = _.table.maxn
+
+_ = nil
+
+local _ENV = require 'std.normalize' {
+ 'table',
+ merge = 'table.merge',
+ min = 'math.min',
+}
+
+
+
+--[[ =============== ]]--
+--[[ Implementation. ]]--
+--[[ =============== ]]--
+
+
+local M
+
+
+local function merge_allfields(t, u, map, nometa)
+ if type(map) ~= 'table' then
+ map, nometa = nil, map
+ end
+
+ if not nometa then
+ setmetatable(t, getmetatable(u))
+ end
+ if map then
+ for k, v in pairs(u) do
+ t[map[k] or k] = v
+ end
+ else
+ for k, v in pairs(u) do
+ t[k] = v
+ end
+ end
+ return t
+end
+
+
+local function merge_namedfields(t, u, keys, nometa)
+ if type(keys) ~= 'table' then
+ keys, nometa = nil, keys
+ end
+
+ if not nometa then
+ setmetatable(t, getmetatable(u))
+ end
+ for _, k in pairs(keys or {}) do
+ t[k] = u[k]
+ end
+ return t
+end
+
+
+local function depair(ls)
+ local t = {}
+ for _, v in ipairs(ls) do
+ t[v[1]] = v[2]
+ end
+ return t
+end
+
+
+local function enpair(t)
+ local tt = {}
+ for i, v in pairs(t) do
+ tt[#tt + 1] = {i, v}
+ end
+ return tt
+end
+
+
+local _insert = table.insert
+
+local function insert(t, pos, v)
+ if v == nil then
+ pos, v = len(t) + 1, pos
+ end
+ if pos < 1 or pos > len(t) + 1 then
+ argerror('std.table.insert', 2, 'position ' .. pos .. ' out of bounds', 2)
+ end
+ _insert(t, pos, v)
+ return t
+end
+
+
+local function keys(t)
+ local l = {}
+ for k in pairs(t) do
+ l[#l + 1] = k
+ end
+ return l
+end
+
+
+local function new(x, t)
+ return setmetatable(t or {}, {__index = function(t, i)
+ return x
+ end})
+end
+
+
+local function project(fkey, tt)
+ local r = {}
+ for _, t in ipairs(tt) do
+ r[#r + 1] = t[fkey]
+ end
+ return r
+end
+
+
+local function size(t)
+ local n = 0
+ for _ in pairs(t) do
+ n = n + 1
+ end
+ return n
+end
+
+
+-- Preserve core table sort function.
+local _sort = table.sort
+
+local function sort(t, c)
+ _sort(t, c)
+ return t
+end
+
+
+local _remove = table.remove
+
+local function remove(t, pos)
+ local lent = len(t)
+ pos = pos or lent
+ if pos < min(1, lent) or pos > lent + 1 then -- +1? whu? that's what 5.2.3 does!?!
+ argerror('std.table.remove', 2, 'position ' .. pos .. ' out of bounds', 2)
+ end
+ return _remove(t, pos)
+end
+
+
+local _unpack = unpack
+
+local function unpack(t, i, j)
+ if j == nil then
+ -- if j was not given, respect __len, otherwise use maxn
+ local m = getmetamethod(t, '__len')
+ j = m and m(t) or maxn(t)
+ end
+ return _unpack(t, tonumber(i) or 1, tonumber(j))
+end
+
+
+local function values(t)
+ local l = {}
+ for _, v in pairs(t) do
+ l[#l + 1] = v
+ end
+ return l
+end
+
+
+
+--[[ ================= ]]--
+--[[ Public Interface. ]]--
+--[[ ================= ]]--
+
+
+local function X(decl, fn)
+ return argscheck and argscheck('std.table.' .. decl, fn) or fn
+end
+
+M = {
+ --- Core Functions
+ -- @section corefuncs
+
+ --- Enhance core *table.insert* to return its result.
+ -- If *pos* is not given, respect `__len` metamethod when calculating
+ -- default append. Also, diagnose out of bounds *pos* arguments
+ -- consistently on any supported version of Lua.
+ -- @function insert
+ -- @tparam table t a table
+ -- @int[opt=len(t)] pos index at which to insert new element
+ -- @param v value to insert into *t*
+ -- @treturn table *t*
+ -- @usage
+ -- --> {1, 'x', 2, 3, 'y'}
+ -- insert(insert({1, 2, 3}, 2, 'x'), 'y')
+ insert = X('insert(table, [int], any)', insert),
+
+ --- Largest integer key in a table.
+ -- @function maxn
+ -- @tparam table t a table
+ -- @treturn int largest integer key in *t*
+ -- @usage
+ -- --> 42
+ -- maxn {'a', b='c', 99, [42]='x', 'x', [5]=67}
+ maxn = X('maxn(table)', maxn),
+
+ --- Turn a tuple into a list, with tuple-size in field `n`
+ -- @function pack
+ -- @param ... tuple
+ -- @return list-like table, with tuple-size in field `n`
+ -- @usage
+ -- --> {1, 2, 'ax', n=3}
+ -- pack(find('ax1', '(%D+)'))
+ pack = pack,
+
+ --- Enhance core *table.remove* to respect `__len` when *pos* is omitted.
+ -- Also, diagnose out of bounds *pos* arguments consistently on any supported
+ -- version of Lua.
+ -- @function remove
+ -- @tparam table t a table
+ -- @int[opt=len(t)] pos index from which to remove an element
+ -- @return removed value, or else `nil`
+ -- @usage
+ -- --> {1, 2, 5}
+ -- t = {1, 2, 'x', 5}
+ -- remove(t, 3) == 'x' and t
+ remove = X('remove(table, ?int)', remove),
+
+ --- Enhance core *table.sort* to return its result.
+ -- @function sort
+ -- @tparam table t unsorted table
+ -- @tparam[opt=std.operator.lt] comparator c ordering function callback
+ -- @return *t* with keys sorted according to *c*
+ -- @usage
+ -- table.concat(sort(object))
+ sort = X('sort(table, ?function)', sort),
+
+ --- Enhance core *table.unpack* to always unpack up to __len or maxn.
+ -- @function unpack
+ -- @tparam table t table to act on
+ -- @int[opt=1] i first index to unpack
+ -- @int[opt=table.maxn(t)] j last index to unpack
+ -- @return ... values of numeric indices of *t*
+ -- @usage
+ -- return unpack(results_table)
+ unpack = X('unpack(table, ?int, ?int)', unpack),
+
+
+ --- Accessor Functions
+ -- @section accessorfuncs
+
+ --- Make a shallow copy of a table, including any metatable.
+ -- @function clone
+ -- @tparam table t source table
+ -- @tparam[opt={}] table map table of `{old_key=new_key, ...}`
+ -- @bool[opt] nometa if non-nil don't copy metatable
+ -- @return copy of *t*, also sharing *t*'s metatable unless *nometa*
+ -- is true, and with keys renamed according to *map*
+ -- @see merge
+ -- @see clone_select
+ -- @usage
+ -- shallowcopy = clone(original, {rename_this='to_this'}, ':nometa')
+ clone = X('clone(table, [table], ?boolean|:nometa)', function(...)
+ return merge_allfields({}, ...)
+ end),
+
+ --- Make a partial clone of a table.
+ --
+ -- Like `clone`, but does not copy any fields by default.
+ -- @function clone_select
+ -- @tparam table t source table
+ -- @tparam[opt={}] table keys list of keys to copy
+ -- @bool[opt] nometa if non-nil don't copy metatable
+ -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s
+ -- metatable unless *nometa*
+ -- @see clone
+ -- @see merge_select
+ -- @usage
+ -- partialcopy = clone_select(original, {'this', 'and_this'}, true)
+ clone_select = X('clone_select(table, [table], ?boolean|:nometa)', function(...)
+ return merge_namedfields({}, ...)
+ end),
+
+ --- Turn a list of pairs into a table.
+ -- @todo Find a better name.
+ -- @function depair
+ -- @tparam table ls list of lists
+ -- @treturn table a flat table with keys and values from *ls*
+ -- @see enpair
+ -- @usage
+ -- --> {a=1, b=2, c=3}
+ -- depair {{'a', 1}, {'b', 2}, {'c', 3}}
+ depair = X('depair(list of lists)', depair),
+
+ --- Turn a table into a list of pairs.
+ -- @todo Find a better name.
+ -- @function enpair
+ -- @tparam table t a table `{i1=v1, ..., in=vn}`
+ -- @treturn table a new list of pairs containing `{{i1, v1}, ..., {in, vn}}`
+ -- @see depair
+ -- @usage
+ -- --> {{1, 'a'}, {2, 'b'}, {3, 'c'}}
+ -- enpair {'a', 'b', 'c'}
+ enpair = X('enpair(table)', enpair),
+
+ --- Return whether table is empty.
+ -- @function empty
+ -- @tparam table t any table
+ -- @treturn boolean `true` if *t* is empty, otherwise `false`
+ -- @usage
+ -- if empty(t) then error 'ohnoes' end
+ empty = X('empty(table)', function(t)
+ return not next(t)
+ end),
+
+ --- Make a table with a default value for unset keys.
+ -- @function new
+ -- @param[opt=nil] x default entry value
+ -- @tparam[opt={}] table t initial table
+ -- @treturn table table whose unset elements are *x*
+ -- @usage
+ -- t = new(0)
+ new = X('new(?any, ?table)', new),
+
+ --- Project a list of fields from a list of tables.
+ -- @function project
+ -- @param fkey field to project
+ -- @tparam table tt a list of tables
+ -- @treturn table list of *fkey* fields from *tt*
+ -- @usage
+ -- --> {1, 3, 'yy'}
+ -- project('xx', {{'a', xx=1, yy='z'}, {'b', yy=2}, {'c', xx=3}, {xx='yy'})
+ project = X('project(any, list of tables)', project),
+
+ --- Find the number of elements in a table.
+ -- @function size
+ -- @tparam table t any table
+ -- @treturn int number of non-nil values in *t*
+ -- @usage
+ -- --> 3
+ -- size {foo=true, bar=true, baz=false}
+ size = X('size(table)', size),
+
+ --- Make the list of values of a table.
+ -- @function values
+ -- @tparam table t any table
+ -- @treturn table list of values in *t*
+ -- @see keys
+ -- @usage
+ -- --> {'a', 'c', 42}
+ -- values {'a', b='c', [-1]=42}
+ values = X('values(table)', values),
+
+
+ --- Mutator Functions
+ -- @section mutatorfuncs
+
+ --- Invert a table.
+ -- @function invert
+ -- @tparam table t a table with `{k=v, ...}`
+ -- @treturn table inverted table `{v=k, ...}`
+ -- @usage
+ -- --> {a=1, b=2, c=3}
+ -- invert {'a', 'b', 'c'}
+ invert = X('invert(table)', invert),
+
+ --- Make the list of keys in table.
+ -- @function keys
+ -- @tparam table t a table
+ -- @treturn table list of keys from *t*
+ -- @see values
+ -- @usage
+ -- globals = keys(_G)
+ keys = X('keys(table)', keys),
+
+ --- Destructively merge one table's fields into another.
+ -- @function merge
+ -- @tparam table t destination table
+ -- @tparam table u table with fields to merge
+ -- @tparam[opt={}] table map table of `{old_key=new_key, ...}`
+ -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable
+ -- @treturn table *t* with fields from *u* merged in
+ -- @see clone
+ -- @see merge_select
+ -- @usage
+ -- merge(_G, require 'std.debug', {say='log'}, ':nometa')
+ merge = X('merge(table, table, [table], ?boolean|:nometa)', merge_allfields),
+
+ --- Destructively merge another table's named fields into *table*.
+ --
+ -- Like `merge`, but does not merge any fields by default.
+ -- @function merge_select
+ -- @tparam table t destination table
+ -- @tparam table u table with fields to merge
+ -- @tparam[opt={}] table keys list of keys to copy
+ -- @bool[opt] nometa if `true` or ':nometa' don't copy metatable
+ -- @treturn table copy of fields in *selection* from *t*, also sharing *t*'s
+ -- metatable unless *nometa*
+ -- @see merge
+ -- @see clone_select
+ -- @usage
+ -- merge_select(_G, require 'std.debug', {'say'}, false)
+ merge_select = X('merge_select(table, table, [table], ?boolean|:nometa)',
+ merge_namedfields),
+}
+
+
+return merge(table, M)
+
+
+
+--- Types
+-- @section Types
+
+--- Signature of a @{sort} comparator function.
+-- @function comparator
+-- @param a any object
+-- @param b any object
+-- @treturn boolean `true` if *a* sorts before *b*, otherwise `false`
+-- @see sort
+-- @usage
+-- local reversor = function(a, b) return a > b end
+-- sort(t, reversor)