Hi,
I'm not sure it nicer, but anyway...
It follows a similar approach as Cedric: pass down unbox info and collect
up constants info. However I use the form itself to carry additional
information. YMMV. One could also put info into meta.
(derive ::let ::recursive)
(derive ::fn ::recursive)
(def call #(%2 %1))
(defn maybe
[pred f form & args]
(if (pred form)
(apply f form args)
form))
(defn update-children
[form f & args]
(update-in form [:children] (partial map #(apply f % args))))
(defn recursive?
[form]
(isa? (:op form) ::recursive))
(defn processor
[pre-fns post-fns]
(fn this [form]
(let [form (reduce call form pre-fns)
form (maybe recursive? update-children form this)]
(reduce call form post-fns))))
(defmulti set-unbox :op)
(defmethod set-unbox :default
[form]
form)
(defmethod set-unbox ::recursive
[{:as form :keys [unbox op]}]
(update-in form [:children] (partial map #(assoc % :unbox (or unbox (= op
::let))))))
(defmulti collect-constants :op)
(defmethod collect-constants :default
[form]
(assoc form :constants #{}))
(defmethod collect-constants ::constant
[form]
(assoc form :constants #{(:form form)}))
(defmethod collect-constants ::recursive
[{:as form :keys [children]}]
(assoc form :constants (reduce into #{} (map :constants children))))
((processor [set-unbox] [collect-constants]) {:op ::fn :children [{:op
::let :children [{:op ::constant :form 1}]}]})
; => {:constants #{1}, :op :user/fn, :children ({:constants #{1}, :unbox
false, :op :user/let, :children ({:constants #{1}, :unbox true, :op
:user/constant, :form 1})})}
Otherwise untested.
Sincerely
Meikel
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en