/
util_macros.clj
68 lines (56 loc) · 2 KB
/
util_macros.clj
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
(ns com.rpl.specter.util-macros)
(defmacro doseqres [backup-res [n aseq] & body]
`(reduce
(fn [curr# ~n]
(let [ret# (do ~@body)]
(if (identical? ret# ~backup-res)
curr#
(if (reduced? ret#) (reduced ret#) ret#))))
~backup-res
~aseq))
(defn- gensyms [amt]
(vec (repeatedly amt gensym)))
(defmacro mk-comp-navs []
(let [impls (for [i (range 3 20)]
(let [[fsym & rsyms :as syms] (gensyms i)]
`([~@syms] (~'comp-navs ~fsym (~'comp-navs ~@rsyms)))))
last-syms (gensyms 19)]
`(defn ~'comp-navs
([] ~'com.rpl.specter.impl/STAY*)
([nav1#] nav1#)
([nav1# nav2#] (~'com.rpl.specter.impl/combine-two-navs nav1# nav2#))
~@impls
([~@last-syms ~'& rest#]
(~'comp-navs
(~'comp-navs ~@last-syms)
(reduce ~'comp-navs rest#))))))
;;TODO: move these definitions somewhere else
(defn late-fn-record-name [i]
(symbol (str "LateFn" i)))
(defn late-fn-record-constructor-name [i]
(symbol (str "->LateFn" i)))
(defn- mk-late-fn-record [i]
(let [fields (concat ['fn] (for [j (range i)] (symbol (str "arg" j))))
dparams (gensym "dynamic-params")
resolvers (for [f fields]
`(~'late-resolve ~f ~dparams))]
`(defrecord ~(late-fn-record-name i) [~@fields]
~'LateResolve
(~'late-resolve [this# ~dparams]
(~@resolvers)))))
(defmacro mk-late-fn-records []
(let [impls (for [i (range 20)] (mk-late-fn-record i))]
`(do ~@impls)))
(defmacro mk-late-fn []
(let [f (gensym "afn")
args (gensym "args")
cases (for [i (range 19)]
[i
(let [gets (for [j (range i)] `(nth ~args ~j))]
`(~(late-fn-record-constructor-name i)
~f
~@gets))])]
`(defn ~'late-fn [~f ~args]
(case (count ~args)
~@(apply concat cases)
(com.rpl.specter.impl/throw-illegal "Cannot have late function with more than 18 args")))))