waypoint on the documentation -- almost halfway through the nodes

This commit is contained in:
Jeremy Ashkenas
2010-03-07 17:31:39 -05:00
parent 094b198d5d
commit c6d7a27848
4 changed files with 311 additions and 216 deletions

View File

@@ -18,6 +18,9 @@ p {
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
margin: 40px 0 15px 0; margin: 40px 0 15px 0;
} }
h3, h4, h5, h6 {
margin-top: 20px;
}
#container { #container {
position: relative; position: relative;
} }

View File

@@ -10,7 +10,7 @@ including the <a href="scope.html">Scope</a> class.</p> </td>
expression, and nodes tagged as <em>pure_statement</em> cannot be closure-wrapped expression, and nodes tagged as <em>pure_statement</em> cannot be closure-wrapped
without losing their meaning.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">statement: </span><span class="p">(</span><span class="nx">klass</span><span class="p">,</span> <span class="nx">only</span><span class="p">)</span> <span class="o">-&gt;</span> without losing their meaning.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">statement: </span><span class="p">(</span><span class="nx">klass</span><span class="p">,</span> <span class="nx">only</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">klass::is_statement: </span><span class="o">-&gt;</span> <span class="kc">true</span> <span class="nv">klass::is_statement: </span><span class="o">-&gt;</span> <span class="kc">true</span>
<span class="p">(</span><span class="nv">klass::is_pure_statement: </span><span class="o">-&gt;</span> <span class="kc">true</span><span class="p">)</span> <span class="k">if</span> <span class="nx">only</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>The <strong>BaseNode</strong> is the abstract base class for all nodes in the syntax tree. <span class="p">(</span><span class="nv">klass::is_pure_statement: </span><span class="o">-&gt;</span> <span class="kc">true</span><span class="p">)</span> <span class="k">if</span> <span class="nx">only</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <h3>BaseNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>The <strong>BaseNode</strong> is the abstract base class for all nodes in the syntax tree.
Each subclass implements the <code>compile_node</code> method, which performs the Each subclass implements the <code>compile_node</code> method, which performs the
code generation for that node. To compile a node to JavaScript, code generation for that node. To compile a node to JavaScript,
call <code>compile</code> on it, which wraps <code>compile_node</code> in some generic extra smarts, call <code>compile</code> on it, which wraps <code>compile_node</code> in some generic extra smarts,
@@ -18,90 +18,107 @@ to know when the generated code needs to be wrapped up in a closure.
An options hash is passed and cloned throughout, containing information about An options hash is passed and cloned throughout, containing information about
the environment from higher in the tree (such as if a returned value is the environment from higher in the tree (such as if a returned value is
being requested by the surrounding function), information about the current being requested by the surrounding function), information about the current
scope, and indentation level.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.BaseNode: </span><span class="nx">class</span> <span class="nx">BaseNode</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Common logic for determining whether to wrap this node in a closure before scope, and indentation level.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.BaseNode: </span><span class="nx">class</span> <span class="nx">BaseNode</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Common logic for determining whether to wrap this node in a closure before
compiling it, or to compile directly. We need to wrap if this node is a compiling it, or to compile directly. We need to wrap if this node is a
<em>statement</em>, and it's not a <em>pure_statement</em>, and we're not at <em>statement</em>, and it's not a <em>pure_statement</em>, and we're not at
the top level of a block (which would be unnecessary), and we haven't the top level of a block (which would be unnecessary), and we haven't
already been asked to return the result (because statements know how to already been asked to return the result (because statements know how to
return results).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> return results).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">options: </span><span class="nx">merge</span> <span class="nx">o</span> <span class="o">or</span> <span class="p">{}</span> <span class="err">@</span><span class="nv">options: </span><span class="nx">merge</span> <span class="nx">o</span> <span class="o">or</span> <span class="p">{}</span>
<span class="err">@</span><span class="nv">indent: </span> <span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="err">@</span><span class="nv">tab: </span> <span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
<span class="nx">del</span> <span class="err">@</span><span class="nx">options</span><span class="p">,</span> <span class="s1">&#39;operation&#39;</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">operation_sensitive</span><span class="p">()</span> <span class="nx">del</span> <span class="err">@</span><span class="nx">options</span><span class="p">,</span> <span class="s1">&#39;operation&#39;</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">operation_sensitive</span><span class="p">()</span>
<span class="nv">top: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">top_sensitive</span><span class="p">()</span> <span class="k">then</span> <span class="err">@</span><span class="nx">options</span><span class="p">.</span><span class="nx">top</span> <span class="k">else</span> <span class="nx">del</span> <span class="err">@</span><span class="nx">options</span><span class="p">,</span> <span class="s1">&#39;top&#39;</span> <span class="nv">top: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">top_sensitive</span><span class="p">()</span> <span class="k">then</span> <span class="err">@</span><span class="nx">options</span><span class="p">.</span><span class="nx">top</span> <span class="k">else</span> <span class="nx">del</span> <span class="err">@</span><span class="nx">options</span><span class="p">,</span> <span class="s1">&#39;top&#39;</span>
<span class="nv">closure: </span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">is_pure_statement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">top</span> <span class="o">and</span> <span class="nv">closure: </span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">is_pure_statement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">top</span> <span class="o">and</span>
<span class="o">not</span> <span class="err">@</span><span class="nx">options</span><span class="p">.</span><span class="nx">returns</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="k">this</span> <span class="k">instanceof</span> <span class="nx">CommentNode</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">options</span><span class="p">.</span><span class="nx">returns</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="k">this</span> <span class="k">instanceof</span> <span class="nx">CommentNode</span><span class="p">)</span> <span class="o">and</span>
<span class="o">not</span> <span class="err">@</span><span class="nx">contains</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_pure_statement</span><span class="p">()</span> <span class="o">not</span> <span class="err">@</span><span class="nx">contains</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_pure_statement</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">closure</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_closure</span><span class="p">(</span><span class="err">@</span><span class="nx">options</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_node</span><span class="p">(</span><span class="err">@</span><span class="nx">options</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-6">#</a> </div> <p>Statements converted into expressions via closure-wrapping share a scope <span class="k">if</span> <span class="nx">closure</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_closure</span><span class="p">(</span><span class="err">@</span><span class="nx">options</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_node</span><span class="p">(</span><span class="err">@</span><span class="nx">options</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Statements converted into expressions via closure-wrapping share a scope
object with their parent closure, to preserve the expected lexical scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_closure: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> object with their parent closure, to preserve the expected lexical scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_closure: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">indent: </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="err">@</span><span class="nv">tab: </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
<span class="nv">o.shared_scope: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span> <span class="nv">o.shared_scope: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span>
<span class="nx">ClosureNode</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>If the code generation wishes to use the result of a complex expression <span class="nx">ClosureNode</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>If the code generation wishes to use the result of a complex expression
in multiple places, ensure that the expression is only ever evaluated once, in multiple places, ensure that the expression is only ever evaluated once,
by assigning it to a temporary variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_reference: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> by assigning it to a temporary variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_reference: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">reference: </span><span class="nx">literal</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">())</span> <span class="nv">reference: </span><span class="nx">literal</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span>
<span class="nv">compiled: </span> <span class="k">new</span> <span class="nx">AssignNode</span><span class="p">(</span><span class="nx">reference</span><span class="p">,</span> <span class="k">this</span><span class="p">)</span> <span class="nv">compiled: </span> <span class="k">new</span> <span class="nx">AssignNode</span> <span class="nx">reference</span><span class="p">,</span> <span class="k">this</span>
<span class="p">[</span><span class="nx">compiled</span><span class="p">,</span> <span class="nx">reference</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Quick short method for the current indentation level, plus tabbing in.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">idt: </span><span class="p">(</span><span class="nx">tabs</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">compiled</span><span class="p">,</span> <span class="nx">reference</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Convenience method to grab the current indentation level, plus tabbing in.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">idt: </span><span class="p">(</span><span class="nx">tabs</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">idt: </span><span class="p">(</span><span class="err">@</span><span class="nx">indent</span> <span class="o">||</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="nv">idt: </span><span class="err">@</span><span class="nx">tab</span> <span class="o">or</span> <span class="s1">&#39;&#39;</span>
<span class="nx">idt</span> <span class="o">+=</span> <span class="nx">TAB</span> <span class="k">for</span> <span class="nx">i</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">...(</span><span class="nx">tabs</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)]</span> <span class="nv">num: </span><span class="p">(</span><span class="nx">tabs</span> <span class="o">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
<span class="nx">idt</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Does this node, or any of its children, contain a node of a certain kind?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">contains: </span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">idt</span> <span class="o">+=</span> <span class="nx">TAB</span> <span class="k">while</span> <span class="nx">num</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="nx">idt</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Does this node, or any of its children, contain a node of a certain kind?
Recursively traverses down the <em>children</em> of the nodes, yielding to a block
and returning true when the block finds a match. <code>contains</code> does not cross
scope boundaries.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">contains: </span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="err">@</span><span class="nx">children</span> <span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="err">@</span><span class="nx">children</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">block</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">block</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">contains</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">block</span> <span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">contains</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">contains</span> <span class="nx">block</span>
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Perform an in-order traversal of the AST.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">traverse: </span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Perform an in-order traversal of the AST. Crosses scope boundaries.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">traverse: </span><span class="p">(</span><span class="nx">block</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="err">@</span><span class="nx">children</span> <span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="err">@</span><span class="nx">children</span>
<span class="nx">block</span> <span class="nx">node</span> <span class="nx">block</span> <span class="nx">node</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">traverse</span> <span class="nx">block</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">traverse</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>toString representation of the node, for inspecting the parse tree.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">toString: </span><span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">node</span><span class="p">.</span><span class="nx">traverse</span> <span class="nx">block</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">traverse</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p><code>toString</code> representation of the node, for inspecting the parse tree.
This is what <code>coffee --nodes</code> prints out.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">toString: </span><span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">idt</span> <span class="o">||=</span> <span class="s1">&#39;&#39;</span> <span class="nx">idt</span> <span class="o">||=</span> <span class="s1">&#39;&#39;</span>
<span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">idt</span> <span class="o">+</span> <span class="err">@</span><span class="nx">type</span> <span class="o">+</span> <span class="p">(</span><span class="nx">child</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="nx">idt</span> <span class="o">+</span> <span class="nx">TAB</span><span class="p">)</span> <span class="k">for</span> <span class="nx">child</span> <span class="k">in</span> <span class="err">@</span><span class="nx">children</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>Default implementations of the common node methods.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unwrap: </span> <span class="o">-&gt;</span> <span class="k">this</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">idt</span> <span class="o">+</span> <span class="err">@</span><span class="nx">type</span> <span class="o">+</span> <span class="p">(</span><span class="nx">child</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="nx">idt</span> <span class="o">+</span> <span class="nx">TAB</span><span class="p">)</span> <span class="k">for</span> <span class="nx">child</span> <span class="k">in</span> <span class="err">@</span><span class="nx">children</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Default implementations of the common node identification methods. Nodes
will override these with custom logic, if needed.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unwrap: </span> <span class="o">-&gt;</span> <span class="k">this</span>
<span class="nv">children: </span> <span class="p">[]</span> <span class="nv">children: </span> <span class="p">[]</span>
<span class="nv">is_statement: </span> <span class="o">-&gt;</span> <span class="kc">false</span> <span class="nv">is_statement: </span> <span class="o">-&gt;</span> <span class="kc">false</span>
<span class="nv">is_pure_statement: </span> <span class="o">-&gt;</span> <span class="kc">false</span> <span class="nv">is_pure_statement: </span> <span class="o">-&gt;</span> <span class="kc">false</span>
<span class="nv">top_sensitive: </span> <span class="o">-&gt;</span> <span class="kc">false</span> <span class="nv">top_sensitive: </span> <span class="o">-&gt;</span> <span class="kc">false</span>
<span class="nv">operation_sensitive: </span> <span class="o">-&gt;</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>A collection of nodes, each one representing an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Expressions: </span><span class="nx">class</span> <span class="nx">Expressions</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="nv">operation_sensitive: </span> <span class="o">-&gt;</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <h3>Expressions</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>The expressions body is the list of expressions that forms the body of an
indented block of code -- the implementation of a function, a clause in an
<code>if</code>, <code>switch</code>, or <code>try</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Expressions: </span><span class="nx">class</span> <span class="nx">Expressions</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Expressions&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Expressions&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span><span class="err">@</span><span class="nv">expressions: </span><span class="nx">compact</span> <span class="nx">flatten</span> <span class="nx">nodes</span> <span class="o">or</span> <span class="p">[]</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Tack an expression on to the end of this expression list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">push: </span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="err">@</span><span class="nv">children: </span><span class="err">@</span><span class="nv">expressions: </span><span class="nx">compact</span> <span class="nx">flatten</span> <span class="nx">nodes</span> <span class="o">or</span> <span class="p">[]</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Tack an expression on to the end of this expression list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">push: </span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Tack an expression on to the beginning of this expression list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unshift: </span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Add an expression at the beginning of this expression list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unshift: </span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>If this Expressions consists of a single node, pull it back out.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unwrap: </span><span class="o">-&gt;</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>If this Expressions consists of just a single node, unwrap it by pulling
<span class="k">if</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="k">then</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">else</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Is this an empty block of code?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">empty: </span><span class="o">-&gt;</span> it back out.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unwrap: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Is the node last in this block of expressions?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_last: </span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">if</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="k">then</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">else</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Is this an empty block of code?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">empty: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Is the given node the last one in this block of expressions?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_last: </span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">l: </span><span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="nv">l: </span><span class="err">@</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">last_index: </span><span class="k">if</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">[</span><span class="nx">l</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">CommentNode</span> <span class="k">then</span> <span class="mi">2</span> <span class="k">else</span> <span class="mi">1</span> <span class="nv">last_index: </span><span class="k">if</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">[</span><span class="nx">l</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">CommentNode</span> <span class="k">then</span> <span class="mi">2</span> <span class="k">else</span> <span class="mi">1</span>
<span class="nx">node</span> <span class="o">is</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">[</span><span class="nx">l</span> <span class="o">-</span> <span class="nx">last_index</span><span class="p">]</span> <span class="nx">node</span> <span class="o">is</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">[</span><span class="nx">l</span> <span class="o">-</span> <span class="nx">last_index</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>An <strong>Expressions</strong> is the only node that can serve as the root.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">compile: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">o</span> <span class="o">||=</span> <span class="p">{}</span> <span class="nx">o</span> <span class="o">||=</span> <span class="p">{}</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span> <span class="k">then</span> <span class="k">super</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_root</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Compile each expression in the Expressions body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span> <span class="k">then</span> <span class="k">super</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_root</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="p">(</span><span class="err">@</span><span class="nx">compile_expression</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">))</span> <span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;\n&quot;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>If this is the top-level Expressions, wrap everything in a safety closure.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_root: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o.indent: </span><span class="err">@</span><span class="nv">indent: indent: </span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">no_wrap</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="nx">TAB</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">(</span><span class="err">@</span><span class="nx">compile_expression</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">))</span> <span class="k">for</span> <span class="nx">node</span> <span class="k">in</span> <span class="err">@</span><span class="nx">expressions</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;\n&quot;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>If we happen to be the top-level <strong>Expressions</strong>, wrap everything in
a safety closure, unless requested not to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_root: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o.indent: </span><span class="err">@</span><span class="nv">tab: </span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">no_wrap</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="nx">TAB</span>
<span class="nv">o.scope: </span><span class="k">new</span> <span class="nx">Scope</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span> <span class="nv">o.scope: </span><span class="k">new</span> <span class="nx">Scope</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="kc">null</span><span class="p">)</span>
<span class="nv">code: </span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">globals</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_node</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_with_declarations</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">code: </span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">globals</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_node</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_with_declarations</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">code: </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">TRAILING_WHITESPACE</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="nv">code: </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">TRAILING_WHITESPACE</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">no_wrap</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(function(){\n$code\n})();\n&quot;</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>Compile the expressions body, with declarations of all inner variables <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">no_wrap</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(function(){\n$code\n})();\n&quot;</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>Compile the expressions body for the contents of a function, with
pushed up to the top.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_with_declarations: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> declarations of all inner variables pushed up to the top.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_with_declarations: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">code: </span><span class="err">@</span><span class="nx">compile_node</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">code: </span><span class="err">@</span><span class="nx">compile_node</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">args: </span><span class="err">@</span><span class="nx">contains</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_arguments</span><span class="p">()</span> <span class="nv">args: </span><span class="err">@</span><span class="nx">contains</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_arguments</span><span class="p">()</span>
<span class="nv">code: </span><span class="s2">&quot;${@idt()}arguments = Array.prototype.slice.call(arguments, 0);\n$code&quot;</span> <span class="k">if</span> <span class="nx">args</span> <span class="nv">code: </span><span class="s2">&quot;${@tab}arguments = Array.prototype.slice.call(arguments, 0);\n$code&quot;</span> <span class="k">if</span> <span class="nx">args</span>
<span class="nv">code: </span><span class="s2">&quot;${@idt()}var ${o.scope.compiled_assignments()};\n$code&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">has_assignments</span><span class="p">(</span><span class="k">this</span><span class="p">)</span> <span class="nv">code: </span><span class="s2">&quot;${@tab}var ${o.scope.compiled_assignments()};\n$code&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">has_assignments</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
<span class="nv">code: </span><span class="s2">&quot;${@idt()}var ${o.scope.compiled_declarations()};\n$code&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">has_declarations</span><span class="p">(</span><span class="k">this</span><span class="p">)</span> <span class="nv">code: </span><span class="s2">&quot;${@tab}var ${o.scope.compiled_declarations()};\n$code&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">has_declarations</span><span class="p">(</span><span class="k">this</span><span class="p">)</span>
<span class="nx">code</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>Compiles a single expression within the expressions body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_expression: </span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>Compiles a single expression within the expressions body. If we need to
<span class="err">@</span><span class="nv">indent: </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> return the result, and it's an expression, simply return it. If it's a
<span class="nv">stmt: </span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-23">#</a> </div> <p>We need to return the result if this is the last node in the expressions body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">returns: </span><span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;returns&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="err">@</span><span class="nx">is_last</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_pure_statement</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>Return the regular compile of the node, unless we need to return the result.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="p">(</span><span class="k">if</span> <span class="nx">stmt</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="err">@</span><span class="nx">idt</span><span class="p">())</span> <span class="o">+</span> <span class="nx">node</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">top: </span><span class="kc">true</span><span class="p">}))</span> <span class="o">+</span> <span class="p">(</span><span class="k">if</span> <span class="nx">stmt</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="s1">&#39;;&#39;</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">returns</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>If it's a statement, the node knows how to return itself.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="nx">node</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">returns: </span><span class="kc">true</span><span class="p">}))</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Otherwise, we can just return the value of the expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="s2">&quot;${@idt()}return ${node.compile(o)};&quot;</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Wrap up a node as an Expressions, unless it already is one.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Expressions.wrap: </span><span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="o">-&gt;</span> statement, ask the statement to do so.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_expression: </span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">tab: </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
<span class="nv">stmt: </span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span>
<span class="nv">returns: </span><span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;returns&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="err">@</span><span class="nx">is_last</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_pure_statement</span><span class="p">()</span>
<span class="k">return</span> <span class="p">(</span><span class="k">if</span> <span class="nx">stmt</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="err">@</span><span class="nx">idt</span><span class="p">())</span> <span class="o">+</span> <span class="nx">node</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">top: </span><span class="kc">true</span><span class="p">}))</span> <span class="o">+</span> <span class="p">(</span><span class="k">if</span> <span class="nx">stmt</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="s1">&#39;;&#39;</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">returns</span>
<span class="k">return</span> <span class="nx">node</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">returns: </span><span class="kc">true</span><span class="p">}))</span> <span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span>
<span class="s2">&quot;${@tab}return ${node.compile(o)};&quot;</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>Wrap up the given nodes as an <strong>Expressions</strong>, unless it already happens
to be one.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">Expressions.wrap: </span><span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">Expressions</span> <span class="k">return</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">Expressions</span>
<span class="k">new</span> <span class="nx">Expressions</span><span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="k">new</span> <span class="nx">Expressions</span><span class="p">(</span><span class="nx">nodes</span><span class="p">)</span>
<span class="nx">statement</span> <span class="nx">Expressions</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Literals are static values that can be passed through directly into <span class="nx">statement</span> <span class="nx">Expressions</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <h3>LiteralNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Literals are static values that can be passed through directly into
JavaScript without translation, eg.: strings, numbers, true, false, null...</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.LiteralNode: </span><span class="nx">class</span> <span class="nx">LiteralNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> JavaScript without translation, such as: strings, numbers,
<code>true</code>, <code>false</code>, <code>null</code>...</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.LiteralNode: </span><span class="nx">class</span> <span class="nx">LiteralNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Literal&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Literal&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">value: </span><span class="nx">value</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>Break and continue must be treated as statements -- they lose their meaning <span class="err">@</span><span class="nv">value: </span><span class="nx">value</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Break and continue must be treated as pure statements -- they lose their
when wrapped in a closure.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-&gt;</span> meaning when wrapped in a closure.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;break&#39;</span> <span class="o">or</span> <span class="err">@</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;continue&#39;</span> <span class="err">@</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;break&#39;</span> <span class="o">or</span> <span class="err">@</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;continue&#39;</span>
<span class="nv">is_pure_statement: </span><span class="nx">LiteralNode</span><span class="o">::</span><span class="nx">is_statement</span> <span class="nv">is_pure_statement: </span><span class="nx">LiteralNode</span><span class="o">::</span><span class="nx">is_statement</span>
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -110,7 +127,8 @@ when wrapped in a closure.</p> </td> <td class="code">
<span class="s2">&quot;$idt$@value$end&quot;</span> <span class="s2">&quot;$idt$@value$end&quot;</span>
<span class="nv">toString: </span><span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">toString: </span><span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot; \&quot;$@value\&quot;&quot;</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>Return an expression, or wrap it in a closure and return it.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ReturnNode: </span><span class="nx">class</span> <span class="nx">ReturnNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="s2">&quot; \&quot;$@value\&quot;&quot;</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <h3>ReturnNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>A <code>return</code> is a <em>pure_statement</em> -- wrapping it in a closure wouldn't
make sense.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ReturnNode: </span><span class="nx">class</span> <span class="nx">ReturnNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Return&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Return&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -118,17 +136,14 @@ when wrapped in a closure.</p> </td> <td class="code">
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">expression</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">returns: </span><span class="kc">true</span><span class="p">}))</span> <span class="k">if</span> <span class="err">@</span><span class="nx">expression</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">return</span> <span class="err">@</span><span class="nx">expression</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">returns: </span><span class="kc">true</span><span class="p">}))</span> <span class="k">if</span> <span class="err">@</span><span class="nx">expression</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span>
<span class="s2">&quot;${@idt()}return ${@expression.compile(o)};&quot;</span> <span class="s2">&quot;${@tab}return ${@expression.compile(o)};&quot;</span>
<span class="nx">statement</span> <span class="nx">ReturnNode</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>A value, indexed or dotted into, or vanilla.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ValueNode: </span><span class="nx">class</span> <span class="nx">ValueNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="nx">statement</span> <span class="nx">ReturnNode</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <h3>ValueNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>A value, variable or literal or parenthesized, indexed or dotted into,
or vanilla.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ValueNode: </span><span class="nx">class</span> <span class="nx">ValueNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Value&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Value&#39;</span>
<span class="nv">SOAK: </span><span class="s2">&quot; == undefined ? undefined : &quot;</span> <span class="nv">SOAK: </span><span class="s2">&quot; == undefined ? undefined : &quot;</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <p>A <strong>ValueNode</strong> has a base and a list of property accesses.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">base</span><span class="p">,</span> <span class="nx">properties</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span> <span class="nx">flatten</span> <span class="p">[</span><span class="err">@</span><span class="nv">base: </span><span class="nx">base</span><span class="p">,</span> <span class="err">@</span><span class="nv">properties: </span><span class="p">(</span><span class="nx">properties</span> <span class="o">or</span> <span class="p">[])]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>Add a property access to the list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">push: </span><span class="p">(</span><span class="nx">prop</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">base</span><span class="p">,</span> <span class="nx">properties</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span> <span class="nx">flatten</span> <span class="p">[</span><span class="err">@</span><span class="nv">base: </span><span class="nx">base</span><span class="p">,</span> <span class="err">@</span><span class="nv">properties: </span><span class="p">(</span><span class="nx">properties</span> <span class="o">or</span> <span class="p">[])]</span>
<span class="nv">push: </span><span class="p">(</span><span class="nx">prop</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">prop</span><span class="p">)</span> <span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">prop</span><span class="p">)</span>
<span class="err">@</span><span class="nx">children</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">prop</span><span class="p">)</span> <span class="err">@</span><span class="nx">children</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">prop</span><span class="p">)</span>
<span class="k">this</span> <span class="k">this</span>
@@ -137,9 +152,7 @@ when wrapped in a closure.</p> </td> <td class="code">
<span class="kc">true</span> <span class="kc">true</span>
<span class="nv">has_properties: </span><span class="o">-&gt;</span> <span class="nv">has_properties: </span><span class="o">-&gt;</span>
<span class="o">!!</span><span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">!!</span><span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Some boolean checks for the benefit of other nodes.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_array: </span><span class="o">-&gt;</span>
<span class="nv">is_array: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">ArrayNode</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">has_properties</span><span class="p">()</span> <span class="err">@</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">ArrayNode</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">has_properties</span><span class="p">()</span>
<span class="nv">is_object: </span><span class="o">-&gt;</span> <span class="nv">is_object: </span><span class="o">-&gt;</span>
@@ -149,13 +162,13 @@ when wrapped in a closure.</p> </td> <td class="code">
<span class="err">@</span><span class="nx">has_properties</span><span class="p">()</span> <span class="o">and</span> <span class="err">@</span><span class="nx">properties</span><span class="p">[</span><span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">SliceNode</span> <span class="err">@</span><span class="nx">has_properties</span><span class="p">()</span> <span class="o">and</span> <span class="err">@</span><span class="nx">properties</span><span class="p">[</span><span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">SliceNode</span>
<span class="nv">is_arguments: </span><span class="o">-&gt;</span> <span class="nv">is_arguments: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;arguments&#39;</span> <span class="err">@</span><span class="nx">base</span><span class="p">.</span><span class="nx">value</span> <span class="o">is</span> <span class="s1">&#39;arguments&#39;</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>The value can be unwrapped as its inner node, if there are no attached
properties.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unwrap: </span><span class="o">-&gt;</span>
<span class="nv">unwrap: </span><span class="o">-&gt;</span> <span class="k">if</span> <span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="k">this</span> <span class="k">else</span> <span class="err">@</span><span class="nx">base</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>Values are considered to be statements if their base is a statement.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-&gt;</span>
<span class="k">if</span> <span class="err">@</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="k">this</span> <span class="k">else</span> <span class="err">@</span><span class="nx">base</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>Values are statements if their base is a statement.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-&gt;</span> <span class="err">@</span><span class="nx">base</span><span class="p">.</span><span class="nx">is_statement</span> <span class="o">and</span> <span class="err">@</span><span class="nx">base</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">has_properties</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>We compile a value to JavaScript by compiling and joining each property.
<span class="err">@</span><span class="nx">base</span><span class="p">.</span><span class="nx">is_statement</span> <span class="o">and</span> <span class="err">@</span><span class="nx">base</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">has_properties</span><span class="p">()</span> Things get much more insteresting if the chain of properties has <em>soak</em>
operators <code>?.</code> interspersed. Then we have to take care not to accidentally
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> evaluate a anything twice when building the soak chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">soaked: </span> <span class="kc">false</span> <span class="nv">soaked: </span> <span class="kc">false</span>
<span class="nv">only: </span> <span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;only_first&#39;</span><span class="p">)</span> <span class="nv">only: </span> <span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;only_first&#39;</span><span class="p">)</span>
<span class="nv">op: </span> <span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;operation&#39;</span><span class="p">)</span> <span class="nv">op: </span> <span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;operation&#39;</span><span class="p">)</span>
@@ -179,7 +192,7 @@ when wrapped in a closure.</p> </td> <td class="code">
<span class="nx">complete</span> <span class="o">+=</span> <span class="nx">part</span> <span class="nx">complete</span> <span class="o">+=</span> <span class="nx">part</span>
<span class="err">@</span><span class="nv">last: </span><span class="nx">part</span> <span class="err">@</span><span class="nv">last: </span><span class="nx">part</span>
<span class="k">if</span> <span class="nx">op</span> <span class="o">and</span> <span class="nx">soaked</span> <span class="k">then</span> <span class="s2">&quot;($complete)&quot;</span> <span class="k">else</span> <span class="nx">complete</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-33">#</a> </div> <p>Pass through CoffeeScript comments into JavaScript comments at the <span class="k">if</span> <span class="nx">op</span> <span class="o">and</span> <span class="nx">soaked</span> <span class="k">then</span> <span class="s2">&quot;($complete)&quot;</span> <span class="k">else</span> <span class="nx">complete</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <h3>CommentNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>CoffeeScript passes through comments as JavaScript comments at the
same position.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.CommentNode: </span><span class="nx">class</span> <span class="nx">CommentNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> same position.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.CommentNode: </span><span class="nx">class</span> <span class="nx">CommentNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Comment&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Comment&#39;</span>
@@ -188,34 +201,32 @@ same position.</p> </td> <td class="code">
<span class="k">this</span> <span class="k">this</span>
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot;${@idt()}//&quot;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">lines</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;\n${@idt()}//&quot;</span><span class="p">)</span> <span class="s2">&quot;$@tab//&quot;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">lines</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;\n$@tab//&quot;</span><span class="p">)</span>
<span class="nx">statement</span> <span class="nx">CommentNode</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <p>Node for a function invocation. Takes care of converting super() calls into <span class="nx">statement</span> <span class="nx">CommentNode</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <h3>CallNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>Node for a function invocation. Takes care of converting <code>super()</code> calls into
calls against the prototype's function of the same name.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.CallNode: </span><span class="nx">class</span> <span class="nx">CallNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> calls against the prototype's function of the same name.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.CallNode: </span><span class="nx">class</span> <span class="nx">CallNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Call&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Call&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">variable</span><span class="p">,</span> <span class="nx">args</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">variable</span><span class="p">,</span> <span class="nx">args</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span> <span class="nx">flatten</span> <span class="p">[</span><span class="err">@</span><span class="nv">variable: </span><span class="nx">variable</span><span class="p">,</span> <span class="err">@</span><span class="nv">args: </span><span class="p">(</span><span class="nx">args</span> <span class="o">or</span> <span class="p">[])]</span> <span class="err">@</span><span class="nv">children: </span> <span class="nx">flatten</span> <span class="p">[</span><span class="err">@</span><span class="nv">variable: </span><span class="nx">variable</span><span class="p">,</span> <span class="err">@</span><span class="nv">args: </span><span class="p">(</span><span class="nx">args</span> <span class="o">or</span> <span class="p">[])]</span>
<span class="err">@</span><span class="nv">prefix: </span> <span class="s1">&#39;&#39;</span> <span class="err">@</span><span class="nv">prefix: </span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>Tag this invocation as creating a new instance.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">new_instance: </span><span class="o">-&gt;</span>
<span class="nv">new_instance: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">prefix: </span><span class="s1">&#39;new &#39;</span> <span class="err">@</span><span class="nv">prefix: </span><span class="s1">&#39;new &#39;</span>
<span class="k">this</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>Add an argument to the call's arugment list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">push: </span><span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">push: </span><span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">args</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="err">@</span><span class="nx">args</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arg</span><span class="p">)</span>
<span class="err">@</span><span class="nx">children</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arg</span><span class="p">)</span> <span class="err">@</span><span class="nx">children</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arg</span><span class="p">)</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</a> </div> <p>Compile a vanilla function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>Compile a vanilla function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_splat</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">args</span><span class="p">[</span><span class="err">@</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span> <span class="k">return</span> <span class="err">@</span><span class="nx">compile_splat</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">args</span><span class="p">[</span><span class="err">@</span><span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span>
<span class="nv">args: </span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="err">@</span><span class="nx">args</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;, &#39;</span><span class="p">)</span> <span class="nv">args: </span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="err">@</span><span class="nx">args</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;, &#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_super</span><span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">variable</span> <span class="o">is</span> <span class="s1">&#39;super&#39;</span> <span class="k">return</span> <span class="err">@</span><span class="nx">compile_super</span><span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">variable</span> <span class="o">is</span> <span class="s1">&#39;super&#39;</span>
<span class="s2">&quot;$@prefix${@variable.compile(o)}($args)&quot;</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</a> </div> <p>Compile a call against the superclass's implementation of the current function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_super: </span><span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="s2">&quot;$@prefix${@variable.compile(o)}($args)&quot;</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p><code>super()</code> is converted into a call against the superclass's implementation
of the current function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_super: </span><span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">methname: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">method</span><span class="p">.</span><span class="nx">name</span> <span class="nv">methname: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">method</span><span class="p">.</span><span class="nx">name</span>
<span class="nv">meth: </span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">method</span><span class="p">.</span><span class="nx">proto</span> <span class="nv">meth: </span><span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">method</span><span class="p">.</span><span class="nx">proto</span>
<span class="s2">&quot;${o.scope.method.proto}.__superClass__.$methname&quot;</span> <span class="s2">&quot;${o.scope.method.proto}.__superClass__.$methname&quot;</span>
<span class="k">else</span> <span class="k">else</span>
<span class="s2">&quot;$methname.__superClass__.constructor&quot;</span> <span class="s2">&quot;$methname.__superClass__.constructor&quot;</span>
<span class="s2">&quot;$meth.call(this${ if args.length then &#39;, &#39; else &#39;&#39; }$args)&quot;</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>Compile a function call being passed variable arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_splat: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="s2">&quot;$meth.call(this${ if args.length then &#39;, &#39; else &#39;&#39; }$args)&quot;</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>If you call a function with a splat, it's converted into a JavaScript
<code>.apply()</code> call to allow the variable-length arguments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_splat: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">meth: </span><span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="nv">meth: </span><span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nv">obj: </span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">source</span> <span class="o">or</span> <span class="s1">&#39;this&#39;</span> <span class="nv">obj: </span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">source</span> <span class="o">or</span> <span class="s1">&#39;this&#39;</span>
<span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\(/</span><span class="p">)</span> <span class="k">if</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="sr">/\(/</span><span class="p">)</span>
@@ -226,8 +237,9 @@ calls against the prototype's function of the same name.</p> </td>
<span class="nv">code: </span><span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="nv">code: </span><span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nv">code: </span><span class="k">if</span> <span class="nx">arg</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;[$code]&quot;</span> <span class="nv">code: </span><span class="k">if</span> <span class="nx">arg</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;[$code]&quot;</span>
<span class="k">if</span> <span class="nx">i</span> <span class="o">is</span> <span class="mi">0</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;.concat($code)&quot;</span> <span class="k">if</span> <span class="nx">i</span> <span class="o">is</span> <span class="mi">0</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;.concat($code)&quot;</span>
<span class="s2">&quot;$@prefix$meth.apply($obj, ${ args.join(&#39;&#39;) })&quot;</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-38">#</a> </div> <p>Node to extend an object's prototype with an ancestor object. <span class="s2">&quot;$@prefix$meth.apply($obj, ${ args.join(&#39;&#39;) })&quot;</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <h3>ExtendsNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Node to extend an object's prototype with an ancestor object.
After goog.inherits from the Closure Library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ExtendsNode: </span><span class="nx">class</span> <span class="nx">ExtendsNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> After <code>goog.inherits</code> from the
<a href="http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html">Closure Library</a>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ExtendsNode: </span><span class="nx">class</span> <span class="nx">ExtendsNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Extends&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Extends&#39;</span>
<span class="nv">code: </span><span class="s1">&#39;&#39;&#39;</span> <span class="nv">code: </span><span class="s1">&#39;&#39;&#39;</span>
@@ -241,11 +253,11 @@ After goog.inherits from the Closure Library.</p> </td>
<span class="s1"> &#39;&#39;&#39;</span> <span class="s1"> &#39;&#39;&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">child</span><span class="p">,</span> <span class="nx">parent</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">child</span><span class="p">,</span> <span class="nx">parent</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span> <span class="p">[</span><span class="err">@</span><span class="nv">child: </span><span class="nx">child</span><span class="p">,</span> <span class="err">@</span><span class="nv">parent: </span><span class="nx">parent</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-39">#</a> </div> <p>Hooking one constructor into another's prototype chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="err">@</span><span class="nv">children: </span> <span class="p">[</span><span class="err">@</span><span class="nv">child: </span><span class="nx">child</span><span class="p">,</span> <span class="err">@</span><span class="nv">parent: </span><span class="nx">parent</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Hooks one constructor into another's prototype chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="s1">&#39;__extends&#39;</span><span class="p">,</span> <span class="err">@</span><span class="nx">code</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="s1">&#39;__extends&#39;</span><span class="p">,</span> <span class="err">@</span><span class="nx">code</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
<span class="nv">ref: </span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;__extends&#39;</span><span class="p">)</span> <span class="nv">ref: </span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;__extends&#39;</span><span class="p">)</span>
<span class="nv">call: </span><span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">ref</span><span class="p">,</span> <span class="p">[</span><span class="err">@</span><span class="nx">child</span><span class="p">,</span> <span class="err">@</span><span class="nx">parent</span><span class="p">]</span> <span class="nv">call: </span><span class="k">new</span> <span class="nx">CallNode</span> <span class="nx">ref</span><span class="p">,</span> <span class="p">[</span><span class="err">@</span><span class="nx">child</span><span class="p">,</span> <span class="err">@</span><span class="nx">parent</span><span class="p">]</span>
<span class="nx">call</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</a> </div> <p>A dotted accessor into a part of a value, or the :: shorthand for <span class="nx">call</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <h3>AccessorNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>A <code>.</code> accessor into a property of a value, or the <code>::</code> shorthand for
an accessor into the object's prototype.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.AccessorNode: </span><span class="nx">class</span> <span class="nx">AccessorNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> an accessor into the object's prototype.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.AccessorNode: </span><span class="nx">class</span> <span class="nx">AccessorNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Accessor&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Accessor&#39;</span>
@@ -256,7 +268,7 @@ an accessor into the object's prototype.</p> </td> <td c
<span class="k">this</span> <span class="k">this</span>
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s1">&#39;.&#39;</span> <span class="o">+</span> <span class="p">(</span><span class="k">if</span> <span class="err">@</span><span class="nx">prototype</span> <span class="k">then</span> <span class="s1">&#39;prototype.&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="err">@</span><span class="nx">name</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>An indexed accessor into a part of an array or object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.IndexNode: </span><span class="nx">class</span> <span class="nx">IndexNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="s1">&#39;.&#39;</span> <span class="o">+</span> <span class="p">(</span><span class="k">if</span> <span class="err">@</span><span class="nx">prototype</span> <span class="k">then</span> <span class="s1">&#39;prototype.&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="err">@</span><span class="nx">name</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <h3>IndexNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>An indexed accessor into an array or object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.IndexNode: </span><span class="nx">class</span> <span class="nx">IndexNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Index&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Index&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -265,21 +277,19 @@ an accessor into the object's prototype.</p> </td> <td c
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">idx: </span><span class="err">@</span><span class="nx">index</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="nv">idx: </span><span class="err">@</span><span class="nx">index</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="s2">&quot;[$idx]&quot;</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>A range literal. Ranges can be used to extract portions (slices) of arrays, <span class="s2">&quot;[$idx]&quot;</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <h3>RangeNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>A range literal. Ranges can be used to extract portions (slices) of arrays,
or to specify a range for list comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.RangeNode: </span><span class="nx">class</span> <span class="nx">RangeNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> to specify a range for comprehensions, or as a value, to be expanded into the
corresponding array of integers at runtime.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.RangeNode: </span><span class="nx">class</span> <span class="nx">RangeNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Range&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Range&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">,</span> <span class="nx">exclusive</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">,</span> <span class="nx">exclusive</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span> <span class="p">[</span><span class="err">@</span><span class="nv">from: </span><span class="nx">from</span><span class="p">,</span> <span class="err">@</span><span class="nv">to: </span><span class="nx">to</span><span class="p">]</span> <span class="err">@</span><span class="nv">children: </span> <span class="p">[</span><span class="err">@</span><span class="nv">from: </span><span class="nx">from</span><span class="p">,</span> <span class="err">@</span><span class="nv">to: </span><span class="nx">to</span><span class="p">]</span>
<span class="err">@</span><span class="nv">exclusive: </span><span class="o">!!</span><span class="nx">exclusive</span> <span class="err">@</span><span class="nv">exclusive: </span><span class="o">!!</span><span class="nx">exclusive</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>Compiles the range's source variables -- where it starts and where it ends.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_variables: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">tab: </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
<span class="nv">compile_variables: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">indent: </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
<span class="p">[</span><span class="err">@</span><span class="nx">from_var</span><span class="p">,</span> <span class="err">@</span><span class="nx">to_var</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">(),</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()]</span> <span class="p">[</span><span class="err">@</span><span class="nx">from_var</span><span class="p">,</span> <span class="err">@</span><span class="nx">to_var</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">(),</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()]</span>
<span class="p">[</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="err">@</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span> <span class="p">[</span><span class="nx">from</span><span class="p">,</span> <span class="nx">to</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="err">@</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span>
<span class="s2">&quot;$@from_var = $from; $@to_var = $to;\n${@idt()}&quot;</span> <span class="s2">&quot;$@from_var = $from; $@to_var = $to;\n$@tab&quot;</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</a> </div> <p>When compiled normally, the range returns the contents of the <em>for loop</em>
needed to iterate over the values in the range. Used by comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_array</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">index</span> <span class="k">return</span> <span class="err">@</span><span class="nx">compile_array</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">index</span>
<span class="nv">idx: </span> <span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;index&#39;</span> <span class="nv">idx: </span> <span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;index&#39;</span>
<span class="nv">step: </span> <span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;step&#39;</span> <span class="nv">step: </span> <span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;step&#39;</span>
@@ -289,13 +299,13 @@ or to specify a range for list comprehensions.</p> </td>
<span class="nv">intro: </span> <span class="s2">&quot;($@from_var &lt;= $@to_var ? $idx&quot;</span> <span class="nv">intro: </span> <span class="s2">&quot;($@from_var &lt;= $@to_var ? $idx&quot;</span>
<span class="nv">compare: </span> <span class="s2">&quot;$intro &lt;$equals $@to_var : $idx &gt;$equals $@to_var)&quot;</span> <span class="nv">compare: </span> <span class="s2">&quot;$intro &lt;$equals $@to_var : $idx &gt;$equals $@to_var)&quot;</span>
<span class="nv">incr: </span> <span class="s2">&quot;$intro += $step : $idx -= $step)&quot;</span> <span class="nv">incr: </span> <span class="s2">&quot;$intro += $step : $idx -= $step)&quot;</span>
<span class="s2">&quot;$vars; $compare; $incr&quot;</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>Expand the range into the equivalent array, if it's not being used as <span class="s2">&quot;$vars; $compare; $incr&quot;</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>When used as a value, expand the range into the equivalent array. In the
part of a comprehension, slice, or splice. future, the code this generates should probably be cleaned up by handwriting
TODO: This generates pretty ugly code ... shrink it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_array: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> it instead of wrapping nodes.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_array: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">name: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span> <span class="nv">name: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span>
<span class="nv">body: </span><span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">literal</span><span class="p">(</span><span class="nx">name</span><span class="p">)])</span> <span class="nv">body: </span><span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">literal</span><span class="p">(</span><span class="nx">name</span><span class="p">)])</span>
<span class="nv">arr: </span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="k">new</span> <span class="nx">ForNode</span><span class="p">(</span><span class="nx">body</span><span class="p">,</span> <span class="p">{</span><span class="nv">source: </span><span class="p">(</span><span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="k">this</span><span class="p">))},</span> <span class="nx">literal</span><span class="p">(</span><span class="nx">name</span><span class="p">))])</span> <span class="nv">arr: </span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="k">new</span> <span class="nx">ForNode</span><span class="p">(</span><span class="nx">body</span><span class="p">,</span> <span class="p">{</span><span class="nv">source: </span><span class="p">(</span><span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="k">this</span><span class="p">))},</span> <span class="nx">literal</span><span class="p">(</span><span class="nx">name</span><span class="p">))])</span>
<span class="p">(</span><span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">CallNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">CodeNode</span><span class="p">([],</span> <span class="nx">arr</span><span class="p">)))).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <p>An array slice literal. Unlike JavaScript's Array#slice, the second parameter <span class="p">(</span><span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">CallNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">CodeNode</span><span class="p">([],</span> <span class="nx">arr</span><span class="p">)))).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <p>An array slice literal. Unlike JavaScript's Array#slice, the second parameter
specifies the index of the end of the slice (just like the first parameter) specifies the index of the end of the slice (just like the first parameter)
is the index of the beginning.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.SliceNode: </span><span class="nx">class</span> <span class="nx">SliceNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> is the index of the beginning.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.SliceNode: </span><span class="nx">class</span> <span class="nx">SliceNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Slice&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Slice&#39;</span>
@@ -308,11 +318,11 @@ is the index of the beginning.</p> </td> <td class="code
<span class="nv">from: </span> <span class="err">@</span><span class="nx">range</span><span class="p">.</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">from: </span> <span class="err">@</span><span class="nx">range</span><span class="p">.</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">to: </span> <span class="err">@</span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">to: </span> <span class="err">@</span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">plus_part: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">range</span><span class="p">.</span><span class="nx">exclusive</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="s1">&#39; + 1&#39;</span> <span class="nv">plus_part: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">range</span><span class="p">.</span><span class="nx">exclusive</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="s1">&#39; + 1&#39;</span>
<span class="s2">&quot;.slice($from, $to$plus_part)&quot;</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>An object literal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ObjectNode: </span><span class="nx">class</span> <span class="nx">ObjectNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="s2">&quot;.slice($from, $to$plus_part)&quot;</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <p>An object literal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ObjectNode: </span><span class="nx">class</span> <span class="nx">ObjectNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Object&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Object&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span><span class="err">@</span><span class="nv">objects: </span><span class="err">@</span><span class="nv">properties: </span><span class="nx">props</span> <span class="o">or</span> <span class="p">[]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>All the mucking about with commas is to make sure that CommentNodes and <span class="err">@</span><span class="nv">children: </span><span class="err">@</span><span class="nv">objects: </span><span class="err">@</span><span class="nv">properties: </span><span class="nx">props</span> <span class="o">or</span> <span class="p">[]</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</a> </div> <p>All the mucking about with commas is to make sure that CommentNodes and
AssignNodes get interleaved correctly, with no trailing commas or AssignNodes get interleaved correctly, with no trailing commas or
commas affixed to comments. TODO: Extract this and add it to ArrayNode.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> commas affixed to comments. TODO: Extract this and add it to ArrayNode.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o.indent: </span><span class="err">@</span><span class="nx">idt</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="nv">o.indent: </span><span class="err">@</span><span class="nx">idt</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
@@ -326,7 +336,7 @@ commas affixed to comments. TODO: Extract this and add it to ArrayNode.</p>
<span class="nx">indent</span> <span class="o">+</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="nx">join</span> <span class="nx">indent</span> <span class="o">+</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="nx">join</span>
<span class="nv">props: </span><span class="nx">props</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="nv">props: </span><span class="nx">props</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="nv">inner: </span><span class="k">if</span> <span class="nx">props</span> <span class="k">then</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">props</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span> <span class="nv">inner: </span><span class="k">if</span> <span class="nx">props</span> <span class="k">then</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">props</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="s2">&quot;{$inner}&quot;</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>A class literal, including optional superclass and constructor.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ClassNode: </span><span class="nx">class</span> <span class="nx">ClassNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="s2">&quot;{$inner}&quot;</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <p>A class literal, including optional superclass and constructor.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ClassNode: </span><span class="nx">class</span> <span class="nx">ClassNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Class&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Class&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">variable</span><span class="p">,</span> <span class="nx">parent</span><span class="p">,</span> <span class="nx">props</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">variable</span><span class="p">,</span> <span class="nx">parent</span><span class="p">,</span> <span class="nx">props</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -365,7 +375,7 @@ commas affixed to comments. TODO: Extract this and add it to ArrayNode.</p>
<span class="nv">returns: </span> <span class="k">if</span> <span class="nx">ret</span> <span class="k">then</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">idt</span><span class="p">()</span> <span class="o">+</span> <span class="s1">&#39;return &#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;;&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span> <span class="nv">returns: </span> <span class="k">if</span> <span class="nx">ret</span> <span class="k">then</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">idt</span><span class="p">()</span> <span class="o">+</span> <span class="s1">&#39;return &#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;;&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="s2">&quot;$construct$extension$props$returns&quot;</span> <span class="s2">&quot;$construct$extension$props$returns&quot;</span>
<span class="nx">statement</span> <span class="nx">ClassNode</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>An array literal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ArrayNode: </span><span class="nx">class</span> <span class="nx">ArrayNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="nx">statement</span> <span class="nx">ClassNode</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>An array literal.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ArrayNode: </span><span class="nx">class</span> <span class="nx">ArrayNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Array&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Array&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">objects</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">objects</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -382,8 +392,8 @@ commas affixed to comments. TODO: Extract this and add it to ArrayNode.</p>
<span class="k">else</span> <span class="k">else</span>
<span class="s2">&quot;$code, &quot;</span> <span class="s2">&quot;$code, &quot;</span>
<span class="nv">objects: </span><span class="nx">objects</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="nv">objects: </span><span class="nx">objects</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="nv">ending: </span><span class="k">if</span> <span class="nx">objects</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;\n&#39;</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">then</span> <span class="s2">&quot;\n${@idt()}]&quot;</span> <span class="k">else</span> <span class="s1">&#39;]&#39;</span> <span class="nv">ending: </span><span class="k">if</span> <span class="nx">objects</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s1">&#39;\n&#39;</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">then</span> <span class="s2">&quot;\n$@tab]&quot;</span> <span class="k">else</span> <span class="s1">&#39;]&#39;</span>
<span class="s2">&quot;[$objects$ending&quot;</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>A faux-node that is never created by the grammar, but is used during <span class="s2">&quot;[$objects$ending&quot;</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-65">#</a> </div> <p>A faux-node that is never created by the grammar, but is used during
code generation to generate a quick "array.push(value)" tree of nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">PushNode: exports.PushNode: </span><span class="p">{</span> code generation to generate a quick "array.push(value)" tree of nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">PushNode: exports.PushNode: </span><span class="p">{</span>
<span class="nv">wrap: </span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">wrap: </span><span class="p">(</span><span class="nx">array</span><span class="p">,</span> <span class="nx">expressions</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -393,14 +403,14 @@ code generation to generate a quick "array.push(value)" tree of nodes.</p>
<span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="nx">array</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;push&#39;</span><span class="p">))]),</span> <span class="p">[</span><span class="nx">expr</span><span class="p">]</span> <span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="nx">array</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;push&#39;</span><span class="p">))]),</span> <span class="p">[</span><span class="nx">expr</span><span class="p">]</span>
<span class="p">)])</span> <span class="p">)])</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>A faux-node used to wrap an expressions body in a closure.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ClosureNode: exports.ClosureNode: </span><span class="p">{</span> <span class="p">}</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-66">#</a> </div> <p>A faux-node used to wrap an expressions body in a closure.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ClosureNode: exports.ClosureNode: </span><span class="p">{</span>
<span class="nv">wrap: </span><span class="p">(</span><span class="nx">expressions</span><span class="p">,</span> <span class="nx">statement</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">wrap: </span><span class="p">(</span><span class="nx">expressions</span><span class="p">,</span> <span class="nx">statement</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">func: </span><span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">CodeNode</span><span class="p">([],</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">expressions</span><span class="p">])))</span> <span class="nv">func: </span><span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">CodeNode</span><span class="p">([],</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">expressions</span><span class="p">])))</span>
<span class="nv">call: </span><span class="k">new</span> <span class="nx">CallNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">func</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;call&#39;</span><span class="p">))]),</span> <span class="p">[</span><span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;this&#39;</span><span class="p">)])</span> <span class="nv">call: </span><span class="k">new</span> <span class="nx">CallNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">func</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;call&#39;</span><span class="p">))]),</span> <span class="p">[</span><span class="nx">literal</span><span class="p">(</span><span class="s1">&#39;this&#39;</span><span class="p">)])</span>
<span class="k">if</span> <span class="nx">statement</span> <span class="k">then</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">call</span><span class="p">])</span> <span class="k">else</span> <span class="nx">call</span> <span class="k">if</span> <span class="nx">statement</span> <span class="k">then</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="nx">call</span><span class="p">])</span> <span class="k">else</span> <span class="nx">call</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>Setting the value of a local variable, or the value of an object property.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.AssignNode: </span><span class="nx">class</span> <span class="nx">AssignNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="p">}</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <p>Setting the value of a local variable, or the value of an object property.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.AssignNode: </span><span class="nx">class</span> <span class="nx">AssignNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Assign&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Assign&#39;</span>
<span class="nv">PROTO_ASSIGN: </span><span class="sr">/^(\S+)\.prototype/</span> <span class="nv">PROTO_ASSIGN: </span><span class="sr">/^(\S+)\.prototype/</span>
@@ -435,15 +445,15 @@ code generation to generate a quick "array.push(value)" tree of nodes.</p>
<span class="k">return</span> <span class="s2">&quot;$name: $val&quot;</span> <span class="k">if</span> <span class="err">@</span><span class="nx">context</span> <span class="o">is</span> <span class="s1">&#39;object&#39;</span> <span class="k">return</span> <span class="s2">&quot;$name: $val&quot;</span> <span class="k">if</span> <span class="err">@</span><span class="nx">context</span> <span class="o">is</span> <span class="s1">&#39;object&#39;</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">find</span> <span class="nx">name</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">is_value</span><span class="p">()</span> <span class="o">and</span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">has_properties</span><span class="p">()</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">find</span> <span class="nx">name</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">is_value</span><span class="p">()</span> <span class="o">and</span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">has_properties</span><span class="p">()</span>
<span class="nv">val: </span><span class="s2">&quot;$name = $val&quot;</span> <span class="nv">val: </span><span class="s2">&quot;$name = $val&quot;</span>
<span class="k">return</span> <span class="s2">&quot;${@idt()}$val;&quot;</span> <span class="k">if</span> <span class="nx">stmt</span> <span class="k">return</span> <span class="s2">&quot;$@tab$val;&quot;</span> <span class="k">if</span> <span class="nx">stmt</span>
<span class="nv">val: </span><span class="s2">&quot;($val)&quot;</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">top</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">returns</span> <span class="nv">val: </span><span class="s2">&quot;($val)&quot;</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">top</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">returns</span>
<span class="nv">val: </span><span class="s2">&quot;${@idt()}return $val&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">returns</span> <span class="nv">val: </span><span class="s2">&quot;${@tab}return $val&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">returns</span>
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Implementation of recursive pattern matching, when assigning array or <span class="nx">val</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <p>Implementation of recursive pattern matching, when assigning array or
object literals to a value. Peeks at their properties to assign inner names. object literals to a value. Peeks at their properties to assign inner names.
See: <a href='http://wiki.ecmascript.org/doku.php?id=harmony:destructuring'>http://wiki.ecmascript.org/doku.php?id=harmony:destructuring</a></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_pattern_match: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> See: <a href='http://wiki.ecmascript.org/doku.php?id=harmony:destructuring'>http://wiki.ecmascript.org/doku.php?id=harmony:destructuring</a></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_pattern_match: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">val_var: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span> <span class="nv">val_var: </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span>
<span class="nv">value: </span><span class="k">if</span> <span class="err">@</span><span class="nx">value</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">then</span> <span class="nx">ClosureNode</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="err">@</span><span class="nx">value</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">value</span> <span class="nv">value: </span><span class="k">if</span> <span class="err">@</span><span class="nx">value</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">then</span> <span class="nx">ClosureNode</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="err">@</span><span class="nx">value</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">value</span>
<span class="nv">assigns: </span><span class="p">[</span><span class="s2">&quot;${@idt()}$val_var = ${ value.compile(o) };&quot;</span><span class="p">]</span> <span class="nv">assigns: </span><span class="p">[</span><span class="s2">&quot;$@tab$val_var = ${ value.compile(o) };&quot;</span><span class="p">]</span>
<span class="nv">o.top: </span><span class="kc">true</span> <span class="nv">o.top: </span><span class="kc">true</span>
<span class="nv">o.as_statement: </span><span class="kc">true</span> <span class="nv">o.as_statement: </span><span class="kc">true</span>
<span class="k">for</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span> <span class="k">for</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="err">@</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span>
@@ -457,7 +467,7 @@ See: <a href='http://wiki.ecmascript.org/doku.php?id=harmony:destructuring'>http
<span class="nv">val: </span><span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="nx">val_var</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">access_class</span><span class="p">(</span><span class="nx">idx</span><span class="p">)])</span> <span class="nv">val: </span><span class="k">new</span> <span class="nx">ValueNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="nx">val_var</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">access_class</span><span class="p">(</span><span class="nx">idx</span><span class="p">)])</span>
<span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">new</span> <span class="nx">AssignNode</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">val</span><span class="p">).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">))</span> <span class="nx">assigns</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">new</span> <span class="nx">AssignNode</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">val</span><span class="p">).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">))</span>
<span class="nv">code: </span><span class="nx">assigns</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;\n&quot;</span><span class="p">)</span> <span class="nv">code: </span><span class="nx">assigns</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;\n&quot;</span><span class="p">)</span>
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">&quot;\n${@idt()}return ${ @variable.compile(o) };&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">returns</span> <span class="nx">code</span> <span class="o">+=</span> <span class="s2">&quot;\n${@tab}return ${ @variable.compile(o) };&quot;</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">returns</span>
<span class="nx">code</span> <span class="nx">code</span>
<span class="nv">compile_splice: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_splice: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -468,7 +478,7 @@ See: <a href='http://wiki.ecmascript.org/doku.php?id=harmony:destructuring'>http
<span class="nv">from: </span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">from: </span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">to: </span> <span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; - &#39;</span> <span class="o">+</span> <span class="nx">from</span> <span class="o">+</span> <span class="nx">plus</span> <span class="nv">to: </span> <span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; - &#39;</span> <span class="o">+</span> <span class="nx">from</span> <span class="o">+</span> <span class="nx">plus</span>
<span class="nv">val: </span> <span class="err">@</span><span class="nx">value</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">val: </span> <span class="err">@</span><span class="nx">value</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="s2">&quot;$name.splice.apply($name, [$from, $to].concat($val))&quot;</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-53">#</a> </div> <p>A function definition. The only node that creates a new Scope. <span class="s2">&quot;$name.splice.apply($name, [$from, $to].concat($val))&quot;</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</a> </div> <p>A function definition. The only node that creates a new Scope.
A CodeNode does not have any children -- they're within the new scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.CodeNode: </span><span class="nx">class</span> <span class="nx">CodeNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> A CodeNode does not have any children -- they're within the new scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.CodeNode: </span><span class="nx">class</span> <span class="nx">CodeNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Code&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Code&#39;</span>
@@ -498,7 +508,7 @@ A CodeNode does not have any children -- they're within the new scope.</p>
<span class="nv">func: </span><span class="s2">&quot;($func)&quot;</span> <span class="k">if</span> <span class="nx">top</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">bound</span> <span class="nv">func: </span><span class="s2">&quot;($func)&quot;</span> <span class="k">if</span> <span class="nx">top</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">bound</span>
<span class="k">return</span> <span class="nx">func</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">bound</span> <span class="k">return</span> <span class="nx">func</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">bound</span>
<span class="nv">inner: </span><span class="s2">&quot;(function$name_part() {\n${@idt(2)}return __func.apply(__this, arguments);\n${@idt(1)}});&quot;</span> <span class="nv">inner: </span><span class="s2">&quot;(function$name_part() {\n${@idt(2)}return __func.apply(__this, arguments);\n${@idt(1)}});&quot;</span>
<span class="s2">&quot;(function(__this) {\n${@idt(1)}var __func = $func;\n${@idt(1)}return $inner\n${@idt()}})(this)&quot;</span> <span class="s2">&quot;(function(__this) {\n${@idt(1)}var __func = $func;\n${@idt(1)}return $inner\n$@tab})(this)&quot;</span>
<span class="nv">top_sensitive: </span><span class="o">-&gt;</span> <span class="nv">top_sensitive: </span><span class="o">-&gt;</span>
<span class="kc">true</span> <span class="kc">true</span>
@@ -513,7 +523,7 @@ A CodeNode does not have any children -- they're within the new scope.</p>
<span class="nv">toString: </span><span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">toString: </span><span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">idt</span> <span class="o">||=</span> <span class="s1">&#39;&#39;</span> <span class="nx">idt</span> <span class="o">||=</span> <span class="s1">&#39;&#39;</span>
<span class="nv">children: </span><span class="p">(</span><span class="nx">child</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="nx">idt</span> <span class="o">+</span> <span class="nx">TAB</span><span class="p">)</span> <span class="k">for</span> <span class="nx">child</span> <span class="k">in</span> <span class="err">@</span><span class="nx">real_children</span><span class="p">()).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="nv">children: </span><span class="p">(</span><span class="nx">child</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="nx">idt</span> <span class="o">+</span> <span class="nx">TAB</span><span class="p">)</span> <span class="k">for</span> <span class="nx">child</span> <span class="k">in</span> <span class="err">@</span><span class="nx">real_children</span><span class="p">()).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span>
<span class="s2">&quot;\n$idt$children&quot;</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>A splat, either as a parameter to a function, an argument to a call, <span class="s2">&quot;\n$idt$children&quot;</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <p>A splat, either as a parameter to a function, an argument to a call,
or in a destructuring assignment.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.SplatNode: </span><span class="nx">class</span> <span class="nx">SplatNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> or in a destructuring assignment.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.SplatNode: </span><span class="nx">class</span> <span class="nx">SplatNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Splat&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Splat&#39;</span>
@@ -530,7 +540,7 @@ or in a destructuring assignment.</p> </td> <td class="c
<span class="s2">&quot;$name = Array.prototype.slice.call(arguments, $@index)&quot;</span> <span class="s2">&quot;$name = Array.prototype.slice.call(arguments, $@index)&quot;</span>
<span class="nv">compile_value: </span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_value: </span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot;Array.prototype.slice.call($name, $index)&quot;</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>A while loop, the only sort of low-level loop exposed by CoffeeScript. From <span class="s2">&quot;Array.prototype.slice.call($name, $index)&quot;</span></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-71">#</a> </div> <p>A while loop, the only sort of low-level loop exposed by CoffeeScript. From
it, all other loops can be manufactured.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.WhileNode: </span><span class="nx">class</span> <span class="nx">WhileNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> it, all other loops can be manufactured.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.WhileNode: </span><span class="nx">class</span> <span class="nx">WhileNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;While&#39;</span> <span class="nv">type: </span><span class="s1">&#39;While&#39;</span>
@@ -554,15 +564,15 @@ it, all other loops can be manufactured.</p> </td> <td c
<span class="nv">set: </span> <span class="s1">&#39;&#39;</span> <span class="nv">set: </span> <span class="s1">&#39;&#39;</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">top</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">top</span>
<span class="nv">rvar: </span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span> <span class="nv">rvar: </span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span>
<span class="nv">set: </span> <span class="s2">&quot;${@idt()}$rvar = [];\n&quot;</span> <span class="nv">set: </span> <span class="s2">&quot;$@tab$rvar = [];\n&quot;</span>
<span class="err">@</span><span class="nv">body: </span> <span class="nx">PushNode</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">rvar</span><span class="p">,</span> <span class="err">@</span><span class="nx">body</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">body</span> <span class="err">@</span><span class="nv">body: </span> <span class="nx">PushNode</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">rvar</span><span class="p">,</span> <span class="err">@</span><span class="nx">body</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">body</span>
<span class="nv">post: </span> <span class="k">if</span> <span class="nx">returns</span> <span class="k">then</span> <span class="s2">&quot;\n${@idt()}return $rvar;&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span> <span class="nv">post: </span> <span class="k">if</span> <span class="nx">returns</span> <span class="k">then</span> <span class="s2">&quot;\n${@tab}return $rvar;&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">pre: </span> <span class="s2">&quot;$set${@idt()}while ($cond)&quot;</span> <span class="nv">pre: </span> <span class="s2">&quot;$set${@tab}while ($cond)&quot;</span>
<span class="k">return</span> <span class="s2">&quot;$pre null;$post&quot;</span> <span class="k">if</span> <span class="o">not</span> <span class="err">@</span><span class="nx">body</span> <span class="k">return</span> <span class="s2">&quot;$pre null;$post&quot;</span> <span class="k">if</span> <span class="o">not</span> <span class="err">@</span><span class="nx">body</span>
<span class="err">@</span><span class="nv">body: </span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="k">new</span> <span class="nx">IfNode</span><span class="p">(</span><span class="err">@</span><span class="nx">filter</span><span class="p">,</span> <span class="err">@</span><span class="nx">body</span><span class="p">)])</span> <span class="k">if</span> <span class="err">@</span><span class="nx">filter</span> <span class="err">@</span><span class="nv">body: </span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="k">new</span> <span class="nx">IfNode</span><span class="p">(</span><span class="err">@</span><span class="nx">filter</span><span class="p">,</span> <span class="err">@</span><span class="nx">body</span><span class="p">)])</span> <span class="k">if</span> <span class="err">@</span><span class="nx">filter</span>
<span class="s2">&quot;$pre {\n${ @body.compile(o) }\n${@idt()}}$post&quot;</span> <span class="s2">&quot;$pre {\n${ @body.compile(o) }\n$@tab}$post&quot;</span>
<span class="nx">statement</span> <span class="nx">WhileNode</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>Simple Arithmetic and logical operations. Performs some conversion from <span class="nx">statement</span> <span class="nx">WhileNode</span></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-72">#</a> </div> <p>Simple Arithmetic and logical operations. Performs some conversion from
CoffeeScript operations into their JavaScript equivalents.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OpNode: </span><span class="nx">class</span> <span class="nx">OpNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> CoffeeScript operations into their JavaScript equivalents.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.OpNode: </span><span class="nx">class</span> <span class="nx">OpNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Op&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Op&#39;</span>
@@ -598,7 +608,7 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_assignment</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">ASSIGNMENT</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="err">@</span><span class="nx">operator</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">return</span> <span class="err">@</span><span class="nx">compile_assignment</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">ASSIGNMENT</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="err">@</span><span class="nx">operator</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_unary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_unary</span><span class="p">()</span> <span class="k">return</span> <span class="err">@</span><span class="nx">compile_unary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_unary</span><span class="p">()</span>
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_existence</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">operator</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span> <span class="k">return</span> <span class="err">@</span><span class="nx">compile_existence</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">operator</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span>
<span class="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">operator</span><span class="p">,</span> <span class="err">@</span><span class="nx">second</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)].</span><span class="nx">join</span> <span class="s1">&#39; &#39;</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>Mimic Python's chained comparisons. See: <span class="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">operator</span><span class="p">,</span> <span class="err">@</span><span class="nx">second</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)].</span><span class="nx">join</span> <span class="s1">&#39; &#39;</span></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-73">#</a> </div> <p>Mimic Python's chained comparisons. See:
<a href='http://docs.python.org/reference/expressions.html#notin'>http://docs.python.org/reference/expressions.html#notin</a></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_chain: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <a href='http://docs.python.org/reference/expressions.html#notin'>http://docs.python.org/reference/expressions.html#notin</a></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_chain: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">shared: </span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">second</span> <span class="nv">shared: </span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">second</span>
<span class="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">second</span><span class="p">,</span> <span class="nx">shared</span><span class="p">]</span><span class="o">:</span> <span class="nx">shared</span><span class="p">.</span><span class="nx">compile_reference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">shared</span> <span class="k">instanceof</span> <span class="nx">CallNode</span> <span class="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">second</span><span class="p">,</span> <span class="nx">shared</span><span class="p">]</span><span class="o">:</span> <span class="nx">shared</span><span class="p">.</span><span class="nx">compile_reference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">shared</span> <span class="k">instanceof</span> <span class="nx">CallNode</span>
@@ -620,7 +630,7 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
<span class="nv">space: </span><span class="k">if</span> <span class="err">@</span><span class="nx">PREFIX_OPERATORS</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="err">@</span><span class="nx">operator</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">then</span> <span class="s1">&#39; &#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span> <span class="nv">space: </span><span class="k">if</span> <span class="err">@</span><span class="nx">PREFIX_OPERATORS</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="err">@</span><span class="nx">operator</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="k">then</span> <span class="s1">&#39; &#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">parts: </span><span class="p">[</span><span class="err">@</span><span class="nx">operator</span><span class="p">,</span> <span class="nx">space</span><span class="p">,</span> <span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span> <span class="nv">parts: </span><span class="p">[</span><span class="err">@</span><span class="nx">operator</span><span class="p">,</span> <span class="nx">space</span><span class="p">,</span> <span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span>
<span class="nv">parts: </span><span class="nx">parts</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span> <span class="k">if</span> <span class="err">@</span><span class="nx">flip</span> <span class="nv">parts: </span><span class="nx">parts</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span> <span class="k">if</span> <span class="err">@</span><span class="nx">flip</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</a> </div> <p>A try/catch/finally block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.TryNode: </span><span class="nx">class</span> <span class="nx">TryNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="nx">parts</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39;&#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-74">#</a> </div> <p>A try/catch/finally block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.TryNode: </span><span class="nx">class</span> <span class="nx">TryNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Try&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Try&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">attempt</span><span class="p">,</span> <span class="nx">error</span><span class="p">,</span> <span class="nx">recovery</span><span class="p">,</span> <span class="nx">ensure</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">attempt</span><span class="p">,</span> <span class="nx">error</span><span class="p">,</span> <span class="nx">recovery</span><span class="p">,</span> <span class="nx">ensure</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -633,20 +643,20 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
<span class="nv">o.top: </span> <span class="kc">true</span> <span class="nv">o.top: </span> <span class="kc">true</span>
<span class="nv">attempt_part: </span><span class="err">@</span><span class="nx">attempt</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">attempt_part: </span><span class="err">@</span><span class="nx">attempt</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">error_part: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">error</span> <span class="k">then</span> <span class="s2">&quot; (${ @error.compile(o) }) &quot;</span> <span class="k">else</span> <span class="s1">&#39; &#39;</span> <span class="nv">error_part: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">error</span> <span class="k">then</span> <span class="s2">&quot; (${ @error.compile(o) }) &quot;</span> <span class="k">else</span> <span class="s1">&#39; &#39;</span>
<span class="nv">catch_part: </span> <span class="s2">&quot;${ (@recovery or &#39;&#39;) and &#39; catch&#39; }$error_part{\n${ @recovery.compile(o) }\n${@idt()}}&quot;</span> <span class="nv">catch_part: </span> <span class="s2">&quot;${ (@recovery or &#39;&#39;) and &#39; catch&#39; }$error_part{\n${ @recovery.compile(o) }\n$@tab}&quot;</span>
<span class="nv">finally_part: </span><span class="p">(</span><span class="err">@</span><span class="nx">ensure</span> <span class="o">or</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="s1">&#39; finally {\n&#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">ensure</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">returns: </span><span class="kc">null</span><span class="p">}))</span> <span class="o">+</span> <span class="s2">&quot;\n${@idt()}}&quot;</span> <span class="nv">finally_part: </span><span class="p">(</span><span class="err">@</span><span class="nx">ensure</span> <span class="o">or</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="s1">&#39; finally {\n&#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">ensure</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">returns: </span><span class="kc">null</span><span class="p">}))</span> <span class="o">+</span> <span class="s2">&quot;\n$@tab}&quot;</span>
<span class="s2">&quot;${@idt()}try {\n$attempt_part\n${@idt()}}$catch_part$finally_part&quot;</span> <span class="s2">&quot;${@tab}try {\n$attempt_part\n$@tab}$catch_part$finally_part&quot;</span>
<span class="nx">statement</span> <span class="nx">TryNode</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>Throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ThrowNode: </span><span class="nx">class</span> <span class="nx">ThrowNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="nx">statement</span> <span class="nx">TryNode</span></pre></div> </td> </tr> <tr id="section-75"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-75">#</a> </div> <p>Throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ThrowNode: </span><span class="nx">class</span> <span class="nx">ThrowNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Throw&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Throw&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">children: </span><span class="p">[</span><span class="err">@</span><span class="nv">expression: </span><span class="nx">expression</span><span class="p">]</span> <span class="err">@</span><span class="nv">children: </span><span class="p">[</span><span class="err">@</span><span class="nv">expression: </span><span class="nx">expression</span><span class="p">]</span>
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot;${@idt()}throw ${@expression.compile(o)};&quot;</span> <span class="s2">&quot;${@tab}throw ${@expression.compile(o)};&quot;</span>
<span class="nx">statement</span> <span class="nx">ThrowNode</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <p>Check an expression for existence (meaning not null or undefined).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ExistenceNode: </span><span class="nx">class</span> <span class="nx">ExistenceNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="nx">statement</span> <span class="nx">ThrowNode</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-76"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-76">#</a> </div> <p>Check an expression for existence (meaning not null or undefined).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ExistenceNode: </span><span class="nx">class</span> <span class="nx">ExistenceNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Existence&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Existence&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -660,7 +670,7 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
<span class="k">if</span> <span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">CallNode</span> <span class="o">or</span> <span class="p">(</span><span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="nx">variable</span><span class="p">.</span><span class="nx">has_properties</span><span class="p">())</span> <span class="k">if</span> <span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">CallNode</span> <span class="o">or</span> <span class="p">(</span><span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="nx">variable</span><span class="p">.</span><span class="nx">has_properties</span><span class="p">())</span>
<span class="p">[</span><span class="nx">first</span><span class="p">,</span> <span class="nx">second</span><span class="p">]</span><span class="o">:</span> <span class="nx">variable</span><span class="p">.</span><span class="nx">compile_reference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="p">[</span><span class="nx">first</span><span class="p">,</span> <span class="nx">second</span><span class="p">]</span><span class="o">:</span> <span class="nx">variable</span><span class="p">.</span><span class="nx">compile_reference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="p">[</span><span class="nx">first</span><span class="p">,</span> <span class="nx">second</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="nx">second</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span> <span class="p">[</span><span class="nx">first</span><span class="p">,</span> <span class="nx">second</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="nx">second</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span>
<span class="s2">&quot;(typeof $first !== \&quot;undefined\&quot; &amp;&amp; $second !== null)&quot;</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <p>An extra set of parentheses, specified explicitly in the source.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ParentheticalNode: </span><span class="nx">class</span> <span class="nx">ParentheticalNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> <span class="s2">&quot;(typeof $first !== \&quot;undefined\&quot; &amp;&amp; $second !== null)&quot;</span></pre></div> </td> </tr> <tr id="section-77"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-77">#</a> </div> <p>An extra set of parentheses, specified explicitly in the source.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ParentheticalNode: </span><span class="nx">class</span> <span class="nx">ParentheticalNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nv">type: </span><span class="s1">&#39;Paren&#39;</span> <span class="nv">type: </span><span class="s1">&#39;Paren&#39;</span>
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -674,7 +684,7 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
<span class="k">return</span> <span class="nx">code</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">return</span> <span class="nx">code</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span>
<span class="nv">l: </span> <span class="nx">code</span><span class="p">.</span><span class="nx">length</span> <span class="nv">l: </span> <span class="nx">code</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">code: </span><span class="nx">code</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">l</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="nx">code</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">l</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;;&#39;</span> <span class="nv">code: </span><span class="nx">code</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">l</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="nx">code</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="nx">l</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;;&#39;</span>
<span class="s2">&quot;($code)&quot;</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</a> </div> <p>The replacement for the for loop is an array comprehension (that compiles) <span class="s2">&quot;($code)&quot;</span></pre></div> </td> </tr> <tr id="section-78"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-78">#</a> </div> <p>The replacement for the for loop is an array comprehension (that compiles)
into a for loop. Also acts as an expression, able to return the result into a for loop. Also acts as an expression, able to return the result
of the comprehenion. Unlike Python array comprehensions, it's able to pass of the comprehenion. Unlike Python array comprehensions, it's able to pass
the current index of the loop as a second parameter.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ForNode: </span><span class="nx">class</span> <span class="nx">ForNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> the current index of the loop as a second parameter.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ForNode: </span><span class="nx">class</span> <span class="nx">ForNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
@@ -716,7 +726,7 @@ the current index of the loop as a second parameter.</p> </td>
<span class="nv">for_part: </span> <span class="s2">&quot;$index_var = 0, $for_part, $index_var++&quot;</span> <span class="nv">for_part: </span> <span class="s2">&quot;$index_var = 0, $for_part, $index_var++&quot;</span>
<span class="k">else</span> <span class="k">else</span>
<span class="nv">index_var: </span> <span class="kc">null</span> <span class="nv">index_var: </span> <span class="kc">null</span>
<span class="nv">source_part: </span> <span class="s2">&quot;$svar = ${ @source.compile(o) };\n${@idt()}&quot;</span> <span class="nv">source_part: </span> <span class="s2">&quot;$svar = ${ @source.compile(o) };\n$@tab&quot;</span>
<span class="nv">var_part: </span> <span class="s2">&quot;$body_dent$name = $svar[$ivar];\n&quot;</span> <span class="k">if</span> <span class="nx">name</span> <span class="nv">var_part: </span> <span class="s2">&quot;$body_dent$name = $svar[$ivar];\n&quot;</span> <span class="k">if</span> <span class="nx">name</span>
<span class="k">if</span> <span class="o">not</span> <span class="err">@</span><span class="nx">object</span> <span class="k">if</span> <span class="o">not</span> <span class="err">@</span><span class="nx">object</span>
<span class="nv">lvar: </span> <span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span> <span class="nv">lvar: </span> <span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">()</span>
@@ -735,13 +745,13 @@ the current index of the loop as a second parameter.</p> </td>
<span class="k">if</span> <span class="err">@</span><span class="nx">object</span> <span class="k">if</span> <span class="err">@</span><span class="nx">object</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="s1">&#39;__hasProp&#39;</span><span class="p">,</span> <span class="s1">&#39;Object.prototype.hasOwnProperty&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="s1">&#39;__hasProp&#39;</span><span class="p">,</span> <span class="s1">&#39;Object.prototype.hasOwnProperty&#39;</span><span class="p">,</span> <span class="kc">true</span><span class="p">)</span>
<span class="nv">for_part: </span><span class="s2">&quot;$ivar in $svar) { if (__hasProp.call($svar, $ivar)&quot;</span> <span class="nv">for_part: </span><span class="s2">&quot;$ivar in $svar) { if (__hasProp.call($svar, $ivar)&quot;</span>
<span class="nv">return_result: </span> <span class="s2">&quot;\n${@idt()}$return_result;&quot;</span> <span class="nx">unless</span> <span class="nx">top_level</span> <span class="nv">return_result: </span> <span class="s2">&quot;\n$@tab$return_result;&quot;</span> <span class="nx">unless</span> <span class="nx">top_level</span>
<span class="nv">body: </span> <span class="nx">body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">indent: </span><span class="nx">body_dent</span><span class="p">,</span> <span class="nv">top: </span><span class="kc">true</span><span class="p">}))</span> <span class="nv">body: </span> <span class="nx">body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">indent: </span><span class="nx">body_dent</span><span class="p">,</span> <span class="nv">top: </span><span class="kc">true</span><span class="p">}))</span>
<span class="nv">vars: </span> <span class="k">if</span> <span class="nx">range</span> <span class="k">then</span> <span class="nx">name</span> <span class="k">else</span> <span class="s2">&quot;$name, $ivar&quot;</span> <span class="nv">vars: </span> <span class="k">if</span> <span class="nx">range</span> <span class="k">then</span> <span class="nx">name</span> <span class="k">else</span> <span class="s2">&quot;$name, $ivar&quot;</span>
<span class="nv">close: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">object</span> <span class="k">then</span> <span class="s1">&#39;}}\n&#39;</span> <span class="k">else</span> <span class="s1">&#39;}\n&#39;</span> <span class="nv">close: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">object</span> <span class="k">then</span> <span class="s1">&#39;}}\n&#39;</span> <span class="k">else</span> <span class="s1">&#39;}\n&#39;</span>
<span class="s2">&quot;$set_result${source_part}for ($for_part) {\n$var_part$body\n${@idt()}$close${@idt()}$return_result&quot;</span> <span class="s2">&quot;$set_result${source_part}for ($for_part) {\n$var_part$body\n$@tab$close$@tab$return_result&quot;</span>
<span class="nx">statement</span> <span class="nx">ForNode</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <p>If/else statements. Switch/whens get compiled into these. Acts as an <span class="nx">statement</span> <span class="nx">ForNode</span></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-79">#</a> </div> <p>If/else statements. Switch/whens get compiled into these. Acts as an
expression by pushing down requested returns to the expression bodies. expression by pushing down requested returns to the expression bodies.
Single-expression IfNodes are compiled into ternary operators if possible, Single-expression IfNodes are compiled into ternary operators if possible,
because ternaries are first-class returnable assignable expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.IfNode: </span><span class="nx">class</span> <span class="nx">IfNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span> because ternaries are first-class returnable assignable expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.IfNode: </span><span class="nx">class</span> <span class="nx">IfNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
@@ -763,9 +773,9 @@ because ternaries are first-class returnable assignable expressions.</p>
<span class="nv">force_statement: </span><span class="o">-&gt;</span> <span class="nv">force_statement: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">tags.statement: </span><span class="kc">true</span> <span class="err">@</span><span class="nv">tags.statement: </span><span class="kc">true</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>Tag a chain of IfNodes with their switch condition for equality.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_condition: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-80">#</a> </div> <p>Tag a chain of IfNodes with their switch condition for equality.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_condition: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nv">switcher: </span><span class="nx">expression</span> <span class="err">@</span><span class="nv">switcher: </span><span class="nx">expression</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-65">#</a> </div> <p>Rewrite a chain of IfNodes with their switch condition for equality.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_switch: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-81"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-81">#</a> </div> <p>Rewrite a chain of IfNodes with their switch condition for equality.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_switch: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">assigner: </span><span class="err">@</span><span class="nx">switcher</span> <span class="nv">assigner: </span><span class="err">@</span><span class="nx">switcher</span>
<span class="k">if</span> <span class="o">not</span> <span class="p">(</span><span class="err">@</span><span class="nx">switcher</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">LiteralNode</span><span class="p">)</span> <span class="k">if</span> <span class="o">not</span> <span class="p">(</span><span class="err">@</span><span class="nx">switcher</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">LiteralNode</span><span class="p">)</span>
<span class="nv">variable: </span><span class="nx">literal</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">())</span> <span class="nv">variable: </span><span class="nx">literal</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">())</span>
@@ -777,14 +787,14 @@ because ternaries are first-class returnable assignable expressions.</p>
<span class="k">else</span> <span class="k">else</span>
<span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;is&#39;</span><span class="p">,</span> <span class="nx">assigner</span><span class="p">,</span> <span class="err">@</span><span class="nx">condition</span><span class="p">)</span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;is&#39;</span><span class="p">,</span> <span class="nx">assigner</span><span class="p">,</span> <span class="err">@</span><span class="nx">condition</span><span class="p">)</span>
<span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">rewrite_condition</span><span class="p">(</span><span class="err">@</span><span class="nx">switcher</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">rewrite_condition</span><span class="p">(</span><span class="err">@</span><span class="nx">switcher</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-66">#</a> </div> <p>Rewrite a chain of IfNodes to add a default case as the final else.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add_else: </span><span class="p">(</span><span class="nx">exprs</span><span class="p">,</span> <span class="nx">statement</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-82"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-82">#</a> </div> <p>Rewrite a chain of IfNodes to add a default case as the final else.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add_else: </span><span class="p">(</span><span class="nx">exprs</span><span class="p">,</span> <span class="nx">statement</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span>
<span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">exprs</span><span class="p">,</span> <span class="nx">statement</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">exprs</span><span class="p">,</span> <span class="nx">statement</span>
<span class="k">else</span> <span class="k">else</span>
<span class="nv">exprs: </span><span class="nx">exprs</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">statement</span> <span class="nv">exprs: </span><span class="nx">exprs</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">statement</span>
<span class="err">@</span><span class="nx">children</span><span class="p">.</span><span class="nx">push</span> <span class="err">@</span><span class="nv">else_body: </span><span class="nx">exprs</span> <span class="err">@</span><span class="nx">children</span><span class="p">.</span><span class="nx">push</span> <span class="err">@</span><span class="nv">else_body: </span><span class="nx">exprs</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <p>If the else_body is an IfNode itself, then we've got an if-else chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_chain: </span><span class="o">-&gt;</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-83"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-83">#</a> </div> <p>If the else_body is an IfNode itself, then we've got an if-else chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_chain: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">chain</span> <span class="o">||=</span> <span class="err">@</span><span class="nx">else_body</span> <span class="o">and</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">instanceof</span> <span class="nx">IfNode</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <p>The IfNode only compiles into a statement if either of the bodies needs <span class="err">@</span><span class="nx">chain</span> <span class="o">||=</span> <span class="err">@</span><span class="nx">else_body</span> <span class="o">and</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">instanceof</span> <span class="nx">IfNode</span></pre></div> </td> </tr> <tr id="section-84"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-84">#</a> </div> <p>The IfNode only compiles into a statement if either of the bodies needs
to be a statement.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-&gt;</span> to be a statement.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">statement</span> <span class="o">||=</span> <span class="o">!!</span><span class="p">(</span><span class="err">@</span><span class="nx">comment</span> <span class="o">or</span> <span class="err">@</span><span class="nx">tags</span><span class="p">.</span><span class="nx">statement</span> <span class="o">or</span> <span class="err">@</span><span class="nx">body</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="o">or</span> <span class="p">(</span><span class="err">@</span><span class="nx">else_body</span> <span class="o">and</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()))</span> <span class="err">@</span><span class="nx">statement</span> <span class="o">||=</span> <span class="o">!!</span><span class="p">(</span><span class="err">@</span><span class="nx">comment</span> <span class="o">or</span> <span class="err">@</span><span class="nx">tags</span><span class="p">.</span><span class="nx">statement</span> <span class="o">or</span> <span class="err">@</span><span class="nx">body</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="o">or</span> <span class="p">(</span><span class="err">@</span><span class="nx">else_body</span> <span class="o">and</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()))</span>
@@ -792,7 +802,7 @@ to be a statement.</p> </td> <td class="code">
<span class="p">(</span><span class="nx">cond</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">for</span> <span class="nx">cond</span> <span class="k">in</span> <span class="nx">flatten</span><span class="p">([</span><span class="err">@</span><span class="nx">condition</span><span class="p">])).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39; || &#39;</span><span class="p">)</span> <span class="p">(</span><span class="nx">cond</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">for</span> <span class="nx">cond</span> <span class="k">in</span> <span class="nx">flatten</span><span class="p">([</span><span class="err">@</span><span class="nx">condition</span><span class="p">])).</span><span class="nx">join</span><span class="p">(</span><span class="s1">&#39; || &#39;</span><span class="p">)</span>
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_statement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_ternary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</a> </div> <p>Compile the IfNode as a regular if-else statement. Flattened chains <span class="k">if</span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_statement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_ternary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-85"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-85">#</a> </div> <p>Compile the IfNode as a regular if-else statement. Flattened chains
force sub-else bodies into statement form.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_statement: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> force sub-else bodies into statement form.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_statement: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="err">@</span><span class="nx">rewrite_switch</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">switcher</span> <span class="err">@</span><span class="nx">rewrite_switch</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">switcher</span>
<span class="nv">child: </span> <span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;chain_child&#39;</span> <span class="nv">child: </span> <span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;chain_child&#39;</span>
@@ -804,28 +814,28 @@ force sub-else bodies into statement form.</p> </td> <td
<span class="nv">com_dent: </span> <span class="k">if</span> <span class="nx">child</span> <span class="k">then</span> <span class="err">@</span><span class="nx">idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span> <span class="nv">com_dent: </span> <span class="k">if</span> <span class="nx">child</span> <span class="k">then</span> <span class="err">@</span><span class="nx">idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">prefix: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">comment</span> <span class="k">then</span> <span class="s2">&quot;${ @comment.compile(cond_o) }\n$com_dent&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span> <span class="nv">prefix: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">comment</span> <span class="k">then</span> <span class="s2">&quot;${ @comment.compile(cond_o) }\n$com_dent&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">body: </span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="err">@</span><span class="nx">body</span><span class="p">]).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">body: </span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span><span class="p">([</span><span class="err">@</span><span class="nx">body</span><span class="p">]).</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">if_part: </span> <span class="s2">&quot;$prefix${if_dent}if (${ @compile_condition(cond_o) }) {\n$body\n${@idt()}}&quot;</span> <span class="nv">if_part: </span> <span class="s2">&quot;$prefix${if_dent}if (${ @compile_condition(cond_o) }) {\n$body\n$@tab}&quot;</span>
<span class="k">return</span> <span class="nx">if_part</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">return</span> <span class="nx">if_part</span> <span class="nx">unless</span> <span class="err">@</span><span class="nx">else_body</span>
<span class="nv">else_part: </span><span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span> <span class="nv">else_part: </span><span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span>
<span class="s1">&#39; else &#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">indent: </span><span class="err">@</span><span class="nx">idt</span><span class="p">(),</span> <span class="nv">chain_child: </span><span class="kc">true</span><span class="p">}))</span> <span class="s1">&#39; else &#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">indent: </span><span class="err">@</span><span class="nx">idt</span><span class="p">(),</span> <span class="nv">chain_child: </span><span class="kc">true</span><span class="p">}))</span>
<span class="k">else</span> <span class="k">else</span>
<span class="s2">&quot; else {\n${ Expressions.wrap([@else_body]).compile(o) }\n${@idt()}}&quot;</span> <span class="s2">&quot; else {\n${ Expressions.wrap([@else_body]).compile(o) }\n$@tab}&quot;</span>
<span class="s2">&quot;$if_part$else_part&quot;</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <p>Compile the IfNode into a ternary operator.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_ternary: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="s2">&quot;$if_part$else_part&quot;</span></pre></div> </td> </tr> <tr id="section-86"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-86">#</a> </div> <p>Compile the IfNode into a ternary operator.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_ternary: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">if_part: </span> <span class="err">@</span><span class="nx">condition</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; ? &#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="nv">if_part: </span> <span class="err">@</span><span class="nx">condition</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39; ? &#39;</span> <span class="o">+</span> <span class="err">@</span><span class="nx">body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nv">else_part: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">then</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;null&#39;</span> <span class="nv">else_part: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">then</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="s1">&#39;null&#39;</span>
<span class="s2">&quot;$if_part : $else_part&quot;</span></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-71">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-72">#</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB: </span><span class="s1">&#39; &#39;</span> <span class="s2">&quot;$if_part : $else_part&quot;</span></pre></div> </td> </tr> <tr id="section-87"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-87">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-88"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-88">#</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB: </span><span class="s1">&#39; &#39;</span>
<span class="nv">TRAILING_WHITESPACE: </span><span class="sr">/\s+$/gm</span></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-73">#</a> </div> <p>Keep the identifier regex in sync with the Lexer.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER: </span> <span class="sr">/^[a-zA-Z$_](\w|\$)*$/</span></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-74">#</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-75"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-75">#</a> </div> <p>Merge objects.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">merge: </span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">overrides</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nv">TRAILING_WHITESPACE: </span><span class="sr">/\s+$/gm</span></pre></div> </td> </tr> <tr id="section-89"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-89">#</a> </div> <p>Keep the identifier regex in sync with the Lexer.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER: </span> <span class="sr">/^[a-zA-Z$_](\w|\$)*$/</span></pre></div> </td> </tr> <tr id="section-90"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-90">#</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-91"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-91">#</a> </div> <p>Merge objects.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">merge: </span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">overrides</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">fresh: </span><span class="p">{}</span> <span class="nv">fresh: </span><span class="p">{}</span>
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">options</span> <span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">options</span>
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">overrides</span> <span class="k">if</span> <span class="nx">overrides</span> <span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">overrides</span> <span class="k">if</span> <span class="nx">overrides</span>
<span class="nx">fresh</span></pre></div> </td> </tr> <tr id="section-76"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-76">#</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compact: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-77"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-77">#</a> </div> <p>Return a completely flattened version of an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">flatten: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">fresh</span></pre></div> </td> </tr> <tr id="section-92"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-92">#</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compact: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-93"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-93">#</a> </div> <p>Return a completely flattened version of an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">flatten: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">memo: </span><span class="p">[]</span> <span class="nv">memo: </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span>
<span class="k">if</span> <span class="nx">item</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nv">memo: </span><span class="nx">memo</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="k">else</span> <span class="nx">memo</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="k">if</span> <span class="nx">item</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nv">memo: </span><span class="nx">memo</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="k">else</span> <span class="nx">memo</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>
<span class="nx">memo</span></pre></div> </td> </tr> <tr id="section-78"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-78">#</a> </div> <p>Delete a key from an object, returning the value.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">del: </span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">memo</span></pre></div> </td> </tr> <tr id="section-94"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-94">#</a> </div> <p>Delete a key from an object, returning the value.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">del: </span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">val: </span><span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="nv">val: </span><span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
<span class="k">delete</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="k">delete</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-79">#</a> </div> <p>Quickie helper for a generated LiteralNode.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">literal: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">val</span></pre></div> </td> </tr> <tr id="section-95"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-95">#</a> </div> <p>Quickie helper for a generated LiteralNode.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">literal: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html> </pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -28,6 +28,7 @@
})); }));
} }
}; };
//### BaseNode
// The **BaseNode** is the abstract base class for all nodes in the syntax tree. // The **BaseNode** is the abstract base class for all nodes in the syntax tree.
// Each subclass implements the `compile_node` method, which performs the // Each subclass implements the `compile_node` method, which performs the
// code generation for that node. To compile a node to JavaScript, // code generation for that node. To compile a node to JavaScript,
@@ -76,15 +77,18 @@
}; };
// Convenience method to grab the current indentation level, plus tabbing in. // Convenience method to grab the current indentation level, plus tabbing in.
BaseNode.prototype.idt = function idt(tabs) { BaseNode.prototype.idt = function idt(tabs) {
var _a, _b, _c, _d, i, idt; var idt, num;
idt = this.tab || ''; idt = this.tab || '';
_c = 0; _d = (tabs || 0); num = (tabs || 0) + 1;
for (_b = 0, i = _c; (_c <= _d ? i < _d : i > _d); (_c <= _d ? i += 1 : i -= 1), _b++) { while (num -= 1) {
idt += TAB; idt += TAB
} }
return idt; return idt;
}; };
// Does this node, or any of its children, contain a node of a certain kind? // Does this node, or any of its children, contain a node of a certain kind?
// Recursively traverses down the *children* of the nodes, yielding to a block
// and returning true when the block finds a match. `contains` does not cross
// scope boundaries.
BaseNode.prototype.contains = function contains(block) { BaseNode.prototype.contains = function contains(block) {
var _a, _b, _c, node; var _a, _b, _c, node;
_a = this.children; _a = this.children;
@@ -99,7 +103,7 @@
} }
return false; return false;
}; };
// Perform an in-order traversal of the AST. // Perform an in-order traversal of the AST. Crosses scope boundaries.
BaseNode.prototype.traverse = function traverse(block) { BaseNode.prototype.traverse = function traverse(block) {
var _a, _b, _c, _d, node; var _a, _b, _c, _d, node;
_a = []; _b = this.children; _a = []; _b = this.children;
@@ -114,7 +118,8 @@
} }
return _a; return _a;
}; };
// toString representation of the node, for inspecting the parse tree. // `toString` representation of the node, for inspecting the parse tree.
// This is what `coffee --nodes` prints out.
BaseNode.prototype.toString = function toString(idt) { BaseNode.prototype.toString = function toString(idt) {
var _a, _b, _c, _d, child; var _a, _b, _c, _d, child;
idt = idt || ''; idt = idt || '';
@@ -127,7 +132,8 @@
return _a; return _a;
}).call(this).join(''); }).call(this).join('');
}; };
// Default implementations of the common node methods. // Default implementations of the common node identification methods. Nodes
// will override these with custom logic, if needed.
BaseNode.prototype.unwrap = function unwrap() { BaseNode.prototype.unwrap = function unwrap() {
return this; return this;
}; };
@@ -146,7 +152,10 @@
}; };
return BaseNode; return BaseNode;
}).call(this); }).call(this);
// A collection of nodes, each one representing an expression. //### Expressions
// The expressions body is the list of expressions that forms the body of an
// indented block of code -- the implementation of a function, a clause in an
// `if`, `switch`, or `try`, and so on...
exports.Expressions = (function() { exports.Expressions = (function() {
Expressions = function Expressions(nodes) { Expressions = function Expressions(nodes) {
this.children = (this.expressions = compact(flatten(nodes || []))); this.children = (this.expressions = compact(flatten(nodes || [])));
@@ -159,12 +168,13 @@
this.expressions.push(node); this.expressions.push(node);
return this; return this;
}; };
// Tack an expression on to the beginning of this expression list. // Add an expression at the beginning of this expression list.
Expressions.prototype.unshift = function unshift(node) { Expressions.prototype.unshift = function unshift(node) {
this.expressions.unshift(node); this.expressions.unshift(node);
return this; return this;
}; };
// If this Expressions consists of a single node, pull it back out. // If this Expressions consists of just a single node, unwrap it by pulling
// it back out.
Expressions.prototype.unwrap = function unwrap() { Expressions.prototype.unwrap = function unwrap() {
return this.expressions.length === 1 ? this.expressions[0] : this; return this.expressions.length === 1 ? this.expressions[0] : this;
}; };
@@ -172,18 +182,18 @@
Expressions.prototype.empty = function empty() { Expressions.prototype.empty = function empty() {
return this.expressions.length === 0; return this.expressions.length === 0;
}; };
// Is the node last in this block of expressions? // Is the given node the last one in this block of expressions?
Expressions.prototype.is_last = function is_last(node) { Expressions.prototype.is_last = function is_last(node) {
var l, last_index; var l, last_index;
l = this.expressions.length; l = this.expressions.length;
last_index = this.expressions[l - 1] instanceof CommentNode ? 2 : 1; last_index = this.expressions[l - 1] instanceof CommentNode ? 2 : 1;
return node === this.expressions[l - last_index]; return node === this.expressions[l - last_index];
}; };
// An **Expressions** is the only node that can serve as the root.
Expressions.prototype.compile = function compile(o) { Expressions.prototype.compile = function compile(o) {
o = o || {}; o = o || {};
return o.scope ? Expressions.__superClass__.compile.call(this, o) : this.compile_root(o); return o.scope ? Expressions.__superClass__.compile.call(this, o) : this.compile_root(o);
}; };
// Compile each expression in the Expressions body.
Expressions.prototype.compile_node = function compile_node(o) { Expressions.prototype.compile_node = function compile_node(o) {
var _a, _b, _c, _d, node; var _a, _b, _c, _d, node;
return (function() { return (function() {
@@ -195,7 +205,8 @@
return _a; return _a;
}).call(this).join("\n"); }).call(this).join("\n");
}; };
// If this is the top-level Expressions, wrap everything in a safety closure. // If we happen to be the top-level **Expressions**, wrap everything in
// a safety closure, unless requested not to.
Expressions.prototype.compile_root = function compile_root(o) { Expressions.prototype.compile_root = function compile_root(o) {
var code; var code;
o.indent = (this.tab = o.no_wrap ? '' : TAB); o.indent = (this.tab = o.no_wrap ? '' : TAB);
@@ -204,8 +215,8 @@
code = code.replace(TRAILING_WHITESPACE, ''); code = code.replace(TRAILING_WHITESPACE, '');
return o.no_wrap ? code : "(function(){\n" + code + "\n})();\n"; return o.no_wrap ? code : "(function(){\n" + code + "\n})();\n";
}; };
// Compile the expressions body, with declarations of all inner variables // Compile the expressions body for the contents of a function, with
// pushed up to the top. // declarations of all inner variables pushed up to the top.
Expressions.prototype.compile_with_declarations = function compile_with_declarations(o) { Expressions.prototype.compile_with_declarations = function compile_with_declarations(o) {
var args, code; var args, code;
code = this.compile_node(o); code = this.compile_node(o);
@@ -223,31 +234,30 @@
} }
return code; return code;
}; };
// Compiles a single expression within the expressions body. // Compiles a single expression within the expressions body. If we need to
// return the result, and it's an expression, simply return it. If it's a
// statement, ask the statement to do so.
Expressions.prototype.compile_expression = function compile_expression(node, o) { Expressions.prototype.compile_expression = function compile_expression(node, o) {
var returns, stmt; var returns, stmt;
this.tab = o.indent; this.tab = o.indent;
stmt = node.is_statement(); stmt = node.is_statement();
// We need to return the result if this is the last node in the expressions body.
returns = del(o, 'returns') && this.is_last(node) && !node.is_pure_statement(); returns = del(o, 'returns') && this.is_last(node) && !node.is_pure_statement();
// Return the regular compile of the node, unless we need to return the result.
if (!(returns)) { if (!(returns)) {
return (stmt ? '' : this.idt()) + node.compile(merge(o, { return (stmt ? '' : this.idt()) + node.compile(merge(o, {
top: true top: true
})) + (stmt ? '' : ';'); })) + (stmt ? '' : ';');
} }
// If it's a statement, the node knows how to return itself.
if (node.is_statement()) { if (node.is_statement()) {
return node.compile(merge(o, { return node.compile(merge(o, {
returns: true returns: true
})); }));
} }
// Otherwise, we can just return the value of the expression.
return (this.tab) + "return " + (node.compile(o)) + ";"; return (this.tab) + "return " + (node.compile(o)) + ";";
}; };
return Expressions; return Expressions;
}).call(this); }).call(this);
// Wrap up a node as an Expressions, unless it already is one. // Wrap up the given nodes as an **Expressions**, unless it already happens
// to be one.
Expressions.wrap = function wrap(nodes) { Expressions.wrap = function wrap(nodes) {
if (nodes.length === 1 && nodes[0] instanceof Expressions) { if (nodes.length === 1 && nodes[0] instanceof Expressions) {
return nodes[0]; return nodes[0];
@@ -255,8 +265,10 @@
return new Expressions(nodes); return new Expressions(nodes);
}; };
statement(Expressions); statement(Expressions);
//### LiteralNode
// Literals are static values that can be passed through directly into // Literals are static values that can be passed through directly into
// JavaScript without translation, eg.: strings, numbers, true, false, null... // JavaScript without translation, such as: strings, numbers,
// `true`, `false`, `null`...
exports.LiteralNode = (function() { exports.LiteralNode = (function() {
LiteralNode = function LiteralNode(value) { LiteralNode = function LiteralNode(value) {
this.value = value; this.value = value;
@@ -264,8 +276,8 @@
}; };
__extends(LiteralNode, BaseNode); __extends(LiteralNode, BaseNode);
LiteralNode.prototype.type = 'Literal'; LiteralNode.prototype.type = 'Literal';
// Break and continue must be treated as statements -- they lose their meaning // Break and continue must be treated as pure statements -- they lose their
// when wrapped in a closure. // meaning when wrapped in a closure.
LiteralNode.prototype.is_statement = function is_statement() { LiteralNode.prototype.is_statement = function is_statement() {
return this.value === 'break' || this.value === 'continue'; return this.value === 'break' || this.value === 'continue';
}; };
@@ -281,7 +293,9 @@
}; };
return LiteralNode; return LiteralNode;
}).call(this); }).call(this);
// Return an expression, or wrap it in a closure and return it. //### ReturnNode
// A `return` is a *pure_statement* -- wrapping it in a closure wouldn't
// make sense.
exports.ReturnNode = (function() { exports.ReturnNode = (function() {
ReturnNode = function ReturnNode(expression) { ReturnNode = function ReturnNode(expression) {
this.children = [(this.expression = expression)]; this.children = [(this.expression = expression)];
@@ -300,7 +314,9 @@
return ReturnNode; return ReturnNode;
}).call(this); }).call(this);
statement(ReturnNode, true); statement(ReturnNode, true);
// A value, indexed or dotted into, or vanilla. //### ValueNode
// A value, variable or literal or parenthesized, indexed or dotted into,
// or vanilla.
exports.ValueNode = (function() { exports.ValueNode = (function() {
ValueNode = function ValueNode(base, properties) { ValueNode = function ValueNode(base, properties) {
this.children = flatten([(this.base = base), (this.properties = (properties || []))]); this.children = flatten([(this.base = base), (this.properties = (properties || []))]);
@@ -309,6 +325,8 @@
__extends(ValueNode, BaseNode); __extends(ValueNode, BaseNode);
ValueNode.prototype.type = 'Value'; ValueNode.prototype.type = 'Value';
ValueNode.prototype.SOAK = " == undefined ? undefined : "; ValueNode.prototype.SOAK = " == undefined ? undefined : ";
// A **ValueNode** has a base and a list of property accesses.
// Add a property access to the list.
ValueNode.prototype.push = function push(prop) { ValueNode.prototype.push = function push(prop) {
this.properties.push(prop); this.properties.push(prop);
this.children.push(prop); this.children.push(prop);
@@ -320,6 +338,7 @@
ValueNode.prototype.has_properties = function has_properties() { ValueNode.prototype.has_properties = function has_properties() {
return !!this.properties.length; return !!this.properties.length;
}; };
// Some boolean checks for the benefit of other nodes.
ValueNode.prototype.is_array = function is_array() { ValueNode.prototype.is_array = function is_array() {
return this.base instanceof ArrayNode && !this.has_properties(); return this.base instanceof ArrayNode && !this.has_properties();
}; };
@@ -332,13 +351,19 @@
ValueNode.prototype.is_arguments = function is_arguments() { ValueNode.prototype.is_arguments = function is_arguments() {
return this.base.value === 'arguments'; return this.base.value === 'arguments';
}; };
// The value can be unwrapped as its inner node, if there are no attached
// properties.
ValueNode.prototype.unwrap = function unwrap() { ValueNode.prototype.unwrap = function unwrap() {
return this.properties.length ? this : this.base; return this.properties.length ? this : this.base;
}; };
// Values are statements if their base is a statement. // Values are considered to be statements if their base is a statement.
ValueNode.prototype.is_statement = function is_statement() { ValueNode.prototype.is_statement = function is_statement() {
return this.base.is_statement && this.base.is_statement() && !this.has_properties(); return this.base.is_statement && this.base.is_statement() && !this.has_properties();
}; };
// We compile a value to JavaScript by compiling and joining each property.
// Things get much more insteresting if the chain of properties has *soak*
// operators `?.` interspersed. Then we have to take care not to accidentally
// evaluate a anything twice when building the soak chain.
ValueNode.prototype.compile_node = function compile_node(o) { ValueNode.prototype.compile_node = function compile_node(o) {
var _a, _b, _c, baseline, complete, only, op, part, prop, props, soaked, temp; var _a, _b, _c, baseline, complete, only, op, part, prop, props, soaked, temp;
soaked = false; soaked = false;
@@ -373,7 +398,8 @@
}; };
return ValueNode; return ValueNode;
}).call(this); }).call(this);
// Pass through CoffeeScript comments into JavaScript comments at the //### CommentNode
// CoffeeScript passes through comments as JavaScript comments at the
// same position. // same position.
exports.CommentNode = (function() { exports.CommentNode = (function() {
CommentNode = function CommentNode(lines) { CommentNode = function CommentNode(lines) {
@@ -389,7 +415,8 @@
return CommentNode; return CommentNode;
}).call(this); }).call(this);
statement(CommentNode); statement(CommentNode);
// Node for a function invocation. Takes care of converting super() calls into //### CallNode
// Node for a function invocation. Takes care of converting `super()` calls into
// calls against the prototype's function of the same name. // calls against the prototype's function of the same name.
exports.CallNode = (function() { exports.CallNode = (function() {
CallNode = function CallNode(variable, args) { CallNode = function CallNode(variable, args) {
@@ -399,10 +426,12 @@
}; };
__extends(CallNode, BaseNode); __extends(CallNode, BaseNode);
CallNode.prototype.type = 'Call'; CallNode.prototype.type = 'Call';
// Tag this invocation as creating a new instance.
CallNode.prototype.new_instance = function new_instance() { CallNode.prototype.new_instance = function new_instance() {
this.prefix = 'new '; this.prefix = 'new ';
return this; return this;
}; };
// Add an argument to the call's arugment list.
CallNode.prototype.push = function push(arg) { CallNode.prototype.push = function push(arg) {
this.args.push(arg); this.args.push(arg);
this.children.push(arg); this.children.push(arg);
@@ -427,14 +456,16 @@
} }
return this.prefix + (this.variable.compile(o)) + "(" + args + ")"; return this.prefix + (this.variable.compile(o)) + "(" + args + ")";
}; };
// Compile a call against the superclass's implementation of the current function. // `super()` is converted into a call against the superclass's implementation
// of the current function.
CallNode.prototype.compile_super = function compile_super(args, o) { CallNode.prototype.compile_super = function compile_super(args, o) {
var meth, methname; var meth, methname;
methname = o.scope.method.name; methname = o.scope.method.name;
meth = o.scope.method.proto ? (o.scope.method.proto) + ".__superClass__." + methname : methname + ".__superClass__.constructor"; meth = o.scope.method.proto ? (o.scope.method.proto) + ".__superClass__." + methname : methname + ".__superClass__.constructor";
return meth + ".call(this" + (args.length ? ', ' : '') + args + ")"; return meth + ".call(this" + (args.length ? ', ' : '') + args + ")";
}; };
// Compile a function call being passed variable arguments. // If you call a function with a splat, it's converted into a JavaScript
// `.apply()` call to allow the variable-length arguments.
CallNode.prototype.compile_splat = function compile_splat(o) { CallNode.prototype.compile_splat = function compile_splat(o) {
var _a, _b, _c, arg, args, code, i, meth, obj, temp; var _a, _b, _c, arg, args, code, i, meth, obj, temp;
meth = this.variable.compile(o); meth = this.variable.compile(o);
@@ -460,8 +491,10 @@
}; };
return CallNode; return CallNode;
}).call(this); }).call(this);
//### ExtendsNode
// Node to extend an object's prototype with an ancestor object. // Node to extend an object's prototype with an ancestor object.
// After goog.inherits from the Closure Library. // After `goog.inherits` from the
// [Closure Library](http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html).
exports.ExtendsNode = (function() { exports.ExtendsNode = (function() {
ExtendsNode = function ExtendsNode(child, parent) { ExtendsNode = function ExtendsNode(child, parent) {
this.children = [(this.child = child), (this.parent = parent)]; this.children = [(this.child = child), (this.parent = parent)];
@@ -470,7 +503,7 @@
__extends(ExtendsNode, BaseNode); __extends(ExtendsNode, BaseNode);
ExtendsNode.prototype.type = 'Extends'; ExtendsNode.prototype.type = 'Extends';
ExtendsNode.prototype.code = "function(child, parent) {\n var ctor = function(){ };\n ctor.prototype = parent.prototype;\n child.__superClass__ = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n }"; ExtendsNode.prototype.code = "function(child, parent) {\n var ctor = function(){ };\n ctor.prototype = parent.prototype;\n child.__superClass__ = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n }";
// Hooking one constructor into another's prototype chain. // Hooks one constructor into another's prototype chain.
ExtendsNode.prototype.compile_node = function compile_node(o) { ExtendsNode.prototype.compile_node = function compile_node(o) {
var call, ref; var call, ref;
o.scope.assign('__extends', this.code, true); o.scope.assign('__extends', this.code, true);
@@ -480,7 +513,8 @@
}; };
return ExtendsNode; return ExtendsNode;
}).call(this); }).call(this);
// A dotted accessor into a part of a value, or the :: shorthand for //### AccessorNode
// A `.` accessor into a property of a value, or the `::` shorthand for
// an accessor into the object's prototype. // an accessor into the object's prototype.
exports.AccessorNode = (function() { exports.AccessorNode = (function() {
AccessorNode = function AccessorNode(name, tag) { AccessorNode = function AccessorNode(name, tag) {
@@ -497,7 +531,8 @@
}; };
return AccessorNode; return AccessorNode;
}).call(this); }).call(this);
// An indexed accessor into a part of an array or object. //### IndexNode
// An indexed accessor into an array or object.
exports.IndexNode = (function() { exports.IndexNode = (function() {
IndexNode = function IndexNode(index, tag) { IndexNode = function IndexNode(index, tag) {
this.children = [(this.index = index)]; this.children = [(this.index = index)];
@@ -513,8 +548,10 @@
}; };
return IndexNode; return IndexNode;
}).call(this); }).call(this);
//### RangeNode
// A range literal. Ranges can be used to extract portions (slices) of arrays, // A range literal. Ranges can be used to extract portions (slices) of arrays,
// or to specify a range for list comprehensions. // to specify a range for comprehensions, or as a value, to be expanded into the
// corresponding array of integers at runtime.
exports.RangeNode = (function() { exports.RangeNode = (function() {
RangeNode = function RangeNode(from, to, exclusive) { RangeNode = function RangeNode(from, to, exclusive) {
this.children = [(this.from = from), (this.to = to)]; this.children = [(this.from = from), (this.to = to)];
@@ -523,6 +560,7 @@
}; };
__extends(RangeNode, BaseNode); __extends(RangeNode, BaseNode);
RangeNode.prototype.type = 'Range'; RangeNode.prototype.type = 'Range';
// Compiles the range's source variables -- where it starts and where it ends.
RangeNode.prototype.compile_variables = function compile_variables(o) { RangeNode.prototype.compile_variables = function compile_variables(o) {
var _a, _b, from, to; var _a, _b, from, to;
this.tab = o.indent; this.tab = o.indent;
@@ -534,6 +572,8 @@
to = _b[1]; to = _b[1];
return this.from_var + " = " + from + "; " + this.to_var + " = " + to + ";\n" + this.tab; return this.from_var + " = " + from + "; " + this.to_var + " = " + to + ";\n" + this.tab;
}; };
// When compiled normally, the range returns the contents of the *for loop*
// needed to iterate over the values in the range. Used by comprehensions.
RangeNode.prototype.compile_node = function compile_node(o) { RangeNode.prototype.compile_node = function compile_node(o) {
var compare, equals, idx, incr, intro, step, vars; var compare, equals, idx, incr, intro, step, vars;
if (!(o.index)) { if (!(o.index)) {
@@ -549,9 +589,9 @@
incr = intro + " += " + step + " : " + idx + " -= " + step + ")"; incr = intro + " += " + step + " : " + idx + " -= " + step + ")";
return vars + "; " + compare + "; " + incr; return vars + "; " + compare + "; " + incr;
}; };
// Expand the range into the equivalent array, if it's not being used as // When used as a value, expand the range into the equivalent array. In the
// part of a comprehension, slice, or splice. // future, the code this generates should probably be cleaned up by handwriting
// TODO: This generates pretty ugly code ... shrink it. // it instead of wrapping nodes.
RangeNode.prototype.compile_array = function compile_array(o) { RangeNode.prototype.compile_array = function compile_array(o) {
var arr, body, name; var arr, body, name;
name = o.scope.free_variable(); name = o.scope.free_variable();

View File

@@ -18,6 +18,8 @@ statement: (klass, only) ->
klass::is_statement: -> true klass::is_statement: -> true
(klass::is_pure_statement: -> true) if only (klass::is_pure_statement: -> true) if only
#### BaseNode
# The **BaseNode** is the abstract base class for all nodes in the syntax tree. # The **BaseNode** is the abstract base class for all nodes in the syntax tree.
# Each subclass implements the `compile_node` method, which performs the # Each subclass implements the `compile_node` method, which performs the
# code generation for that node. To compile a node to JavaScript, # code generation for that node. To compile a node to JavaScript,
@@ -63,28 +65,34 @@ exports.BaseNode: class BaseNode
# Convenience method to grab the current indentation level, plus tabbing in. # Convenience method to grab the current indentation level, plus tabbing in.
idt: (tabs) -> idt: (tabs) ->
idt: @tab or '' idt: @tab or ''
idt += TAB for i in [0...(tabs or 0)] num: (tabs or 0) + 1
idt += TAB while num -= 1
idt idt
# Does this node, or any of its children, contain a node of a certain kind? # Does this node, or any of its children, contain a node of a certain kind?
# Recursively traverses down the *children* of the nodes, yielding to a block
# and returning true when the block finds a match. `contains` does not cross
# scope boundaries.
contains: (block) -> contains: (block) ->
for node in @children for node in @children
return true if block(node) return true if block(node)
return true if node.contains and node.contains block return true if node.contains and node.contains block
false false
# Perform an in-order traversal of the AST. # Perform an in-order traversal of the AST. Crosses scope boundaries.
traverse: (block) -> traverse: (block) ->
for node in @children for node in @children
block node block node
node.traverse block if node.traverse node.traverse block if node.traverse
# toString representation of the node, for inspecting the parse tree. # `toString` representation of the node, for inspecting the parse tree.
# This is what `coffee --nodes` prints out.
toString: (idt) -> toString: (idt) ->
idt ||= '' idt ||= ''
'\n' + idt + @type + (child.toString(idt + TAB) for child in @children).join('') '\n' + idt + @type + (child.toString(idt + TAB) for child in @children).join('')
# Default implementations of the common node methods. # Default implementations of the common node identification methods. Nodes
# will override these with custom logic, if needed.
unwrap: -> this unwrap: -> this
children: [] children: []
is_statement: -> false is_statement: -> false
@@ -92,8 +100,11 @@ exports.BaseNode: class BaseNode
top_sensitive: -> false top_sensitive: -> false
operation_sensitive: -> false operation_sensitive: -> false
#### Expressions
# A collection of nodes, each one representing an expression. # The expressions body is the list of expressions that forms the body of an
# indented block of code -- the implementation of a function, a clause in an
# `if`, `switch`, or `try`, and so on...
exports.Expressions: class Expressions extends BaseNode exports.Expressions: class Expressions extends BaseNode
type: 'Expressions' type: 'Expressions'
@@ -105,12 +116,13 @@ exports.Expressions: class Expressions extends BaseNode
@expressions.push(node) @expressions.push(node)
this this
# Tack an expression on to the beginning of this expression list. # Add an expression at the beginning of this expression list.
unshift: (node) -> unshift: (node) ->
@expressions.unshift(node) @expressions.unshift(node)
this this
# If this Expressions consists of a single node, pull it back out. # If this Expressions consists of just a single node, unwrap it by pulling
# it back out.
unwrap: -> unwrap: ->
if @expressions.length is 1 then @expressions[0] else this if @expressions.length is 1 then @expressions[0] else this
@@ -118,21 +130,22 @@ exports.Expressions: class Expressions extends BaseNode
empty: -> empty: ->
@expressions.length is 0 @expressions.length is 0
# Is the node last in this block of expressions? # Is the given node the last one in this block of expressions?
is_last: (node) -> is_last: (node) ->
l: @expressions.length l: @expressions.length
last_index: if @expressions[l - 1] instanceof CommentNode then 2 else 1 last_index: if @expressions[l - 1] instanceof CommentNode then 2 else 1
node is @expressions[l - last_index] node is @expressions[l - last_index]
# An **Expressions** is the only node that can serve as the root.
compile: (o) -> compile: (o) ->
o ||= {} o ||= {}
if o.scope then super(o) else @compile_root(o) if o.scope then super(o) else @compile_root(o)
# Compile each expression in the Expressions body.
compile_node: (o) -> compile_node: (o) ->
(@compile_expression(node, merge(o)) for node in @expressions).join("\n") (@compile_expression(node, merge(o)) for node in @expressions).join("\n")
# If this is the top-level Expressions, wrap everything in a safety closure. # If we happen to be the top-level **Expressions**, wrap everything in
# a safety closure, unless requested not to.
compile_root: (o) -> compile_root: (o) ->
o.indent: @tab: if o.no_wrap then '' else TAB o.indent: @tab: if o.no_wrap then '' else TAB
o.scope: new Scope(null, this, null) o.scope: new Scope(null, this, null)
@@ -140,8 +153,8 @@ exports.Expressions: class Expressions extends BaseNode
code: code.replace(TRAILING_WHITESPACE, '') code: code.replace(TRAILING_WHITESPACE, '')
if o.no_wrap then code else "(function(){\n$code\n})();\n" if o.no_wrap then code else "(function(){\n$code\n})();\n"
# Compile the expressions body, with declarations of all inner variables # Compile the expressions body for the contents of a function, with
# pushed up to the top. # declarations of all inner variables pushed up to the top.
compile_with_declarations: (o) -> compile_with_declarations: (o) ->
code: @compile_node(o) code: @compile_node(o)
args: @contains (node) -> node instanceof ValueNode and node.is_arguments() args: @contains (node) -> node instanceof ValueNode and node.is_arguments()
@@ -150,40 +163,40 @@ exports.Expressions: class Expressions extends BaseNode
code: "${@tab}var ${o.scope.compiled_declarations()};\n$code" if o.scope.has_declarations(this) code: "${@tab}var ${o.scope.compiled_declarations()};\n$code" if o.scope.has_declarations(this)
code code
# Compiles a single expression within the expressions body. # Compiles a single expression within the expressions body. If we need to
# return the result, and it's an expression, simply return it. If it's a
# statement, ask the statement to do so.
compile_expression: (node, o) -> compile_expression: (node, o) ->
@tab: o.indent @tab: o.indent
stmt: node.is_statement() stmt: node.is_statement()
# We need to return the result if this is the last node in the expressions body.
returns: del(o, 'returns') and @is_last(node) and not node.is_pure_statement() returns: del(o, 'returns') and @is_last(node) and not node.is_pure_statement()
# Return the regular compile of the node, unless we need to return the result.
return (if stmt then '' else @idt()) + node.compile(merge(o, {top: true})) + (if stmt then '' else ';') unless returns return (if stmt then '' else @idt()) + node.compile(merge(o, {top: true})) + (if stmt then '' else ';') unless returns
# If it's a statement, the node knows how to return itself.
return node.compile(merge(o, {returns: true})) if node.is_statement() return node.compile(merge(o, {returns: true})) if node.is_statement()
# Otherwise, we can just return the value of the expression. "${@tab}return ${node.compile(o)};"
return "${@tab}return ${node.compile(o)};"
# Wrap up a node as an Expressions, unless it already is one. # Wrap up the given nodes as an **Expressions**, unless it already happens
# to be one.
Expressions.wrap: (nodes) -> Expressions.wrap: (nodes) ->
return nodes[0] if nodes.length is 1 and nodes[0] instanceof Expressions return nodes[0] if nodes.length is 1 and nodes[0] instanceof Expressions
new Expressions(nodes) new Expressions(nodes)
statement Expressions statement Expressions
#### LiteralNode
# Literals are static values that can be passed through directly into # Literals are static values that can be passed through directly into
# JavaScript without translation, eg.: strings, numbers, true, false, null... # JavaScript without translation, such as: strings, numbers,
# `true`, `false`, `null`...
exports.LiteralNode: class LiteralNode extends BaseNode exports.LiteralNode: class LiteralNode extends BaseNode
type: 'Literal' type: 'Literal'
constructor: (value) -> constructor: (value) ->
@value: value @value: value
# Break and continue must be treated as statements -- they lose their meaning # Break and continue must be treated as pure statements -- they lose their
# when wrapped in a closure. # meaning when wrapped in a closure.
is_statement: -> is_statement: ->
@value is 'break' or @value is 'continue' @value is 'break' or @value is 'continue'
is_pure_statement: LiteralNode::is_statement is_pure_statement: LiteralNode::is_statement
compile_node: (o) -> compile_node: (o) ->
@@ -194,8 +207,10 @@ exports.LiteralNode: class LiteralNode extends BaseNode
toString: (idt) -> toString: (idt) ->
" \"$@value\"" " \"$@value\""
#### ReturnNode
# Return an expression, or wrap it in a closure and return it. # A `return` is a *pure_statement* -- wrapping it in a closure wouldn't
# make sense.
exports.ReturnNode: class ReturnNode extends BaseNode exports.ReturnNode: class ReturnNode extends BaseNode
type: 'Return' type: 'Return'
@@ -208,16 +223,20 @@ exports.ReturnNode: class ReturnNode extends BaseNode
statement ReturnNode, true statement ReturnNode, true
#### ValueNode
# A value, indexed or dotted into, or vanilla. # A value, variable or literal or parenthesized, indexed or dotted into,
# or vanilla.
exports.ValueNode: class ValueNode extends BaseNode exports.ValueNode: class ValueNode extends BaseNode
type: 'Value' type: 'Value'
SOAK: " == undefined ? undefined : " SOAK: " == undefined ? undefined : "
# A **ValueNode** has a base and a list of property accesses.
constructor: (base, properties) -> constructor: (base, properties) ->
@children: flatten [@base: base, @properties: (properties or [])] @children: flatten [@base: base, @properties: (properties or [])]
# Add a property access to the list.
push: (prop) -> push: (prop) ->
@properties.push(prop) @properties.push(prop)
@children.push(prop) @children.push(prop)
@@ -229,6 +248,8 @@ exports.ValueNode: class ValueNode extends BaseNode
has_properties: -> has_properties: ->
!!@properties.length !!@properties.length
# Some boolean checks for the benefit of other nodes.
is_array: -> is_array: ->
@base instanceof ArrayNode and not @has_properties() @base instanceof ArrayNode and not @has_properties()
@@ -241,13 +262,19 @@ exports.ValueNode: class ValueNode extends BaseNode
is_arguments: -> is_arguments: ->
@base.value is 'arguments' @base.value is 'arguments'
# The value can be unwrapped as its inner node, if there are no attached
# properties.
unwrap: -> unwrap: ->
if @properties.length then this else @base if @properties.length then this else @base
# Values are statements if their base is a statement. # Values are considered to be statements if their base is a statement.
is_statement: -> is_statement: ->
@base.is_statement and @base.is_statement() and not @has_properties() @base.is_statement and @base.is_statement() and not @has_properties()
# We compile a value to JavaScript by compiling and joining each property.
# Things get much more insteresting if the chain of properties has *soak*
# operators `?.` interspersed. Then we have to take care not to accidentally
# evaluate a anything twice when building the soak chain.
compile_node: (o) -> compile_node: (o) ->
soaked: false soaked: false
only: del(o, 'only_first') only: del(o, 'only_first')
@@ -274,8 +301,9 @@ exports.ValueNode: class ValueNode extends BaseNode
if op and soaked then "($complete)" else complete if op and soaked then "($complete)" else complete
#### CommentNode
# Pass through CoffeeScript comments into JavaScript comments at the # CoffeeScript passes through comments as JavaScript comments at the
# same position. # same position.
exports.CommentNode: class CommentNode extends BaseNode exports.CommentNode: class CommentNode extends BaseNode
type: 'Comment' type: 'Comment'
@@ -289,8 +317,9 @@ exports.CommentNode: class CommentNode extends BaseNode
statement CommentNode statement CommentNode
#### CallNode
# Node for a function invocation. Takes care of converting super() calls into # Node for a function invocation. Takes care of converting `super()` calls into
# calls against the prototype's function of the same name. # calls against the prototype's function of the same name.
exports.CallNode: class CallNode extends BaseNode exports.CallNode: class CallNode extends BaseNode
type: 'Call' type: 'Call'
@@ -299,10 +328,12 @@ exports.CallNode: class CallNode extends BaseNode
@children: flatten [@variable: variable, @args: (args or [])] @children: flatten [@variable: variable, @args: (args or [])]
@prefix: '' @prefix: ''
# Tag this invocation as creating a new instance.
new_instance: -> new_instance: ->
@prefix: 'new ' @prefix: 'new '
this this
# Add an argument to the call's arugment list.
push: (arg) -> push: (arg) ->
@args.push(arg) @args.push(arg)
@children.push(arg) @children.push(arg)
@@ -315,7 +346,8 @@ exports.CallNode: class CallNode extends BaseNode
return @compile_super(args, o) if @variable is 'super' return @compile_super(args, o) if @variable is 'super'
"$@prefix${@variable.compile(o)}($args)" "$@prefix${@variable.compile(o)}($args)"
# Compile a call against the superclass's implementation of the current function. # `super()` is converted into a call against the superclass's implementation
# of the current function.
compile_super: (args, o) -> compile_super: (args, o) ->
methname: o.scope.method.name methname: o.scope.method.name
meth: if o.scope.method.proto meth: if o.scope.method.proto
@@ -324,7 +356,8 @@ exports.CallNode: class CallNode extends BaseNode
"$methname.__superClass__.constructor" "$methname.__superClass__.constructor"
"$meth.call(this${ if args.length then ', ' else '' }$args)" "$meth.call(this${ if args.length then ', ' else '' }$args)"
# Compile a function call being passed variable arguments. # If you call a function with a splat, it's converted into a JavaScript
# `.apply()` call to allow the variable-length arguments.
compile_splat: (o) -> compile_splat: (o) ->
meth: @variable.compile o meth: @variable.compile o
obj: @variable.source or 'this' obj: @variable.source or 'this'
@@ -338,9 +371,11 @@ exports.CallNode: class CallNode extends BaseNode
if i is 0 then code else ".concat($code)" if i is 0 then code else ".concat($code)"
"$@prefix$meth.apply($obj, ${ args.join('') })" "$@prefix$meth.apply($obj, ${ args.join('') })"
#### ExtendsNode
# Node to extend an object's prototype with an ancestor object. # Node to extend an object's prototype with an ancestor object.
# After goog.inherits from the Closure Library. # After `goog.inherits` from the
# [Closure Library](http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html).
exports.ExtendsNode: class ExtendsNode extends BaseNode exports.ExtendsNode: class ExtendsNode extends BaseNode
type: 'Extends' type: 'Extends'
@@ -357,15 +392,16 @@ exports.ExtendsNode: class ExtendsNode extends BaseNode
constructor: (child, parent) -> constructor: (child, parent) ->
@children: [@child: child, @parent: parent] @children: [@child: child, @parent: parent]
# Hooking one constructor into another's prototype chain. # Hooks one constructor into another's prototype chain.
compile_node: (o) -> compile_node: (o) ->
o.scope.assign('__extends', @code, true) o.scope.assign('__extends', @code, true)
ref: new ValueNode literal('__extends') ref: new ValueNode literal('__extends')
call: new CallNode ref, [@child, @parent] call: new CallNode ref, [@child, @parent]
call.compile(o) call.compile(o)
#### AccessorNode
# A dotted accessor into a part of a value, or the :: shorthand for # A `.` accessor into a property of a value, or the `::` shorthand for
# an accessor into the object's prototype. # an accessor into the object's prototype.
exports.AccessorNode: class AccessorNode extends BaseNode exports.AccessorNode: class AccessorNode extends BaseNode
type: 'Accessor' type: 'Accessor'
@@ -379,8 +415,9 @@ exports.AccessorNode: class AccessorNode extends BaseNode
compile_node: (o) -> compile_node: (o) ->
'.' + (if @prototype then 'prototype.' else '') + @name.compile(o) '.' + (if @prototype then 'prototype.' else '') + @name.compile(o)
#### IndexNode
# An indexed accessor into a part of an array or object. # An indexed accessor into an array or object.
exports.IndexNode: class IndexNode extends BaseNode exports.IndexNode: class IndexNode extends BaseNode
type: 'Index' type: 'Index'
@@ -392,9 +429,11 @@ exports.IndexNode: class IndexNode extends BaseNode
idx: @index.compile o idx: @index.compile o
"[$idx]" "[$idx]"
#### RangeNode
# A range literal. Ranges can be used to extract portions (slices) of arrays, # A range literal. Ranges can be used to extract portions (slices) of arrays,
# or to specify a range for list comprehensions. # to specify a range for comprehensions, or as a value, to be expanded into the
# corresponding array of integers at runtime.
exports.RangeNode: class RangeNode extends BaseNode exports.RangeNode: class RangeNode extends BaseNode
type: 'Range' type: 'Range'
@@ -402,12 +441,15 @@ exports.RangeNode: class RangeNode extends BaseNode
@children: [@from: from, @to: to] @children: [@from: from, @to: to]
@exclusive: !!exclusive @exclusive: !!exclusive
# Compiles the range's source variables -- where it starts and where it ends.
compile_variables: (o) -> compile_variables: (o) ->
@tab: o.indent @tab: o.indent
[@from_var, @to_var]: [o.scope.free_variable(), o.scope.free_variable()] [@from_var, @to_var]: [o.scope.free_variable(), o.scope.free_variable()]
[from, to]: [@from.compile(o), @to.compile(o)] [from, to]: [@from.compile(o), @to.compile(o)]
"$@from_var = $from; $@to_var = $to;\n$@tab" "$@from_var = $from; $@to_var = $to;\n$@tab"
# When compiled normally, the range returns the contents of the *for loop*
# needed to iterate over the values in the range. Used by comprehensions.
compile_node: (o) -> compile_node: (o) ->
return @compile_array(o) unless o.index return @compile_array(o) unless o.index
idx: del o, 'index' idx: del o, 'index'
@@ -420,9 +462,9 @@ exports.RangeNode: class RangeNode extends BaseNode
incr: "$intro += $step : $idx -= $step)" incr: "$intro += $step : $idx -= $step)"
"$vars; $compare; $incr" "$vars; $compare; $incr"
# Expand the range into the equivalent array, if it's not being used as # When used as a value, expand the range into the equivalent array. In the
# part of a comprehension, slice, or splice. # future, the code this generates should probably be cleaned up by handwriting
# TODO: This generates pretty ugly code ... shrink it. # it instead of wrapping nodes.
compile_array: (o) -> compile_array: (o) ->
name: o.scope.free_variable() name: o.scope.free_variable()
body: Expressions.wrap([literal(name)]) body: Expressions.wrap([literal(name)])