------ -- @module std.base -- Doc-commented in table.lua... local function clone (t, nometa) local u = {} if not nometa then setmetatable (u, getmetatable (t)) end for i, v in pairs (t) do u[i] = v end return u end -- Doc-commented in table.lua... local function clone_rename (map, t) local r = clone (t) for i, v in pairs (map) do r[v] = t[i] r[i] = nil end return r end -- Doc-commented in table.lua... local function merge (t, u) for i, v in pairs (u) do t[i] = v end return t end local new -- forward declaration -- Doc-commented in list.lua... local function append (l, x) local r = {unpack (l)} table.insert (r, x) return r end -- Doc-commented in list.lua... local function compare (l, m) for i = 1, math.min (#l, #m) do if l[i] < m[i] then return -1 elseif l[i] > m[i] then return 1 end end if #l < #m then return -1 elseif #l > #m then return 1 end return 0 end -- Doc-commented in list.lua... local function elems (l) local n = 0 return function (l) n = n + 1 if n <= #l then return l[n] end end, l, true end --- Concatenate lists. -- @param ... lists -- @return `{l1[1], ..., -- l1[#l1], ..., ln[1], ..., -- ln[#ln]}` local function concat (...) local r = new () for l in elems ({...}) do for v in elems (l) do table.insert (r, v) end end return r 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 coroutine.yield (n) end end return coroutine.wrap (visit), tr end -- Metamethods for lists -- It would be nice to define this in `list.lua`, but then we -- couldn't keep `new` here, and other modules that really only -- need `list.new` (as opposed to the entire `std.list` API) get -- caught in a dependency loop. local metatable = { -- list .. table = list.concat __concat = concat, -- list == list retains its referential meaning -- -- list < list = list.compare returns < 0 __lt = function (l, m) return compare (l, m) < 0 end, -- list <= list = list.compare returns <= 0 __le = function (l, m) return compare (l, m) <= 0 end, __append = append, } --- List constructor. -- Needed in order to use metamethods. -- @param t list (as a table), or nil for empty list -- @return list (with list metamethods) function new (t) return setmetatable (t or {}, metatable) end -- Doc-commented in tree.lua... local function ileaves (tr) assert (type (tr) == "table", "bad argument #1 to 'ileaves' (table expected, got " .. type (tr) .. ")") return _leaves (ipairs, tr) end -- Doc-commented in tree.lua... local function leaves (tr) assert (type (tr) == "table", "bad argument #1 to 'leaves' (table expected, got " .. type (tr) .. ")") return _leaves (pairs, tr) end local M = { append = append, clone = clone, clone_rename = clone_rename, compare = compare, concat = concat, elems = elems, ileaves = ileaves, leaves = leaves, merge = merge, new = new, -- list metatable _list_mt = metatable, } return M