(defn
fspec-impl
"Do not call this directly, use 'fspec'"
[argspec aform retspec rform fnspec fform gfn]
(let
[specs {:args argspec, :ret retspec, :fn fnspec}]
(reify
ILookup
(-lookup [this k] (get specs k))
(-lookup [_ k not-found] (get specs k not-found))
Specize
(specize* [s] s)
(specize* [s _] s)
Spec
(conform*
[_ f]
(if
(ifn? f)
(if
(identical? f (validate-fn f specs *fspec-iterations*))
f
:clojure.core/invalid)
:clojure.core/invalid))
(unform* [_ f] f)
(explain*
[_ path via in f]
(if
(ifn? f)
(let
[args (validate-fn f specs 100)]
(if
(identical? f args)
nil
(let
[ret (try (apply f args) (catch js/Error t t))]
(if
(instance? js/Error ret)
[{:path path,
:pred '(apply fn),
:val args,
:reason (.-message ret),
:via via,
:in in}]
(let
[cret (dt retspec ret rform)]
(if
(invalid? cret)
(explain-1 rform retspec (conj path :ret) via in ret)
(when
fnspec
(let
[cargs (conform argspec args)]
(explain-1
fform
fnspec
(conj path :fn)
via
in
{:args cargs, :ret cret})))))))))
[{:path path, :pred 'ifn?, :val f, :via via, :in in}]))
(gen*
[_ overrides _ _]
(if
gfn
(gfn)
(gen/return
(fn
[& args]
(assert
(pvalid? argspec args)
(with-out-str (explain argspec args)))
(gen/generate (gen retspec overrides))))))
(with-gen*
[_ gfn]
(fspec-impl argspec aform retspec rform fnspec fform gfn))
(describe*
[_]
(clojure.core/sequence
(clojure.core/seq
(clojure.core/concat
(clojure.core/list 'clojure.core/fspec)
(clojure.core/list :args)
(clojure.core/list aform)
(clojure.core/list :ret)
(clojure.core/list rform)
(clojure.core/list :fn)
(clojure.core/list fform))))))))