aboutsummaryrefslogtreecommitdiffstats
path: root/alv-lib/util.moon
blob: 350c08761ef44f80fb27591e621237d4c11a79d2 (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
66
67
68
69
70
import Constant, Op, Input, T, val, evt from require 'alv.base'

all_same = (list) ->
  for v in *list[2,]
    if v != list[1]
      return false

  list[1]

switch_ = Constant.meta
  meta:
    name: 'switch'
    summary: "Switch between multiple inputs."
    examples: { '(switch i v1 v2…)' }
    description: "
- when `i` is `true`, the first value is reproduced.
- when `i` is `false`, the second value is reproduced.
- when `i` is a `num`, it is [math/floor][]ed and the matching argument
  (indexed starting from 0) is reproduced."

  value: class extends Op
    val_or_evt = (val! / evt!)!
    pattern = (val.num / val.bool) + val_or_evt*0
    setup: (inputs) =>
      { i, values } = pattern\match inputs

      @out = if values[1].result.metatype ~= '!'
        values[1]\type!\mk_sig!
      else
        values[1]\type!\mk_evt!

      super
        i: Input.hot i
        values: [Input.hot v for v in *values]

    tick: =>
      { :i, :values } = @inputs
      active = switch i!
        when true
          values[1]
        when false
          values[2]
        else
          i = 1 + (math.floor i!) % #values
          values[i]

      @out\set active and active!

edge = Constant.meta
  meta:
    name: 'edge'
    summary: "Convert rising edges to bangs."
    examples: { '(edge bool)' }

  value: class extends Op
    setup: (inputs) =>
      @out or= T.bang\mk_evt!
      value = val.bool\match inputs
      super value: Input.hot value

    tick: =>
      now = @inputs.value!
      if now and not @state
        @out\set true
      @state = now

{
  'switch': switch_
  :edge
}