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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to