1--[[--
2 Lua Standard Libraries.
3
4 This module contains a selection of improved Lua core functions, among
5 others.
6
7 Also, after requiring this module, simply referencing symbols in the
8 submodule hierarchy will load the necessary modules on demand.
9
10 By default there are no changes to any global symbols, or monkey
11 patching of core module tables and metatables.  However, sometimes it's
12 still convenient to do that: For example, when using stdlib from the
13 REPL, or in a prototype where you want to throw caution to the wind and
14 compatibility with other modules be damned. In that case, you can give
15 `stdlib` permission to scribble all over your namespaces by using the
16 various `monkey_patch` calls in the library.
17
18 @todo Write a style guide (indenting/wrapping, capitalisation,
19   function and variable names); library functions should call
20   error, not die; OO vs non-OO (a thorny problem).
21 @todo pre-compile.
22 @module std
23]]
24
25
26local base = require "std.base"
27
28local M, monkeys
29
30
31local function monkey_patch (namespace)
32  base.copy (namespace or _G, monkeys)
33  return M
34end
35
36
37local function barrel (namespace)
38  namespace = namespace or _G
39
40  -- Older releases installed the following into _G by default.
41  for _, name in pairs {
42    "functional.bind", "functional.collect", "functional.compose",
43    "functional.curry", "functional.filter", "functional.id",
44    "functional.map",
45
46    "io.die", "io.warn",
47
48    "string.pickle", "string.prettytostring", "string.render",
49
50    "table.pack",
51
52    "tree.ileaves", "tree.inodes", "tree.leaves", "tree.nodes",
53  } do
54    local module, method = name:match "^(.*)%.(.-)$"
55    namespace[method] = M[module][method]
56  end
57
58  -- Support old api names, for backwards compatibility.
59  namespace.fold = M.functional.fold
60  namespace.metamethod = M.getmetamethod
61  namespace.op = M.operator
62  namespace.require_version = M.require
63
64  require "std.io".monkey_patch (namespace)
65  require "std.math".monkey_patch (namespace)
66  require "std.string".monkey_patch (namespace)
67  require "std.table".monkey_patch (namespace)
68
69  return monkey_patch (namespace)
70end
71
72
73
74--- Module table.
75--
76-- In addition to the functions documented on this page, and a `version`
77-- field, references to other submodule functions will be loaded on
78-- demand.
79-- @table std
80-- @field version release version string
81
82local function X (decl, fn)
83  return require "std.debug".argscheck ("std." .. decl, fn)
84end
85
86M = {
87  --- Enhance core `assert` to also allow formatted arguments.
88  -- @function assert
89  -- @param expect expression, expected to be *truthy*
90  -- @string[opt=""] f format string
91  -- @param[opt] ... arguments to format
92  -- @return value of *expect*, if *truthy*
93  -- @usage
94  -- std.assert (expected ~= nil, "100% unexpected!")
95  -- std.assert (expected ~= nil, "%s unexpected!", expected)
96  assert = X ("assert (?any, ?string, [any...])", base.assert),
97
98  --- A [barrel of monkey_patches](http://dictionary.reference.com/browse/barrel+of+monkeys).
99  --
100  -- Apply **all** `monkey_patch` functions.  Additionally, for backwards
101  -- compatibility only, write a selection of sub-module functions into
102  -- the given namespace.
103  -- @function barrel
104  -- @tparam[opt=_G] table namespace where to install global functions
105  -- @treturn table module table
106  -- @usage local std = require "std".barrel ()
107  barrel = X ("barrel (?table)", barrel),
108
109  --- An iterator over all elements of a sequence.
110  -- If *t* has a `__pairs` metamethod, use that to iterate.
111  -- @function elems
112  -- @tparam table t a table
113  -- @treturn function iterator function
114  -- @treturn table *t*, the table being iterated over
115  -- @return *key*, the previous iteration key
116  -- @see ielems
117  -- @see pairs
118  -- @usage
119  -- for value in std.elems {a = 1, b = 2, c = 5} do process (value) end
120  elems = X ("elems (table)", base.elems),
121
122  --- Evaluate a string as Lua code.
123  -- @function eval
124  -- @string s string of Lua code
125  -- @return result of evaluating `s`
126  -- @usage std.eval "math.min (2, 10)"
127  eval = X ("eval (string)", base.eval),
128
129  --- An iterator over the integer keyed elements of a sequence.
130  -- If *t* has a `__len` metamethod, iterate up to the index it returns.
131  -- @function ielems
132  -- @tparam table t a table
133  -- @treturn function iterator function
134  -- @treturn table *t*, the table being iterated over
135  -- @treturn int *index*, the previous iteration index
136  -- @see elems
137  -- @see ipairs
138  -- @usage
139  -- for v in std.ielems {"a", "b", "c"} do process (v) end
140  ielems = X ("ielems (table)", base.ielems),
141
142  --- An iterator over elements of a sequence, until the first `nil` value.
143  --
144  -- Like Lua 5.1 and 5.3, but unlike Lua 5.2 (which looks for and uses the
145  -- `__ipairs` metamethod), this iterator returns successive key-value
146  -- pairs with integer keys starting at 1, up to the first `nil` valued
147  -- pair.
148  -- @function ipairs
149  -- @tparam table t a table
150  -- @treturn function iterator function
151  -- @treturn table *t*, the table being iterated over
152  -- @treturn int *index*, the previous iteration index
153  -- @see ielems
154  -- @see npairs
155  -- @see pairs
156  -- @usage
157  -- -- length of sequence
158  -- args = {"first", "second", nil, "last"}
159  -- --> 1=first
160  -- --> 2=second
161  -- for i, v in std.ipairs (args) do
162  --   print (string.format ("%d=%s", i, v))
163  -- end
164  ipairs = X ("ipairs (table)", base.ipairs),
165
166  --- Return a new table with element order reversed.
167  -- Apart from the order of the elments returned, this function follows
168  -- the same rules as @{ipairs} for determining first and last elements.
169  -- @function ireverse
170  -- @tparam table t a table
171  -- @treturn table a new table with integer keyed elements in reverse
172  --   order with respect to *t*
173  -- @see ielems
174  -- @see ipairs
175  -- @usage
176  -- local rielems = std.functional.compose (std.ireverse, std.ielems)
177  -- for e in rielems (l) do process (e) end
178  ireverse = X ("ireverse (table)", base.ireverse),
179
180  --- Return named metamethod, if any, otherwise `nil`.
181  -- @function getmetamethod
182  -- @param x item to act on
183  -- @string n name of metamethod to lookup
184  -- @treturn function|nil metamethod function, or `nil` if no metamethod
185  -- @usage lookup = std.getmetamethod (require "std.object", "__index")
186  getmetamethod = X ("getmetamethod (?any, string)", base.getmetamethod),
187
188  --- Overwrite core methods and metamethods with `std` enhanced versions.
189  --
190  -- Write all functions from this module, except `std.barrel` and
191  -- `std.monkey_patch`, into the given namespace.
192  -- @function monkey_patch
193  -- @tparam[opt=_G] table namespace where to install global functions
194  -- @treturn table the module table
195  -- @usage local std = require "std".monkey_patch ()
196  monkey_patch = X ("monkey_patch (?table)", monkey_patch),
197
198  --- Ordered iterator for integer keyed values.
199  -- Like ipairs, but does not stop until the largest integer key.
200  -- @function npairs
201  -- @tparam table t a table
202  -- @treturn function iterator function
203  -- @treturn table t
204  -- @see ipairs
205  -- @see rnpairs
206  -- @usage
207  -- for i,v in npairs {"one", nil, "three"} do ... end
208  npairs = X ("npairs (table)", base.npairs),
209
210  --- Enhance core `pairs` to respect `__pairs` even in Lua 5.1.
211  -- @function pairs
212  -- @tparam table t a table
213  -- @treturn function iterator function
214  -- @treturn table *t*, the table being iterated over
215  -- @return *key*, the previous iteration key
216  -- @see elems
217  -- @see ipairs
218  -- @usage
219  -- for k, v in pairs {"a", b = "c", foo = 42} do process (k, v) end
220  pairs = X ("pairs (table)", base.pairs),
221
222  --- Enhance core `require` to assert version number compatibility.
223  -- By default match against the last substring of (dot-delimited)
224  -- digits in the module version string.
225  -- @function require
226  -- @string module module to require
227  -- @string[opt] min lowest acceptable version
228  -- @string[opt] too_big lowest version that is too big
229  -- @string[opt] pattern to match version in `module.version` or
230  --  `module._VERSION` (default: `"([%.%d]+)%D*$"`)
231  -- @usage
232  -- -- posix.version == "posix library for Lua 5.2 / 32"
233  -- posix = require ("posix", "29")
234  require = X ("require (string, ?string, ?string, ?string)", base.require),
235
236  --- An iterator like ipairs, but in reverse.
237  -- Apart from the order of the elments returned, this function follows
238  -- the same rules as @{ipairs} for determining first and last elements.
239  -- @function ripairs
240  -- @tparam table t any table
241  -- @treturn function iterator function
242  -- @treturn table *t*
243  -- @treturn number `#t + 1`
244  -- @see ipairs
245  -- @see rnpairs
246  -- @usage for i, v = ripairs (t) do ... end
247  ripairs = X ("ripairs (table)", base.ripairs),
248
249  --- An iterator like npairs, but in reverse.
250  -- Apart from the order of the elments returned, this function follows
251  -- the same rules as @{npairs} for determining first and last elements.
252  -- @function rnpairs
253  -- @tparam table t a table
254  -- @treturn function iterator function
255  -- @treturn table t
256  -- @see npairs
257  -- @see ripairs
258  -- @usage
259  -- for i,v in rnpairs {"one", nil, "three"} do ... end
260  rnpairs = X ("rnpairs (table)", base.rnpairs),
261
262  --- Enhance core `tostring` to render table contents as a string.
263  -- @function tostring
264  -- @param x object to convert to string
265  -- @treturn string compact string rendering of *x*
266  -- @usage
267  -- -- {1=baz,foo=bar}
268  -- print (std.tostring {foo="bar","baz"})
269  tostring = X ("tostring (?any)", base.tostring),
270
271  version = "General Lua libraries / @VERSION@",
272}
273
274
275monkeys = base.copy ({}, M)
276
277-- Don't monkey_patch these apis into _G!
278for _, api in ipairs {"barrel", "monkey_patch", "version"} do
279  monkeys[api] = nil
280end
281
282
283--- Metamethods
284-- @section Metamethods
285
286return setmetatable (M, {
287  --- Lazy loading of stdlib modules.
288  -- Don't load everything on initial startup, wait until first attempt
289  -- to access a submodule, and then load it on demand.
290  -- @function __index
291  -- @string name submodule name
292  -- @treturn table|nil the submodule that was loaded to satisfy the missing
293  --   `name`, otherwise `nil` if nothing was found
294  -- @usage
295  -- local std = require "std"
296  -- local prototype = std.object.prototype
297  __index = function (self, name)
298              local ok, t = pcall (require, "std." .. name)
299              if ok then
300		rawset (self, name, t)
301		return t
302	      end
303	    end,
304})
305