(multi-spec-impl form mmvar retag)
(multi-spec-impl form mmvar retag gfn)
Do not call this directly, use 'multi-spec'
Source
(defn ^:skip-wiki multi-spec-impl
"Do not call this directly, use 'multi-spec'"
([form mmvar retag] (multi-spec-impl form mmvar retag nil))
([form mmvar retag gfn]
(let [id (java.util.UUID/randomUUID)
predx #(let [^clojure.lang.MultiFn mm @mmvar]
(c/and (.getMethod mm ((.dispatchFn mm) %))
(mm %)))
dval #((.dispatchFn ^clojure.lang.MultiFn @mmvar) %)
tag (if (keyword? retag)
#(assoc %1 retag %2)
retag)]
(reify
Specize
(specize* [s] s)
(specize* [s _] s)
Spec
(conform* [_ x] (if-let [pred (predx x)]
(dt pred x form)
::invalid))
(unform* [_ x] (if-let [pred (predx x)]
(unform pred x)
(throw (IllegalStateException. (str "No method of: " form " for dispatch value: " (dval x))))))
(explain* [_ path via in x]
(let [dv (dval x)
path (conj path dv)]
(if-let [pred (predx x)]
(explain-1 form pred path via in x)
[{:path path :pred form :val x :reason "no method" :via via :in in}])))
(gen* [_ overrides path rmap]
(if gfn
(gfn)
(let [gen (fn [[k f]]
(let [p (f nil)]
(let [rmap (inck rmap id)]
(when-not (recur-limit? rmap id path k)
(gen/delay
(gen/fmap
#(tag % k)
(gensub p overrides (conj path k) rmap (list 'method form k))))))))
gs (->> (methods @mmvar)
(remove (fn [[k]] (invalid? k)))
(map gen)
(remove nil?))]
(when (every? identity gs)
(gen/one-of gs)))))
(with-gen* [_ gfn] (multi-spec-impl form mmvar retag gfn))
(describe* [_] `(multi-spec ~form ~retag))))))