git.s-ol.nu alive / fc23b6a
move util/switch to builtins s-ol 1 year, 3 months ago
2 changed file(s) with 58 addition(s) and 49 deletion(s). Raw diff Collapse all Expand all
271271 { xif, xthen, xelse } = tail
272272
273273 xif = L\push xif\eval, scope
274 xif = xif\const!\unwrap!
274 if not xif\is_const!
275 msg = "'if'-expression needs to be constant, did you mean 'switch'?"
276 error Error 'argument', msg
277 xif = xif\result!\unwrap!
275278
276279 super if xif
277280 xthen\eval scope
279282 xelse\eval scope
280283 else
281284 RTNode!
285
286 switch_ = Constant.meta
287 meta:
288 name: 'switch'
289 summary: "Switch between multiple inputs."
290 examples: { '(switch i v1 v2…)' }
291 description: "
292 - When fed a bang! trigger, steps forward to the next step on each trigger.
293 - When fed a num~ or num! stream, reproduces the matching argument (indexed
294 starting from 0).
295 - When fed a bool~ or bool! stream, outputs the first or second argument for
296 `true` and `false` respectively. This version takes at most two argumetns."
297
298 value: class extends Op
299 val_or_evt = (sig! / evt!)!
300 pattern = (sig.num / sig.bool / evt.num / evt.bool / evt.bang) + val_or_evt*0
301 setup: (inputs) =>
302 { i, values } = pattern\match inputs
303
304 @out = if values[1].result.metatype ~= '!'
305 values[1]\type!\mk_sig!
306 else
307 values[1]\type!\mk_evt!
308
309 if i\type! == T.bang
310 @state or= 1
311 else
312 @state = nil
313
314 super
315 i: Input.hot i
316 values: [Input.hot v for v in *values]
317
318 tick: =>
319 { :i, :values } = @inputs
320
321 ii = if i\type! == T.bang
322 if i\dirty!
323 @state += 1
324 while @state >= #values
325 @state -= #values
326 @state
327 else
328 switch i!
329 when true then 0
330 when false then 1
331 else (math.floor i!) % #values
332
333 @out\set if v = values[ii + 1] then v!
282334
283335 trace_ = Constant.meta
284336 meta:
560612 export: export_
561613 'export*': export_star
562614
615 :fn, :defn
616 'do': do_expr
617 'if': if_
618 'switch': switch_
619
563620 '=': to_const
564621 '~': to_sig
565622 '!': to_evt
585642 name: 'bang'
586643 summary: "A `bang` value-constant."
587644 value: Constant T.bang, true
588
589 :fn, :defn
590 'do': do_expr
591 if: if_
592645 }
00 import Constant, Op, Input, T, sig, evt from require 'alv.base'
1
2 all_same = (list) ->
3 for v in *list[2,]
4 if v != list[1]
5 return false
6
7 list[1]
8
9 switch_ = Constant.meta
10 meta:
11 name: 'switch'
12 summary: "Switch between multiple inputs."
13 examples: { '(switch i v1 v2…)' }
14 description: "
15 - when `i` is `true`, the first value is reproduced.
16 - when `i` is `false`, the second value is reproduced.
17 - when `i` is a `num`, it is [math/floor][]ed and the matching argument
18 (indexed starting from 0) is reproduced."
19
20 value: class extends Op
21 val_or_evt = (sig! / evt!)!
22 pattern = (sig.num / sig.bool) + val_or_evt*0
23 setup: (inputs) =>
24 { i, values } = pattern\match inputs
25
26 @out = if values[1].result.metatype ~= '!'
27 values[1]\type!\mk_sig!
28 else
29 values[1]\type!\mk_evt!
30
31 super
32 i: Input.hot i
33 values: [Input.hot v for v in *values]
34
35 tick: =>
36 { :i, :values } = @inputs
37 ii = switch i!
38 when true then 1
39 when false then 2
40 else 1 + (math.floor i!) % #values
41
42 @state = ii - 1
43 @out\set values[ii] and values[ii]!
441
452 edge = Constant.meta
463 meta:
6118 @state = now
6219
6320 {
64 'switch': switch_
6521 :edge
6622 }