...
- Solution must retain "AST is just data" property. ie No API should be required to interpret it
- Idea: store :children as keys into the AST map
- would be nice: (defn children [ast] ((apply juxt (:children ast)) ast))
- but need to handle implicit do blocks: (defn children [ast](mapcat #(if (coll? %) % [%]) ((apply juxt (:children ast)) ast)))
- ticket: http://dev.clojure.org/jira/browse/CLJS-289
- outstanding issue: interleaved bindings
- would be nice: (defn children [ast] ((apply juxt (:children ast)) ast))
- Alternate idea: all child nodes are moved from the top level into a map in :children
- For "if" this would change {:op :if :env {env} :test test-expr :then then-expr :else else-expr :children [test-expr then-expr else-expr]} into {:op :if :env {env} :children {:test test-expr :then then-expr :else else-expr}}
- This idea doesn't address blocks or bindings.
- dnolen: What about forms like let where :children is a bit complex?
- :children (into (vec (map :init bes))(conj (vec statements) ret))acohen: I think that should become: {:op :let :children {:init [inits] :statements [statements] :ret ret}We might want to discuss whether the inits are truly a child here, at the moment I think they are though.
dnolen: So if a :children value entry is a vector it's something you need to iterate over? What about :ret? So you'll always need to look at :children if you want to know :ret?
acohen: Yes, if :children entry is a seq, it must be a seq of nodes. For :let, I forgot that this is something else I changed in CinC. I made bindings an :op.So it should actually look like:{:op :let:children {:inits [{:op :binding :name x :children {:init init-expr}}...]:statements [{...} ...]:ret ret}}dnolen: What about :ret? So you'll always need to look at :children if you want to know :ret?acohen: Yep, that's right. Tree traversal would _always_ go through :children, rather than having this separation of "syntax-aware walkers go through the nodes that they know the names of" and "generic walkers go through :children"bbloom: I think this approach suffers another issue: Generic walkers might need to know evaluation order. I should be able to post-walk the :childrens nodes to get a strict top-to-bottom, inside-out, left-to-right sequence of nodes, ignoring conditional and repeated evaluation. Otherwise, I need knowledge of nodes to tell if side effects from :init may happen before those from :statementsacohen: Can we mandate that the children map be a map-like structure that preserves order?bbloom: I don't think that's reasonable unless core gets such a map-like structure.acohen: It's slightly gross, but we could add a :rank or :order attribute to nodes.