-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
core.clj
executable file
·95 lines (79 loc) · 2.64 KB
/
core.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
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
(ns day8.re-frame.debux.core
(:require [day8.re-frame.debux.dbgn :as dbgn]
[day8.re-frame.debux.common.util :as ut]
[clojure.walk :as walk]
[clojure.spec.alpha :as s]
[day8.re-frame.debux.common.macro-specs :as ms]))
(def reset-indent-level! ut/reset-indent-level!)
(def set-print-seq-length! ut/set-print-seq-length!)
(def ^boolean trace-enabled? true)
(defn ^boolean is-trace-enabled?
"See https://groups.google.com/d/msg/clojurescript/jk43kmYiMhA/IHglVr_TPdgJ for more details"
[]
trace-enabled?)
;;; debugging APIs
(defmacro dbgn [form & opts]
(let [opts' (ut/parse-opts opts)]
`(dbgn/dbgn ~form ~opts')))
;; defn-traced and fn-traced macros
(defn fn-body [args+body]
(if (= :body (nth (:body args+body) 0))
`(~(or (:args (:args args+body)) [])
~@(map (fn [body] `(dbgn ~body)) (nth (:body args+body) 1)))
;; prepost+body
`(~(or (:args (:args args+body)) [])
~(:prepost (nth (:body args+body) 1))
~@(map (fn [body] `(dbgn ~body)) (:body (nth (:body args+body) 1))))))
;; Components of a defn
;; name
;; docstring?
;; meta?
;; bs (1-n)
;; body
;; prepost?
(defmacro defn-traced*
[& definition]
(let [conformed (s/conform ::ms/defn-args definition)
name (:name conformed)
bs (:bs conformed)
arity-1? (= (nth bs 0) :arity-1)
args+body (nth bs 1)]
(if arity-1?
`(defn ~name ~@(fn-body args+body))
`(defn ~name ~@(map fn-body (:bodies args+body))))))
(defmacro defn-traced
"Traced defn"
{:arglists '([name doc-string? attr-map? [params*] prepost-map? body]
[name doc-string? attr-map? ([params*] prepost-map? body) + attr-map?])}
[& definition]
`(if (is-trace-enabled?)
(defn-traced* ~@definition)
(defn ~@definition)))
;; Components of a fn
;; name?
;; bs (1-n)
;; body
;; prepost?
(defmacro fn-traced*
"Traced form of fn. Prefer fn-traced to compile out under advanced optimizations."
[& definition]
(let [conformed (s/conform ::ms/fn-args definition)
name (:name conformed)
bs (:bs conformed)
arity-1? (= (nth bs 0) :arity-1)
args+body (nth bs 1)]
(if arity-1?
;; If name is nil, then the empty vector is removed by the unquote
`(fn ~@(when name [name])
~@(fn-body args+body))
;; arity-n
(let [bodies (:bodies args+body)]
`(fn ~@(when name [name])
~@(map fn-body bodies))))))
(defmacro fn-traced
"Defines a traced fn"
{:arglists '[(fn name? [params*] exprs*) (fn name? ([params*] exprs*) +)]}
[& definition]
`(if (is-trace-enabled?)
(fn-traced* ~@definition)
(fn ~@definition)))