Advertisement
Guest User

libt

a guest
May 28th, 2017
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.46 KB | None | 0 0
  1. -- libt can be invoked as a script to force
  2. -- clean the modules cache.
  3. local args = {...}
  4. local forceReload = args[1]
  5.  
  6. -- Initialize the T module
  7. local t = {}
  8.  
  9. -- Set up the versioning system
  10. t.Version = {}
  11.  
  12. t.Version.le = function(a, b)
  13.   for v1, v2 in t.imap(
  14.     t.from(t.zip(a, b)),
  15.     unpack
  16.   ) do
  17.     if v1 < v2 then
  18.       return true
  19.     elseif v1 > v2 then
  20.       return false
  21.     end
  22.   end
  23.   -- then they are equal
  24.   return true
  25. end
  26.  
  27. t.Version.lt = function(a, b)
  28.   for v1, v2 in t.imap(
  29.     t.from(t.zip(a, b)),
  30.     unpack
  31.   ) do
  32.     if v1 < v2 then
  33.       return true
  34.     elseif v1 > v2 then
  35.       return false
  36.     end
  37.   end
  38.   -- then they are equal
  39.   return false
  40. end
  41.  
  42. t.Version.eq = function(a, b)
  43.   return t.all(
  44.     t.zip(a, b),
  45.     function(v1, v2)
  46.       return v1 == v2
  47.     end
  48.   )
  49. end
  50.  
  51. t.Version.gt = function(a, b)
  52.   return not t.Version.le(a, b)
  53. end
  54.  
  55. t.Version.ge = function(a, b)
  56.   return not t.Version.lt(a, b)
  57. end
  58.  
  59. -- | The version of libt
  60. t.VERSION = { 0, 1, 0, 0 }
  61.  
  62. -- Initialize the modules cache and check
  63. -- whether libt is already loaded.
  64. --
  65. -- libt is the only library that gets stored
  66. -- *directly* into the libtmodules cache.
  67. -- Other libtmodules must first be indexed
  68. -- by their version.
  69.  
  70. local libtmodules = _G.libtmodules or {}
  71.  
  72. function t.clearModuleCache()
  73.   _G["libtmodules"] = {}
  74.   libtmodules = _G["libtmodules"]
  75. end
  76.  
  77. if forceReload then
  78.   t.clearModuleCache()
  79.   print("libt reloaded")
  80. end
  81.  
  82. -- | Directories in which to search for
  83. -- libraries
  84. t.LIBRARY_PATH = {
  85.   "/lib",
  86.   "/"
  87. }
  88.  
  89. -- | Produces a table of the keys in a
  90. -- table.
  91. function t.keys(tab)
  92.   local result = {}
  93.   for k, _ in pairs(tab) do
  94.     table.insert(result, k)
  95.   end
  96.   return result
  97. end
  98.  
  99. -- | Creates an iterator for the values in a
  100. -- table
  101. function t.ivalues(tab)
  102.   return t.imap(
  103.     pairs(tab),
  104.     function(_, v)
  105.       return v
  106.     end
  107.   )
  108. end
  109.  
  110. -- | Creates a new table by running a
  111. -- function on each element of a table.
  112. function t.map(func, array)
  113.   local result = {}
  114.   for _, v in ipairs(array) do
  115.     table.insert(result, func(v))
  116.   end
  117.   return result
  118. end
  119.  
  120. -- | Maps a function inside an iterator.
  121. function t.imap(it, func)
  122.   return function()
  123.     local x = pack(it())
  124.     if x[1] == nil then
  125.       return nil
  126.     else
  127.       return func(unpack(x))
  128.     end
  129.   end
  130. end
  131.  
  132. -- | Creates a new table containing only the
  133. -- elements satisfying a predicate.
  134. function t.filter(func, array)
  135.   local result = {}
  136.   for _, v in ipairs(array) do
  137.     if func(v) then
  138.       table.insert(result, v)
  139.     end
  140.   end
  141.   return result
  142. end
  143.  
  144. -- | Drops elements from an iterator unless
  145. -- they satisfy a predicate.
  146. function t.ifilter(func, it)
  147.   return function()
  148.     local x = nil
  149.     while x == nil do
  150.       x = it()
  151.       if x == nil then
  152.         return nil
  153.       elseif func(x) then
  154.         return x
  155.       else
  156.         x = nil
  157.       end
  158.     end
  159.   end
  160. end
  161.  
  162. -- | Construct an iterator from an array.
  163. function t.from(array)
  164.   local i = 1
  165.   return function()
  166.     if i <= #array then
  167.       local x = array[i]
  168.       i = i + 1
  169.       return x
  170.     else
  171.       return nil
  172.     end
  173.   end
  174. end
  175.  
  176. -- | Constructs a function that checks
  177. -- whether its argument is equal to the
  178. -- supplied value.
  179. function t.eq(x)
  180.   return function(y)
  181.     return x == y
  182.   end
  183. end
  184.  
  185. -- | Construct an array from an iterator.
  186. function t.consume(it)
  187.   local result = {}
  188.   for x in it do
  189.     table.insert(result, x)
  190.   end
  191.   return result
  192. end
  193.  
  194. -- | Iterate over the tokens in a string
  195. -- that result by separating by any of the
  196. -- characters in `sep`.
  197. function t.splitBy(str, sep)
  198.   return string.gmatch(str, "[^"..sep.."]+")
  199. end
  200.  
  201. -- | Iterate over the tokens in a string
  202. -- that result by separating by one or more
  203. -- whitespace characters
  204. function t.spaceSplit(str)
  205.   return string.gmatch(str, "(%S+)")
  206. end
  207.  
  208. local function compose(i, fns)
  209.   if i == #fns then
  210.     return fns[i]
  211.   else
  212.     return function(x)
  213.       return fns[i](compose(i+1, fns)(x))
  214.     end
  215.   end
  216. end
  217.  
  218. -- | Right-to-left composition of functions.
  219. -- The functions must all be unary.
  220. function t.c(...)
  221.   return compose(1, arg)
  222. end
  223.  
  224. -- | Makes a three-dimensional array with
  225. -- the given size.
  226. function t.makeArray3(x, y, z)
  227.   local arr = {}
  228.  
  229.   for i=1,x do
  230.     local arrX = {}
  231.     for j=1,y do
  232.       local arrY = {}
  233.       for k=1,z do
  234.         table.insert(arrY, nil)
  235.       end
  236.       table.insert(arrX, arrY)
  237.     end
  238.     table.insert(arr, arrX)
  239.   end
  240.  
  241.   return arr
  242. end
  243.  
  244. -- | Maps a function over every element of a
  245. -- three-dimensional array, passing in the
  246. -- coordinates of each element as well as
  247. -- the value.
  248. function t.transformi3(arr, f)
  249.   for i=1,#arr do
  250.     for j=1,#(arr[1]) do
  251.       for k=1,#(arr[1][1]) do
  252.         arr[i][j][k] =
  253.           f(i, j, k, arr[i][j][k])
  254.       end
  255.     end
  256.   end
  257. end
  258.  
  259. function t.divmod(num, denom)
  260.   local div = math.floor(num / denom)
  261.   local mod = num % denom
  262.   return div, mod
  263. end
  264.  
  265. -- | Searches for a module in the library
  266. -- search path and returns its path if it can
  267. -- be found. Else, returns nil.
  268. function t.findModule(name)
  269.   for dir in t.from(t.LIBRARY_PATH) do
  270.     local path = fs.combine(dir, name)
  271.     if fs.exists(path) then
  272.       return path
  273.     end
  274.   end
  275.   return nil
  276. end
  277.  
  278. -- | Find the first element of a table
  279. -- satisfying a predicate.
  280. -- If no predicate is given, returns the
  281. -- first truthy value in the table.
  282. -- If no value can be found, returns nil,
  283. -- so don't try t.find(tab, t.isNil) !
  284. function t.find(tab, pred)
  285.   pred = pred or t.id
  286.  
  287.   for x in t.from(tab) do
  288.     if pred(x) then
  289.       return x
  290.     end
  291.   end
  292.  
  293.   return nil
  294. end
  295.  
  296. -- | Loads a libt module.
  297. -- Does not account for circular imports, so
  298. -- don't make cycles!
  299. -- An inclusive lower bound on the version
  300. -- can be given as the second argument, and
  301. -- an exclusive upper bound on the version
  302. -- can be given as a third argument.
  303. function t.require(name, v1, v2)
  304.   local m = libtmodules[name]
  305.  
  306.   if m ~= nil then
  307.     for v, mod in pairs(m) do
  308.       local v = textutils.unserialize(v)
  309.       if v1 ~= nil then
  310.         if t.Version.le(v1, v) then
  311.           if v2 ~= nil then
  312.             if t.Version.lt(v, v2) then
  313.               return mod
  314.             end
  315.           else -- don't care about upper
  316.             return mod
  317.           end
  318.         end
  319.       else -- don't care about lower
  320.         return mod
  321.       end
  322.     end
  323.     -- no cached version is acceptable
  324.   end
  325.  
  326.   -- search for a module in the filesystem
  327.   local path = t.findModule(name)
  328.  
  329.   if path == nil then
  330.     return nil
  331.   end
  332.  
  333.   -- try to parse the file
  334.   local f = loadfile(path)
  335.   if f == nil then
  336.     return nil
  337.   end
  338.  
  339.   -- load the library
  340.   m = f()
  341.   if m == nil then
  342.     error("library " .. path .. " has no exports")
  343.   end
  344.   if m.VERSION == nil then
  345.     print(
  346.       "warning: module ", name,
  347.       " does not declare a version"
  348.     )
  349.     m.VERSION = { 0, 0, 0, 0 }
  350.   end
  351.  
  352.   local found = nil
  353.  
  354.   if v1 ~= nil then
  355.     if t.Version.le(v1, m.VERSION) then
  356.       if v2 ~= nil then
  357.         if t.Version.lt(m.Version, v2) then
  358.           found = m
  359.         end
  360.       else
  361.         found = m
  362.       end
  363.     end
  364.   else
  365.     found = m
  366.   end
  367.  
  368.   if found == nil then
  369.     return nil
  370.   else
  371.     if libtmodules[name] == nil then
  372.       libtmodules[name] = {}
  373.     end
  374.     local k = textutils.serialize(m.VERSION)
  375.     libtmodules[name][k] = found
  376.     return found
  377.   end
  378. end
  379.  
  380. function t.requireStrict(name, v1, v2)
  381.   return t.require(name, v1, v2)
  382.     or error("failed to load module " ..  name)
  383. end
  384.  
  385. function t.requireStrictTg(name, prefix)
  386.   local module = t.require(name)
  387.   if module ~= nil then
  388.     return module
  389.   end
  390.   if name == "libtput" then
  391.     error(
  392.       "failed to load libtput " ..
  393.       "and it cannot be obtained from " ..
  394.       "the network!"
  395.     )
  396.   end
  397.   local tput = t.require("libtput")
  398.   if tput == nil then
  399.     error(
  400.       "loading module " .. name .. ": " ..
  401.       "failed to load libtput in order " ..
  402.       "download module."
  403.     )
  404.   end
  405.   local prefix = prefix or "lib/"
  406.   tput.getStrict(prefix .. name)
  407.   print('downloaded ' , name)
  408.   return t.requireStrict(name)
  409. end
  410.  
  411. -- | Stick all the elements of the second
  412. -- table onto the end of the first table.
  413. function t.extend(tab1, tab2)
  414.   for _, v in ipairs(tab2) do
  415.     table.insert(tab1, v)
  416.   end
  417. end
  418.  
  419. -- | Turn a function of many arguments into
  420. -- a function that takes a table by
  421. -- composing with unpack.
  422. --
  423. -- forall f. forall x.
  424. --   (t.unpackC(t.packC(f)))(x) == f(x)
  425. function t.unpackC(func)
  426.   return function(tab)
  427.     return func(unpack(tab))
  428.   end
  429. end
  430.  
  431. -- | Turn a function that accepts a table
  432. -- into a function of many arguments by
  433. -- composing with pack.
  434. --
  435. -- forall f. forall x.
  436. --   (t.unpackC(t.packC(f)))(x) == f(x)
  437. function t.packC(func)
  438.   return function(...)
  439.     return func(pack(arg))
  440.   end
  441. end
  442.  
  443. -- | The identity function. Returns its
  444. -- argument unchanged.
  445. function t.id(x)
  446.   return x
  447. end
  448.  
  449. -- | Build a table from an association list.
  450. function t.tableFromAssocs(assocs)
  451.   local tab = {}
  452.   for tup in t.from(assocs) do
  453.     tab[tup[1]] = tup[2]
  454.   end
  455.   return tab
  456. end
  457.  
  458. -- | Checks that all elements of a table
  459. -- satisfy a predicate. If no predicate is
  460. -- given, elements are checked on the basis
  461. -- of their truthiness.
  462. function t.all(tab, func)
  463.   func = func or t.id
  464.  
  465.   for v in t.from(tab) do
  466.     if not func(v) then
  467.       return false
  468.     end
  469.   end
  470.  
  471.   return true
  472. end
  473.  
  474. -- | Checks that there is at least one
  475. -- element of a table satisfying a
  476. -- predicate. If no predicate is given,
  477. -- elements are checked on the basis on
  478. -- their truthiness.
  479. function t.any(tab, func)
  480.   func = func or t.id
  481.  
  482.   for v in t.from(tab) do
  483.     if func(v) then
  484.       return true
  485.     end
  486.   end
  487.  
  488.   return false
  489. end
  490.  
  491. -- | Perform a left fold of a table.
  492. function t.fold(tab, func, start)
  493.   for v in t.from(tab) do
  494.     start = func(start, v)
  495.   end
  496.   return start
  497. end
  498.  
  499. -- | Compute the sum of the elements in an
  500. -- array.
  501. function t.sum(tab)
  502.   return t.fold(
  503.     tab,
  504.     function(acc, x) return acc + x end,
  505.     0
  506.   )
  507. end
  508.  
  509. function t.dot(key)
  510.   return function(tab)
  511.     return tab[key]
  512.   end
  513. end
  514.  
  515. function t.product(tab)
  516.   return t.fold(
  517.     tab,
  518.     function(acc, x) return acc * x end,
  519.     1
  520.   )
  521. end
  522.  
  523. function t.min(tab, func)
  524.   it = t.from(tab)
  525.   local m = tab[1]
  526.   local fm = func(m)
  527.   for x in it do
  528.     if func(x) < fm then
  529.       m = x
  530.     end
  531.   end
  532.   return m
  533. end
  534.  
  535. function t.len(ts)
  536.   return #ts
  537. end
  538.  
  539. function t.zip(...)
  540.   local n = t.min(t.map(t.len, arg))
  541.  
  542.   local result = {}
  543.   for i=1, n do
  544.     table.insert(result, {tab1[i], tab2[i]})
  545.   end
  546.  
  547.   return result
  548. end
  549.  
  550. function t.call(f)
  551.   return f()
  552. end
  553.  
  554. function t.apply(...)
  555.   local xs = arg
  556.   return function(f)
  557.     return f(unpack(xs))
  558.   end
  559. end
  560.  
  561. function t.eq(x)
  562.   return function(y)
  563.     return x == y
  564.   end
  565. end
  566.  
  567. t.isNil = t.eq(nil)
  568.  
  569. function t.izip(...)
  570.   return function()
  571.     local xs = t.map(call, arg)
  572.     if any(xs, isNil) then
  573.       return nil
  574.     else
  575.       return unpack(xs)
  576.     end
  577.   end
  578. end
  579.  
  580. -- | An infinite range.
  581. function t.count(start, step)
  582.   start = start or 1
  583.   step = step or 1
  584.   local i = start
  585.   return function()
  586.     local j = i
  587.     i = i + step
  588.     return j
  589.   end
  590. end
  591.  
  592. function t.range(start, stop, step)
  593.   step = step or 1
  594.   local r = {}
  595.   for i=start,stop,step do
  596.     table.insert(r, i)
  597.   end
  598.   return r
  599. end
  600.  
  601. function t.irange(start, stop, step)
  602.   step = step or 1
  603.   local i = start
  604.   return function()
  605.     if i <= stop then
  606.       local j = i
  607.       i = i + step
  608.       return j
  609.     else
  610.       return nil
  611.     end
  612.   end
  613. end
  614.  
  615. -- | Compute a table that is the union of
  616. -- all given tables.
  617. function t.union(...)
  618.   local u = {}
  619.   for i, a in ipairs(arg) do
  620.     for k, _ in pairs(arg[i]) do
  621.       u[k] = true
  622.     end
  623.   end
  624.   return u
  625. end
  626.  
  627. -- | Convert an array into a set. The array
  628. -- is iterated with ipairs, and the values
  629. -- are serialized and used as keys mapping
  630. -- to true in a new table, which acts as a
  631. -- set.
  632. function t.arrayToSet(arr)
  633.   local set = {}
  634.   for k, v in ipairs(arr) do
  635.     set[textutils.serialize(v)] = true
  636.   end
  637.   return set
  638. end
  639.  
  640. function t.setMember(elem, set)
  641.   return set[textutils.serialize(elem)]
  642.     or false
  643. end
  644.  
  645. -- Convenient.
  646. -- We perform a null-check so that when
  647. -- running libt under Lua outside of CC, it
  648. -- doesn't blow up.
  649. t.show = textutils and textutils.serialize
  650. t.read = textutils and textutils.unserialize
  651.  
  652. function t.stringStartsWith(str, start)
  653.   return string.sub(str, 1, string.len(start)) == start
  654. end
  655.  
  656. function t.stringEndsWith(str, ending)
  657.   return ending == "" or string.sub(str, string.len(ending)) == ending
  658. end
  659.  
  660. function t.byOrderedKeys(tab)
  661.   local ks = {}
  662.   for k, v in pairs(tab) do
  663.     table.insert(ks, k)
  664.   end
  665.   local i = 1
  666.   return function()
  667.     local k = ks[i]
  668.     if k == nil then
  669.       return nil
  670.     else
  671.       i = i + 1
  672.       return tab[k]
  673.     end
  674.   end
  675. end
  676.  
  677. function t.finally(func, done)
  678.   local status, result = pcall(func)
  679.   done()
  680.   if status then
  681.     return result
  682.   else
  683.     error(result)
  684.   end
  685. end
  686.  
  687. function t.tablecopy(src)
  688.   local dst = {}
  689.   for k, v in pairs(src) do
  690.     if type(v) == 'table' then
  691.       dst[k] = t.tablecopy(v)
  692.     else
  693.       dst[k] = v
  694.     end
  695.   end
  696.   return dst
  697. end
  698.  
  699. return t
  700.  
  701. -- vim: ft=lua shiftwidth=2 expandtab colorcolumn=45 tw=44
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement