Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Clojure Design
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
Colour
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Undo
Redo
Keyboard Shortcuts Help
<h1>Problem</h1><p>The AST nodes produced by the ClojureScript analyzer have a :children key to allow generic traversals. Unfortunately, this key is currently a denormalized view of child ast nodes.</p><p>For example, an :if node has :test, :then, and :else keys whose values are also contained in :children. This presents some difficulty when writing AST transformations because every transform function must be aware of this duplication. To correctly replace the :test of an :if node, you must also replace the first element of the :children vector.</p><h1>Discussion</h1><ul><li><a href="https://groups.google.com/d/topic/clojure-dev/vZLVKmKX0oc/discussion">https://groups.google.com/d/topic/clojure-dev/vZLVKmKX0oc/discussion</a></li><li><a href="https://docs.google.com/document/d/1DRN-tBIqhqVVyoHIDs7CMkduBFk-vqd_958ojeIBLHQ/edit">https://docs.google.com/document/d/1DRN-tBIqhqVVyoHIDs7CMkduBFk-vqd_958ojeIBLHQ/edit</a></li><li><a href="http://dev.clojure.org/jira/browse/CLJS-289">http://dev.clojure.org/jira/browse/CLJS-289</a></li></ul><h1>Design</h1><ul><li>Solution must retain "AST is just data" property. ie No API should be required to interpret it</li><li>Idea: store :children as keys into the AST map<ul><li>would be nice: (defn children [ast] ((apply juxt (:children ast)) ast))<ul><li>but need to handle implicit do blocks: (defn children [ast](mapcat #(if (coll? %) % [%]) ((apply juxt (:children ast)) ast)))</li></ul></li><li>ticket: <a href="http://dev.clojure.org/jira/browse/CLJS-289">http://dev.clojure.org/jira/browse/CLJS-289</a></li><li>outstanding issue: interleaved bindings</li></ul></li><li>Alternate idea: all child nodes are moved from the top level into a map in :children<ul><li>For "if" this would change<span style="color: rgb(34,34,34);"> {:op :if :env {env} :test test-expr :then then-expr :else else-expr :</span><span class="il" style="color: rgb(34,34,34);">children</span><span style="color: rgb(34,34,34);"> [test-expr then-expr else-expr]} </span><span style="color: rgb(34,34,34);">into {:op :if :env {env} :</span><span class="il" style="color: rgb(34,34,34);">children</span><span style="color: rgb(34,34,34);"> {:test test-expr :then then-expr :else else-expr}} </span></li><ul><li><span style="color: rgb(34,34,34);">This idea doesn't address blocks or bindings.</span></li><li><span style="color: rgb(34,34,34);">dnolen: </span><span style="font-size: 10.0pt;line-height: 13.0pt;font-style: italic;">What about forms like let where :children is a bit complex?</span></li></ul><li><div class="h7 hn "><div class="Bk"><div class="G3 G2 afm" style="margin-left: 0.0px;"><div class="adn ads"><div class="gs" style="margin-left: 44.0px;"><div class="ii gt adP adO"><div class="gmail_quote"><blockquote class="gmail_quote"><div class="gmail_quote"><div class="im"><div> </div><div>:children (into (vec (map :init bes))</div><div> (conj (vec statements) ret)) </div><div> </div><div> </div></div></div></blockquote><div>acohen: I think that should become: {:op :let :children {:init [inits] :statements [statements] :ret ret}</div><div><span style="font-size: 10.0pt;line-height: 13.0pt;"> We might want to discuss whether the inits are truly a child here, at the moment I think they are though.</span></div><div class="yj6qo ajU"><div class="ajR"><img class="confluence-embedded-image ajT confluence-external-resource" src="https://mail.google.com/mail/u/0/images/cleardot.gif" data-image-src="https://mail.google.com/mail/u/0/images/cleardot.gif"></div></div></div></div><div class="hi"> </div></div><div class="ajx"> </div></div></div></div></div><div class="h7 "><div class="Bk"><div class="G3 G2 afm" style="margin-left: 0.0px;"><div class="adn ads"><div class="gs" style="margin-left: 44.0px;"><div class="ii gt adP adO"><div class="gmail_quote"><div>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?</div><div class="yj6qo ajU"><div class="ajR"><img class="confluence-embedded-image ajT confluence-external-resource" src="https://mail.google.com/mail/u/0/images/cleardot.gif" data-image-src="https://mail.google.com/mail/u/0/images/cleardot.gif"></div></div></div></div><div class="hi"><span style="font-size: 10.0pt;line-height: 13.0pt;"> </span><span style="font-size: 10.0pt;line-height: 13.0pt;"> </span></div></div></div></div></div></div><div class="h7 "><div class="Bk"><div class="G3 G2 afm" style="margin-left: 0.0px;"><div class="adn ads"><div class="gs" style="margin-left: 44.0px;"><div class="ii gt adP adO"><div class="gmail_quote"><div>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.</div><div>So it should actually look like:</div><div><div>{:op :let </div><div> :children {:inits [{:op :binding :name x :children {:init init-expr}} </div><div> ...] </div><div> :statements [{...} ...] </div><div> :ret ret}}</div></div><div> </div><div>dnolen: <span style="font-size: 10.0pt;font-style: italic;line-height: 13.0pt;">What about :ret? So you'll always need to look at :children if you want to know :ret?</span></div><div><div class="im"><div> </div><div>acohen: <span style="font-size: 10.0pt;line-height: 13.0pt;">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"</span></div><div><span style="font-size: 10.0pt;line-height: 13.0pt;"><br /></span></div><div><span style="font-size: 10.0pt;line-height: 13.0pt;">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 :statements</span></div><div><span style="font-size: 10.0pt;line-height: 13.0pt;"><br /></span></div><div><span style="font-size: 10.0pt;line-height: 13.0pt;">acohen: Can we mandate that the children map be a map-like structure that preserves order?</span></div><div><span style="font-size: 10.0pt;line-height: 13.0pt;"><br /></span></div><div><span style="font-size: 10.0pt;line-height: 13.0pt;">bbloom: I don't think that's reasonable unless core gets such a map-like structure.</span></div></div></div><div><div> </div></div></div></div></div></div></div></div></div></li></ul></li></ul>
Attachments
Labels
Location
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced