(defn find-mismatches [{:keys [op exprs] :as ast} bindings]
(case op
:recur
(when (some true? (mapv (fn [e {:keys [tag init form]}]
(and (or (primitive? tag)
(not (or (:tag (meta form))
(:tag (meta (:form init))))))
(not= (:tag e) tag))) exprs bindings))
(swap! mismatch? conj (mapv :tag exprs)))
:do
(doseq [child (children ast)]
(find-mismatches child bindings))
(:let :letfn)
(find-mismatches (:body ast) bindings)
:if
(do (find-mismatches (:then ast) bindings)
(find-mismatches (:else ast) bindings))
:case
(do (find-mismatches (:default ast) bindings)
(doseq [child (:thens ast)]
(find-mismatches child bindings)))
nil)
ast)