aboutsummaryrefslogtreecommitdiffstats
path: root/alv/util.moon
blob: defca7064f9ba2a79b3ea0faafb137e2119c35fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
-----
--- General utilities
--
-- @module util

sort = (t, order_fn, only_strings) ->
  with index = [k for k,v in pairs t when (not only_strings) or 'string' == type k]
    table.sort index, order_fn

-- ordered next(t)
onext = (state, key) ->
  state.i += 1
  { :t, :index, :i } = state

  if key = index[i]
    key, t[key]

--- ordered pairs(t).
--
-- @tparam table t table to iterate
-- @tparam function order_fn fn for `table.sort`
-- @tparam ?boolean only_strings whether to exclude non-strings from iteration
opairs = (t, order_fn, only_strings=false) ->
  state = { :t, i: 0, index: sort t, order_fn, only_strings }
  onext, state, nil

--- find the ancestor of a MoonScript class
ancestor = (klass) ->
  assert klass, "cant find the ancestor of nil"
  while klass.__parent
    klass = klass.__parent
  klass

--- check whether a table is a 'plain' table
is_plain_table = (val) -> (type val) == 'table' and not val.__class

--- recursively copy a value
deep_copy = (val) ->
  if is_plain_table val
    {(deep_copy k), (deep_copy v) for k,v in pairs val}
  else
    val

--- map leaf values in a table
deep_map = (val, fn) ->
  if is_plain_table val
    {k, (deep_map v, fn) for k,v in pairs val}
  else
    fn val

--- yield all leaf values in a table
deep_iter = (table) ->
  if is_plain_table table
    for k, v in pairs table
      deep_iter v
  else
    coroutine.yield table

{
  :opairs
  :ancestor
  :deep_copy
  :deep_map
  :deep_iter
}