Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- libt can be invoked as a script to force
- -- clean the modules cache.
- local args = {...}
- local forceReload = args[1]
- -- Initialize the T module
- local t = {}
- -- Set up the versioning system
- t.Version = {}
- t.Version.le = function(a, b)
- for v1, v2 in t.imap(
- t.from(t.zip(a, b)),
- unpack
- ) do
- if v1 < v2 then
- return true
- elseif v1 > v2 then
- return false
- end
- end
- -- then they are equal
- return true
- end
- t.Version.lt = function(a, b)
- for v1, v2 in t.imap(
- t.from(t.zip(a, b)),
- unpack
- ) do
- if v1 < v2 then
- return true
- elseif v1 > v2 then
- return false
- end
- end
- -- then they are equal
- return false
- end
- t.Version.eq = function(a, b)
- return t.all(
- t.zip(a, b),
- function(v1, v2)
- return v1 == v2
- end
- )
- end
- t.Version.gt = function(a, b)
- return not t.Version.le(a, b)
- end
- t.Version.ge = function(a, b)
- return not t.Version.lt(a, b)
- end
- -- | The version of libt
- t.VERSION = { 0, 1, 0, 0 }
- -- Initialize the modules cache and check
- -- whether libt is already loaded.
- --
- -- libt is the only library that gets stored
- -- *directly* into the libtmodules cache.
- -- Other libtmodules must first be indexed
- -- by their version.
- local libtmodules = _G.libtmodules or {}
- function t.clearModuleCache()
- _G["libtmodules"] = {}
- libtmodules = _G["libtmodules"]
- end
- if forceReload then
- t.clearModuleCache()
- print("libt reloaded")
- end
- -- | Directories in which to search for
- -- libraries
- t.LIBRARY_PATH = {
- "/lib",
- "/"
- }
- -- | Produces a table of the keys in a
- -- table.
- function t.keys(tab)
- local result = {}
- for k, _ in pairs(tab) do
- table.insert(result, k)
- end
- return result
- end
- -- | Creates an iterator for the values in a
- -- table
- function t.ivalues(tab)
- return t.imap(
- pairs(tab),
- function(_, v)
- return v
- end
- )
- end
- -- | Creates a new table by running a
- -- function on each element of a table.
- function t.map(func, array)
- local result = {}
- for _, v in ipairs(array) do
- table.insert(result, func(v))
- end
- return result
- end
- -- | Maps a function inside an iterator.
- function t.imap(it, func)
- return function()
- local x = pack(it())
- if x[1] == nil then
- return nil
- else
- return func(unpack(x))
- end
- end
- end
- -- | Creates a new table containing only the
- -- elements satisfying a predicate.
- function t.filter(func, array)
- local result = {}
- for _, v in ipairs(array) do
- if func(v) then
- table.insert(result, v)
- end
- end
- return result
- end
- -- | Drops elements from an iterator unless
- -- they satisfy a predicate.
- function t.ifilter(func, it)
- return function()
- local x = nil
- while x == nil do
- x = it()
- if x == nil then
- return nil
- elseif func(x) then
- return x
- else
- x = nil
- end
- end
- end
- end
- -- | Construct an iterator from an array.
- function t.from(array)
- local i = 1
- return function()
- if i <= #array then
- local x = array[i]
- i = i + 1
- return x
- else
- return nil
- end
- end
- end
- -- | Constructs a function that checks
- -- whether its argument is equal to the
- -- supplied value.
- function t.eq(x)
- return function(y)
- return x == y
- end
- end
- -- | Construct an array from an iterator.
- function t.consume(it)
- local result = {}
- for x in it do
- table.insert(result, x)
- end
- return result
- end
- -- | Iterate over the tokens in a string
- -- that result by separating by any of the
- -- characters in `sep`.
- function t.splitBy(str, sep)
- return string.gmatch(str, "[^"..sep.."]+")
- end
- -- | Iterate over the tokens in a string
- -- that result by separating by one or more
- -- whitespace characters
- function t.spaceSplit(str)
- return string.gmatch(str, "(%S+)")
- end
- local function compose(i, fns)
- if i == #fns then
- return fns[i]
- else
- return function(x)
- return fns[i](compose(i+1, fns)(x))
- end
- end
- end
- -- | Right-to-left composition of functions.
- -- The functions must all be unary.
- function t.c(...)
- return compose(1, arg)
- end
- -- | Makes a three-dimensional array with
- -- the given size.
- function t.makeArray3(x, y, z)
- local arr = {}
- for i=1,x do
- local arrX = {}
- for j=1,y do
- local arrY = {}
- for k=1,z do
- table.insert(arrY, nil)
- end
- table.insert(arrX, arrY)
- end
- table.insert(arr, arrX)
- end
- return arr
- end
- -- | Maps a function over every element of a
- -- three-dimensional array, passing in the
- -- coordinates of each element as well as
- -- the value.
- function t.transformi3(arr, f)
- for i=1,#arr do
- for j=1,#(arr[1]) do
- for k=1,#(arr[1][1]) do
- arr[i][j][k] =
- f(i, j, k, arr[i][j][k])
- end
- end
- end
- end
- function t.divmod(num, denom)
- local div = math.floor(num / denom)
- local mod = num % denom
- return div, mod
- end
- -- | Searches for a module in the library
- -- search path and returns its path if it can
- -- be found. Else, returns nil.
- function t.findModule(name)
- for dir in t.from(t.LIBRARY_PATH) do
- local path = fs.combine(dir, name)
- if fs.exists(path) then
- return path
- end
- end
- return nil
- end
- -- | Find the first element of a table
- -- satisfying a predicate.
- -- If no predicate is given, returns the
- -- first truthy value in the table.
- -- If no value can be found, returns nil,
- -- so don't try t.find(tab, t.isNil) !
- function t.find(tab, pred)
- pred = pred or t.id
- for x in t.from(tab) do
- if pred(x) then
- return x
- end
- end
- return nil
- end
- -- | Loads a libt module.
- -- Does not account for circular imports, so
- -- don't make cycles!
- -- An inclusive lower bound on the version
- -- can be given as the second argument, and
- -- an exclusive upper bound on the version
- -- can be given as a third argument.
- function t.require(name, v1, v2)
- local m = libtmodules[name]
- if m ~= nil then
- for v, mod in pairs(m) do
- local v = textutils.unserialize(v)
- if v1 ~= nil then
- if t.Version.le(v1, v) then
- if v2 ~= nil then
- if t.Version.lt(v, v2) then
- return mod
- end
- else -- don't care about upper
- return mod
- end
- end
- else -- don't care about lower
- return mod
- end
- end
- -- no cached version is acceptable
- end
- -- search for a module in the filesystem
- local path = t.findModule(name)
- if path == nil then
- return nil
- end
- -- try to parse the file
- local f = loadfile(path)
- if f == nil then
- return nil
- end
- -- load the library
- m = f()
- if m == nil then
- error("library " .. path .. " has no exports")
- end
- if m.VERSION == nil then
- print(
- "warning: module ", name,
- " does not declare a version"
- )
- m.VERSION = { 0, 0, 0, 0 }
- end
- local found = nil
- if v1 ~= nil then
- if t.Version.le(v1, m.VERSION) then
- if v2 ~= nil then
- if t.Version.lt(m.Version, v2) then
- found = m
- end
- else
- found = m
- end
- end
- else
- found = m
- end
- if found == nil then
- return nil
- else
- if libtmodules[name] == nil then
- libtmodules[name] = {}
- end
- local k = textutils.serialize(m.VERSION)
- libtmodules[name][k] = found
- return found
- end
- end
- function t.requireStrict(name, v1, v2)
- return t.require(name, v1, v2)
- or error("failed to load module " .. name)
- end
- function t.requireStrictTg(name, prefix)
- local module = t.require(name)
- if module ~= nil then
- return module
- end
- if name == "libtput" then
- error(
- "failed to load libtput " ..
- "and it cannot be obtained from " ..
- "the network!"
- )
- end
- local tput = t.require("libtput")
- if tput == nil then
- error(
- "loading module " .. name .. ": " ..
- "failed to load libtput in order " ..
- "download module."
- )
- end
- local prefix = prefix or "lib/"
- tput.getStrict(prefix .. name)
- print('downloaded ' , name)
- return t.requireStrict(name)
- end
- -- | Stick all the elements of the second
- -- table onto the end of the first table.
- function t.extend(tab1, tab2)
- for _, v in ipairs(tab2) do
- table.insert(tab1, v)
- end
- end
- -- | Turn a function of many arguments into
- -- a function that takes a table by
- -- composing with unpack.
- --
- -- forall f. forall x.
- -- (t.unpackC(t.packC(f)))(x) == f(x)
- function t.unpackC(func)
- return function(tab)
- return func(unpack(tab))
- end
- end
- -- | Turn a function that accepts a table
- -- into a function of many arguments by
- -- composing with pack.
- --
- -- forall f. forall x.
- -- (t.unpackC(t.packC(f)))(x) == f(x)
- function t.packC(func)
- return function(...)
- return func(pack(arg))
- end
- end
- -- | The identity function. Returns its
- -- argument unchanged.
- function t.id(x)
- return x
- end
- -- | Build a table from an association list.
- function t.tableFromAssocs(assocs)
- local tab = {}
- for tup in t.from(assocs) do
- tab[tup[1]] = tup[2]
- end
- return tab
- end
- -- | Checks that all elements of a table
- -- satisfy a predicate. If no predicate is
- -- given, elements are checked on the basis
- -- of their truthiness.
- function t.all(tab, func)
- func = func or t.id
- for v in t.from(tab) do
- if not func(v) then
- return false
- end
- end
- return true
- end
- -- | Checks that there is at least one
- -- element of a table satisfying a
- -- predicate. If no predicate is given,
- -- elements are checked on the basis on
- -- their truthiness.
- function t.any(tab, func)
- func = func or t.id
- for v in t.from(tab) do
- if func(v) then
- return true
- end
- end
- return false
- end
- -- | Perform a left fold of a table.
- function t.fold(tab, func, start)
- for v in t.from(tab) do
- start = func(start, v)
- end
- return start
- end
- -- | Compute the sum of the elements in an
- -- array.
- function t.sum(tab)
- return t.fold(
- tab,
- function(acc, x) return acc + x end,
- 0
- )
- end
- function t.dot(key)
- return function(tab)
- return tab[key]
- end
- end
- function t.product(tab)
- return t.fold(
- tab,
- function(acc, x) return acc * x end,
- 1
- )
- end
- function t.min(tab, func)
- it = t.from(tab)
- local m = tab[1]
- local fm = func(m)
- for x in it do
- if func(x) < fm then
- m = x
- end
- end
- return m
- end
- function t.len(ts)
- return #ts
- end
- function t.zip(...)
- local n = t.min(t.map(t.len, arg))
- local result = {}
- for i=1, n do
- table.insert(result, {tab1[i], tab2[i]})
- end
- return result
- end
- function t.call(f)
- return f()
- end
- function t.apply(...)
- local xs = arg
- return function(f)
- return f(unpack(xs))
- end
- end
- function t.eq(x)
- return function(y)
- return x == y
- end
- end
- t.isNil = t.eq(nil)
- function t.izip(...)
- return function()
- local xs = t.map(call, arg)
- if any(xs, isNil) then
- return nil
- else
- return unpack(xs)
- end
- end
- end
- -- | An infinite range.
- function t.count(start, step)
- start = start or 1
- step = step or 1
- local i = start
- return function()
- local j = i
- i = i + step
- return j
- end
- end
- function t.range(start, stop, step)
- step = step or 1
- local r = {}
- for i=start,stop,step do
- table.insert(r, i)
- end
- return r
- end
- function t.irange(start, stop, step)
- step = step or 1
- local i = start
- return function()
- if i <= stop then
- local j = i
- i = i + step
- return j
- else
- return nil
- end
- end
- end
- -- | Compute a table that is the union of
- -- all given tables.
- function t.union(...)
- local u = {}
- for i, a in ipairs(arg) do
- for k, _ in pairs(arg[i]) do
- u[k] = true
- end
- end
- return u
- end
- -- | Convert an array into a set. The array
- -- is iterated with ipairs, and the values
- -- are serialized and used as keys mapping
- -- to true in a new table, which acts as a
- -- set.
- function t.arrayToSet(arr)
- local set = {}
- for k, v in ipairs(arr) do
- set[textutils.serialize(v)] = true
- end
- return set
- end
- function t.setMember(elem, set)
- return set[textutils.serialize(elem)]
- or false
- end
- -- Convenient.
- -- We perform a null-check so that when
- -- running libt under Lua outside of CC, it
- -- doesn't blow up.
- t.show = textutils and textutils.serialize
- t.read = textutils and textutils.unserialize
- function t.stringStartsWith(str, start)
- return string.sub(str, 1, string.len(start)) == start
- end
- function t.stringEndsWith(str, ending)
- return ending == "" or string.sub(str, string.len(ending)) == ending
- end
- function t.byOrderedKeys(tab)
- local ks = {}
- for k, v in pairs(tab) do
- table.insert(ks, k)
- end
- local i = 1
- return function()
- local k = ks[i]
- if k == nil then
- return nil
- else
- i = i + 1
- return tab[k]
- end
- end
- end
- function t.finally(func, done)
- local status, result = pcall(func)
- done()
- if status then
- return result
- else
- error(result)
- end
- end
- function t.tablecopy(src)
- local dst = {}
- for k, v in pairs(src) do
- if type(v) == 'table' then
- dst[k] = t.tablecopy(v)
- else
- dst[k] = v
- end
- end
- return dst
- end
- return t
- -- vim: ft=lua shiftwidth=2 expandtab colorcolumn=45 tw=44
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement