If deep nesting's not a concern, how about
(defn process-node [node descendant-of-let?]
(let [op (:op node)
children (:children node)
let-or-descendant? (or descendant-of-let? (= op :let))
processed-children (map #(process-node % let-or-descendant?) children)
children (map first processed-children)
constants (vec (apply concat (map second processed-children)))
node (if descendant-of-let? (assoc node :unbox true) node)]
(condp = op
:fn
[(assoc node :constants constants) constants]
:let
[node constants]
:constant
[node (conj constants {:value (:form node)})])))
(defn process-tree [root]
(first (process-node root false)))
Untested. Assumes that constants always are {:op :constant :form
<value>}, i.e. the key with the desired value is always :form. If it's
not, then that adds complication. How much depends on how the key is
to be identified. Is it always the only other key besides :op? Then
replace (:form node) on the last line above with (val (first (remove
#(= (key %) :op) node))). Otherwise, something probably more
complicated.
It works by recursing, passing descendant-of-let? information down the
stack, and accumulating constants up the stack. The implementation fn
returns a two-element vector of the modified node and a vector of the
constants in it (if a :op :constant node) and its descendants. Where
it recurses it maps this over children and then uses (map first
processed-children) and (map second processed-children) to extract the
modified children themselves and the constant-vectors, respectively,
and uses (vec (apply concat ...)) to convert the latter into a single
vector with all the constants.
--
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