Skip to content

Commit 7bae582

Browse files
committed
working instrument
1 parent 7f0b3f8 commit 7bae582

File tree

2 files changed

+40
-32
lines changed

2 files changed

+40
-32
lines changed

src/main/cljs/cljs/spec.clj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,3 +353,15 @@
353353
"Returns a spec for a map whose keys satisfy kpred and vals satisfy vpred."
354354
[kpred vpred]
355355
`(and (coll-of (tuple ~kpred ~vpred) {}) map?))
356+
357+
(defmacro instrument
358+
"Instruments the var at v, a var or symbol, to check specs
359+
registered with fdef. Wraps the fn at v to check :args/:ret/:fn
360+
specs, if they exist, throwing an ex-info with explain-data if a
361+
check fails. Idempotent."
362+
[v]
363+
(let [v (if-not (seq? v) (list 'var v) v)
364+
sym (second v)]
365+
`(when-let [checked# (cljs.spec/instrument* ~v)]
366+
(set! ~sym checked#)
367+
~v)))

src/main/cljs/cljs/spec.cljs

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,22 @@
242242
[spec v]
243243
)
244244

245+
(defn- ->sym
246+
"Returns a symbol from a symbol or var"
247+
[x]
248+
(if (var? x)
249+
(.-sym x)
250+
x))
251+
245252
(defn- fn-specs?
246253
"Fn-specs must include at least :args or :ret specs."
247254
[m]
248255
(c/or (:args m) (:ret m)))
249256

257+
(defn- fn-spec-sym
258+
[sym role]
259+
(symbol (str sym "$" (name role))))
260+
250261
(defn fn-specs
251262
"Returns :args/:ret/:fn map of specs for var or symbol v."
252263
[v]
@@ -303,38 +314,23 @@
303314
(ex-info (str "Fn at " v " is not spec'ed.")
304315
{:var v :specs specs}))
305316

306-
;(def ^:private instrumented-vars
307-
; "Map for instrumented vars to :raw/:wrapped fns"
308-
; (atom {}))
309-
;
310-
;(defn- ->var
311-
; [s-or-v]
312-
; (if (var? s-or-v)
313-
; s-or-v
314-
; (let [v (c/and (symbol? s-or-v) (resolve s-or-v))]
315-
; (if (var? v)
316-
; v
317-
; (throw (js/Error. (str (pr-str s-or-v) " does not name a var")))))))
318-
319-
;(defn instrument
320-
; "Instruments the var at v, a var or symbol, to check specs
321-
;registered with fdef. Wraps the fn at v to check :args/:ret/:fn
322-
;specs, if they exist, throwing an ex-info with explain-data if a
323-
;check fails. Idempotent."
324-
; [v]
325-
; (let [v (->var v)
326-
; specs (fn-specs v)]
327-
; (if (fn-specs? specs)
328-
; (locking instrumented-vars
329-
; (let [{:keys [raw wrapped]} (get @instrumented-vars v)
330-
; current @v]
331-
; (when-not (= wrapped current)
332-
; (let [checked (spec-checking-fn v current)]
333-
; (alter-var-root v (constantly checked))
334-
; (swap! instrumented-vars assoc v {:raw current :wrapped checked}))))
335-
; v)
336-
; (throw (no-fn-specs v specs)))))
337-
;
317+
(def ^:private instrumented-vars
318+
"Map for instrumented vars to :raw/:wrapped fns"
319+
(atom {}))
320+
321+
(defn instrument*
322+
[v]
323+
(let [specs (fn-specs v)]
324+
(if (fn-specs? specs)
325+
(locking instrumented-vars
326+
(let [{:keys [raw wrapped]} (get @instrumented-vars v)
327+
current @v]
328+
(when-not (= wrapped current)
329+
(let [checked (spec-checking-fn v current)]
330+
(swap! instrumented-vars assoc v {:raw current :wrapped checked})
331+
checked))))
332+
(throw (no-fn-specs v specs)))))
333+
338334
;(defn unstrument
339335
; "Undoes instrument on the var at v, a var or symbol. Idempotent."
340336
; [v]

0 commit comments

Comments
 (0)