(defn compile-passes [passes walk info]
(let [with-state (filter (comp :state info) passes)
state (zipmap with-state (mapv #(:state (info %)) with-state))
pfns (reduce (fn [f p]
(let [i (info p)
p (cond
(:state i)
(fn [_ s ast] (p (s p) ast))
(:affects i)
(fn [a _ ast] ((p a) ast))
:else
(fn [_ _ ast] (p ast)))]
(fn [a s ast]
(p a s (f a s ast))))) (fn [_ _ ast] ast) passes)]
(fn analyze [ast]
(walk ast (partial pfns analyze (update-vals state #(%)))))))