-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathMacros.ark
More file actions
157 lines (146 loc) · 4.51 KB
/
Macros.ark
File metadata and controls
157 lines (146 loc) · 4.51 KB
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# internal, do not use
(macro __replace_all_placeholders_with (replacement x ...xs) {
($if ($empty? xs)
($if (= "_" ($repr x))
replacement
x)
($if (= "_" ($repr x))
{
replacement
(__replace_all_placeholders_with replacement ...xs) }
{
x
(__replace_all_placeholders_with replacement ...xs) })) })
# @brief Chain calls on a given value, for a nicer syntax
# @param arg value to transform
# @param ...fns series of functions to apply one by one to `arg`
# =begin
# (import std.Macros)
# (-> "f0" f1) # equivalent to (f1 "f0")
# (-> "f0" f1 f2 f3) # equivalent to (f3 (f2 (f1 "f0")))
# (-> "f0" f1 (foo _ f2) (bar _ f3)) # equivalent to (bar (foo (f1 "f0") f2) f3)
# =end
# @author https://github.com/SuperFola
(macro -> (arg fn1 ...fns) {
($if (= "Symbol" ($type fn1))
(macro call (fn1 arg))
(macro call ((__replace_all_placeholders_with arg ...fn1))))
($if (> ($len fns) 0)
(-> call ...fns)
call) })
# internal, do not use
(macro __suffix-dup (sym x) {
($if (> x 1) (__suffix-dup sym (- x 1)))
($symcat sym x) })
# @brief Create a partial function with prefilled arguments
# @param func function to make partial
# @param ...defargs predefined arguments
# =begin
# (import std.Macros)
# (let test_func (fun (a b c) (* a b c)))
# (let test_func1 (partial test_func 1))
# (let test_func2 (partial test_func1 2))
# (print (test_func1 2 3)) # 6
# (print (test_func2 3)) # 6
# =end
# @author https://github.com/SuperFola
(macro partial (func ...defargs) {
(macro bloc (__suffix-dup a (- ($argcount func) ($len defargs))))
(fun (bloc) (func ...defargs bloc))
($undef bloc) })
(macro __count_placeholders (acc x ...xs) ($if ($empty? xs)
($if (= "_" ($repr x))
(+ 1 acc)
acc)
($if (= "_" ($repr x))
(__count_placeholders (+ 1 acc) ...xs)
(__count_placeholders acc ...xs))))
(macro __replace_placeholders (replacements x ...xs) {
($if ($empty? xs)
($if (= "_" ($repr x))
($head replacements)
x)
($if (= "_" ($repr x))
{
($head replacements)
(__replace_placeholders ($tail replacements) ...xs) }
{
x
(__replace_placeholders replacements ...xs) })) })
# @brief Create a partial function with prefilled arguments, allowing some arguments to be skipped
# @param call function to make partial
# @param ...args predefined arguments
# =begin
# (import std.Macros)
# (let test_func (fun (a b c) (* a b c)))
# (let test_func3 (partial2 test_func 1 _ 3))
# (print (test_func3 2)) # 6
# =end
# @author https://github.com/SuperFola
(macro partial2 (call ...args) {
(macro length (__count_placeholders 0 ...args))
(macro arg_bloc (__suffix-dup arg length))
(macro all_args (__replace_placeholders [arg_bloc] ...args))
(fun (arg_bloc) (call all_args)) })
# @brief Create a reversed condition
# @param cond condition
# @param body then node (or then/else nodes)
# =begin
# (import std.Macros)
# (unless (canCall? dog)
# (print "dog can't call")
# (print "dog can actually call us!"))
# (unless false
# (print "this will always be executed"))
# =end
# @author https://github.com/SuperFola
(macro unless (cond ...body) (if (not cond) ...body))
# @brief Iterate until the condition is truthy
# @param cond condition
# @param body loop body
# =begin
# (import std.Macros)
# (mut data [0])
# (until (= 10 (len data))
# (append! data (+ 1 (@ data -1))))
# (print data) # [0 1 2 3 4 5 6 7 8 9]
# =end
# @author https://github.com/SuperFola
(macro until (cond body) (while (not cond) body))
# @brief Unpack a pair of two elements into two new variables
# @param pair list of two elements to unpack
# @param outx name of the variable which will hold the first element
# @param outy name of the variable which will hold the second element
# =begin
# (let data [[1 2] [2 3] [5 8]])
# (list:forEach data
# (fun (pair) {
# (unpackPair pair x y)
# (print (+ x y)) }))
# =end
# @author https://github.com/SuperFola
(macro unpackPair (pair outx outy) {
(let outx ($as-is (@ pair 0)))
(let outy ($as-is (@ pair 1))) })
# @brief Increment a variable, by generating a `set`
# @param value symbol to increment
# =begin
# (mut n 0)
# (++ n)
# (print n) # 1
# (++ n)
# (print n) # 2
# =end
# @author https://github.com/SuperFola
(macro ++ (value) (set value (+ 1 value)))
# @brief Decrement a variable, by generating a `set`
# @param value symbol to decrement
# =begin
# (mut n 0)
# (-- n)
# (print n) # -1
# (-- n)
# (print n) # -2
# =end
# @author https://github.com/SuperFola
(macro -- (value) (set value (- value 1)))