git.s-ol.nu alive / fb0a7f2
add thread-first/thread-last macro + spec s-ol 4 months ago
2 changed file(s) with 72 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
619619 table.insert children, node
620620 super RTNode :children, result: node.result
621621
622 mk_thread = (name, thread_first) ->
623 class extends Builtin
624 eval: (scope, tail) =>
625 L\trace "evaling #{@}"
626 assert #tail > 1, "'#{name}' requires at least 2 arguments"
627
628 last_result = tail[1]
629
630 for cell in *tail[2,]
631 assert cell.__class == Cell, "'#{name}'s arguments have to be expressions"
632
633 children = [c for c in *cell.children]
634 if thread_first
635 table.insert children, 2, last_result
636 else
637 table.insert children, last_result
638
639 last_result = Cell cell.tag, children
640
641 super last_result\eval scope, tail
642
643 thread_first = Constant.meta
644 meta:
645 name: '->'
646 summary: "Thread first macro."
647 examples: { '(-> initial [expr1 expr2…])' }
648 description: "
649 Evaluate expressions `expr1`, `expr2`, … while passing the result of the
650 previous expression to the following one, starting with `initial`. The value
651 is always inserted as the first argument."
652
653 value: mk_thread '->', true
654
655 thread_last = Constant.meta
656 meta:
657 name: '->>'
658 summary: "Thread last macro."
659 examples: { '(->> initial [expr1 expr2…])' }
660 description: "
661 Evaluate expressions `expr1`, `expr2`, … while passing the result of the
662 previous expression to the following one, starting with `initial`. The value
663 is always inserted as the last argument."
664
665 value: mk_thread '->>', false
622666
623667 Constant.meta
624668 meta:
645689 '~': to_sig
646690 '!': to_evt
647691
692 '->': thread_first
693 '->>': thread_last
694
648695 :array, :struct
649696
650697 :loop, :recur
0 import TestPilot from require 'spec.test_setup'
1 import T, Struct, Array, Constant from require 'alv'
2
3 describe "thread macros", ->
4 COPILOT = TestPilot ''
5
6 it "thread forward (->)", ->
7 rt = COPILOT\eval_once '
8 (import* math)
9 #((/ (+ 10 2) 2) = 6)
10 (-> 10
11 (+ 2)
12 (/ 2))'
13 assert.is.true rt\is_const!
14 assert.is.equal (Constant.num 6), rt.result
15
16 it "thread last forward (->>)", ->
17 rt = COPILOT\eval_once '
18 (import* math)
19 #((/ 10 (+ 2 3)) = 2)
20 (->> 3
21 (+ 2)
22 (/ 10))'
23 assert.is.true rt\is_const!
24 assert.is.equal (Constant.num 2), rt.result