Compare commits

..

54 Commits
0.9.1 ... 0.9.2

Author SHA1 Message Date
Jeremy Ashkenas
e2c46d14f0 CoffeeScript 0.9.2 2010-08-23 22:08:33 -04:00
Jeremy Ashkenas
bd3471b3d1 Issue #641. Rename __superClass__ to __super__ 2010-08-23 21:19:43 -04:00
Jeremy Ashkenas
1b88d18d61 more tweaks and futzes to block comments. 2010-08-23 21:00:47 -04:00
Jeremy Ashkenas
b4de17d504 more tweaks to the herecomment regex. 2010-08-23 20:33:18 -04:00
Jeremy Ashkenas
f90fac0e55 Issue #572. Flexible JavaScript block comments, compatible with JSDoc, YUI-compressor, and Google Closure compiler preservation syntax. 2010-08-23 20:27:34 -04:00
Jeremy Ashkenas
9fd92bf884 updating package.json for newer NPM. 2010-08-23 11:39:06 -04:00
Jeremy Ashkenas
117204a784 Revert "Issue #619. 'new' operator misbehavior."
This reverts commit e7834de929.
2010-08-21 19:16:02 -04:00
Jeremy Ashkenas
e7834de929 Issue #619. 'new' operator misbehavior. 2010-08-21 18:54:24 -04:00
Jeremy Ashkenas
d5d5de55ae Fixing the longstanding and important Issue #637. I'm glad this one got got. 2010-08-21 12:13:43 -04:00
Jeremy Ashkenas
143c4d5efc Issue #572. Block comments now compile to // for aesthetic reasons. 2010-08-21 09:30:25 -04:00
Jeremy Ashkenas
13adc44867 Issue #633. 'not instanceof' 2010-08-21 08:56:25 -04:00
Jeremy Ashkenas
87693d84cb Updating Underscore to 1.1.0, fixing a hasOwnProperty glitch in Scope, and a double-semicolon bug in ParentheticalNode. 2010-08-21 08:30:22 -04:00
Jeremy Ashkenas
6ed33fcc6d Updating contributors in README. 2010-08-20 17:53:45 -04:00
Jeremy Ashkenas
2e59cc4807 Using unbounded ranges in a couple spots in the compiler. 2010-08-18 22:08:09 -04:00
Jeremy Ashkenas
4ddd65a4c4 Issue #621. Added the ability to leave the start and end index off of arrays. list[5..] is now valid CoffeeScript, slicing to the end of the array. 2010-08-18 21:51:44 -04:00
Jeremy Ashkenas
bf6bafa3ac Disallowing Splats outside of ParamLists and ArgLists ... where they belong. This is in anticipation of the next commit... 2010-08-18 21:27:10 -04:00
Jeremy Ashkenas
24f1174b16 Adding a test for issue #631. 2010-08-18 20:42:23 -04:00
Jeremy Ashkenas
098caa9979 Revert "Fixes Issue #618. Close implicit arguments in the middle of param lists."
This reverts commit 474c372b17.
2010-08-18 20:39:55 -04:00
Jeremy Ashkenas
b608d4a5ea Issue #626. Making the isInvertible check a little stricter. 2010-08-17 21:46:00 -04:00
Jeremy Ashkenas
4d32c47bee Merge branch 'remote_script' of http://github.com/satyr/coffee-script 2010-08-17 21:35:00 -04:00
Jeremy Ashkenas
ec54b50c67 allowing empty parens. 2010-08-17 21:31:32 -04:00
satyr
387c690530 removed noWrap (setTimeout evaluates on global) 2010-08-18 10:29:13 +09:00
Jeremy Ashkenas
536e24b024 Merge branch 'remote_script' of http://github.com/satyr/coffee-script 2010-08-17 21:15:41 -04:00
Jeremy Ashkenas
1b05cd81f0 Enabling bound functions as static members of classes... Issue #627 2010-08-17 21:07:36 -04:00
satyr
db181e2a36 enabled remote scripts in browsers 2010-08-18 09:35:52 +09:00
Jeremy Ashkenas
f41ca2e5e8 a touch of safety from trailing catches falling off the end of the rewriter. 2010-08-17 20:04:34 -04:00
Jeremy Ashkenas
a8c6a641d7 stop supressing left-hand whitespace in newline'd strings. Make 'em more literal. 2010-08-16 22:02:37 -04:00
Jeremy Ashkenas
474c372b17 Fixes Issue #618. Close implicit arguments in the middle of param lists. 2010-08-16 21:19:34 -04:00
Jeremy Ashkenas
5b9b45814f Fixing Issue #622 with a light refactor to start using a 'tags' property on all nodes. 2010-08-16 20:18:42 -04:00
Stan Angeloff
01cd5476a0 '-r' should work with $NODE_PATH as well (where previously it was an absolute/relative path) 2010-08-16 17:36:55 +03:00
Jeremy Ashkenas
027b9e9dc3 simplifying generated output for unless/is to (a isnt b) instead of not (a is b). Ticket #617 2010-08-15 15:13:33 -04:00
Jeremy Ashkenas
197f576cab Merged in Stan's patch that allows -r scripts to modify input and output. 2010-08-15 08:32:09 -04:00
Jeremy Ashkenas
0b8facc66f Merge branch 'master' of git://github.com/StanAngeloff/coffee-script 2010-08-15 08:20:50 -04:00
Jeremy Ashkenas
7a0d95c612 Issue #575. Allowing implicit objects to force implicit calls. 2010-08-14 19:56:00 -04:00
Jeremy Ashkenas
975b82f09b Issue #609. Slightly faster implementation of ||= and &&= 2010-08-14 18:02:07 -04:00
Jeremy Ashkenas
f496cc229b Further reducing amount of redundant parentheses. 2010-08-14 17:52:37 -04:00
Jeremy Ashkenas
9894eeb8e9 Improving double-parentheses suppression. Issue #587 2010-08-14 17:43:58 -04:00
Jeremy Ashkenas
129e950c59 Fixing naked chained existential checks -- the associativity recently got reversed. 2010-08-14 16:33:20 -04:00
Jeremy Ashkenas
c90a75ebc5 Fixing first part of #614 -- improperly cached existential operator, when first operand is a function call. 2010-08-14 16:24:05 -04:00
Jeremy Ashkenas
1d6eca76f8 disabling javascriptlint's 'test for equality mistyped as assignment', because it's not relevant to coffeescript. 2010-08-14 16:05:14 -04:00
Jeremy Ashkenas
6555d86328 Adding a jsl.conf configuration file for JavaScript lint, and switching to == null for soaks, accordingly. 2010-08-14 16:02:01 -04:00
Jeremy Ashkenas
c71f2794eb Fixing compound assignment as a right-hand sub expression of a larger operation. Invalid in JS, valid in Coffee. 2010-08-14 14:43:25 -04:00
Jeremy Ashkenas
ca18f1fad6 Core Compiler is JSLint-free again, after removing a couple extra semicolons that snuck in when if statements compiled at the top level. 2010-08-14 11:42:19 -04:00
Jeremy Ashkenas
ead9b1041c tweaking existential compilation. 2010-08-14 11:29:10 -04:00
Jeremy Ashkenas
1eebbfe2bc allowing more flexible whitespace-started regexes. You have to wrap 'em in parens or assign to 'em, but it's better than nothing. 2010-08-12 20:24:53 -04:00
Stan Angeloff
d30c8b321c Allow required files to change the input and output of compiled files. 2010-08-13 01:28:38 +03:00
Jeremy Ashkenas
083500fc0e fixing string interpolation docco. 2010-08-12 00:00:28 -04:00
Jeremy Ashkenas
fd6e9a1e66 Adding support for compound assignment to indented implicit objects. 2010-08-11 23:14:50 -04:00
Jeremy Ashkenas
8c45aa480b Reduced the time it takes to build the grammar from 80 seconds to 15, by consolidating Operation terminals by precedence level. 2010-08-11 23:04:33 -04:00
Jeremy Ashkenas
d704afa0e9 Fixes Issue #574 ... number keys in implicit object literals. 2010-08-11 21:49:18 -04:00
Jeremy Ashkenas
2ec857ef8d Fixing implicit object literals with leading string keys. 2010-08-11 21:41:29 -04:00
Jeremy Ashkenas
ba02ebc3dc Fixes Issue #603 -- a longstanding precedence issue involving prefix vs postfix if and unless, involving using the entire single-line if statment as an expression. 2010-08-11 21:28:22 -04:00
Jeremy Ashkenas
ac752a46bc removing bound functions from the Rewriter. 2010-08-11 21:07:47 -04:00
Jeremy Ashkenas
398ec3be5a Issue #602. Adding JS's Bitwise Assignment operators. 2010-08-11 19:24:59 -04:00
56 changed files with 1857 additions and 1569 deletions

View File

@@ -97,10 +97,9 @@ task 'test', 'run the CoffeeScript language test suite', ->
passedTests = failedTests = 0
startTime = new Date
originalOk = ok
helpers.extend global, {
helpers.extend global,
ok: (args...) -> passedTests += 1; originalOk(args...)
CoffeeScript: CoffeeScript
}
process.on 'exit', ->
time = ((new Date - startTime) / 1000).toFixed(2)
message = "passed #{passedTests} tests in #{time} seconds#{reset}"

2
README
View File

@@ -56,10 +56,12 @@
Timothy Jones (Tesco)
Chris Lloyd (chrislloyd)
Matt Lyon (mattly)
Satoshi Murakami (satyr)
Jeff Olson (olsonjeffery)
Nathan Ostgard (noonat)
Samuel Reis (grgh)
Tom Robinson (tlrobinson)
Tim Smart (Tim-Smart)
Sam Stephenson (sstephenson)
Dr. Nic Williams (drnic)

View File

@@ -6,7 +6,7 @@ require 'yui/compressor'
HEADER = <<-EOS
/**
* CoffeeScript Compiler v0.9.1
* CoffeeScript Compiler v0.9.2
* http://coffeescript.org
*
* Copyright 2010, Jeremy Ashkenas

View File

@@ -1,4 +1,4 @@
###
CoffeeScript Compiler v0.9.1
CoffeeScript Compiler v0.9.2
Released under the MIT License
###

View File

@@ -1,8 +1,8 @@
mobyDick = "Call me Ishmael. Some years ago --
never mind how long precisely -- having little
or no money in my purse, and nothing particular
to interest me on shore, I thought I would sail
about a little and see the watery part of the
world..."
never mind how long precisely -- having little
or no money in my purse, and nothing particular
to interest me on shore, I thought I would sail
about a little and see the watery part of the
world..."

View File

@@ -15,7 +15,7 @@ a {
color: #000055;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 40px;
margin-top: 50px;
}
br.clear {
height: 0;

View File

@@ -16,7 +16,7 @@ execute all scripts present in <code>text/coffeescript</code> tags.</p>
<span class="k">this</span><span class="p">.</span><span class="nv">exports = </span><span class="k">this</span><span class="p">.</span><span class="nv">CoffeeScript = </span><span class="p">{}</span>
<span class="nv">Lexer = </span><span class="k">this</span><span class="p">.</span><span class="nx">Lexer</span>
<span class="nv">parser = </span><span class="k">this</span><span class="p">.</span><span class="nx">parser</span>
<span class="nv">helpers = </span><span class="k">this</span><span class="p">.</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s1">&#39;0.9.1&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
<span class="nv">helpers = </span><span class="k">this</span><span class="p">.</span><span class="nx">helpers</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-3">#</a> </div> <p>The current CoffeeScript version number.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.VERSION = </span><span class="s1">&#39;0.9.2&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-5">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">options</span> <span class="o">or=</span> <span class="p">{}</span>
<span class="k">try</span>
@@ -45,15 +45,28 @@ directly as a "Jison lexer".</p> </td> <td class="code">
<span class="vi">@tokens = </span><span class="nx">tokens</span>
<span class="vi">@pos = </span><span class="mi">0</span>
<span class="nx">upcomingInput</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="s2">&quot;&quot;</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of <code>text/coffeescript</code>. This happens
on page load. Unfortunately, the text contents of remote scripts cannot be
accessed from the browser, so only inline script tags will work.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">document</span><span class="o">?</span> <span class="o">and</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span>
all script tags with a content-type of <code>text/coffeescript</code>.
This happens on page load.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">document</span><span class="o">?</span><span class="p">.</span><span class="nx">getElementsByTagName</span>
<span class="nv">grind = </span><span class="p">(</span><span class="nx">coffee</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">setTimeout</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">coffee</span>
<span class="nv">grindRemote = </span><span class="p">(</span><span class="nx">url</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">xhr = </span><span class="k">new</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span> <span class="o">or</span> <span class="nx">XMLHttpRequest</span><span class="p">)(</span><span class="s1">&#39;Microsoft.XMLHTTP&#39;</span><span class="p">)</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span> <span class="s1">&#39;GET&#39;</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">overrideMimeType</span> <span class="s1">&#39;text/plain&#39;</span> <span class="k">if</span> <span class="s1">&#39;overrideMimeType&#39;</span> <span class="k">of</span> <span class="nx">xhr</span>
<span class="nv">xhr.onreadystatechange = </span><span class="o">-&gt;</span>
<span class="nx">grind</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span> <span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span> <span class="kc">null</span>
<span class="nv">processScripts = </span><span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;script&#39;</span><span class="p">)</span> <span class="k">when</span> <span class="nx">tag</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">&#39;text/coffeescript&#39;</span>
<span class="nb">eval</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">tag</span><span class="p">.</span><span class="nx">innerHTML</span>
<span class="k">for</span> <span class="nx">script</span> <span class="k">in</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s1">&#39;script&#39;</span>
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">&#39;text/coffeescript&#39;</span>
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
<span class="nx">grindRemote</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
<span class="k">else</span>
<span class="nx">grind</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span>
<span class="kc">null</span>
<span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span> <span class="s1">&#39;load&#39;</span><span class="p">,</span> <span class="nx">processScripts</span><span class="p">,</span> <span class="kc">false</span>
<span class="k">else</span> <span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">attachEvent</span> <span class="s1">&#39;onload&#39;</span><span class="p">,</span> <span class="nx">processScripts</span>
<span class="nx">addEventListener</span> <span class="s1">&#39;DOMContentLoaded&#39;</span><span class="p">,</span> <span class="nx">processScripts</span><span class="p">,</span> <span class="kc">false</span>
<span class="k">else</span>
<span class="nx">attachEvent</span> <span class="s1">&#39;onload&#39;</span><span class="p">,</span> <span class="nx">processScripts</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -29,24 +29,24 @@ interactive REPL.</p> </td> <td class="code">
<span class="p">[</span><span class="s1">&#39;-n&#39;</span><span class="p">,</span> <span class="s1">&#39;--nodes&#39;</span><span class="p">,</span> <span class="s1">&#39;print the parse tree that Jison produces&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-v&#39;</span><span class="p">,</span> <span class="s1">&#39;--version&#39;</span><span class="p">,</span> <span class="s1">&#39;display CoffeeScript version&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s1">&#39;-h&#39;</span><span class="p">,</span> <span class="s1">&#39;--help&#39;</span><span class="p">,</span> <span class="s1">&#39;display this help message&#39;</span><span class="p">]</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>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">options = </span><span class="p">{}</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>Top-level objects shared by all the functions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">opts = </span><span class="p">{}</span>
<span class="nv">sources = </span><span class="p">[]</span>
<span class="nv">optionParser = </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
Many flags cause us to divert before compiling anything. Flags passed after
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="o">-&gt;</span>
<span class="nx">parseOptions</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">help</span>
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">version</span>
<span class="k">return</span> <span class="nx">require</span> <span class="s1">&#39;./repl&#39;</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">interactive</span>
<span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">stdio</span>
<span class="k">return</span> <span class="nx">compileScript</span> <span class="s1">&#39;console&#39;</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nb">eval</span>
<span class="k">return</span> <span class="nx">usage</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">help</span>
<span class="k">return</span> <span class="nx">version</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">version</span>
<span class="k">return</span> <span class="nx">require</span> <span class="s1">&#39;./repl&#39;</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">interactive</span>
<span class="k">return</span> <span class="nx">compileStdio</span><span class="p">()</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">stdio</span>
<span class="k">return</span> <span class="nx">compileScript</span> <span class="s1">&#39;console&#39;</span><span class="p">,</span> <span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nb">eval</span>
<span class="k">return</span> <span class="nx">require</span> <span class="s1">&#39;./repl&#39;</span> <span class="nx">unless</span> <span class="nx">sources</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">separator = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span> <span class="s1">&#39;--&#39;</span>
<span class="nv">flags = </span><span class="p">[]</span>
<span class="k">if</span> <span class="nx">separator</span> <span class="o">&gt;=</span> <span class="mi">0</span>
<span class="nv">flags = </span><span class="nx">sources</span><span class="p">[(</span><span class="nx">separator</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)...</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span>
<span class="nv">sources = </span><span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">...</span><span class="nx">separator</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">run</span>
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">run</span>
<span class="nv">flags = </span><span class="nx">sources</span><span class="p">[</span><span class="mi">1</span><span class="p">..</span><span class="nx">sources</span><span class="p">.</span><span class="nx">length</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">flags</span>
<span class="nv">sources = </span><span class="p">[</span><span class="nx">sources</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
<span class="nv">process.ARGV = process.argv = </span><span class="nx">flags</span>
@@ -65,30 +65,32 @@ compile them. If a directory is passed, recursively compile all
<span class="nx">compile</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">)</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;.coffee&#39;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">code</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">compileScript</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">base</span><span class="p">)</span>
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">compile</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Compile a single source script, containing the given code, according to the
requested options. If evaluating the script directly sets <code>__filename</code>,
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScript = </span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o = </span><span class="nx">options</span>
<span class="nv">codeOpts = </span><span class="nx">compileOptions</span> <span class="nx">source</span>
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileScript = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">base</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o = </span><span class="nx">opts</span>
<span class="nv">options = </span><span class="nx">compileOptions</span> <span class="nx">file</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">require</span>
<span class="nx">require</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="nx">file</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">o</span><span class="p">.</span><span class="nx">require</span>
<span class="nx">require</span><span class="p">(</span><span class="k">if</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">starts</span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="s1">&#39;.&#39;</span><span class="p">)</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="k">else</span> <span class="nx">file</span><span class="p">)</span> <span class="k">for</span> <span class="nx">file</span> <span class="k">in</span> <span class="nx">o</span><span class="p">.</span><span class="nx">require</span>
<span class="k">try</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">&#39;compile&#39;</span><span class="p">,</span> <span class="p">{</span><span class="nx">source</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="nx">options</span><span class="p">}</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">code</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">code</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">codeOpts</span>
<span class="nv">t = task = </span><span class="p">{</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">options</span><span class="p">}</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">&#39;compile&#39;</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
<span class="k">else</span>
<span class="nv">js = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">codeOpts</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">&#39;success&#39;</span><span class="p">,</span> <span class="nx">js</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">print</span> <span class="nx">js</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="k">then</span> <span class="nx">writeJs</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">base</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">js</span>
<span class="nv">t.output = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">&#39;success&#39;</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">print</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="k">then</span> <span class="nx">writeJs</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">base</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span>
<span class="k">catch</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Avoid using 'error' as it is a special event -- if there is no handler,
node will print a stack trace and exit the program.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">&#39;failure&#39;</span><span class="p">,</span> <span class="nx">err</span>
node will print a stack trace and exit the program.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">&#39;failure&#39;</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s1">&#39;failure&#39;</span><span class="p">).</span><span class="nx">length</span>
<span class="nx">error</span><span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">stack</span><span class="p">)</span> <span class="o">and</span> <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
<span class="k">return</span> <span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">error</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileStdio = </span><span class="o">-&gt;</span>
<span class="nv">code = </span><span class="s1">&#39;&#39;</span>
<span class="nv">stdin = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span>
@@ -106,17 +108,18 @@ directory can be customized with <code>--output</code>.</p> </td>
<span class="nv">filename = </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="o">+</span> <span class="s1">&#39;.js&#39;</span>
<span class="nv">srcDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">source</span>
<span class="nv">baseDir = </span><span class="nx">srcDir</span><span class="p">.</span><span class="nx">substring</span> <span class="nx">base</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">dir = </span><span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">options</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
<span class="nv">dir = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
<span class="nv">jsPath = </span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">filename</span>
<span class="nv">compile = </span><span class="o">-&gt;</span>
<span class="nv">js = </span><span class="s1">&#39; &#39;</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;=</span> <span class="mi">0</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">puts</span> <span class="s2">&quot;Compiled #{source}&quot;</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">puts</span> <span class="s2">&quot;Compiled #{source}&quot;</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">dir</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">exists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s2">&quot;mkdir -p #{dir}&quot;</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
any errors or warnings that arise.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lint = </span><span class="p">(</span><span class="nx">js</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">print</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s1">&#39;jsl&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;-nologo&#39;</span><span class="p">,</span> <span class="s1">&#39;-stdin&#39;</span><span class="p">]</span>
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">puts</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">&#39;/../extras/jsl.conf&#39;</span>
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s1">&#39;jsl&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;-nologo&#39;</span><span class="p">,</span> <span class="s1">&#39;-stdin&#39;</span><span class="p">,</span> <span class="s1">&#39;-conf&#39;</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="kc">on</span> <span class="s1">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
@@ -126,14 +129,14 @@ any errors or warnings that arise.</p> </td> <td class="
<span class="s2">&quot;[#{tag} #{value}]&quot;</span>
<span class="nx">puts</span> <span class="nx">strings</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-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parseOptions = </span><span class="o">-&gt;</span>
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
<span class="nv">o = options = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">length</span><span class="p">])</span>
<span class="nx">options</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
<span class="nv">options.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
<span class="nv">options.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
<span class="nv">sources = </span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">fileName</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">length</span><span class="p">])</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
<span class="nv">o.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
<span class="nv">o.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">fileName</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o = </span><span class="p">{</span><span class="nx">fileName</span><span class="p">}</span>
<span class="nv">o.noWrap = </span><span class="nx">options</span><span class="p">[</span><span class="s1">&#39;no-wrap&#39;</span><span class="p">]</span>
<span class="nv">o.noWrap = </span><span class="nx">opts</span><span class="p">[</span><span class="s1">&#39;no-wrap&#39;</span><span class="p">]</span>
<span class="nx">o</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Print the <code>--help</code> usage message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage = </span><span class="o">-&gt;</span>
<span class="nx">puts</span> <span class="nx">optionParser</span><span class="p">.</span><span class="nx">help</span><span class="p">()</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Print the <code>--version</code> message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">version = </span><span class="o">-&gt;</span>

View File

@@ -65,7 +65,6 @@ them somewhat circular.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s2">&quot;Switch&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Extends&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Class&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Splat&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Existence&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Comment&quot;</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>An indented block of expressions. Note that the <a href="rewriter.html">Rewriter</a>
@@ -215,41 +214,49 @@ object.</p> </td> <td class="code"> <div c
<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>The slice literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Slice</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START Expression . . Expression INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$5</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START Expression . . . Expression INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START Expression . . INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START Expression . . . INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START . . Expression INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;INDEX_START . . . Expression INDEX_END&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">RangeNode</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$5</span><span class="p">,</span> <span class="kc">true</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <p>The array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;[ ArgList OptComma ]&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ArrayNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
as well as the contents of an array literal
(i.e. comma-separated expressions). Newlines work as well.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ArgList</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s2">&quot;Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ArgList , Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ArgList OptComma TERMINATOR Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;Arg&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ArgList , Arg&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$3</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ArgList OptComma TERMINATOR Arg&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="p">[</span><span class="nx">$4</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ArgList OptComma INDENT ArgList OptComma OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span> <span class="nx">$4</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Just simple, comma-separated, required arguments (no fancy syntax). We need
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Valid arguments are Expressions or Splats.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Arg</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Expression&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Splat&quot;</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>Just simple, comma-separated, required arguments (no fancy syntax). We need
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
having the newlines wouldn't make sense.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">SimpleArgs</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Expression&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;SimpleArgs , Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">$1</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">concat</span><span class="p">([</span><span class="nx">$3</span><span class="p">])</span> <span class="k">else</span> <span class="p">[</span><span class="nx">$1</span><span class="p">].</span><span class="nx">concat</span><span class="p">([</span><span class="nx">$3</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>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Try</span><span class="o">:</span> <span class="p">[</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>The variants of <em>try/catch/finally</em> exception handling blocks.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Try</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;TRY Block Catch&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;TRY Block FINALLY Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;TRY Block Catch FINALLY Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">TryNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</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>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Catch</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Catch</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;CATCH Identifier Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Throw</span><span class="o">:</span> <span class="p">[</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> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Throw</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;THROW Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ThrowNode</span> <span class="nx">$2</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> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
not an <strong>Expression</strong>, so if you need to use an expression in a place
where only values are accepted, wrapping it in parentheses will always do
the trick.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Parenthetical</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;( Line )&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-54">#</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;( )&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">&#39;&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>The condition portion of a while loop.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">WhileSource</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;WHILE Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;WHILE Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;UNTIL Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;UNTIL Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>The while loop can either be normal, with a block of expressions to execute,
or postfix, with a single expression. There is no do..while.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">While</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;WhileSource Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;Statement WhileSource&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">addBody</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
@@ -260,7 +267,7 @@ or postfix, with a single expression. There is no do..while.</p> </t
<span class="nx">Loop</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;LOOP Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">&#39;true&#39;</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;LOOP Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">WhileNode</span><span class="p">(</span><span class="k">new</span> <span class="nx">LiteralNode</span> <span class="s1">&#39;true&#39;</span><span class="p">).</span><span class="nx">addBody</span> <span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">$2</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>Array, object, and range comprehensions, at the most generic level.
Comprehensions can either be normal, with a block of expressions to execute,
or postfix, with a single expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">For</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Statement ForBody&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ForNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">vars</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$2</span><span class="p">.</span><span class="nx">vars</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
@@ -276,17 +283,17 @@ or postfix, with a single expression.</p> </td> <td clas
<span class="nx">ForStart</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;FOR ForVariables&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;FOR ALL ForVariables&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nv">$3.raw = </span><span class="kc">true</span><span class="p">;</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>An array of all accepted values for a variable inside the loop. This
<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>An array of all accepted values for a variable inside the loop. This
enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForValue</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;Identifier&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Array&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s2">&quot;Object&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">$1</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>An array or range comprehension has variables for the current element and
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>An array or range comprehension has variables for the current element and
(optional) reference to the current index. Or, <em>key, value</em>, in the case
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForVariables</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;ForValue&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">]</span>
<span class="nx">o</span> <span class="s2">&quot;ForValue , ForValue&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <p>The source of a comprehension is an array or object with an optional guard
<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>The source of a comprehension is an array or object with an optional guard
clause. If it's an array comprehension, you can also choose to step through
in fixed-size increments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForSource</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span>
@@ -296,92 +303,68 @@ in fixed-size increments.</p> </td> <td class="code">
<span class="nx">o</span> <span class="s2">&quot;IN Expression BY Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression WHEN Expression BY Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$6</span>
<span class="nx">o</span> <span class="s2">&quot;IN Expression BY Expression WHEN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">source</span><span class="o">:</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">step</span><span class="o">:</span> <span class="nx">$4</span><span class="p">,</span> <span class="nx">guard</span><span class="o">:</span> <span class="nx">$6</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>The CoffeeScript switch/when/else block replaces the JavaScript
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <p>The CoffeeScript switch/when/else block replaces the JavaScript
switch/case/default by compiling into an if-else chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Switch</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;SWITCH Expression INDENT Whens OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$4</span><span class="p">.</span><span class="nx">switchesOver</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;SWITCH Expression INDENT Whens ELSE Block OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$4</span><span class="p">.</span><span class="nx">switchesOver</span><span class="p">(</span><span class="nx">$2</span><span class="p">).</span><span class="nx">addElse</span> <span class="nx">$6</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;SWITCH INDENT Whens OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;SWITCH INDENT Whens ELSE Block OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$3</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$5</span><span class="p">,</span> <span class="kc">true</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <p>The inner list of whens is left recursive. At code-generation time, the
<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>The inner list of whens is left recursive. At code-generation time, the
IfNode will rewrite them into a proper chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Whens</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;When&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Whens When&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$2</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>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <p>An individual <strong>When</strong> clause, with action.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">When</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;LEADING_WHEN SimpleArgs Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;LEADING_WHEN SimpleArgs Block TERMINATOR&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>The most basic form of <em>if</em> is a condition and an action. The following
if-related rules are broken up along these lines in order to avoid
ambiguity.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">IfBlock</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IF Expression Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;UNLESS Expression Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;IfBlock ELSE IF Expression Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="p">(</span><span class="k">new</span> <span class="nx">IfNode</span><span class="p">(</span><span class="nx">$4</span><span class="p">,</span> <span class="nx">$5</span><span class="p">)).</span><span class="nx">forceStatement</span><span class="p">()</span>
<span class="nx">o</span> <span class="s2">&quot;IfBlock ELSE Block&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">addElse</span> <span class="nx">$3</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-65">#</a> </div> <p>The full complement of <em>if</em> expressions, including postfix one-liner
<em>if</em> and <em>unless</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">If</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;IfBlock&quot;</span>
<span class="nx">o</span> <span class="s2">&quot;Statement IF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Expression IF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Statement UNLESS Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Expression UNLESS Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-65">#</a> </div> <p>Arithmetic and logical operators, working on one or more operands.
<span class="nx">o</span> <span class="s2">&quot;Statement POST_IF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Expression POST_IF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Statement POST_UNLESS Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Expression POST_UNLESS Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">IfNode</span> <span class="nx">$3</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">$1</span><span class="p">]),</span> <span class="nx">statement</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span> <span class="nx">invert</span><span class="o">:</span> <span class="kc">true</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>Arithmetic and logical operators, working on one or more operands.
Here they are grouped by order of precedence. The actual precedence rules
are defined at the bottom of the page. It would be shorter if we could
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
-type rule, but in order to make the precedence binding possible, separate
rules are necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Operation</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s2">&quot;! Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;!! Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;!!&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span><span class="p">(</span><span class="s2">&quot;- Expression&quot;</span><span class="p">,</span> <span class="p">(</span><span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;-&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">&#39;UMINUS&#39;</span><span class="p">})</span>
<span class="nx">o</span><span class="p">(</span><span class="s2">&quot;+ Expression&quot;</span><span class="p">,</span> <span class="p">(</span><span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">&#39;UPLUS&#39;</span><span class="p">})</span>
<span class="nx">o</span> <span class="s2">&quot;~ Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;~&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;UNARY Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span><span class="p">(</span><span class="s2">&quot;- Expression&quot;</span><span class="p">,</span> <span class="p">(</span><span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;-&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">&#39;UNARY&#39;</span><span class="p">})</span>
<span class="nx">o</span><span class="p">(</span><span class="s2">&quot;+ Expression&quot;</span><span class="p">,</span> <span class="p">(</span><span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">)),</span> <span class="p">{</span><span class="nx">prec</span><span class="o">:</span> <span class="s1">&#39;UNARY&#39;</span><span class="p">})</span>
<span class="nx">o</span> <span class="s2">&quot;-- Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;++ Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;DELETE Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;delete&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;TYPEOF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;typeof&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s2">&quot;Expression --&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ++&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s2">&quot;Expression * Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;*&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression / Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression % Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;%&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ? Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;?&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression + Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression - Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;-&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &lt;&lt; Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&lt;&lt;&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &gt;&gt; Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&gt;&gt;&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &gt;&gt;&gt; Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&gt;&gt;&gt;&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &amp; Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&amp;&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression | Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;|&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ^ Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;^&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &lt;= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&lt;=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &lt; Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&lt;&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &gt; Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &gt;= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&gt;=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression == Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;==&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression != Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;!=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &amp;&amp; Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&amp;&amp;&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression || Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;||&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression OP? Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;?&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression MATH Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression SHIFT Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression COMPARE Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression LOGIC Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Value COMPOUND_ASSIGN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Value COMPOUND_ASSIGN INDENT Expression OUTDENT&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;Expression -= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;-=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression += Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;+=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression /= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;/=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression *= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;*=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression %= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;%=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ||= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;||=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression &amp;&amp;= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;&amp;&amp;=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ?= Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;?=&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression INSTANCEOF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;instanceof&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression IN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">InNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression OF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;in&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ! IN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="k">new</span> <span class="nx">InNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;Expression ! OF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;in&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</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> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
<span class="nx">o</span> <span class="s2">&quot;Expression INSTANCEOF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;instanceof&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s2">&quot;Expression UNARY IN Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="k">new</span> <span class="nx">InNode</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;Expression UNARY OF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;in&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
<span class="nx">o</span> <span class="s2">&quot;Expression UNARY INSTANCEOF Expression&quot;</span><span class="p">,</span> <span class="o">-&gt;</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="nx">$2</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;instanceof&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</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> <h2>Precedence</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <p>Operators at the top of this list have higher precedence than the ones lower
down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<pre><code>2 + (3 * 4)
@@ -391,26 +374,24 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<pre><code>(2 + 3) * 4
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">operators = </span><span class="p">[</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;?&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;nonassoc&quot;</span><span class="p">,</span> <span class="s1">&#39;UMINUS&#39;</span><span class="p">,</span> <span class="s1">&#39;UPLUS&#39;</span><span class="p">,</span> <span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="s1">&#39;!!&#39;</span><span class="p">,</span> <span class="s1">&#39;~&#39;</span><span class="p">,</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="s1">&#39;--&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;*&#39;</span><span class="p">,</span> <span class="s1">&#39;/&#39;</span><span class="p">,</span> <span class="s1">&#39;%&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;?&#39;</span><span class="p">,</span> <span class="s1">&#39;NEW&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;nonassoc&quot;</span><span class="p">,</span> <span class="s1">&#39;++&#39;</span><span class="p">,</span> <span class="s1">&#39;--&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;UNARY&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;MATH&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;+&#39;</span><span class="p">,</span> <span class="s1">&#39;-&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&lt;&lt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&gt;&gt;&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&amp;&#39;</span><span class="p">,</span> <span class="s1">&#39;|&#39;</span><span class="p">,</span> <span class="s1">&#39;^&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&lt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;&lt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">,</span> <span class="s1">&#39;INSTANCEOF&#39;</span><span class="p">,</span> <span class="s1">&#39;TYPEOF&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;SHIFT&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;COMPARE&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;INSTANCEOF&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;==&#39;</span><span class="p">,</span> <span class="s1">&#39;!=&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;&#39;</span><span class="p">,</span> <span class="s1">&#39;||&#39;</span><span class="p">,</span> <span class="s1">&#39;OP?&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;-=&#39;</span><span class="p">,</span> <span class="s1">&#39;+=&#39;</span><span class="p">,</span> <span class="s1">&#39;/=&#39;</span><span class="p">,</span> <span class="s1">&#39;*=&#39;</span><span class="p">,</span> <span class="s1">&#39;%=&#39;</span><span class="p">,</span> <span class="s1">&#39;||=&#39;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;=&#39;</span><span class="p">,</span> <span class="s1">&#39;?=&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;LOGIC&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;COMPOUND_ASSIGN&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;.&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;nonassoc&quot;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;LEADING_WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;IN&#39;</span><span class="p">,</span> <span class="s1">&#39;OF&#39;</span><span class="p">,</span> <span class="s1">&#39;BY&#39;</span><span class="p">,</span> <span class="s1">&#39;THROW&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;FOR&#39;</span><span class="p">,</span> <span class="s1">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s1">&#39;UNTIL&#39;</span><span class="p">,</span> <span class="s1">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s1">&#39;NEW&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;CLASS&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;left&quot;</span><span class="p">,</span> <span class="s1">&#39;EXTENDS&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;FOR&#39;</span><span class="p">,</span> <span class="s1">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s1">&#39;UNTIL&#39;</span><span class="p">,</span> <span class="s1">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;CLASS&#39;</span><span class="p">,</span> <span class="s1">&#39;EXTENDS&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">,</span> <span class="s1">&#39;:&#39;</span><span class="p">,</span> <span class="s1">&#39;RETURN&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</a> </div> <p>Finally, now what we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
<span class="p">[</span><span class="s2">&quot;right&quot;</span><span class="p">,</span> <span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;POST_IF&#39;</span><span class="p">,</span> <span class="s1">&#39;POST_UNLESS&#39;</span><span class="p">]</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> <h2>Wrapping Up</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <p>Finally, now what we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
our <strong>Jison.Parser</strong>. We do this by processing all of our rules, recording all
terminals (every symbol which does not appear as the name of a rule above)
as "tokens".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tokens = </span><span class="p">[]</span>
@@ -419,14 +400,13 @@ as "tokens".</p> </td> <td class="code"> <
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s1">&#39; &#39;</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="nx">unless</span> <span class="nx">grammar</span><span class="p">[</span><span class="nx">token</span><span class="p">]</span>
<span class="nx">alt</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;return #{alt[1]}&quot;</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">is</span> <span class="s1">&#39;Root&#39;</span>
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
<span class="nx">alt</span></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-71">#</a> </div> <p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
rules, and the name of the root. Reverse the operators because Jison orders
precedence from low to high, and we have it high to low
(as in <a href="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.parser = </span><span class="k">new</span> <span class="nx">Parser</span> <span class="p">{</span>
(as in <a href="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.parser = </span><span class="k">new</span> <span class="nx">Parser</span>
<span class="nx">tokens</span><span class="o">:</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">join</span> <span class="s1">&#39; &#39;</span>
<span class="nx">bnf</span><span class="o">:</span> <span class="nx">grammar</span>
<span class="nx">operators</span><span class="o">:</span> <span class="nx">operators</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span>
<span class="nx">startSymbol</span><span class="o">:</span> <span class="s1">&#39;Root&#39;</span>
<span class="p">}</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

File diff suppressed because one or more lines are too long

View File

@@ -16,7 +16,10 @@ 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
the environment from higher in the tree (such as if a returned value is
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-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
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>
<span class="nx">constructor</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="vi">@tags = </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>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
<em>statement</em>, and it's not a <em>pureStatement</em>, and we're not at
the top level of a block (which would be unnecessary), and we haven't
@@ -28,12 +31,10 @@ depending on whether it's being used as part of a larger expression, or is a
top-level statement within the function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compile</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@options = </span><span class="nx">merge</span> <span class="nx">o</span> <span class="o">or</span> <span class="p">{}</span>
<span class="vi">@tab = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
<span class="nx">unless</span> <span class="k">this</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">or</span> <span class="k">this</span> <span class="k">instanceof</span> <span class="nx">CallNode</span>
<span class="nx">del</span> <span class="nx">@options</span><span class="p">,</span> <span class="s1">&#39;operation&#39;</span>
<span class="nx">del</span> <span class="nx">@options</span><span class="p">,</span> <span class="s1">&#39;chainRoot&#39;</span> <span class="nx">unless</span> <span class="k">this</span> <span class="k">instanceof</span> <span class="nx">AccessorNode</span> <span class="o">or</span> <span class="k">this</span> <span class="k">instanceof</span> <span class="nx">IndexNode</span>
<span class="nx">del</span> <span class="nx">@options</span><span class="p">,</span> <span class="s1">&#39;chainRoot&#39;</span> <span class="nx">unless</span> <span class="k">this</span> <span class="k">instanceof</span> <span class="nx">AccessorNode</span> <span class="o">or</span> <span class="k">this</span> <span class="k">instanceof</span> <span class="nx">IndexNode</span>
<span class="nv">top = </span><span class="k">if</span> <span class="nx">@topSensitive</span><span class="p">()</span> <span class="k">then</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="nx">@options</span><span class="p">,</span> <span class="s1">&#39;top&#39;</span>
<span class="nv">closure = </span><span class="nx">@isStatement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@isPureStatement</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="nx">@options</span><span class="p">.</span><span class="nx">asStatement</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="nv">closure = </span><span class="nx">@isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@isPureStatement</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="nx">@options</span><span class="p">.</span><span class="nx">asStatement</span> <span class="o">and</span> <span class="k">this</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">CommentNode</span> <span class="o">and</span>
<span class="o">not</span> <span class="nx">@containsPureStatement</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">closure</span> <span class="k">then</span> <span class="nx">@compileClosure</span><span class="p">(</span><span class="nx">@options</span><span class="p">)</span> <span class="k">else</span> <span class="nx">@compileNode</span><span class="p">(</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="nx">compileClosure</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -108,6 +109,7 @@ indented block of code -- the implementation of a function, a clause in an
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="vi">@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-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</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="nx">push</span><span class="o">:</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</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-20"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-20">#</a> </div> <p>Add an expression at the beginning of this expression list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unshift</span><span class="o">:</span> <span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -145,7 +147,7 @@ return the result, and it's an expression, simply return it. If it's a
statement, ask the statement to do so.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileExpression</span><span class="o">:</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="vi">@tab = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
<span class="nv">compiledNode = </span><span class="nx">node</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">merge</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">top</span><span class="o">:</span> <span class="kc">true</span>
<span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">()</span> <span class="k">then</span> <span class="nx">compiledNode</span> <span class="k">else</span> <span class="s2">&quot;#{@idt()}#{compiledNode};&quot;</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Wrap up the given nodes as an <strong>Expressions</strong>, unless it already happens
<span class="k">if</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">then</span> <span class="nx">compiledNode</span> <span class="k">else</span> <span class="s2">&quot;#{@idt()}#{compiledNode};&quot;</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</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">new</span> <span class="nx">Expressions</span><span class="p">(</span><span class="nx">nodes</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <h3>LiteralNode</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>Literals are static values that can be passed through directly into
@@ -155,6 +157,7 @@ JavaScript without translation, such as: strings, numbers,
<span class="nx">class</span><span class="o">:</span> <span class="s1">&#39;LiteralNode&#39;</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@value</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@isStatement</span><span class="p">()</span> <span class="k">then</span> <span class="k">this</span> <span class="k">else</span> <span class="k">super</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>Break and continue must be treated as pure statements -- they lose their
@@ -163,8 +166,8 @@ meaning when wrapped in a closure.</p> </td> <td class="
<span class="nx">isPureStatement</span><span class="o">:</span> <span class="nx">LiteralNode</span><span class="o">::</span><span class="nx">isStatement</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">idt = </span><span class="k">if</span> <span class="nx">@isStatement</span><span class="p">()</span> <span class="k">then</span> <span class="nx">@idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">end = </span><span class="k">if</span> <span class="nx">@isStatement</span><span class="p">()</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">idt = </span><span class="k">if</span> <span class="nx">@isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">then</span> <span class="nx">@idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">end = </span><span class="k">if</span> <span class="nx">@isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</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="nx">idt</span> <span class="o">+</span> <span class="nx">@value</span> <span class="o">+</span> <span class="nx">end</span>
<span class="nx">toString</span><span class="o">:</span> <span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -177,6 +180,7 @@ make sense.</p> </td> <td class="code"> <d
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;expression&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">this</span>
@@ -187,14 +191,13 @@ make sense.</p> </td> <td class="code"> <d
<span class="k">super</span> <span class="nx">o</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o.asStatement = </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">@expression</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">()</span>
<span class="nv">o.asStatement = </span><span class="kc">true</span> <span class="k">if</span> <span class="nx">@expression</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="s2">&quot;#{@tab}return #{@expression.compile(o)};&quot;</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-34">#</a> </div> <h3>ValueNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-35">#</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="nx">SOAK</span><span class="o">:</span> <span class="s2">&quot; == undefined ? undefined : &quot;</span>
<span class="nx">class</span><span class="o">:</span> <span class="s1">&#39;ValueNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;base&#39;</span><span class="p">,</span> <span class="s1">&#39;properties&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-36">#</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="nx">constructor</span><span class="o">:</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="k">super</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-37"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-37">#</a> </div> <p>Add a property access to the list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">push</span><span class="o">:</span> <span class="p">(</span><span class="nx">prop</span><span class="p">)</span> <span class="o">-&gt;</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="k">this</span>
@@ -212,32 +215,29 @@ or vanilla.</p> </td> <td class="code"> <d
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@hasProperties</span><span class="p">()</span> <span class="k">then</span> <span class="k">super</span><span class="p">()</span> <span class="k">else</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">makeReturn</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>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="nx">unwrap</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">if</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="nx">@base</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</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="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@base</span><span class="p">.</span><span class="nx">isStatement</span> <span class="o">and</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">()</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@hasProperties</span><span class="p">()</span>
<span class="k">if</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="nx">@base</span></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-40">#</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="nx">isStatement</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@base</span><span class="p">.</span><span class="nx">isStatement</span> <span class="o">and</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@hasProperties</span><span class="p">()</span>
<span class="nx">isNumber</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">LiteralNode</span> <span class="o">and</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">NUMBER</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>Works out if the value is the start of a chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">isStart</span><span class="o">:</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="kc">true</span> <span class="k">if</span> <span class="k">this</span> <span class="o">is</span> <span class="nx">o</span><span class="p">.</span><span class="nx">chainRoot</span> <span class="o">and</span> <span class="nx">@properties</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">AccessorNode</span>
<span class="nv">node = </span><span class="nx">o</span><span class="p">.</span><span class="nx">chainRoot</span><span class="p">.</span><span class="nx">base</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">chainRoot</span><span class="p">.</span><span class="nx">variable</span>
<span class="k">while</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">CallNode</span> <span class="k">then</span> <span class="nv">node = </span><span class="nx">node</span><span class="p">.</span><span class="nx">variable</span>
<span class="nx">node</span> <span class="o">is</span> <span class="k">this</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>If the value node has indexes containing function calls, and the value node
<span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">LiteralNode</span> <span class="o">and</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">NUMBER</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-41">#</a> </div> <p>If the value node has indexes containing function calls, and the value node
needs to be used twice, in compound assignment ... then we need to cache
the value of the indexes.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">cacheIndexes</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">copy = </span><span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">0</span>
<span class="nv">copy = </span><span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">@base</span><span class="p">,</span> <span class="nx">@properties</span><span class="p">[</span><span class="mi">0</span><span class="p">..]</span>
<span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">copy</span><span class="p">.</span><span class="nx">properties</span>
<span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">IndexNode</span> <span class="o">and</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">contains</span><span class="p">((</span><span class="nx">n</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">n</span> <span class="k">instanceof</span> <span class="nx">CallNode</span><span class="p">)</span>
<span class="p">[</span><span class="nx">index</span><span class="p">,</span> <span class="nx">indexVar</span><span class="p">]</span> <span class="o">=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">index</span><span class="p">.</span><span class="nx">compileReference</span> <span class="nx">o</span>
<span class="k">this</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">IndexNode</span> <span class="nx">index</span>
<span class="nx">copy</span><span class="p">.</span><span class="nx">properties</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">IndexNode</span> <span class="nx">indexVar</span>
<span class="p">[</span><span class="k">this</span><span class="p">,</span> <span class="nx">copy</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>Override compile to unwrap the value when possible.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compile</span><span class="o">:</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="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">top</span> <span class="o">or</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</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="nx">@base</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>We compile a value to JavaScript by compiling and joining each property.
<span class="p">[</span><span class="k">this</span><span class="p">,</span> <span class="nx">copy</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-42">#</a> </div> <p>Override compile to unwrap the value when possible.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compile</span><span class="o">:</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="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">top</span> <span class="o">or</span> <span class="nx">@properties</span><span class="p">.</span><span class="nx">length</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="nx">@base</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-43"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-43">#</a> </div> <p>We compile a value to JavaScript by compiling and joining each property.
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
evaluate a anything twice when building the soak chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">only = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;onlyFirst&#39;</span>
<span class="nv">op = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;operation&#39;</span>
<span class="nv">op = </span><span class="nx">@tags</span><span class="p">.</span><span class="nx">operation</span>
<span class="nv">props = </span><span class="k">if</span> <span class="nx">only</span> <span class="k">then</span> <span class="nx">@properties</span><span class="p">[</span><span class="mi">0</span><span class="p">...</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">else</span> <span class="nx">@properties</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">chainRoot</span> <span class="o">or=</span> <span class="k">this</span>
<span class="vi">@base.parenthetical = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">@parenthetical</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">baseline = </span><span class="nx">@base</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nv">baseline = </span><span class="s2">&quot;(#{baseline})&quot;</span> <span class="k">if</span> <span class="nx">@hasProperties</span><span class="p">()</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">ObjectNode</span> <span class="o">or</span> <span class="nx">@isNumber</span><span class="p">())</span>
<span class="nv">complete = </span><span class="vi">@last = </span><span class="nx">baseline</span>
@@ -248,61 +248,69 @@ evaluate a anything twice when building the soak chain.</p> </td>
<span class="k">if</span> <span class="nx">@base</span> <span class="k">instanceof</span> <span class="nx">CallNode</span> <span class="o">or</span> <span class="nx">@base</span><span class="p">.</span><span class="nx">contains</span><span class="p">((</span><span class="nx">n</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">n</span> <span class="k">instanceof</span> <span class="nx">CallNode</span><span class="p">)</span> <span class="o">and</span> <span class="nx">i</span> <span class="o">is</span> <span class="mi">0</span>
<span class="nv">temp = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span><span class="p">()</span>
<span class="nv">complete = </span><span class="s2">&quot;(#{ baseline = temp } = (#{complete}))&quot;</span>
<span class="nv">complete = </span><span class="s2">&quot;typeof #{complete} === \&quot;undefined\&quot; || #{baseline}&quot;</span> <span class="k">if</span> <span class="nx">i</span> <span class="o">is</span> <span class="mi">0</span> <span class="o">and</span> <span class="nx">@isStart</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nx">complete</span> <span class="o">+=</span> <span class="nx">@SOAK</span> <span class="o">+</span> <span class="p">(</span><span class="nx">baseline</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="nv">complete = </span><span class="k">if</span> <span class="nx">i</span> <span class="o">is</span> <span class="mi">0</span>
<span class="s2">&quot;(typeof #{complete} === \&quot;undefined\&quot; || #{baseline} === null) ? undefined : &quot;</span>
<span class="k">else</span>
<span class="s2">&quot;#{complete} == null ? undefined : &quot;</span>
<span class="nx">complete</span> <span class="o">+=</span> <span class="p">(</span><span class="nx">baseline</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="k">else</span>
<span class="nv">part = </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="nx">baseline</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="vi">@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">@wrapped</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-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <h3>CommentNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <p>CoffeeScript passes through block comments as JavaScript block comments
<span class="k">if</span> <span class="nx">op</span> <span class="o">and</span> <span class="nx">@wrapped</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-44"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-44">#</a> </div> <h3>CommentNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-45">#</a> </div> <p>CoffeeScript passes through block comments as JavaScript block 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>
<span class="nx">class</span><span class="o">:</span> <span class="s1">&#39;CommentNode&#39;</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@lines</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@comment</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">this</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">sep = </span><span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">@tab</span>
<span class="s2">&quot;#{@tab}/*#{sep + @lines.join(sep) }\n#{@tab}*/&quot;</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</a> </div> <h3>CallNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>Node for a function invocation. Takes care of converting <code>super()</code> calls into
<span class="nx">@tab</span> <span class="o">+</span> <span class="s1">&#39;/*&#39;</span> <span class="o">+</span> <span class="nx">@comment</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\r?\n/g</span><span class="p">,</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">@tab</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;*/&#39;</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-46">#</a> </div> <h3>CallNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-47">#</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>
<span class="nx">class</span><span class="o">:</span> <span class="s1">&#39;CallNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;variable&#39;</span><span class="p">,</span> <span class="s1">&#39;args&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</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="k">super</span><span class="p">()</span>
<span class="vi">@isNew = </span><span class="kc">false</span>
<span class="vi">@isSuper = </span><span class="nx">variable</span> <span class="o">is</span> <span class="s1">&#39;super&#39;</span>
<span class="vi">@variable = </span><span class="k">if</span> <span class="nx">@isSuper</span> <span class="k">then</span> <span class="kc">null</span> <span class="k">else</span> <span class="nx">variable</span>
<span class="nx">@args</span> <span class="o">or=</span> <span class="p">[]</span>
<span class="vi">@compileSplatArguments = </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">SplatNode</span><span class="p">.</span><span class="nx">compileSplattedArray</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">@args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Tag this invocation as creating a new instance.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">newInstance</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">SplatNode</span><span class="p">.</span><span class="nx">compileSplattedArray</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">@args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-48">#</a> </div> <p>Tag this invocation as creating a new instance.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">newInstance</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="vi">@isNew = </span><span class="kc">true</span>
<span class="k">this</span>
<span class="nx">prefix</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@isNew</span> <span class="k">then</span> <span class="s1">&#39;new &#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Grab the reference to the superclass' implementation of the current method.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">superReference</span><span class="o">:</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">@isNew</span> <span class="k">then</span> <span class="s1">&#39;new &#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-49">#</a> </div> <p>Grab the reference to the superclass' implementation of the current method.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">superReference</span><span class="o">:</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">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}.__super__.#{methname}&quot;</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">methname</span>
<span class="s2">&quot;#{methname}.__superClass__.constructor&quot;</span>
<span class="k">else</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;cannot call super on an anonymous function.&quot;</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</a> </div> <p>Compile a vanilla function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot;#{methname}.__super__.constructor&quot;</span>
<span class="k">else</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;cannot call super on an anonymous function.&quot;</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-50">#</a> </div> <p>Compile a vanilla function call.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o.chainRoot = </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">o</span><span class="p">.</span><span class="nx">chainRoot</span>
<span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">@args</span> <span class="k">when</span> <span class="nx">arg</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span>
<span class="nv">compilation = </span><span class="nx">@compileSplat</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nx">unless</span> <span class="nx">compilation</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="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">compilation = </span><span class="k">if</span> <span class="nx">@isSuper</span> <span class="k">then</span> <span class="nx">@compileSuper</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">else</span> <span class="s2">&quot;#{@prefix()}#{@variable.compile(o)}(#{args})&quot;</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">operation</span> <span class="o">and</span> <span class="nx">@wrapped</span> <span class="k">then</span> <span class="s2">&quot;(#{compilation})&quot;</span> <span class="k">else</span> <span class="nx">compilation</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p><code>super()</code> is converted into a call against the superclass's implementation
<span class="k">if</span> <span class="o">not</span> <span class="nx">compilation</span>
<span class="nv">args = </span><span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">@args</span>
<span class="nv">arg.parenthetical = </span><span class="kc">true</span>
<span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nv">compilation = </span><span class="k">if</span> <span class="nx">@isSuper</span>
<span class="nx">@compileSuper</span><span class="p">(</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="nx">o</span><span class="p">)</span>
<span class="k">else</span>
<span class="s2">&quot;#{@prefix()}#{@variable.compile(o)}(#{ args.join(&#39;, &#39;) })&quot;</span>
<span class="nx">compilation</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-51">#</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="nx">compileSuper</span><span class="o">:</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;#{@superReference(o)}.call(this#{ if args.length then &#39;, &#39; else &#39;&#39; }#{args})&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>If you call a function with a splat, it's converted into a JavaScript
<span class="s2">&quot;#{@superReference(o)}.call(this#{ if args.length then &#39;, &#39; else &#39;&#39; }#{args})&quot;</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-52">#</a> </div> <p>If you call a function with a splat, it's converted into a JavaScript
<code>.apply()</code> call to allow an array of arguments to be passed.
If it's a constructor, then things get real tricky. We have to inject an
inner constructor in order to be able to pass the varargs.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSplat</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -320,24 +328,26 @@ inner constructor in order to be able to pass the varargs.</p> </td>
<span class="s2">#DIVIDER</span>
<span class="s2"> &quot;&quot;&quot;</span>
<span class="k">else</span>
<span class="s2">&quot;#{@prefix()}#{meth}.apply(#{obj}, #{ @compileSplatArguments(o) })&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>{@idt(1)}var ctor = function(){};
<span class="s2">&quot;#{@prefix()}#{meth}.apply(#{obj}, #{ @compileSplatArguments(o) })&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>{@idt(1)}var ctor = function(){};
{@idt(1)}__extends(ctor, #{meth});
{@idt(1)}return #{meth}.apply(new ctor, #{ @compileSplatArguments(o) });
{@tab}}).call(this)</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <h3>ExtendsNode</h3> </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>
{@tab}}).call(this)</p> </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> <h3>ExtendsNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;ExtendsNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;child&#39;</span><span class="p">,</span> <span class="s1">&#39;parent&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</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></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>Node to extend an object's prototype with an ancestor object.
<span class="nx">constructor</span><span class="o">:</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="k">super</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-55">#</a> </div> <p>Node to extend an object's prototype with an ancestor object.
After <code>goog.inherits</code> from the
<a href="http://closure-library.googlecode.com/svn/docs/closureGoogBase.js.html">Closure Library</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">ref = </span> <span class="k">new</span> <span class="nx">ValueNode</span> <span class="nx">literal</span> <span class="nx">utility</span> <span class="s1">&#39;extends&#39;</span>
<span class="p">(</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="nx">@child</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">]).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <p>Hooks one constructor into another's prototype chain.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-58">#</a> </div> <h3>AccessorNode</h3> </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="p">(</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="nx">@child</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">]).</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-56">#</a> </div> <p>Hooks one constructor into another's prototype chain.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-57"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-57">#</a> </div> <h3>AccessorNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;AccessorNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@name</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="vi">@prototype = </span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;prototype&#39;</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="vi">@soakNode = </span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;soak&#39;</span>
@@ -345,26 +355,28 @@ After <code>goog.inherits</code> from the
<span class="nv">name = </span><span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">chainRoot</span><span class="p">.</span><span class="nx">wrapped</span> <span class="o">or=</span> <span class="nx">@soakNode</span>
<span class="nv">namePart = </span><span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">IS_STRING</span><span class="p">)</span> <span class="k">then</span> <span class="s2">&quot;[#{name}]&quot;</span> <span class="k">else</span> <span class="s2">&quot;.#{name}&quot;</span>
<span class="nx">@prototype</span> <span class="o">+</span> <span class="nx">namePart</span></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</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></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <h3>IndexNode</h3> </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="nx">@prototype</span> <span class="o">+</span> <span class="nx">namePart</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 <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></pre></div> </td> </tr> <tr id="section-59"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-59">#</a> </div> <h3>IndexNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;IndexNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;index&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@index</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">compileNode</span><span class="o">:</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">chainRoot</span><span class="p">.</span><span class="nx">wrapped</span> <span class="o">or=</span> <span class="nx">@soakNode</span>
<span class="nv">idx = </span><span class="nx">@index</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nv">prefix = </span><span class="k">if</span> <span class="nx">@proto</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="s2">&quot;#{prefix}[#{idx}]&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>A <code>[ ... ]</code> indexed accessor into an array or object.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</a> </div> <h3>RangeNode</h3> </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="s2">&quot;#{prefix}[#{idx}]&quot;</span></pre></div> </td> </tr> <tr id="section-60"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-60">#</a> </div> <p>A <code>[ ... ]</code> indexed accessor into an array or object.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-61"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-61">#</a> </div> <h3>RangeNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;RangeNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;from&#39;</span><span class="p">,</span> <span class="s1">&#39;to&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</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="k">super</span><span class="p">()</span>
<span class="vi">@exclusive = </span><span class="o">!!</span><span class="nx">exclusive</span>
<span class="vi">@equals = </span><span class="k">if</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;=&#39;</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 range literal. Ranges can be used to extract portions (slices) of arrays,
<span class="vi">@equals = </span><span class="k">if</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;=&#39;</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-62">#</a> </div> <p>A range literal. Ranges can be used to extract portions (slices) of arrays,
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="nx">compileVariables</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o = </span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">top</span><span class="o">:</span> <span class="kc">true</span><span class="p">)</span>
@@ -374,7 +386,7 @@ corresponding array of integers at runtime.</p> </td> <t
<span class="nv">parts = </span><span class="p">[]</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@from</span> <span class="k">if</span> <span class="nx">@from</span> <span class="o">isnt</span> <span class="nx">@fromVar</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@to</span> <span class="k">if</span> <span class="nx">@to</span> <span class="o">isnt</span> <span class="nx">@toVar</span>
<span class="k">if</span> <span class="nx">parts</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="s2">&quot;#{parts.join(&#39;; &#39;)}; &quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</a> </div> <p>Compiles the range's source variables -- where it starts and where it ends.
<span class="k">if</span> <span class="nx">parts</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="s2">&quot;#{parts.join(&#39;; &#39;)}; &quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-63">#</a> </div> <p>Compiles the range's source variables -- where it starts and where it ends.
But only if they need to be cached to avoid double evaluation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</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="nx">@compileArray</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="nx">@compileSimple</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span>
@@ -385,7 +397,7 @@ But only if they need to be cached to avoid double evaluation.</p> <
<span class="nv">compare = </span><span class="s2">&quot;#{intro} &lt;#{@equals} #{@toVar} : #{idx} &gt;#{@equals} #{@toVar})&quot;</span>
<span class="nv">stepPart = </span><span class="k">if</span> <span class="nx">step</span> <span class="k">then</span> <span class="nx">step</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;1&#39;</span>
<span class="nv">incr = </span><span class="k">if</span> <span class="nx">step</span> <span class="k">then</span> <span class="s2">&quot;#{idx} += #{stepPart}&quot;</span> <span class="k">else</span> <span class="s2">&quot;#{intro} += #{stepPart} : #{idx} -= #{stepPart})&quot;</span>
<span class="s2">&quot;#{vars}; #{compare}; #{incr}&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>When compiled normally, the range returns the contents of the <em>for loop</em>
<span class="s2">&quot;#{vars}; #{compare}; #{incr}&quot;</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-64">#</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="nx">compileSimple</span><span class="o">:</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="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="nb">parseInt</span><span class="p">(</span><span class="nx">@fromNum</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">@toNum</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</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>
@@ -394,7 +406,7 @@ needed to iterate over the values in the range. Used by comprehensions.</p>
<span class="k">if</span> <span class="nx">from</span> <span class="o">&lt;=</span> <span class="nx">to</span>
<span class="s2">&quot;#{idx} = #{from}; #{idx} &lt;#{@equals} #{to}; #{step or &quot;</span><span class="c1">#{idx}++&quot;}&quot;</span>
<span class="k">else</span>
<span class="s2">&quot;#{idx} = #{from}; #{idx} &gt;#{@equals} #{to}; #{step or &quot;</span><span class="c1">#{idx}--&quot;}&quot;</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-66">#</a> </div> <p>Compile a simple range comprehension, with integers.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileArray</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="s2">&quot;#{idx} = #{from}; #{idx} &gt;#{@equals} #{to}; #{step or &quot;</span><span class="c1">#{idx}--&quot;}&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>Compile a simple range comprehension, with integers.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileArray</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">idt = </span><span class="nx">@idt</span> <span class="mi">1</span>
<span class="nv">vars = </span><span class="nx">@compileVariables</span> <span class="nx">merge</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">indent</span><span class="o">:</span> <span class="nx">idt</span>
<span class="k">if</span> <span class="nx">@fromNum</span> <span class="o">and</span> <span class="nx">@toNum</span> <span class="o">and</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="o">+</span><span class="nx">@fromNum</span> <span class="o">-</span> <span class="o">+</span><span class="nx">@toNum</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">20</span>
@@ -411,20 +423,22 @@ needed to iterate over the values in the range. Used by comprehensions.</p>
<span class="nv">clause = </span><span class="s2">&quot;#{@fromVar} &lt;= #{@toVar} ?&quot;</span>
<span class="nv">body = </span><span class="s2">&quot;var #{i} = #{@fromVar}; #{clause} #{i} &lt;#{@equals} #{@toVar} : #{i} &gt;#{@equals} #{@toVar}; #{clause} #{i} += 1 : #{i} -= 1&quot;</span>
<span class="nv">post = </span><span class="s2">&quot;{ #{result}.push(#{i}); }\n#{idt}return #{result};\n#{o.indent}&quot;</span>
<span class="s2">&quot;(function() {#{pre}\n#{idt}for (#{body})#{post}}).call(this)&quot;</span></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <p>When used as a value, expand the range into the equivalent array.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <h3>SliceNode</h3> </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="s2">&quot;(function() {#{pre}\n#{idt}for (#{body})#{post}}).call(this)&quot;</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-66">#</a> </div> <p>When used as a value, expand the range into the equivalent array.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-67"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-67">#</a> </div> <h3>SliceNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;SliceNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;range&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@range</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</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="nv">plusPart = </span><span class="k">if</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}#{plusPart})&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>An array slice literal. Unlike JavaScript's <code>Array#slice</code>, the second parameter
<span class="nv">from = </span> <span class="k">if</span> <span class="nx">@range</span><span class="p">.</span><span class="nx">from</span> <span class="k">then</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="k">else</span> <span class="s1">&#39;0&#39;</span>
<span class="nv">to = </span> <span class="k">if</span> <span class="nx">@range</span><span class="p">.</span><span class="nx">to</span> <span class="k">then</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="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nx">to</span> <span class="o">+=</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">to</span> <span class="o">or</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">to = </span> <span class="s1">&#39;, &#39;</span> <span class="o">+</span> <span class="nx">to</span> <span class="k">if</span> <span class="nx">to</span>
<span class="s2">&quot;.slice(#{from}#{to})&quot;</span></pre></div> </td> </tr> <tr id="section-68"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-68">#</a> </div> <p>An array slice literal. Unlike JavaScript's <code>Array#slice</code>, the second parameter
specifies the index of the end of the slice, just as the first parameter
is the index of the beginning.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <h3>ObjectNode</h3> </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>
is the index of the beginning.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-69"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-69">#</a> </div> <h3>ObjectNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;ObjectNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;properties&#39;</span><span class="p">]</span>
@@ -432,12 +446,13 @@ is the index of the beginning.</p> </td> <td class="code
<span class="nx">topSensitive</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">true</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">props</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="vi">@objects = @properties = </span><span class="nx">props</span> <span class="o">or</span> <span class="p">[]</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">top = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;top&#39;</span>
<span class="nv">o.indent = </span><span class="nx">@idt</span> <span class="mi">1</span>
<span class="nv">nonComments = </span><span class="nx">prop</span> <span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="o">not</span> <span class="p">(</span><span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">CommentNode</span><span class="p">)</span>
<span class="nv">nonComments = </span><span class="nx">prop</span> <span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="p">(</span><span class="nx">prop</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">CommentNode</span><span class="p">)</span>
<span class="nv">lastNoncom = </span> <span class="nx">nonComments</span><span class="p">[</span><span class="nx">nonComments</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="nv">props = </span><span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@properties</span>
<span class="nv">join = </span><span class="s2">&quot;,\n&quot;</span>
@@ -448,12 +463,13 @@ is the index of the beginning.</p> </td> <td class="code
<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">obj = </span><span class="s1">&#39;{&#39;</span> <span class="o">+</span> <span class="p">(</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="nx">@idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;}&#39;</span>
<span class="k">if</span> <span class="nx">top</span> <span class="k">then</span> <span class="s2">&quot;(#{obj})&quot;</span> <span class="k">else</span> <span class="nx">obj</span></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-71">#</a> </div> <p>An object literal, nothing fancy.</p> </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> <h3>ArrayNode</h3> </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="k">if</span> <span class="nx">top</span> <span class="k">then</span> <span class="s2">&quot;(#{obj})&quot;</span> <span class="k">else</span> <span class="nx">obj</span></pre></div> </td> </tr> <tr id="section-70"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-70">#</a> </div> <p>An object literal, nothing fancy.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-71">#</a> </div> <h3>ArrayNode</h3> </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">class</span><span class="o">:</span> <span class="s1">&#39;ArrayNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;objects&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@objects</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">@objects</span> <span class="o">or=</span> <span class="p">[]</span>
<span class="vi">@compileSplatLiteral = </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">SplatNode</span><span class="p">.</span><span class="nx">compileSplattedArray</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">@objects</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span>
@@ -475,17 +491,18 @@ is the index of the beginning.</p> </td> <td class="code
<span class="k">if</span> <span class="nx">indexOf</span><span class="p">(</span><span class="nx">objects</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="s2">&quot;[\n#{@idt(1)}#{objects}\n#{@tab}]&quot;</span>
<span class="k">else</span>
<span class="s2">&quot;[#{objects}]&quot;</span></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-73">#</a> </div> <p>An array literal.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-74">#</a> </div> <h3>ClassNode</h3> </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;[#{objects}]&quot;</span></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-72">#</a> </div> <p>An array literal.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-73"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-73">#</a> </div> <h3>ClassNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;ClassNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;variable&#39;</span><span class="p">,</span> <span class="s1">&#39;parent&#39;</span><span class="p">,</span> <span class="s1">&#39;properties&#39;</span><span class="p">]</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-75"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-75">#</a> </div> <p>The CoffeeScript class definition.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">constructor</span><span class="o">:</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">@properties</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-74"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-74">#</a> </div> <p>The CoffeeScript class definition.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">constructor</span><span class="o">:</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">@properties</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">@properties</span> <span class="o">or=</span> <span class="p">[]</span>
<span class="vi">@returns = </span><span class="kc">false</span>
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="vi">@returns = </span><span class="kc">true</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-76"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-76">#</a> </div> <p>Initialize a <strong>ClassNode</strong> with its name, an optional superclass, and a
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-75"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-75">#</a> </div> <p>Initialize a <strong>ClassNode</strong> with its name, an optional superclass, and a
list of prototype property assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="vi">@variable = </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">freeVariable</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@variable</span> <span class="o">is</span> <span class="s1">&#39;__temp__&#39;</span>
<span class="nv">extension = </span><span class="nx">@parent</span> <span class="o">and</span> <span class="k">new</span> <span class="nx">ExtendsNode</span><span class="p">(</span><span class="nx">@variable</span><span class="p">,</span> <span class="nx">@parent</span><span class="p">)</span>
@@ -514,12 +531,15 @@ list of prototype property assignments.</p> </td> <td cl
<span class="nv">constructor = </span><span class="nx">func</span>
<span class="k">continue</span>
<span class="k">if</span> <span class="nx">func</span> <span class="k">instanceof</span> <span class="nx">CodeNode</span> <span class="o">and</span> <span class="nx">func</span><span class="p">.</span><span class="nx">bound</span>
<span class="nv">func.bound = </span><span class="kc">false</span>
<span class="nx">constScope</span> <span class="o">or=</span> <span class="k">new</span> <span class="nx">Scope</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">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">,</span> <span class="nx">constructor</span><span class="p">)</span>
<span class="nx">me</span> <span class="o">or=</span> <span class="nx">constScope</span><span class="p">.</span><span class="nx">freeVariable</span><span class="p">()</span>
<span class="nv">pname = </span><span class="nx">pvar</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">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="nx">literal</span> <span class="s1">&#39;this&#39;</span> <span class="k">if</span> <span class="nx">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">empty</span><span class="p">()</span>
<span class="nx">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">literal</span> <span class="s2">&quot;this.#{pname} = function(){ return #{className}.prototype.#{pname}.apply(#{me}, arguments); }&quot;</span>
<span class="k">if</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">context</span> <span class="o">is</span> <span class="s1">&#39;this&#39;</span>
<span class="nv">func.context = </span><span class="nx">className</span>
<span class="k">else</span>
<span class="nv">func.bound = </span><span class="kc">false</span>
<span class="nx">constScope</span> <span class="o">or=</span> <span class="k">new</span> <span class="nx">Scope</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">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">,</span> <span class="nx">constructor</span><span class="p">)</span>
<span class="nx">me</span> <span class="o">or=</span> <span class="nx">constScope</span><span class="p">.</span><span class="nx">freeVariable</span><span class="p">()</span>
<span class="nv">pname = </span><span class="nx">pvar</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">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">ReturnNode</span> <span class="nx">literal</span> <span class="s1">&#39;this&#39;</span> <span class="k">if</span> <span class="nx">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">empty</span><span class="p">()</span>
<span class="nx">constructor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">literal</span> <span class="s2">&quot;this.#{pname} = function(){ return #{className}.prototype.#{pname}.apply(#{me}, arguments); }&quot;</span>
<span class="k">if</span> <span class="nx">pvar</span>
<span class="nv">access = </span><span class="k">if</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">context</span> <span class="o">is</span> <span class="s1">&#39;this&#39;</span> <span class="k">then</span> <span class="nx">pvar</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="mi">0</span><span class="p">]</span> <span class="k">else</span> <span class="k">new</span> <span class="nx">AccessorNode</span><span class="p">(</span><span class="nx">pvar</span><span class="p">,</span> <span class="s1">&#39;prototype&#39;</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">@variable</span><span class="p">,</span> <span class="p">[</span><span class="nx">access</span><span class="p">])</span>
@@ -531,9 +551,9 @@ list of prototype property assignments.</p> </td> <td cl
<span class="nv">props = </span><span class="k">if</span> <span class="o">!</span><span class="nx">props</span><span class="p">.</span><span class="nx">empty</span><span class="p">()</span> <span class="k">then</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">props</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;&#39;</span>
<span class="nv">extension = </span><span class="k">if</span> <span class="nx">extension</span> <span class="k">then</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">@idt</span><span class="p">()</span> <span class="o">+</span> <span class="nx">extension</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">@returns</span> <span class="k">then</span> <span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="k">new</span> <span class="nx">ReturnNode</span><span class="p">(</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="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nx">construct</span> <span class="o">+</span> <span class="nx">extension</span> <span class="o">+</span> <span class="nx">props</span> <span class="o">+</span> <span class="nx">returns</span></pre></div> </td> </tr> <tr id="section-77"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-77">#</a> </div> <p>Instead of generating the JavaScript string directly, we build up the
<span class="nx">construct</span> <span class="o">+</span> <span class="nx">extension</span> <span class="o">+</span> <span class="nx">props</span> <span class="o">+</span> <span class="nx">returns</span></pre></div> </td> </tr> <tr id="section-76"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-76">#</a> </div> <p>Instead of generating the JavaScript string directly, we build up the
equivalent syntax tree and compile that, in pieces. You can see the
constructor, property assignments, and inheritance getting built out below.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-78"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-78">#</a> </div> <h3>AssignNode</h3> </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></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-79">#</a> </div> <p>The <strong>AssignNode</strong> is used to assign a local variable to value, or to set the
constructor, property assignments, and inheritance getting built out below.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-77"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-77">#</a> </div> <h3>AssignNode</h3> </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></pre></div> </td> </tr> <tr id="section-78"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-78">#</a> </div> <p>The <strong>AssignNode</strong> is used to assign a local variable to value, or to set the
property of an object -- including within object literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">PROTO_ASSIGN</span><span class="o">:</span> <span class="sr">/^(\S+)\.prototype/</span>
<span class="nx">LEADING_DOT</span><span class="o">:</span> <span class="sr">/^\.(prototype\.)?/</span>
@@ -541,6 +561,7 @@ property of an object -- including within object literals.</p> </td>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;variable&#39;</span><span class="p">,</span> <span class="s1">&#39;value&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">,</span> <span class="nx">@value</span><span class="p">,</span> <span class="nx">@context</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">topSensitive</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="kc">true</span>
@@ -555,9 +576,9 @@ property of an object -- including within object literals.</p> </td>
<span class="k">super</span><span class="p">()</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@isValue</span><span class="p">()</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">.</span><span class="nx">isArray</span><span class="p">()</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isObject</span><span class="p">())</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-80">#</a> </div> <p>Matchers for detecting prototype assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@isValue</span><span class="p">()</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">.</span><span class="nx">isArray</span><span class="p">()</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isObject</span><span class="p">())</span></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-79">#</a> </div> <p>Matchers for detecting prototype assignments.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">top = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;top&#39;</span>
<span class="k">return</span> <span class="nx">@compilePatternMatch</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@isStatement</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">@compilePatternMatch</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">@compileSplice</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@isValue</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isSplice</span><span class="p">()</span>
<span class="nv">stmt = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;asStatement&#39;</span>
<span class="nv">name = </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>
@@ -572,23 +593,23 @@ property of an object -- including within object literals.</p> </td>
<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="nx">@isValue</span><span class="p">()</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@variable</span><span class="p">.</span><span class="nx">hasProperties</span><span class="p">()</span> <span class="o">or</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">namespaced</span><span class="p">)</span>
<span class="nv">val = </span><span class="s2">&quot;#{name} = #{val}&quot;</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="k">if</span> <span class="nx">top</span> <span class="k">then</span> <span class="nx">val</span> <span class="k">else</span> <span class="s2">&quot;(#{val})&quot;</span></pre></div> </td> </tr> <tr id="section-81"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-81">#</a> </div> <p>Compile an assignment, delegating to <code>compilePatternMatch</code> or
<span class="k">if</span> <span class="nx">top</span> <span class="o">or</span> <span class="nx">@parenthetical</span> <span class="k">then</span> <span class="nx">val</span> <span class="k">else</span> <span class="s2">&quot;(#{val})&quot;</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-80">#</a> </div> <p>Compile an assignment, delegating to <code>compilePatternMatch</code> or
<code>compileSplice</code> if appropriate. Keep track of the name of the base object
we've been assigned to, for correct internal references. If the variable
has not been seen yet within the current scope, declare it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compilePatternMatch</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">valVar = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span><span class="p">()</span>
<span class="nv">value = </span><span class="k">if</span> <span class="nx">@value</span><span class="p">.</span><span class="nx">isStatement</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="nx">@value</span><span class="p">)</span> <span class="k">else</span> <span class="nx">@value</span>
<span class="nv">value = </span><span class="k">if</span> <span class="nx">@value</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</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="nx">@value</span><span class="p">)</span> <span class="k">else</span> <span class="nx">@value</span>
<span class="nv">assigns = </span><span class="p">[</span><span class="s2">&quot;#{@tab}#{valVar} = #{ value.compile(o) };&quot;</span><span class="p">]</span>
<span class="nv">o.top = </span><span class="kc">true</span>
<span class="nv">o.asStatement = </span><span class="kc">true</span>
<span class="nv">splat = </span><span class="kc">false</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="nx">@variable</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span></pre></div> </td> </tr> <tr id="section-82"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-82">#</a> </div> <p>Brief implementation of recursive pattern matching, when assigning array or
<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="nx">@variable</span><span class="p">.</span><span class="nx">base</span><span class="p">.</span><span class="nx">objects</span></pre></div> </td> </tr> <tr id="section-81"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-81">#</a> </div> <p>Brief implementation of recursive pattern matching, when assigning array or
object literals to a value. Peeks at their properties to assign inner names.
See the <a href="http://wiki.ecmascript.org/doku.php?id=harmony:destructuring">ECMAScript Harmony Wiki</a>
for details.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">idx = </span><span class="nx">i</span>
<span class="k">if</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">isObject</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">AssignNode</span></pre></div> </td> </tr> <tr id="section-83"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-83">#</a> </div> <p>A regular array pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">[</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">idx</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">obj</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span><span class="p">]</span>
<span class="k">else</span></pre></div> </td> </tr> <tr id="section-84"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-84">#</a> </div> <p>A regular object pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">idx = </span><span class="nx">obj</span>
<span class="k">if</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">AssignNode</span></pre></div> </td> </tr> <tr id="section-82"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-82">#</a> </div> <p>A regular array pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">[</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">idx</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">obj</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span><span class="p">]</span>
<span class="k">else</span></pre></div> </td> </tr> <tr id="section-83"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-83">#</a> </div> <p>A regular object pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">idx = </span><span class="nx">obj</span>
<span class="k">if</span> <span class="o">not</span> <span class="p">(</span><span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">or</span> <span class="nx">obj</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span><span class="p">)</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s1">&#39;pattern matching must use only identifiers on the left-hand side.&#39;</span>
<span class="nv">isString = </span><span class="nx">idx</span><span class="p">.</span><span class="nx">value</span> <span class="o">and</span> <span class="nx">idx</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">match</span> <span class="nx">IS_STRING</span>
@@ -603,24 +624,26 @@ for details.</p> </td> <td class="code"> <
<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">valVar</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">accessClass</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="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></pre></div> </td> </tr> <tr id="section-85"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-85">#</a> </div> <p>A shorthand <code>{a, b, c} = val</code> pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSplice</span><span class="o">:</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-84"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-84">#</a> </div> <p>A shorthand <code>{a, b, c} = val</code> pattern-match.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSplice</span><span class="o">:</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">@variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">merge</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">onlyFirst</span><span class="o">:</span> <span class="kc">true</span>
<span class="nv">l = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">range = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">properties</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="nx">range</span>
<span class="nv">plus = </span><span class="k">if</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">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">from = </span><span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span> <span class="k">then</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="k">else</span> <span class="s1">&#39;0&#39;</span>
<span class="nv">to = </span><span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">to</span> <span class="k">then</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="k">else</span> <span class="s2">&quot;#{name}.length&quot;</span>
<span class="nv">val = </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-86"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-86">#</a> </div> <p>Compile the assignment from an array splice literal, using JavaScript's
<code>Array#splice</code> method.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-87"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-87">#</a> </div> <h3>CodeNode</h3> </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="s2">&quot;#{name}.splice.apply(#{name}, [#{from}, #{to}].concat(#{val}))&quot;</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 assignment from an array splice literal, using JavaScript's
<code>Array#splice</code> method.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-86"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-86">#</a> </div> <h3>CodeNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;CodeNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;params&#39;</span><span class="p">,</span> <span class="s1">&#39;body&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@params</span><span class="p">,</span> <span class="nx">@body</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@params</span> <span class="o">or=</span> <span class="p">[]</span>
<span class="nx">@body</span> <span class="o">or=</span> <span class="k">new</span> <span class="nx">Expressions</span>
<span class="vi">@bound = </span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;boundfunc&#39;</span></pre></div> </td> </tr> <tr id="section-88"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-88">#</a> </div> <p>A function definition. This is the only node that creates a new Scope.
<span class="k">super</span><span class="p">()</span>
<span class="nx">@params</span> <span class="o">or=</span> <span class="p">[]</span>
<span class="nx">@body</span> <span class="o">or=</span> <span class="k">new</span> <span class="nx">Expressions</span>
<span class="vi">@bound = </span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">&#39;boundfunc&#39;</span>
<span class="vi">@context = </span><span class="s1">&#39;this&#39;</span> <span class="k">if</span> <span class="nx">@bound</span></pre></div> </td> </tr> <tr id="section-87"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-87">#</a> </div> <p>A function definition. This is the only node that creates a new Scope.
When for the purposes of walking the contents of a function body, the CodeNode
has no <em>children</em> -- they're within the inner scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">sharedScope = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;sharedScope&#39;</span>
@@ -657,11 +680,11 @@ has no <em>children</em> -- they're within the inner scope.</p> </td
<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">parameter</span><span class="p">(</span><span class="nx">param</span><span class="p">))</span> <span class="k">for</span> <span class="nx">param</span> <span class="k">in</span> <span class="nx">params</span>
<span class="nv">code = </span><span class="k">if</span> <span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">length</span> <span class="k">then</span> <span class="s2">&quot;\n#{ @body.compileWithDeclarations(o) }\n&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="nv">func = </span><span class="s2">&quot;function(#{ params.join(&#39;, &#39;) }) {#{code}#{ code and @tab }}&quot;</span>
<span class="k">return</span> <span class="s2">&quot;#{utility(&#39;bind&#39;)}(#{func}, this)&quot;</span> <span class="k">if</span> <span class="nx">@bound</span>
<span class="k">return</span> <span class="s2">&quot;#{utility(&#39;bind&#39;)}(#{func}, #{@context})&quot;</span> <span class="k">if</span> <span class="nx">@bound</span>
<span class="k">if</span> <span class="nx">top</span> <span class="k">then</span> <span class="s2">&quot;(#{func})&quot;</span> <span class="k">else</span> <span class="nx">func</span>
<span class="nx">topSensitive</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-89"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-89">#</a> </div> <p>Compilation creates a new scope unless explicitly asked to share with the
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-88"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-88">#</a> </div> <p>Compilation creates a new scope unless explicitly asked to share with the
outer scope. Handles splat parameters in the parameter list by peeking at
the JavaScript <code>arguments</code> objects. If the function is bound with the <code>=&gt;</code>
arrow, generates a wrapper that saves the current value of <code>this</code> through
@@ -670,32 +693,34 @@ a closure.</p> </td> <td class="code"> <di
<span class="nx">toString</span><span class="o">:</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">or=</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="nx">@collectChildren</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="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">idt</span> <span class="o">+</span> <span class="nx">children</span></pre></div> </td> </tr> <tr id="section-90"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-90">#</a> </div> <p>Short-circuit traverseChildren method to prevent it from crossing scope boundaries
unless crossScope is true</p> </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> <h3>ParamNode</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ParamNode = </span><span class="nx">class</span> <span class="nx">ParamNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="nx">idt</span> <span class="o">+</span> <span class="nx">children</span></pre></div> </td> </tr> <tr id="section-89"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-89">#</a> </div> <p>Short-circuit traverseChildren method to prevent it from crossing scope boundaries
unless crossScope is true</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-90"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-90">#</a> </div> <h3>ParamNode</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ParamNode = </span><span class="nx">class</span> <span class="nx">ParamNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
<span class="nx">class</span><span class="o">:</span> <span class="s1">&#39;ParamNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@name</span><span class="p">,</span> <span class="nx">@attach</span><span class="p">,</span> <span class="nx">@splat</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="vi">@value = </span><span class="nx">literal</span> <span class="nx">@name</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@value</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nx">toString</span><span class="o">:</span> <span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@attach</span> <span class="k">then</span> <span class="p">(</span><span class="nx">literal</span> <span class="s1">&#39;@&#39;</span> <span class="o">+</span> <span class="nx">@name</span><span class="p">).</span><span class="nx">toString</span> <span class="nx">idt</span> <span class="k">else</span> <span class="nx">@value</span><span class="p">.</span><span class="nx">toString</span> <span class="nx">idt</span></pre></div> </td> </tr> <tr id="section-92"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-92">#</a> </div> <p>A parameter in a function definition. Beyond a typical Javascript parameter,
<span class="k">if</span> <span class="nx">@attach</span> <span class="k">then</span> <span class="p">(</span><span class="nx">literal</span> <span class="s1">&#39;@&#39;</span> <span class="o">+</span> <span class="nx">@name</span><span class="p">).</span><span class="nx">toString</span> <span class="nx">idt</span> <span class="k">else</span> <span class="nx">@value</span><span class="p">.</span><span class="nx">toString</span> <span class="nx">idt</span></pre></div> </td> </tr> <tr id="section-91"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-91">#</a> </div> <p>A parameter in a function definition. Beyond a typical Javascript parameter,
these parameters can also attach themselves to the context of the function,
as well as be a splat, gathering up a group of parameters into an array.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-93"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-93">#</a> </div> <h3>SplatNode</h3> </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>
as well as be a splat, gathering up a group of parameters into an array.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-92"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-92">#</a> </div> <h3>SplatNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;SplatNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nv">name = </span><span class="nx">literal</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">name</span><span class="p">.</span><span class="nx">compile</span>
<span class="vi">@name = </span><span class="nx">name</span>
<span class="nx">compileNode</span><span class="o">:</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">@index</span><span class="o">?</span> <span class="k">then</span> <span class="nx">@compileParam</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</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-94"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-94">#</a> </div> <p>A splat, either as a parameter to a function, an argument to a call,
<span class="k">if</span> <span class="nx">@index</span><span class="o">?</span> <span class="k">then</span> <span class="nx">@compileParam</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</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-93"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-93">#</a> </div> <p>A splat, either as a parameter to a function, an argument to a call,
or as part of a destructuring assignment.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileParam</span><span class="o">:</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">@name</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">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>
@@ -713,16 +738,16 @@ or as part of a destructuring assignment.</p> </td> <td
<span class="nv">assign.value = </span><span class="nx">trailing</span>
<span class="nv">pos = </span><span class="nx">@trailings</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="nx">idx</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="nx">trailing</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;arguments[#{variadic} ? #{len} - #{pos} : #{@index + idx}]&quot;</span><span class="p">)</span>
<span class="s2">&quot;#{name} = #{utility(&#39;slice&#39;)}.call(arguments, #{@index}#{end})&quot;</span></pre></div> </td> </tr> <tr id="section-95"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-95">#</a> </div> <p>Compiling a parameter splat means recovering the parameters that succeed
<span class="s2">&quot;#{name} = #{utility(&#39;slice&#39;)}.call(arguments, #{@index}#{end})&quot;</span></pre></div> </td> </tr> <tr id="section-94"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-94">#</a> </div> <p>Compiling a parameter splat means recovering the parameters that succeed
the splat in the parameter list, by slicing the arguments object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileValue</span><span class="o">:</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="nx">trailings</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">trail = </span><span class="k">if</span> <span class="nx">trailings</span> <span class="k">then</span> <span class="s2">&quot;, #{name}.length - #{trailings}&quot;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
<span class="s2">&quot;#{utility &#39;slice&#39;}.call(#{name}, #{index}#{trail})&quot;</span></pre></div> </td> </tr> <tr id="section-96"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-96">#</a> </div> <p>A compiling a splat as a destructuring assignment means slicing arguments
<span class="s2">&quot;#{utility &#39;slice&#39;}.call(#{name}, #{index}#{trail})&quot;</span></pre></div> </td> </tr> <tr id="section-95"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-95">#</a> </div> <p>A compiling a splat as a destructuring assignment means slicing arguments
from the right-hand-side's corresponding array.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@compileSplattedArray</span><span class="o">:</span> <span class="p">(</span><span class="nx">list</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">args = </span><span class="p">[]</span>
<span class="k">for</span> <span class="nx">arg</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">list</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">prev = </span><span class="nx">args</span><span class="p">[</span><span class="nv">last = </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">if</span> <span class="o">not</span> <span class="p">(</span><span class="nx">arg</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">arg</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">SplatNode</span>
<span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">starts</span><span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="nx">ends</span><span class="p">(</span><span class="nx">prev</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">)</span>
<span class="nx">args</span><span class="p">[</span><span class="nx">last</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&quot;#{prev.substr(0, prev.length - 1)}, #{code}]&quot;</span>
<span class="k">continue</span>
@@ -732,14 +757,15 @@ from the right-hand-side's corresponding array.</p> </td>
<span class="k">else</span>
<span class="nv">code = </span><span class="s2">&quot;[#{code}]&quot;</span>
<span class="nx">args</span><span class="p">.</span><span class="nx">push</span><span class="p">(</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="p">)</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></pre></div> </td> </tr> <tr id="section-97"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-97">#</a> </div> <p>Utility function that converts arbitrary number of elements, mixed with
splats, to a proper array</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-98"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-98">#</a> </div> <h3>WhileNode</h3> </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="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></pre></div> </td> </tr> <tr id="section-96"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-96">#</a> </div> <p>Utility function that converts arbitrary number of elements, mixed with
splats, to a proper array</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-97"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-97">#</a> </div> <h3>WhileNode</h3> </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="nx">class</span><span class="o">:</span> <span class="s1">&#39;WhileNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;condition&#39;</span><span class="p">,</span> <span class="s1">&#39;guard&#39;</span><span class="p">,</span> <span class="s1">&#39;body&#39;</span><span class="p">]</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">condition</span><span class="p">,</span> <span class="nx">opts</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">opts</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">invert</span>
<span class="nv">condition = </span><span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="nx">condition</span> <span class="k">if</span> <span class="nx">condition</span> <span class="k">instanceof</span> <span class="nx">OpNode</span>
<span class="nv">condition = </span><span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="nx">condition</span><span class="p">)</span>
@@ -755,12 +781,13 @@ splats, to a proper array</p> </td> <td class="code">
<span class="k">this</span>
<span class="nx">topSensitive</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-99"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-99">#</a> </div> <p>A while loop, the only sort of low-level loop exposed by CoffeeScript. From
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-98"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-98">#</a> </div> <p>A while loop, the only sort of low-level loop exposed by CoffeeScript. From
it, all other loops can be manufactured. Useful in cases where you need more
flexibility or more speed than a comprehension can provide.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">top = </span> <span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;top&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@returns</span>
<span class="nv">o.indent = </span> <span class="nx">@idt</span> <span class="mi">1</span>
<span class="nv">o.top = </span> <span class="kc">true</span>
<span class="vi">@condition.parenthetical = </span><span class="kc">yes</span>
<span class="nv">cond = </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="nv">set = </span> <span class="s1">&#39;&#39;</span>
<span class="nx">unless</span> <span class="nx">top</span>
@@ -773,39 +800,55 @@ flexibility or more speed than a comprehension can provide.</p> </td
<span class="nv">post = </span><span class="s1">&#39;\n&#39;</span> <span class="o">+</span> <span class="k">new</span> <span class="nx">ReturnNode</span><span class="p">(</span><span class="nx">literal</span><span class="p">(</span><span class="nx">rvar</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="nx">indent</span><span class="o">:</span> <span class="nx">@idt</span><span class="p">()))</span>
<span class="k">else</span>
<span class="nv">post = </span><span class="s1">&#39;&#39;</span>
<span class="s2">&quot;#{pre} {\n#{ @body.compile(o) }\n#{@tab}}#{post}&quot;</span></pre></div> </td> </tr> <tr id="section-100"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-100">#</a> </div> <p>The main difference from a JavaScript <em>while</em> is that the CoffeeScript
<span class="s2">&quot;#{pre} {\n#{ @body.compile(o) }\n#{@tab}}#{post}&quot;</span></pre></div> </td> </tr> <tr id="section-99"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-99">#</a> </div> <p>The main difference from a JavaScript <em>while</em> is that the CoffeeScript
<em>while</em> can be used as a part of a larger expression -- while loops may
return an array containing the computed result of each iteration.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-101"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-101">#</a> </div> <h3>OpNode</h3> </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></pre></div> </td> </tr> <tr id="section-102"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-102">#</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="nx">CONVERSIONS</span><span class="o">:</span> <span class="p">{</span>
return an array containing the computed result of each iteration.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-100"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-100">#</a> </div> <h3>OpNode</h3> </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></pre></div> </td> </tr> <tr id="section-101"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-101">#</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="nx">CONVERSIONS</span><span class="o">:</span>
<span class="s1">&#39;==&#39;</span><span class="o">:</span> <span class="s1">&#39;===&#39;</span>
<span class="s1">&#39;!=&#39;</span><span class="o">:</span> <span class="s1">&#39;!==&#39;</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-103"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-103">#</a> </div> <p>The map of conversions from CoffeeScript to JavaScript symbols.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">CHAINABLE</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;&lt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;&lt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;===&#39;</span><span class="p">,</span> <span class="s1">&#39;!==&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-104"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-104">#</a> </div> <p>The list of operators for which we perform
<span class="s1">&#39;!=&#39;</span><span class="o">:</span> <span class="s1">&#39;!==&#39;</span></pre></div> </td> </tr> <tr id="section-102"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-102">#</a> </div> <p>The map of conversions from CoffeeScript to JavaScript symbols.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">INVERSIONS</span><span class="o">:</span>
<span class="s1">&#39;!==&#39;</span><span class="o">:</span> <span class="s1">&#39;===&#39;</span>
<span class="s1">&#39;===&#39;</span><span class="o">:</span> <span class="s1">&#39;!==&#39;</span></pre></div> </td> </tr> <tr id="section-103"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-103">#</a> </div> <p>The map of invertible operators.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">CHAINABLE</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;&lt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;&gt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;&lt;=&#39;</span><span class="p">,</span> <span class="s1">&#39;===&#39;</span><span class="p">,</span> <span class="s1">&#39;!==&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-104"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-104">#</a> </div> <p>The list of operators for which we perform
<a href="http://docs.python.org/reference/expressions.html#notin">Python-style comparison chaining</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ASSIGNMENT</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;||=&#39;</span><span class="p">,</span> <span class="s1">&#39;&amp;&amp;=&#39;</span><span class="p">,</span> <span class="s1">&#39;?=&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-105"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-105">#</a> </div> <p>Our assignment operators that have no JavaScript equivalent.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">PREFIX_OPERATORS</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;typeof&#39;</span><span class="p">,</span> <span class="s1">&#39;delete&#39;</span><span class="p">]</span>
<span class="nx">class</span><span class="o">:</span> <span class="s1">&#39;OpNode&#39;</span>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;first&#39;</span><span class="p">,</span> <span class="s1">&#39;second&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@operator</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="nx">flip</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="vi">@operator = </span><span class="nx">@CONVERSIONS</span><span class="p">[</span><span class="nx">@operator</span><span class="p">]</span> <span class="o">or</span> <span class="nx">@operator</span>
<span class="vi">@flip = </span><span class="o">!!</span><span class="nx">flip</span>
<span class="k">if</span> <span class="nx">@first</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">ObjectNode</span>
<span class="vi">@first = </span><span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="nx">@first</span>
<span class="vi">@first.tags.operation = </span><span class="kc">yes</span>
<span class="vi">@second.tags.operation = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">@second</span>
<span class="nx">isUnary</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="o">not</span> <span class="nx">@second</span>
<span class="nx">isInvertible</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="p">(</span><span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;===&#39;</span><span class="p">,</span> <span class="s1">&#39;!==&#39;</span><span class="p">])</span> <span class="o">and</span>
<span class="o">not</span> <span class="p">(</span><span class="nx">@first</span> <span class="k">instanceof</span> <span class="nx">OpNode</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">@second</span> <span class="k">instanceof</span> <span class="nx">OpNode</span><span class="p">)</span>
<span class="nx">isMutator</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">ends</span><span class="p">(</span><span class="nx">@operator</span><span class="p">,</span> <span class="s1">&#39;=&#39;</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;===&#39;</span><span class="p">,</span> <span class="s1">&#39;!==&#39;</span><span class="p">])</span>
<span class="nx">isChainable</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">indexOf</span><span class="p">(</span><span class="nx">@CHAINABLE</span><span class="p">,</span> <span class="nx">@operator</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span>
<span class="nx">include</span><span class="p">(</span><span class="nx">@CHAINABLE</span><span class="p">,</span> <span class="nx">@operator</span><span class="p">)</span>
<span class="nx">invert</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="vi">@operator = </span><span class="nx">@INVERSIONS</span><span class="p">[</span><span class="nx">@operator</span><span class="p">]</span>
<span class="nx">toString</span><span class="o">:</span> <span class="p">(</span><span class="nx">idt</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">(</span><span class="nx">idt</span><span class="p">,</span> <span class="nx">@class</span> <span class="o">+</span> <span class="s1">&#39; &#39;</span> <span class="o">+</span> <span class="nx">@operator</span><span class="p">)</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o.operation = </span><span class="kc">true</span>
<span class="k">return</span> <span class="nx">@compileChain</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@isChainable</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">OpNode</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">isChainable</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">@compileAssignment</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">indexOf</span><span class="p">(</span><span class="nx">@ASSIGNMENT</span><span class="p">,</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="nx">@compileUnary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@isUnary</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">@compileExistence</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@operator</span> <span class="o">is</span> <span class="s1">&#39;?&#39;</span>
<span class="vi">@first = </span><span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="nx">@first</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@first</span> <span class="k">instanceof</span> <span class="nx">OpNode</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isMutator</span><span class="p">()</span>
<span class="vi">@second = </span><span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="nx">@second</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@second</span> <span class="k">instanceof</span> <span class="nx">OpNode</span> <span class="o">and</span> <span class="nx">@second</span><span class="p">.</span><span class="nx">isMutator</span><span class="p">()</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">@operator</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="nx">join</span> <span class="s1">&#39; &#39;</span></pre></div> </td> </tr> <tr id="section-106"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-106">#</a> </div> <p>Operators must come before their operands with a space.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileChain</span><span class="o">:</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="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="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">compileReference</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="p">.</span><span class="nx">containsType</span> <span class="nx">CallNode</span>
@@ -820,13 +863,12 @@ true
<span class="nv">second = </span><span class="nx">@second</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
<span class="nv">second = </span><span class="s2">&quot;(#{second})&quot;</span> <span class="k">if</span> <span class="nx">@second</span> <span class="k">instanceof</span> <span class="nx">OpNode</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="p">(</span><span class="nx">first</span><span class="p">)</span> <span class="k">if</span> <span class="nx">first</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">IDENTIFIER</span><span class="p">)</span>
<span class="k">return</span> <span class="s2">&quot;#{first} = #{ ExistenceNode.compileTest(o, literal(firstVar)) } ? #{firstVar} : #{second}&quot;</span> <span class="k">if</span> <span class="nx">@operator</span> <span class="o">is</span> <span class="s1">&#39;?=&#39;</span>
<span class="s2">&quot;#{first} = #{firstVar} #{ @operator.substr(0, 2) } #{second}&quot;</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-108">#</a> </div> <p>When compiling a conditional assignment, take care to ensure that the
<span class="k">return</span> <span class="s2">&quot;#{first} = #{ ExistenceNode.compileTest(o, literal(firstVar))[0] } ? #{firstVar} : #{second}&quot;</span> <span class="k">if</span> <span class="nx">@operator</span> <span class="o">is</span> <span class="s1">&#39;?=&#39;</span>
<span class="s2">&quot;#{first} #{ @operator.substr(0, 2) } (#{firstVar} = #{second})&quot;</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-108">#</a> </div> <p>When compiling a conditional assignment, take care to ensure that the
operands are only evaluated once, even though we have to reference them
more than once.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileExistence</span><span class="o">:</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="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="nv">test = </span><span class="nx">ExistenceNode</span><span class="p">.</span><span class="nx">compileTest</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">@first</span><span class="p">)</span>
<span class="s2">&quot;#{test} ? #{first} : #{second}&quot;</span></pre></div> </td> </tr> <tr id="section-109"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-109">#</a> </div> <p>If this is an existence operator, we delegate to <code>ExistenceNode.compileTest</code>
<span class="p">[</span><span class="nx">test</span><span class="p">,</span> <span class="nx">ref</span><span class="p">]</span> <span class="o">=</span> <span class="nx">ExistenceNode</span><span class="p">.</span><span class="nx">compileTest</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">@first</span><span class="p">)</span>
<span class="s2">&quot;#{test} ? #{ref} : #{ @second.compile(o) }&quot;</span></pre></div> </td> </tr> <tr id="section-109"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-109">#</a> </div> <p>If this is an existence operator, we delegate to <code>ExistenceNode.compileTest</code>
to give us the safe references for the variables.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileUnary</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">space = </span><span class="k">if</span> <span class="nx">indexOf</span><span class="p">(</span><span class="nx">@PREFIX_OPERATORS</span><span class="p">,</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="nx">@operator</span><span class="p">,</span> <span class="nx">space</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>
@@ -837,6 +879,7 @@ to give us the safe references for the variables.</p> </td>
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;object&#39;</span><span class="p">,</span> <span class="s1">&#39;array&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@object</span><span class="p">,</span> <span class="nx">@array</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">isArray</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@array</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="nx">@array</span><span class="p">.</span><span class="nx">isArray</span><span class="p">()</span>
@@ -861,6 +904,7 @@ to give us the safe references for the variables.</p> </td>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span>
<span class="nx">constructor</span><span class="o">:</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="k">super</span><span class="p">()</span>
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="vi">@attempt = </span><span class="nx">@attempt</span><span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@attempt</span>
@@ -879,7 +923,8 @@ is optional, the <em>catch</em> is not.</p> </td> <td cl
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;expression&#39;</span><span class="p">]</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">)</span> <span class="o">-&gt;</span></pre></div> </td> </tr> <tr id="section-116"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-116">#</a> </div> <p>Simple node to throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-116"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-116">#</a> </div> <p>Simple node to throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="k">this</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
@@ -889,13 +934,15 @@ is optional, the <em>catch</em> is not.</p> </td> <td cl
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;expression&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">ExistenceNode</span><span class="p">.</span><span class="nx">compileTest</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">@expression</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-119"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-119">#</a> </div> <p>Checks a variable for existence -- not <em>null</em> and not <em>undefined</em>. This is
<span class="nv">test = </span><span class="nx">ExistenceNode</span><span class="p">.</span><span class="nx">compileTest</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">@expression</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">@parenthetical</span> <span class="k">then</span> <span class="nx">test</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nx">test</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">else</span> <span class="nx">test</span></pre></div> </td> </tr> <tr id="section-119"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-119">#</a> </div> <p>Checks a variable for existence -- not <em>null</em> and not <em>undefined</em>. This is
similar to <code>.nil?</code> in Ruby, and avoids having to consult a JavaScript truth
table.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@compileTest</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">variable</span><span class="p">)</span> <span class="o">-&gt;</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">compileReference</span> <span class="nx">o</span>
<span class="s2">&quot;(typeof #{first.compile(o)} !== \&quot;undefined\&quot; &amp;&amp; #{second.compile(o)} !== null)&quot;</span></pre></div> </td> </tr> <tr id="section-120"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-120">#</a> </div> <p>The meat of the <strong>ExistenceNode</strong> is in this static <code>compileTest</code> method
<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">compileReference</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">precompile</span><span class="o">:</span> <span class="kc">yes</span>
<span class="p">[</span><span class="s2">&quot;(typeof #{first} !== \&quot;undefined\&quot; &amp;&amp; #{second} !== null)&quot;</span><span class="p">,</span> <span class="nx">second</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-120"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-120">#</a> </div> <p>The meat of the <strong>ExistenceNode</strong> is in this static <code>compileTest</code> method
because other nodes like to check the existence of their variables as well.
Be careful not to double-evaluate anything.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-121"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-121">#</a> </div> <h3>ParentheticalNode</h3> </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>
@@ -903,9 +950,10 @@ Be careful not to double-evaluate anything.</p> </td> <t
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">&#39;expression&#39;</span><span class="p">]</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@expression</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">super</span><span class="p">()</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@expression</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">()</span>
<span class="nx">isStatement</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@expression</span><span class="p">.</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@expression</span><span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span>
@@ -915,12 +963,12 @@ Be careful not to double-evaluate anything.</p> </td> <t
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">top = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">&#39;top&#39;</span>
<span class="vi">@expression.parenthetical = </span><span class="kc">true</span>
<span class="nv">code = </span><span class="nx">@expression</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">if</span> <span class="nx">@isStatement</span><span class="p">()</span>
<span class="k">return</span> <span class="p">(</span><span class="k">if</span> <span class="nx">top</span> <span class="k">then</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="nx">code</span> <span class="o">+</span> <span class="s1">&#39;;&#39;</span> <span class="k">else</span> <span class="nx">code</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">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="k">if</span> <span class="nx">@expression</span> <span class="k">instanceof</span> <span class="nx">AssignNode</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-122"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-122">#</a> </div> <p>An extra set of parentheses, specified explicitly in the source. At one time
<span class="k">return</span> <span class="nx">code</span> <span class="k">if</span> <span class="nx">top</span> <span class="o">and</span> <span class="nx">@expression</span><span class="p">.</span><span class="nx">isPureStatement</span> <span class="nx">o</span>
<span class="k">if</span> <span class="nx">@parenthetical</span> <span class="o">or</span> <span class="nx">@isStatement</span> <span class="nx">o</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">top</span> <span class="k">then</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="nx">code</span> <span class="o">+</span> <span class="s1">&#39;;&#39;</span> <span class="k">else</span> <span class="nx">code</span>
<span class="s2">&quot;(#{code})&quot;</span></pre></div> </td> </tr> <tr id="section-122"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-122">#</a> </div> <p>An extra set of parentheses, specified explicitly in the source. At one time
we tried to clean up the results by detecting and removing redundant
parentheses, but no longer -- you can put in as many as you please.</p>
@@ -931,6 +979,7 @@ parentheses, but no longer -- you can put in as many as you please.</p>
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">yes</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@body</span><span class="p">,</span> <span class="nx">source</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="k">super</span><span class="p">()</span>
<span class="nx">@index</span> <span class="o">or=</span> <span class="kc">null</span>
<span class="vi">@source = </span><span class="nx">source</span><span class="p">.</span><span class="nx">source</span>
<span class="vi">@guard = </span><span class="nx">source</span><span class="p">.</span><span class="nx">guard</span>
@@ -1017,8 +1066,12 @@ some cannot.</p> </td> <td class="code"> <
<span class="nx">topSensitive</span><span class="o">:</span> <span class="o">-&gt;</span> <span class="kc">true</span>
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">@condition</span><span class="p">,</span> <span class="nx">@body</span><span class="p">,</span> <span class="nx">@tags</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@tags</span> <span class="o">or=</span> <span class="p">{}</span>
<span class="vi">@condition = </span><span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="nx">@condition</span><span class="p">))</span> <span class="k">if</span> <span class="nx">@tags</span><span class="p">.</span><span class="nx">invert</span>
<span class="nx">@tags</span> <span class="o">or=</span> <span class="p">{}</span>
<span class="k">if</span> <span class="nx">@tags</span><span class="p">.</span><span class="nx">invert</span>
<span class="k">if</span> <span class="nx">@condition</span> <span class="k">instanceof</span> <span class="nx">OpNode</span> <span class="o">and</span> <span class="nx">@condition</span><span class="p">.</span><span class="nx">isInvertible</span><span class="p">()</span>
<span class="nx">@condition</span><span class="p">.</span><span class="nx">invert</span><span class="p">()</span>
<span class="k">else</span>
<span class="vi">@condition = </span><span class="k">new</span> <span class="nx">OpNode</span> <span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span> <span class="nx">@condition</span>
<span class="vi">@elseBody = </span><span class="kc">null</span>
<span class="vi">@isChain = </span><span class="kc">false</span>
@@ -1051,14 +1104,16 @@ Ensure that the switch expression isn't evaluated more than once.</p>
<span class="k">else</span>
<span class="vi">@isChain = </span><span class="nx">elseBody</span> <span class="k">instanceof</span> <span class="nx">IfNode</span>
<span class="vi">@elseBody = </span><span class="nx">@ensureExpressions</span> <span class="nx">elseBody</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-131"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-131">#</a> </div> <p>Rewrite a chain of <strong>IfNodes</strong> to add a default case as the final <em>else</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">isStatement</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@statement</span> <span class="o">or=</span> <span class="o">!!</span><span class="p">(</span><span class="nx">@tags</span><span class="p">.</span><span class="nx">statement</span> <span class="o">or</span> <span class="nx">@bodyNode</span><span class="p">().</span><span class="nx">isStatement</span><span class="p">()</span> <span class="o">or</span> <span class="p">(</span><span class="nx">@elseBody</span> <span class="o">and</span> <span class="nx">@elseBodyNode</span><span class="p">().</span><span class="nx">isStatement</span><span class="p">()))</span>
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-131"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-131">#</a> </div> <p>Rewrite a chain of <strong>IfNodes</strong> to add a default case as the final <em>else</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">isStatement</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@statement</span> <span class="o">or=</span> <span class="o">!!</span><span class="p">((</span><span class="nx">o</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">top</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@tags</span><span class="p">.</span><span class="nx">statement</span> <span class="o">or</span> <span class="nx">@bodyNode</span><span class="p">().</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">or</span> <span class="p">(</span><span class="nx">@elseBody</span> <span class="o">and</span> <span class="nx">@elseBodyNode</span><span class="p">().</span><span class="nx">isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)))</span>
<span class="nx">compileCondition</span><span class="o">:</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="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="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">conditions = </span><span class="nx">flatten</span> <span class="p">[</span><span class="nx">@condition</span><span class="p">]</span>
<span class="nx">conditions</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nv">parenthetical = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">conditions</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</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">conditions</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="nx">compileNode</span><span class="o">:</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">top</span> <span class="o">or</span> <span class="nx">@isStatement</span><span class="p">()</span> <span class="k">then</span> <span class="nx">@compileStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="nx">@compileTernary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">@isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">then</span> <span class="nx">@compileStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="nx">@compileTernary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
<span class="nx">makeReturn</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">@isStatement</span><span class="p">()</span>
@@ -1077,7 +1132,7 @@ to be a statement. Otherwise a ternary is safe.</p> </td>
<span class="nv">condO = </span><span class="nx">merge</span> <span class="nx">o</span>
<span class="nv">o.indent = </span><span class="nx">@idt</span> <span class="mi">1</span>
<span class="nv">o.top = </span><span class="kc">true</span>
<span class="nv">ifDent = </span><span class="k">if</span> <span class="nx">child</span> <span class="o">or</span> <span class="p">(</span><span class="nx">top</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@isStatement</span><span class="p">())</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="nx">@idt</span><span class="p">()</span>
<span class="nv">ifDent = </span><span class="k">if</span> <span class="nx">child</span> <span class="o">or</span> <span class="p">(</span><span class="nx">top</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@isStatement</span><span class="p">(</span><span class="nx">o</span><span class="p">))</span> <span class="k">then</span> <span class="s1">&#39;&#39;</span> <span class="k">else</span> <span class="nx">@idt</span><span class="p">()</span>
<span class="nv">comDent = </span><span class="k">if</span> <span class="nx">child</span> <span class="k">then</span> <span class="nx">@idt</span><span class="p">()</span> <span class="k">else</span> <span class="s1">&#39;&#39;</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">o</span><span class="p">)</span>
<span class="nv">ifPart = </span><span class="s2">&quot;#{ifDent}if (#{ @compileCondition(condO) }) {\n#{body}\n#{@tab}}&quot;</span>
@@ -1088,22 +1143,21 @@ to be a statement. Otherwise a ternary is safe.</p> </td>
<span class="s2">&quot; else {\n#{ @elseBody.compile(o) }\n#{@tab}}&quot;</span>
<span class="s2">&quot;#{ifPart}#{elsePart}&quot;</span></pre></div> </td> </tr> <tr id="section-133"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-133">#</a> </div> <p>Compile the <strong>IfNode</strong> as a regular <em>if-else</em> statement. Flattened chains
force inner <em>else</em> bodies into statement form.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileTernary</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">o.operation = </span><span class="kc">true</span>
<span class="nx">@bodyNode</span><span class="p">().</span><span class="nv">tags.operation = </span><span class="vi">@condition.tags.operation = </span><span class="kc">yes</span>
<span class="nx">@elseBodyNode</span><span class="p">().</span><span class="nv">tags.operation = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">@elseBody</span>
<span class="nv">ifPart = </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="nx">@bodyNode</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">elsePart = </span><span class="k">if</span> <span class="nx">@elseBody</span> <span class="k">then</span> <span class="nx">@elseBodyNode</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;#{ifPart} : #{elsePart}&quot;</span></pre></div> </td> </tr> <tr id="section-134"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-134">#</a> </div> <p>Compile the IfNode as a ternary operator.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-135"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-135">#</a> </div> <h2>Faux-Nodes</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-136"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-136">#</a> </div> <h3>PushNode</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">PushNode = exports.PushNode = </span><span class="p">{</span>
<span class="nv">code = </span><span class="s2">&quot;#{ifPart} : #{elsePart}&quot;</span>
<span class="k">if</span> <span class="nx">@tags</span><span class="p">.</span><span class="nx">operation</span> <span class="k">then</span> <span class="s2">&quot;(#{code})&quot;</span> <span class="k">else</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-134"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-134">#</a> </div> <p>Compile the IfNode as a ternary operator.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-135"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-135">#</a> </div> <h2>Faux-Nodes</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-136"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-136">#</a> </div> <h3>PushNode</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">PushNode = exports.PushNode =</span>
<span class="nx">wrap</span><span class="o">:</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">expr = </span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">expressions</span> <span class="k">if</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">isPureStatement</span><span class="p">()</span> <span class="o">or</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">containsPureStatement</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="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">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></pre></div> </td> </tr> <tr id="section-137"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-137">#</a> </div> <p>Faux-nodes are never created by the grammar, but are used during code
<span class="p">)])</span></pre></div> </td> </tr> <tr id="section-137"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-137">#</a> </div> <p>Faux-nodes are never created by the grammar, but are used during code
generation to generate other combinations of nodes. The <strong>PushNode</strong> creates
the tree for <code>array.push(value)</code>, which is helpful for recording the result
arrays from comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-138"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-138">#</a> </div> <h3>ClosureNode</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ClosureNode = exports.ClosureNode = </span><span class="p">{</span></pre></div> </td> </tr> <tr id="section-139"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-139">#</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="nx">wrap</span><span class="o">:</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>
arrays from comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-138"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-138">#</a> </div> <h3>ClosureNode</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ClosureNode = exports.ClosureNode =</span></pre></div> </td> </tr> <tr id="section-139"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-139">#</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="nx">wrap</span><span class="o">:</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="k">return</span> <span class="nx">expressions</span> <span class="k">if</span> <span class="nx">expressions</span><span class="p">.</span><span class="nx">containsPureStatement</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">args = </span><span class="p">[]</span>
@@ -1118,18 +1172,16 @@ arrays from comprehensions.</p> </td> <td class="code">
<span class="nx">args</span><span class="p">.</span><span class="nx">push</span> <span class="nx">literal</span> <span class="s1">&#39;arguments&#39;</span> <span class="k">if</span> <span class="nx">mentionsArgs</span>
<span class="nv">func = </span><span class="k">new</span> <span class="nx">ValueNode</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">meth</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="nx">func</span><span class="p">,</span> <span class="nx">args</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="p">}</span></pre></div> </td> </tr> <tr id="section-140"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-140">#</a> </div> <p>Wrap the expressions body, unless it contains a pure statement,
<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></pre></div> </td> </tr> <tr id="section-140"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-140">#</a> </div> <p>Wrap the expressions body, unless it contains a pure statement,
in which case, no dice. If the body mentions <code>this</code> or <code>arguments</code>,
then make sure that the closure wrapper preserves the original values.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">UTILITIES = </span><span class="p">{</span></pre></div> </td> </tr> <tr id="section-141"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-141">#</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre> <span class="k">extends</span><span class="o">:</span> <span class="s2">&quot;&quot;&quot;</span>
then make sure that the closure wrapper preserves the original values.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">UTILITIES =</span></pre></div> </td> </tr> <tr id="section-141"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-141">#</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre> <span class="k">extends</span><span class="o">:</span> <span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> function(child, parent) {</span>
<span class="s2"> var ctor = function(){};</span>
<span class="s2"> ctor.prototype = parent.prototype;</span>
<span class="s2"> child.prototype = new ctor();</span>
<span class="s2"> child.prototype.constructor = child;</span>
<span class="s2"> if (typeof parent.extended === &quot;</span><span class="nx">function</span><span class="s2">&quot;) parent.extended(child);</span>
<span class="s2"> child.__superClass__ = parent.prototype;</span>
<span class="s2"> child.__super__ = parent.prototype;</span>
<span class="s2"> }</span>
<span class="s2"> &quot;&quot;&quot;</span></pre></div> </td> </tr> <tr id="section-142"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-142">#</a> </div> <p>Correctly set up a prototype chain for inheritance, including a reference
to the superclass for <code>super()</code> calls. See:
@@ -1138,9 +1190,7 @@ to the superclass for <code>super()</code> calls. See:
<span class="s2"> return function(){ return func.apply(context, arguments); };</span>
<span class="s2"> }</span>
<span class="s2"> &quot;&quot;&quot;</span></pre></div> </td> </tr> <tr id="section-143"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-143">#</a> </div> <p>Create a function bound to the current value of "this".</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasProp</span><span class="o">:</span> <span class="s1">&#39;Object.prototype.hasOwnProperty&#39;</span>
<span class="nx">slice</span><span class="o">:</span> <span class="s1">&#39;Array.prototype.slice&#39;</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-144"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-144">#</a> </div> <p>Shortcuts to speed up the lookup time for native functions.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-145"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-145">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB = </span><span class="s1">&#39; &#39;</span></pre></div> </td> </tr> <tr id="section-146"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-146">#</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TRAILING_WHITESPACE = </span><span class="sr">/[ \t]+$/gm</span></pre></div> </td> </tr> <tr id="section-147"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-147">#</a> </div> <p>Trim out all trailing whitespace, so that the generated code plays nice
<span class="nx">slice</span><span class="o">:</span> <span class="s1">&#39;Array.prototype.slice&#39;</span></pre></div> </td> </tr> <tr id="section-144"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-144">#</a> </div> <p>Shortcuts to speed up the lookup time for native functions.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-145"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-145">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB = </span><span class="s1">&#39; &#39;</span></pre></div> </td> </tr> <tr id="section-146"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-146">#</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TRAILING_WHITESPACE = </span><span class="sr">/[ \t]+$/gm</span></pre></div> </td> </tr> <tr id="section-147"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-147">#</a> </div> <p>Trim out all trailing whitespace, so that the generated code plays nice
with Git.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER = </span><span class="sr">/^[a-zA-Z\$_](\w|\$)*$/</span>
<span class="nv">NUMBER = </span><span class="sr">/^(((\b0(x|X)[0-9a-fA-F]+)|((\b[0-9]+(\.[0-9]+)?|\.[0-9]+)(e[+\-]?[0-9]+)?)))\b$/i</span>
<span class="nv">SIMPLENUM = </span><span class="sr">/^-?\d+/</span></pre></div> </td> </tr> <tr id="section-148"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-148">#</a> </div> <p>Keep these identifier regexes in sync with the Lexer.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IS_STRING = </span><span class="sr">/^[&#39;&quot;]/</span></pre></div> </td> </tr> <tr id="section-149"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-149">#</a> </div> <p>Is a literal value a string?</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-150"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-150">#</a> </div> <h2>Utility Functions</h2> </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>

View File

@@ -22,6 +22,7 @@ corrected before implicit parentheses can be wrapped around blocks of code.</p>
<span class="nx">@closeOpenIndexes</span><span class="p">()</span>
<span class="nx">@addImplicitIndentation</span><span class="p">()</span>
<span class="nx">@addImplicitBraces</span><span class="p">()</span>
<span class="nx">@tagPostfixConditionals</span><span class="p">()</span>
<span class="nx">@addImplicitParentheses</span><span class="p">()</span>
<span class="nx">@ensureBalance</span> <span class="nx">BALANCED_PAIRS</span>
<span class="nx">@rewriteClosingParens</span><span class="p">()</span>
@@ -33,7 +34,7 @@ our feet.</p> </td> <td class="code"> <div
<span class="nv">i = </span><span class="mi">0</span>
<span class="nx">loop</span>
<span class="k">break</span> <span class="nx">unless</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
<span class="nv">move = </span><span class="nx">block</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">i</span>
<span class="nv">move = </span><span class="nx">block</span><span class="p">.</span><span class="nx">call</span> <span class="k">this</span><span class="p">,</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">i</span>
<span class="nx">i</span> <span class="o">+=</span> <span class="nx">move</span>
<span class="kc">true</span>
@@ -48,7 +49,7 @@ our feet.</p> </td> <td class="code"> <div
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Massage newlines and indentations so that comments don't have to be
correctly indented, or appear on a line of their own.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">adjustComments</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;HERECOMMENT&#39;</span>
<span class="p">[</span><span class="nx">before</span><span class="p">,</span> <span class="nx">prev</span><span class="p">,</span> <span class="nx">post</span><span class="p">,</span> <span class="nx">after</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">],</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]]</span>
<span class="k">if</span> <span class="nx">after</span> <span class="o">and</span> <span class="nx">after</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span>
@@ -69,19 +70,19 @@ correctly indented, or appear on a line of their own.</p> </td>
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">removeLeadingNewlines</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span> <span class="k">while</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">removeMidExpressionNewlines</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">include</span><span class="p">(</span><span class="nx">EXPRESSION_CLOSE</span><span class="p">,</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span> <span class="o">and</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">return</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-11">#</a> </div> <p>The lexer has tagged the opening parenthesis of a method call. Match it with
its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenCalls</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;CALL_START&#39;</span>
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">]</span>
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;CALL_END&#39;</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-12">#</a> </div> <p>The lexer has tagged the opening parenthesis of an indexing operation call.
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">closeOpenIndexes</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;INDEX_START&#39;</span>
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</span><span class="p">]</span>
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;INDEX_END&#39;</span>
@@ -89,7 +90,7 @@ Match it with its paired close.</p> </td> <td class="cod
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-13">#</a> </div> <p>Object literals may be written with implicit braces, for simple cases.
Insert the missing braces here, so that the parser doesn't have to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitBraces</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nv">stack = </span><span class="p">[]</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;{&#39;</span><span class="p">))</span> <span class="k">then</span> <span class="s1">&#39;{&#39;</span> <span class="k">else</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_END</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
@@ -98,7 +99,9 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;:&#39;</span> <span class="o">and</span> <span class="p">(</span><span class="o">not</span> <span class="nx">last</span> <span class="o">or</span> <span class="nx">last</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">&#39;{&#39;</span><span class="p">)</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="s1">&#39;{&#39;</span>
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;@&#39;</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="nv">tok = </span><span class="p">[</span><span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="nv">tok.generated = </span><span class="kc">yes</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</span>
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[</span><span class="nx">one</span><span class="p">,</span> <span class="nx">two</span><span class="p">,</span> <span class="nx">three</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="s1">&#39;HERECOMMENT&#39;</span> <span class="k">in</span> <span class="p">[</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)]</span>
@@ -111,10 +114,17 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-14">#</a> </div> <p>Methods may be optionally called without parentheses, for simple cases.
Insert the implicit parentheses here, so that the parser doesn't have to
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitParentheses</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nv">prev = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_FUNC</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_CALL</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span>
<span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;!&#39;</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;IN&#39;</span><span class="p">,</span> <span class="s1">&#39;OF&#39;</span><span class="p">]))</span>
<span class="nv">classLine = </span><span class="kc">no</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">classLine = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;CLASS&#39;</span>
<span class="nv">prev = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="nv">next = </span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
<span class="nv">idx = </span><span class="mi">1</span>
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">classLine</span> <span class="o">and</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;{&#39;</span> <span class="o">and</span> <span class="nx">prev</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_FUNC</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="nv">idx = </span><span class="mi">2</span> <span class="k">if</span> <span class="nx">callObject</span>
<span class="nv">classLine = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">LINEBREAKS</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">if</span> <span class="nx">prev</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_FUNC</span><span class="p">,</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_CALL</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span>
<span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;UNARY&#39;</span> <span class="o">and</span> <span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;IN&#39;</span><span class="p">,</span> <span class="s1">&#39;OF&#39;</span><span class="p">,</span> <span class="s1">&#39;INSTANCEOF&#39;</span><span class="p">])))</span> <span class="o">or</span> <span class="nx">callObject</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">(</span><span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">&#39;,&#39;</span> <span class="o">and</span> <span class="nx">include</span><span class="p">(</span><span class="nx">IMPLICIT_END</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span>
@@ -123,18 +133,18 @@ deal with them.</p> </td> <td class="code">
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;OUTDENT&#39;</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">i</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="nx">idx</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
blocks, so it doesn't need to. ')' can close a single-line block,
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">addImplicitIndentation</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;ELSE&#39;</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">&#39;OUTDENT&#39;</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;CATCH&#39;</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span> <span class="o">or</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">)</span>
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;TERMINATOR&#39;</span> <span class="o">or</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">)</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@indentation</span><span class="p">(</span><span class="nx">token</span><span class="p">)...</span>
<span class="k">return</span> <span class="mi">4</span>
<span class="k">if</span> <span class="nx">include</span><span class="p">(</span><span class="nx">SINGLE_LINERS</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">&#39;INDENT&#39;</span> <span class="o">and</span>
@@ -152,11 +162,22 @@ but we need to make sure it's balanced.</p> </td> <td cl
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">&#39;THEN&#39;</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</a> </div> <p>Tag postfix conditionals as such, so that we can parse them with a
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tagPostfixConditionals</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">]</span>
<span class="nv">original = </span><span class="nx">token</span>
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">]</span>
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;POST_&#39;</span> <span class="o">+</span> <span class="nx">original</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">&#39;INDENT&#39;</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>Ensure that all listed pairs of tokens are correctly balanced throughout
the course of the token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ensureBalance</span><span class="o">:</span> <span class="p">(</span><span class="nx">pairs</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">levels = </span><span class="p">{}</span>
<span class="nv">openLine = </span><span class="p">{}</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">pairs</span>
<span class="p">[</span><span class="nx">open</span><span class="p">,</span> <span class="nx">close</span><span class="p">]</span> <span class="o">=</span> <span class="nx">pair</span>
<span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">or=</span> <span class="mi">0</span>
@@ -170,7 +191,7 @@ the course of the token stream.</p> </td> <td class="cod
<span class="k">if</span> <span class="nx">unclosed</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">open = </span><span class="nx">unclosed</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">line = </span><span class="nx">openLine</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;unclosed #{open} on line #{line}&quot;</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</a> </div> <p>We'd like to support syntax like this:</p>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s2">&quot;unclosed #{open} on line #{line}&quot;</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>We'd like to support syntax like this:</p>
<pre><code>el.click((event) -&gt;
el.hide())
@@ -192,7 +213,7 @@ rewriting.</li>
<span class="nv">stack = </span><span class="p">[]</span>
<span class="nv">debt = </span><span class="p">{}</span>
<span class="p">(</span><span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</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">INVERSES</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">=&gt;</span>
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">inv = </span><span class="nx">INVERSES</span><span class="p">[</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
<span class="k">if</span> <span class="nx">include</span> <span class="nx">EXPRESSION_START</span><span class="p">,</span> <span class="nx">tag</span>
@@ -217,20 +238,20 @@ rewriting.</li>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">val</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">else</span>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-18">#</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</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>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tag</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">0</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> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-21">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[[</span><span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">],</span>
<span class="p">[</span><span class="s1">&#39;PARAM_START&#39;</span><span class="p">,</span> <span class="s1">&#39;PARAM_END&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;INDEX_START&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</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>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-19">#</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">indentation</span><span class="o">:</span> <span class="p">(</span><span class="nx">token</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="p">[[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span> <span class="p">[</span><span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</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>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tag</span><span class="o">:</span> <span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">][</span><span class="mi">0</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> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-22">#</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[[</span><span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;}&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">],</span>
<span class="p">[</span><span class="s1">&#39;PARAM_START&#39;</span><span class="p">,</span> <span class="s1">&#39;PARAM_END&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">],</span> <span class="p">[</span><span class="s1">&#39;INDEX_START&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</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>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">INVERSES = </span><span class="p">{}</span>
<span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">0</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>The tokens that signal the start of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-24">#</a> </div> <p>The tokens that signal the end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_END = </span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
<span class="nx">INVERSES</span><span class="p">[</span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="nx">pair</span><span class="p">[</span><span class="mi">0</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>The tokens that signal the start of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="nx">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-25">#</a> </div> <p>The tokens that signal the end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_END = </span><span class="nx">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="nx">pair</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-26">#</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s1">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-27">#</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s1">&#39;)&#39;</span><span class="p">,</span> <span class="s1">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s1">&#39;]&#39;</span><span class="p">,</span> <span class="s1">&#39;INDEX_END&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
<span class="s1">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s1">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="s1">&#39;STRING&#39;</span><span class="p">,</span> <span class="s1">&#39;JS&#39;</span><span class="p">,</span> <span class="s1">&#39;REGEX&#39;</span><span class="p">,</span> <span class="s1">&#39;NEW&#39;</span><span class="p">,</span> <span class="s1">&#39;PARAM_START&#39;</span><span class="p">,</span> <span class="s1">&#39;CLASS&#39;</span><span class="p">,</span>
<span class="s1">&#39;TRY&#39;</span><span class="p">,</span> <span class="s1">&#39;DELETE&#39;</span><span class="p">,</span> <span class="s1">&#39;TYPEOF&#39;</span><span class="p">,</span> <span class="s1">&#39;SWITCH&#39;</span><span class="p">,</span> <span class="s1">&#39;THIS&#39;</span><span class="p">,</span> <span class="s1">&#39;NULL&#39;</span><span class="p">,</span>
<span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;TRY&#39;</span><span class="p">,</span> <span class="s1">&#39;SWITCH&#39;</span><span class="p">,</span> <span class="s1">&#39;THIS&#39;</span><span class="p">,</span> <span class="s1">&#39;NULL&#39;</span><span class="p">,</span> <span class="s1">&#39;UNARY&#39;</span>
<span class="s1">&#39;TRUE&#39;</span><span class="p">,</span> <span class="s1">&#39;FALSE&#39;</span><span class="p">,</span> <span class="s1">&#39;YES&#39;</span><span class="p">,</span> <span class="s1">&#39;NO&#39;</span><span class="p">,</span> <span class="s1">&#39;ON&#39;</span><span class="p">,</span> <span class="s1">&#39;OFF&#39;</span><span class="p">,</span>
<span class="s1">&#39;!&#39;</span><span class="p">,</span> <span class="s1">&#39;!!&#39;</span><span class="p">,</span> <span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-28">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;,&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s1">&#39;IF&#39;</span><span class="p">,</span> <span class="s1">&#39;UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;FOR&#39;</span><span class="p">,</span> <span class="s1">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s1">&#39;UNTIL&#39;</span><span class="p">,</span> <span class="s1">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
<span class="s1">&#39;@&#39;</span><span class="p">,</span> <span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;(&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-29">#</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s1">&#39;{&#39;</span><span class="p">,</span> <span class="s1">&#39;[&#39;</span><span class="p">,</span> <span class="s1">&#39;,&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-30">#</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s1">&#39;POST_IF&#39;</span><span class="p">,</span> <span class="s1">&#39;POST_UNLESS&#39;</span><span class="p">,</span> <span class="s1">&#39;FOR&#39;</span><span class="p">,</span> <span class="s1">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s1">&#39;UNTIL&#39;</span><span class="p">,</span> <span class="s1">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-31">#</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS = </span><span class="p">[</span><span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s2">&quot;-&gt;&quot;</span><span class="p">,</span> <span class="s2">&quot;=&gt;&quot;</span><span class="p">,</span> <span class="s1">&#39;TRY&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s1">&#39;THEN&#39;</span><span class="p">]</span>
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;LEADING_WHEN&#39;</span><span class="p">]</span>
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s1">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s1">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;LEADING_WHEN&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-32">#</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s1">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s1">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s1">&#39;OUTDENT&#39;</span><span class="p">]</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -25,7 +25,7 @@ already exist.</p> </td> <td class="code">
<span class="k">return</span> <span class="kc">false</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-7">#</a> </div> <p>Reserve a variable name as originating from a function parameter for this
scope. No <code>var</code> required for internal references.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">parameter</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="nx">@variables</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;param&#39;</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-8">#</a> </div> <p>Just check to see if a variable has already been declared, without reserving.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">check</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-&gt;</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">@variables</span><span class="p">.</span><span class="nx">hasOwnProperty</span> <span class="nx">name</span>
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nb">Object</span><span class="o">::</span><span class="nx">hasOwnProperty</span><span class="p">.</span><span class="nx">call</span> <span class="nx">@variables</span><span class="p">,</span> <span class="nx">name</span>
<span class="o">!!</span><span class="p">(</span><span class="nx">@parent</span> <span class="o">and</span> <span class="nx">@parent</span><span class="p">.</span><span class="nx">check</span><span class="p">(</span><span class="nx">name</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>If we need to store an intermediate result, find an available name for a
compiler-generated variable. <code>_a</code>, <code>_b</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">freeVariable</span><span class="o">:</span> <span class="o">-&gt;</span>
<span class="k">while</span> <span class="nx">@check</span> <span class="nx">@tempVar</span>

File diff suppressed because one or more lines are too long

View File

@@ -127,7 +127,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.1">0.9.1</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.2">0.9.2</a>
</p>
<h2>
@@ -172,7 +172,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
Then clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download the latest
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.9.1">0.9.1</a>.
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.9.2">0.9.2</a>.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
@@ -752,9 +752,8 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<p>
<span id="interpolation" class="bookmark"></span>
<b class="header">String and RegExp Interpolation</b>
A version of <a href="http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation">ECMAScript Harmony's proposed string interpolation</a>
is included in CoffeeScript. Simple variables can be included by prefixing
them with a hash mark.
Ruby-style string interpolation is included in CoffeeScript. Double-quoted
strings allow for interpolated values, while single-quoted strings are literal.
</p>
<%= code_for('interpolation', 'quote') %>
<p>
@@ -946,11 +945,25 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
<span id="change_log" class="bookmark"></span>
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">0.9.2</b>
Specifying the start and end of a range literal is now optional, eg. <tt>array[3..]</tt>.
You can now say <tt>a not instanceof b</tt>.
Fixed important bugs with nested significant and non-significant indentation (Issue #637).
Added a <tt>--require</tt> flag that allows you to hook into the <tt>coffee</tt> command.
Added a custom <tt>jsl.conf</tt> file for our preferred JavaScriptLint setup.
Sped up Jison grammar compilation time by flattening rules for operations.
Block comments can now be used with JavaScript-minifier-friendly syntax.
Added JavaScript's compound assignment bitwise operators. Bugfixes to
implicit object literals with leading number and string keys, as the subject
of implicit calls, and as part of compound assignment.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.9.1</b>
Bugfix release for <b>0.9.1</b>. Greatly improves the handling of mixed
implicit objects, implicit function calls, and implicit indentation.
implicit objects, implicit function calls, and implicit indentation.
String and regex interpolation is now strictly <tt>#{ ... }</tt> (Ruby style).
The compiler now takes a <tt>--require</tt> flag, which specifies scripts
to run before compilation.
@@ -964,7 +977,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
literals use <tt>:</tt>, as in JavaScript. This allows us to have implicit
object literals, and YAML-style object definitions. Half assignments are
removed, in favor of <tt>+=</tt>, <tt>or=</tt>, and friends.
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
<tt>$</tt> &mdash; because dollar signs may be part of a valid JS identifier.
Downwards range comprehensions are now safe again, and are optimized to
straight for loops when created with integer endpoints.
@@ -979,7 +992,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
on the object &mdash; useful in constructors and setter functions.
Constructor functions can now take splats.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.7.2</b>
Quick bugfix (right after 0.7.1) for a problem that prevented <tt>coffee</tt>

View File

@@ -5,12 +5,12 @@ if (ignition === true) {
if (band !== SpinalTap) {
volume = 10;
}
if (!(answer === false)) {
if (answer !== false) {
letTheWildRumpusBegin();
}
if (car.speed < limit) {
accelerate();
};
}
if ((47 === pick || 92 === pick || 13 === pick)) {
winner = true;
}

View File

@@ -1,4 +1,4 @@
/*
CoffeeScript Compiler v0.9.1
CoffeeScript Compiler v0.9.2
Released under the MIT License
*/

View File

@@ -6,5 +6,5 @@ task('build:parser', 'rebuild the Jison parser', function(options) {
require('jison');
code = require('./lib/grammar').parser.generate();
dir = options.output || 'lib';
return fs.writeFile(("" + (dir) + "/parser.js"), code);
return fs.writeFile("" + (dir) + "/parser.js", code);
});

View File

@@ -5,7 +5,7 @@ var __extends = function(child, parent) {
child.prototype = new ctor();
child.prototype.constructor = child;
if (typeof parent.extended === "function") parent.extended(child);
child.__superClass__ = parent.prototype;
child.__super__ = parent.prototype;
};
Animal = function(_a) {
this.name = _a;
@@ -20,7 +20,7 @@ Snake = function() {
__extends(Snake, Animal);
Snake.prototype.move = function() {
alert("Slithering...");
return Snake.__superClass__.move.call(this, 5);
return Snake.__super__.move.call(this, 5);
};
Horse = function() {
return Animal.apply(this, arguments);
@@ -28,7 +28,7 @@ Horse = function() {
__extends(Horse, Animal);
Horse.prototype.move = function() {
alert("Galloping...");
return Horse.__superClass__.move.call(this, 45);
return Horse.__super__.move.call(this, 45);
};
sam = new Snake("Sammy the Python");
tom = new Horse("Tommy the Palomino");

View File

@@ -9,4 +9,4 @@ if (happy && knowsIt) {
showIt();
}
date = friday ? sue : jill;
options = options || defaults;
options || (options = defaults);

View File

@@ -1,4 +1,4 @@
var dates, sentence, sep;
sentence = ("" + (22 / 7) + " is a decent approximation of π");
sep = "[.\\/\\- ]";
dates = (new RegExp(("\\d+" + (sep) + "\\d+" + (sep) + "\\d+"), "g"));
dates = (new RegExp("\\d+" + (sep) + "\\d+" + (sep) + "\\d+", "g"));

View File

@@ -21,7 +21,7 @@ race = function(winner) {
runners = __slice.call(arguments, 1);
return print(winner, runners);
};
if ((typeof elvis !== "undefined" && elvis !== null)) {
if (typeof elvis !== "undefined" && elvis !== null) {
alert("I knew it!");
}
cubes = (function() {

View File

@@ -1,2 +1,2 @@
var _a, _b;
(_b = (typeof (_a = (lottery.drawWinner())) === "undefined" || _a == undefined ? undefined : _a.address)) == undefined ? undefined : _b.zipcode;
(_b = ((typeof (_a = (lottery.drawWinner())) === "undefined" || _a === null) ? undefined : _a.address)) == null ? undefined : _b.zipcode;

View File

@@ -1,7 +1,7 @@
var mobyDick;
mobyDick = "Call me Ishmael. Some years ago -- \
never mind how long precisely -- having little \
or no money in my purse, and nothing particular \
to interest me on shore, I thought I would sail \
about a little and see the watery part of the \
world...";
mobyDick = "Call me Ishmael. Some years ago --\
never mind how long precisely -- having little\
or no money in my purse, and nothing particular\
to interest me on shore, I thought I would sail\
about a little and see the watery part of the\
world...";

View File

@@ -11,8 +11,8 @@ num = 6;
lyrics = (function() {
_a = [];
while (num -= 1) {
_a.push(num + " little monkeys, jumping on the bed. \
One fell out and bumped his head.");
_a.push(num + " little monkeys, jumping on the bed.\
One fell out and bumped his head.");
}
return _a;
})();

View File

@@ -71,7 +71,7 @@
# Current version.
_.VERSION = '1.0.2'
_.VERSION = '1.1.0'
# Collection Functions
@@ -104,8 +104,10 @@
# **Reduce** builds up a single result from a list of values. Also known as
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
_.reduce = (obj, memo, iterator, context) ->
return obj.reduce(_.bind(iterator, context), memo) if nativeReduce and obj.reduce is nativeReduce
_.reduce = (obj, iterator, memo, context) ->
if nativeReduce and obj.reduce is nativeReduce
iterator = _.bind iterator, context if context
return obj.reduce iterator, memo
_.each obj, (value, index, list) ->
memo = iterator.call context, memo, value, index, list
memo
@@ -113,11 +115,12 @@
# The right-associative version of **reduce**, also known as **foldr**. Uses
# JavaScript 1.8's version of **reduceRight**, if available.
_.reduceRight = (obj, memo, iterator, context) ->
return obj.reduceRight(_.bind(iterator, context), memo) if nativeReduceRight and obj.reduceRight is nativeReduceRight
_.each _.clone(_.toArray(obj)).reverse(), (value, index) ->
memo = iterator.call context, memo, value, index, obj
memo
_.reduceRight = (obj, iterator, memo, context) ->
if nativeReduceRight and obj.reduceRight is nativeReduceRight
iterator = _.bind iterator, context if context
return obj.reduceRight iterator, memo
reversed = _.clone(_.toArray(obj)).reverse()
_.reduce reversed, iterator, memo, context
# Return the first value which passes a truth test.
@@ -273,10 +276,11 @@
# Return a completely flattened version of an array.
_.flatten = (array) ->
_.reduce array, [], (memo, value) ->
_.reduce array, (memo, value) ->
return memo.concat(_.flatten(value)) if _.isArray value
memo.push value
memo
, []
# Return a version of the array that does not contain the specified value(s).
@@ -378,6 +382,16 @@
setTimeout((-> func.apply(func, args)), wait)
# Memoize an expensive function by storing its results.
_.memoize = (func, hasher) ->
memo = {}
hasher or= _.identity
->
key = hasher.apply this, arguments
return memo[key] if key of memo
memo[key] = func.apply this, arguments
# Defers a function, scheduling it to run after the current call stack has
# cleared.
_.defer = (func) ->
@@ -457,7 +471,7 @@
# Check dates' integer values.
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
# Both are NaN?
return true if _.isNaN(a) and _.isNaN(b)
return false if _.isNaN(a) and _.isNaN(b)
# Compare regular expressions.
if _.isRegExp(a) and _.isRegExp(b)
return a.source is b.source and
@@ -473,13 +487,13 @@
# Different object sizes?
return false if aKeys.length isnt bKeys.length
# Recursive comparison of contents.
(return false) for key, val of a when !(key in b) or !_.isEqual(val, b[key])
(return false) for all key, val of a when !(key of b) or !_.isEqual(val, b[key])
true
# Is a given array or object empty?
_.isEmpty = (obj) ->
return obj.length is 0 if _.isArray obj
return obj.length is 0 if _.isArray(obj) or _.isString(obj)
(return false) for key of obj when hasOwnProperty.call(obj, key)
true
@@ -582,16 +596,19 @@
# JavaScript templating a-la **ERB**, pilfered from John Resig's
# *Secrets of the JavaScript Ninja*, page 83.
# Single-quote fix from Rick Strahl.
# With alterations for arbitrary delimiters, and to preserve whitespace.
_.template = (str, data) ->
c = _.templateSettings
endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
fn = new Function 'obj',
'var p=[],print=function(){p.push.apply(p,arguments);};' +
'with(obj){p.push(\'' +
str.replace(/[\r\t\n]/g, " ")
.replace(endMatch,"\t")
'with(obj||{}){p.push(\'' +
str.replace(/\r/g, '\\r')
.replace(/\n/g, '\\n')
.replace(/\t/g, '\\t')
.replace(endMatch,"")
.split("'").join("\\'")
.split("\t").join("'")
.split("").join("'")
.replace(c.interpolate, "',$1,'")
.split(c.start).join("');")
.split(c.end).join("p.push('") +
@@ -602,15 +619,16 @@
# Aliases
# -------
_.forEach = _.each
_.foldl = _.inject = _.reduce
_.foldr = _.reduceRight
_.select = _.filter
_.all = _.every
_.any = _.some
_.head = _.first
_.tail = _.rest
_.methods = _.functions
_.forEach = _.each
_.foldl = _.inject = _.reduce
_.foldr = _.reduceRight
_.select = _.filter
_.all = _.every
_.any = _.some
_.contains = _.include
_.head = _.first
_.tail = _.rest
_.methods = _.functions
# Setup the OOP Wrapper

File diff suppressed because one or more lines are too long

44
extras/jsl.conf Normal file
View File

@@ -0,0 +1,44 @@
# JavaScriptLint configuration file for CoffeeScript.
+no_return_value # function {0} does not always return a value
+duplicate_formal # duplicate formal argument {0}
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
+var_hides_arg # variable {0} hides argument
+redeclared_var # redeclaration of {0} {1}
+anon_no_return_value # anonymous function does not always return a value
+missing_semicolon # missing semicolon
+meaningless_block # meaningless block; curly braces have no impact
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
+unreachable_code # unreachable code
+missing_break # missing break statement
+missing_break_for_last_case # missing break statement for last case in switch
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
+inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
+useless_void # use of the void type may be unnecessary (void is always undefined)
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
+use_of_label # use of label
-block_without_braces # block statement without curly braces
+leading_decimal_point # leading decimal point may indicate a number or an object member
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
+octal_number # leading zeros make an octal number
+nested_comment # nested comment
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
+empty_statement # empty statement or extra semicolon
-missing_option_explicit # the "option explicit" control comment is missing
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
+dup_option_explicit # duplicate "option explicit" control comment
+useless_assign # useless assignment
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
+missing_default_case # missing default case in switch statement
+duplicate_case_in_switch # duplicate case in switch statements
+default_not_at_end # the default case is not at the end of the switch statement
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
+useless_comparison # useless comparison; comparing identical expressions
+with_statement # with statement hides undeclared variables; use temporary variable instead
+trailing_comma_in_array # extra comma is not recommended in array initializers
+assign_to_function_call # assignment to a function call
+parseint_missing_radix # parseInt missing radix parameter
+lambda_assign_requires_semicolon

View File

@@ -114,7 +114,7 @@ alert reverse '.eeffoC yrT'</textarea></div>
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.1">0.9.1</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.2">0.9.2</a>
</p>
<h2>
@@ -175,7 +175,7 @@ math <span class="Keyword">=</span> {
runners <span class="Keyword">=</span> __slice.<span class="LibraryFunction">call</span>(arguments, <span class="Number">1</span>);
<span class="Keyword">return</span> <span class="LibraryFunction">print</span>(winner, runners);
};
<span class="Keyword">if</span> ((<span class="Keyword">typeof</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>)) {
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">&amp;</span><span class="Keyword">&amp;</span> elvis <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">null</span>) {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>I knew it!<span class="String">&quot;</span></span>);
}
cubes <span class="Keyword">=</span> (<span class="Storage">function</span>() {
@@ -209,7 +209,7 @@ race = function(winner) {
runners = __slice.call(arguments, 1);
return print(winner, runners);
};
if ((typeof elvis !== "undefined" && elvis !== null)) {
if (typeof elvis !== "undefined" && elvis !== null) {
alert("I knew it!");
}
cubes = (function() {
@@ -254,7 +254,7 @@ cubes = (function() {
Then clone the CoffeeScript
<a href="http://github.com/jashkenas/coffee-script">source repository</a>
from GitHub, or download the latest
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.9.1">0.9.1</a>.
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.9.2">0.9.2</a>.
To install the CoffeeScript compiler system-wide
under <tt>/usr/local</tt>, open the directory and run:
</p>
@@ -612,7 +612,7 @@ inner = changeNumbers();;alert(inner);'>run: inner</button><br class='clear' /><
date <span class="Keyword">=</span> <span class="Keyword">if</span> friday <span class="Keyword">then</span> sue <span class="Keyword">else</span> jill
options or<span class="Keyword">=</span> defaults
options <span class="Keyword">or=</span> defaults
</pre><pre class="idle"><span class="Storage">var</span> date, mood, options;
<span class="Keyword">if</span> (singing) {
mood <span class="Keyword">=</span> greatlyImproved;
@@ -624,7 +624,7 @@ options or<span class="Keyword">=</span> defaults
showIt();
}
date <span class="Keyword">=</span> friday ? sue : jill;
options <span class="Keyword">=</span> options <span class="Keyword">||</span> defaults;
options <span class="Keyword">||</span> (options <span class="Keyword">=</span> defaults);
</pre><br class='clear' /></div>
<p>
@@ -681,12 +681,12 @@ print inspect <span class="String"><span class="String">&quot;</span>My name is
<span class="Keyword">if</span> (band <span class="Keyword">!</span><span class="Keyword">==</span> SpinalTap) {
volume <span class="Keyword">=</span> <span class="Number">10</span>;
}
<span class="Keyword">if</span> (<span class="Keyword">!</span>(answer <span class="Keyword">===</span> <span class="BuiltInConstant">false</span>)) {
<span class="Keyword">if</span> (answer <span class="Keyword">!</span><span class="Keyword">==</span> <span class="BuiltInConstant">false</span>) {
letTheWildRumpusBegin();
}
<span class="Keyword">if</span> (car.speed <span class="Keyword">&lt;</span> limit) {
accelerate();
};
}
<span class="Keyword">if</span> ((<span class="Number">47</span> <span class="Keyword">===</span> pick <span class="Keyword">||</span> <span class="Number">92</span> <span class="Keyword">===</span> pick <span class="Keyword">||</span> <span class="Number">13</span> <span class="Keyword">===</span> pick)) {
winner <span class="Keyword">=</span> <span class="BuiltInConstant">true</span>;
}
@@ -788,8 +788,8 @@ num <span class="Keyword">=</span> <span class="Number">6</span>;
lyrics <span class="Keyword">=</span> (<span class="Storage">function</span>() {
_a <span class="Keyword">=</span> [];
<span class="Keyword">while</span> (num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>) {
_a.<span class="LibraryFunction">push</span>(num <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> little monkeys, jumping on the bed. \</span>
<span class="String">One fell out and bumped his head.<span class="String">&quot;</span></span>);
_a.<span class="LibraryFunction">push</span>(num <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> little monkeys, jumping on the bed.\</span>
<span class="String"> One fell out and bumped his head.<span class="String">&quot;</span></span>);
}
<span class="Keyword">return</span> _a;
})();
@@ -806,8 +806,8 @@ num = 6;
lyrics = (function() {
_a = [];
while (num -= 1) {
_a.push(num + " little monkeys, jumping on the bed. \
One fell out and bumped his head.");
_a.push(num + " little monkeys, jumping on the bed.\
One fell out and bumped his head.");
}
return _a;
})();;alert(lyrics.join("\n"));'>run: lyrics.join("\n")</button><br class='clear' /></div>
@@ -1156,7 +1156,7 @@ speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;;alert(sp
</p>
<div class='code'><pre class="idle">lottery.drawWinner()<span class="Keyword">?</span>.address<span class="Keyword">?</span>.zipcode
</pre><pre class="idle"><span class="Storage">var</span> _a, _b;
(_b <span class="Keyword">=</span> (<span class="Keyword">typeof</span> (_a <span class="Keyword">=</span> (lottery.drawWinner())) <span class="Keyword">===</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">||</span> _a <span class="Keyword">==</span> undefined ? undefined : _a.address)) <span class="Keyword">==</span> undefined ? undefined : _b.zipcode;
(_b <span class="Keyword">=</span> ((<span class="Keyword">typeof</span> (_a <span class="Keyword">=</span> (lottery.drawWinner())) <span class="Keyword">===</span> <span class="String"><span class="String">&quot;</span>undefined<span class="String">&quot;</span></span> <span class="Keyword">||</span> _a <span class="Keyword">===</span> <span class="BuiltInConstant">null</span>) ? undefined : _a.address)) <span class="Keyword">==</span> <span class="BuiltInConstant">null</span> ? undefined : _b.zipcode;
</pre><br class='clear' /></div>
<p>
Soaking up nulls is similar to Ruby's
@@ -1186,18 +1186,18 @@ speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;;alert(sp
set the superclass, assign prototypal properties, and define the constructor,
in a single assignable expression.
</p>
<div class='code'><pre class="idle"><span class="Storage">class</span><span class="TypeName"> Animal</span>
<div class='code'><pre class="idle"><span class="Storage">class</span> <span class="TypeName">Animal</span>
<span class="FunctionName">constructor</span><span class="Keyword">:</span> (<span class="Variable">@name</span>) <span class="Storage">-&gt;</span>
<span class="FunctionName">move</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">meters</span><span class="FunctionArgument">)</span> <span class="Storage">-&gt;</span>
alert <span class="Variable">@name</span> <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> moved <span class="String">&quot;</span></span> <span class="Keyword">+</span> meters <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>m.<span class="String">&quot;</span></span>
<span class="Storage">class</span><span class="TypeName"> Snake</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
<span class="Storage">class</span> <span class="TypeName">Snake</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
<span class="FunctionName">move</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span>
alert <span class="String"><span class="String">&quot;</span>Slithering...<span class="String">&quot;</span></span>
<span class="Variable">super</span> <span class="Number">5</span>
<span class="Storage">class</span><span class="TypeName"> Horse</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
<span class="Storage">class</span> <span class="TypeName">Horse</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
<span class="FunctionName">move</span><span class="Keyword">:</span> <span class="Storage">-&gt;</span>
alert <span class="String"><span class="String">&quot;</span>Galloping...<span class="String">&quot;</span></span>
<span class="Variable">super</span> <span class="Number">45</span>
@@ -1218,7 +1218,7 @@ tom.move()
<span class="LibraryClassType">child</span>.<span class="LibraryConstant">prototype</span> = <span class="Keyword">new</span> <span class="TypeName">ctor</span>();
<span class="LibraryClassType">child</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">constructor</span> = child;
<span class="Keyword">if</span> (<span class="Keyword">typeof</span> parent.extended <span class="Keyword">===</span> <span class="String"><span class="String">&quot;</span>function<span class="String">&quot;</span></span>) parent.extended(child);
child.__superClass__ <span class="Keyword">=</span> parent.<span class="LibraryConstant">prototype</span>;
child.__super__ <span class="Keyword">=</span> parent.<span class="LibraryConstant">prototype</span>;
};
<span class="FunctionName">Animal</span> = <span class="Storage">function</span>(<span class="FunctionArgument">_a</span>) {
<span class="Variable">this</span>.<span class="LibraryConstant">name</span> <span class="Keyword">=</span> _a;
@@ -1233,7 +1233,7 @@ tom.move()
__extends(Snake, Animal);
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>Slithering...<span class="String">&quot;</span></span>);
<span class="Keyword">return</span> Snake.__superClass__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">5</span>);
<span class="Keyword">return</span> Snake.__super__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">5</span>);
};
<span class="FunctionName">Horse</span> = <span class="Storage">function</span>() {
<span class="Keyword">return</span> Animal.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
@@ -1241,7 +1241,7 @@ __extends(Snake, Animal);
__extends(Horse, Animal);
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">&quot;</span>Galloping...<span class="String">&quot;</span></span>);
<span class="Keyword">return</span> Horse.__superClass__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">45</span>);
<span class="Keyword">return</span> Horse.__super__.move.<span class="LibraryFunction">call</span>(<span class="Variable">this</span>, <span class="Number">45</span>);
};
sam <span class="Keyword">=</span> <span class="Keyword">new</span> <span class="TypeName">Snake</span>(<span class="String"><span class="String">&quot;</span>Sammy the Python<span class="String">&quot;</span></span>);
tom <span class="Keyword">=</span> <span class="Keyword">new</span> <span class="TypeName">Horse</span>(<span class="String"><span class="String">&quot;</span>Tommy the Palomino<span class="String">&quot;</span></span>);
@@ -1254,7 +1254,7 @@ var __extends = function(child, parent) {
child.prototype = new ctor();
child.prototype.constructor = child;
if (typeof parent.extended === "function") parent.extended(child);
child.__superClass__ = parent.prototype;
child.__super__ = parent.prototype;
};
Animal = function(_a) {
this.name = _a;
@@ -1269,7 +1269,7 @@ Snake = function() {
__extends(Snake, Animal);
Snake.prototype.move = function() {
alert("Slithering...");
return Snake.__superClass__.move.call(this, 5);
return Snake.__super__.move.call(this, 5);
};
Horse = function() {
return Animal.apply(this, arguments);
@@ -1277,7 +1277,7 @@ Horse = function() {
__extends(Horse, Animal);
Horse.prototype.move = function() {
alert("Galloping...");
return Horse.__superClass__.move.call(this, 45);
return Horse.__super__.move.call(this, 45);
};
sam = new Snake("Sammy the Python");
tom = new Horse("Tommy the Palomino");
@@ -1578,9 +1578,8 @@ healthy = (200 > cholesterol) && (cholesterol > 60);;alert(healthy);'>run: healt
<p>
<span id="interpolation" class="bookmark"></span>
<b class="header">String and RegExp Interpolation</b>
A version of <a href="http://wiki.ecmascript.org/doku.php?id=strawman:string_interpolation">ECMAScript Harmony's proposed string interpolation</a>
is included in CoffeeScript. Simple variables can be included by prefixing
them with a hash mark.
Ruby-style string interpolation is included in CoffeeScript. Double-quoted
strings allow for interpolated values, while single-quoted strings are literal.
</p>
<div class='code'><pre class="idle">author <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Wittgenstein<span class="String">&quot;</span></span>
quote <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>A picture is a fact. -- <span class="String"><span class="String">#{</span>author<span class="String">}</span></span><span class="String">&quot;</span></span>
@@ -1603,11 +1602,11 @@ dates <span class="Keyword">=</span><span class="String"> /\d+#{sep}\d+#{sep}\d+
</pre><pre class="idle"><span class="Storage">var</span> dates, sentence, sep;
sentence <span class="Keyword">=</span> (<span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span> <span class="Keyword">+</span> (<span class="Number">22</span> / <span class="Number">7</span>) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span> is a decent approximation of π<span class="String">&quot;</span></span>);
sep <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>[.<span class="UserDefinedConstant">\\</span>/<span class="UserDefinedConstant">\\</span>- ]<span class="String">&quot;</span></span>;
dates <span class="Keyword">=</span> (<span class="Keyword">new</span> <span class="TypeName">RegExp</span>((<span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> (sep) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> (sep) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span>), <span class="String"><span class="String">&quot;</span>g<span class="String">&quot;</span></span>));
dates <span class="Keyword">=</span> (<span class="Keyword">new</span> <span class="TypeName">RegExp</span>(<span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> (sep) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span> <span class="Keyword">+</span> (sep) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span><span class="UserDefinedConstant">\\</span>d+<span class="String">&quot;</span></span>, <span class="String"><span class="String">&quot;</span>g<span class="String">&quot;</span></span>));
</pre><button onclick='javascript: var dates, sentence, sep;
sentence = ("" + (22 / 7) + " is a decent approximation of π");
sep = "[.\\/\\- ]";
dates = (new RegExp(("\\d+" + (sep) + "\\d+" + (sep) + "\\d+"), "g"));;alert(sentence);'>run: sentence</button><br class='clear' /></div>
dates = (new RegExp("\\d+" + (sep) + "\\d+" + (sep) + "\\d+", "g"));;alert(sentence);'>run: sentence</button><br class='clear' /></div>
<p>
<span id="heredocs" class="bookmark"></span>
@@ -1615,27 +1614,27 @@ dates = (new RegExp(("\\d+" + (sep) + "\\d+" + (sep) + "\\d+"), "g"));;alert(sen
Multiline strings are allowed in CoffeeScript.
</p>
<div class='code'><pre class="idle">mobyDick <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Call me Ishmael. Some years ago --</span>
<span class="String">never mind how long precisely -- having little</span>
<span class="String">or no money in my purse, and nothing particular</span>
<span class="String">to interest me on shore, I thought I would sail</span>
<span class="String">about a little and see the watery part of the</span>
<span class="String">world...<span class="String">&quot;</span></span>
<span class="String"> never mind how long precisely -- having little</span>
<span class="String"> or no money in my purse, and nothing particular</span>
<span class="String"> to interest me on shore, I thought I would sail</span>
<span class="String"> about a little and see the watery part of the</span>
<span class="String"> world...<span class="String">&quot;</span></span>
</pre><pre class="idle"><span class="Storage">var</span> mobyDick;
mobyDick <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Call me Ishmael. Some years ago -- \</span>
<span class="String">never mind how long precisely -- having little \</span>
<span class="String">or no money in my purse, and nothing particular \</span>
<span class="String">to interest me on shore, I thought I would sail \</span>
<span class="String">about a little and see the watery part of the \</span>
<span class="String">world...<span class="String">&quot;</span></span>;
mobyDick <span class="Keyword">=</span> <span class="String"><span class="String">&quot;</span>Call me Ishmael. Some years ago --\</span>
<span class="String"> never mind how long precisely -- having little\</span>
<span class="String"> or no money in my purse, and nothing particular\</span>
<span class="String"> to interest me on shore, I thought I would sail\</span>
<span class="String"> about a little and see the watery part of the\</span>
<span class="String"> world...<span class="String">&quot;</span></span>;
</pre><button onclick='javascript: var mobyDick;
mobyDick = "Call me Ishmael. Some years ago -- \
never mind how long precisely -- having little \
or no money in my purse, and nothing particular \
to interest me on shore, I thought I would sail \
about a little and see the watery part of the \
world...";;alert(mobyDick);'>run: mobyDick</button><br class='clear' /></div>
mobyDick = "Call me Ishmael. Some years ago --\
never mind how long precisely -- having little\
or no money in my purse, and nothing particular\
to interest me on shore, I thought I would sail\
about a little and see the watery part of the\
world...";;alert(mobyDick);'>run: mobyDick</button><br class='clear' /></div>
<p>
Heredocs can be used to hold formatted or indentation-sensitive text
(or, if you just don't feel like escaping quotes and apostrophes). The
@@ -1660,11 +1659,11 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
are preserved in the generated code.
</p>
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">###</span></span>
<span class="Comment">CoffeeScript Compiler v0.9.1</span>
<span class="Comment">CoffeeScript Compiler v0.9.2</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">###</span></span>
<span class="Comment">###</span>
</pre><pre class="idle"><span class="Comment"><span class="Comment">/*</span></span>
<span class="Comment">CoffeeScript Compiler v0.9.1</span>
<span class="Comment">CoffeeScript Compiler v0.9.2</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">*/</span></span>
</pre><br class='clear' /></div>
@@ -1709,7 +1708,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
require(<span class="String"><span class="String">'</span>jison<span class="String">'</span></span>);
code <span class="Keyword">=</span> require(<span class="String"><span class="String">'</span>./lib/grammar<span class="String">'</span></span>).parser.generate();
dir <span class="Keyword">=</span> options.output <span class="Keyword">||</span> <span class="String"><span class="String">'</span>lib<span class="String">'</span></span>;
<span class="Keyword">return</span> fs.writeFile((<span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span> <span class="Keyword">+</span> (dir) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>/parser.js<span class="String">&quot;</span></span>), code);
<span class="Keyword">return</span> fs.writeFile(<span class="String"><span class="String">&quot;</span><span class="String">&quot;</span></span> <span class="Keyword">+</span> (dir) <span class="Keyword">+</span> <span class="String"><span class="String">&quot;</span>/parser.js<span class="String">&quot;</span></span>, code);
});
</pre><br class='clear' /></div>
@@ -1847,11 +1846,25 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
<span id="change_log" class="bookmark"></span>
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">0.9.2</b>
Specifying the start and end of a range literal is now optional, eg. <tt>array[3..]</tt>.
You can now say <tt>a not instanceof b</tt>.
Fixed important bugs with nested significant and non-significant indentation (Issue #637).
Added a <tt>--require</tt> flag that allows you to hook into the <tt>coffee</tt> command.
Added a custom <tt>jsl.conf</tt> file for our preferred JavaScriptLint setup.
Sped up Jison grammar compilation time by flattening rules for operations.
Block comments can now be used with JavaScript-minifier-friendly syntax.
Added JavaScript's compound assignment bitwise operators. Bugfixes to
implicit object literals with leading number and string keys, as the subject
of implicit calls, and as part of compound assignment.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.9.1</b>
Bugfix release for <b>0.9.1</b>. Greatly improves the handling of mixed
implicit objects, implicit function calls, and implicit indentation.
implicit objects, implicit function calls, and implicit indentation.
String and regex interpolation is now strictly <tt>#{ ... }</tt> (Ruby style).
The compiler now takes a <tt>--require</tt> flag, which specifies scripts
to run before compilation.
@@ -1865,7 +1878,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
literals use <tt>:</tt>, as in JavaScript. This allows us to have implicit
object literals, and YAML-style object definitions. Half assignments are
removed, in favor of <tt>+=</tt>, <tt>or=</tt>, and friends.
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
Interpolation now uses a hash mark <tt>#</tt> instead of the dollar sign
<tt>$</tt> &mdash; because dollar signs may be part of a valid JS identifier.
Downwards range comprehensions are now safe again, and are optimized to
straight for loops when created with integer endpoints.
@@ -1880,7 +1893,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
on the object &mdash; useful in constructors and setter functions.
Constructor functions can now take splats.
</p>
<p>
<b class="header" style="margin-top: 20px;">0.7.2</b>
Quick bugfix (right after 0.7.1) for a problem that prevented <tt>coffee</tt>

View File

@@ -37,7 +37,7 @@
return path.exists('Cakefile', function(exists) {
var _a, _b, _c, _d, arg, args;
if (!(exists)) {
throw new Error(("Cakefile not found in " + (process.cwd())));
throw new Error("Cakefile not found in " + (process.cwd()));
}
args = process.argv.slice(2, process.argv.length);
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
@@ -71,14 +71,14 @@
return _b;
})().join('') : '';
desc = task.description ? ("# " + (task.description)) : '';
puts(("cake " + (name) + (spaces) + " " + (desc)));
puts("cake " + (name) + (spaces) + " " + (desc));
}
if (switches.length) {
return puts(oparse.help());
}
};
missingTask = function(task) {
puts(("No such task: \"" + (task) + "\""));
puts("No such task: \"" + (task) + "\"");
return process.exit(1);
};
})();

57
lib/coffee-script.js Normal file → Executable file
View File

@@ -1,6 +1,6 @@
(function() {
var Lexer, compile, helpers, lexer, parser, path, processScripts;
if ((typeof process !== "undefined" && process !== null)) {
var Lexer, compile, grind, grindRemote, helpers, lexer, parser, path, processScripts;
if (typeof process !== "undefined" && process !== null) {
path = require('path');
Lexer = require('./lexer').Lexer;
parser = require('./parser').parser;
@@ -10,17 +10,17 @@
require.registerExtension('.coffee', function(content) {
return compile(content);
});
};
}
} else {
this.exports = (this.CoffeeScript = {});
Lexer = this.Lexer;
parser = this.parser;
helpers = this.helpers;
}
exports.VERSION = '0.9.1';
exports.VERSION = '0.9.2';
lexer = new Lexer();
exports.compile = (compile = function(code, options) {
options = options || {};
options || (options = {});
try {
return (parser.parse(lexer.tokenize(code))).compile(options);
} catch (err) {
@@ -59,22 +59,43 @@
return "";
}
};
if ((typeof document !== "undefined" && document !== null) && document.getElementsByTagName) {
processScripts = function() {
var _a, _b, _c, _d, tag;
_a = []; _c = document.getElementsByTagName('script');
for (_b = 0, _d = _c.length; _b < _d; _b++) {
tag = _c[_b];
if (tag.type === 'text/coffeescript') {
_a.push(eval(exports.compile(tag.innerHTML)));
};
if ((typeof document === "undefined" || document === null) ? undefined : document.getElementsByTagName) {
grind = function(coffee) {
return setTimeout(exports.compile(coffee));
};
grindRemote = function(url) {
var xhr;
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) {
xhr.overrideMimeType('text/plain');
}
return _a;
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
return grind(xhr.responseText);
}
};
return xhr.send(null);
};
processScripts = function() {
var _a, _b, _c, script;
_b = document.getElementsByTagName('script');
for (_a = 0, _c = _b.length; _a < _c; _a++) {
script = _b[_a];
if (script.type === 'text/coffeescript') {
if (script.src) {
grindRemote(script.src);
} else {
grind(script.innerHTML);
}
}
}
return null;
};
if (window.addEventListener) {
window.addEventListener('load', processScripts, false);
} else if (window.attachEvent) {
window.attachEvent('onload', processScripts);
addEventListener('DOMContentLoaded', processScripts, false);
} else {
attachEvent('onload', processScripts);
}
}
})();

View File

@@ -1,5 +1,5 @@
(function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, _a, _b, _c, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, helpers, lint, optionParser, options, optparse, parseOptions, path, printTokens, sources, spawn, usage, version, watch, writeJs;
var BANNER, CoffeeScript, EventEmitter, SWITCHES, _a, _b, _c, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, helpers, lint, optionParser, optparse, opts, parseOptions, path, printTokens, sources, spawn, usage, version, watch, writeJs;
fs = require('fs');
path = require('path');
optparse = require('./optparse');
@@ -15,25 +15,25 @@
global.CoffeeScript = CoffeeScript;
BANNER = 'coffee compiles CoffeeScript source files into JavaScript.\n\nUsage:\n coffee path/to/script.coffee';
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['--no-wrap', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
options = {};
opts = {};
sources = [];
optionParser = null;
exports.run = function() {
var flags, separator;
parseOptions();
if (options.help) {
if (opts.help) {
return usage();
}
if (options.version) {
if (opts.version) {
return version();
}
if (options.interactive) {
if (opts.interactive) {
return require('./repl');
}
if (options.stdio) {
if (opts.stdio) {
return compileStdio();
}
if (options.eval) {
if (opts.eval) {
return compileScript('console', sources[0]);
}
if (!(sources.length)) {
@@ -45,7 +45,7 @@
flags = sources.slice((separator + 1), sources.length);
sources = sources.slice(0, separator);
}
if (options.run) {
if (opts.run) {
flags = sources.slice(1, sources.length + 1).concat(flags);
sources = [sources[0]];
}
@@ -64,7 +64,7 @@
compile = function(source, topLevel) {
return path.exists(source, function(exists) {
if (!(exists)) {
throw new Error(("File not found: " + (source)));
throw new Error("File not found: " + (source));
}
return fs.stat(source, function(err, stats) {
if (stats.isDirectory()) {
@@ -81,7 +81,7 @@
fs.readFile(source, function(err, code) {
return compileScript(source, code.toString(), base);
});
if (options.watch) {
if (opts.watch) {
return watch(source, base);
}
}
@@ -94,50 +94,51 @@
}
return _d;
};
compileScript = function(source, code, base) {
var _d, _e, _f, codeOpts, file, js, o;
o = options;
codeOpts = compileOptions(source);
compileScript = function(file, input, base) {
var _d, _e, _f, o, options, t, task;
o = opts;
options = compileOptions(file);
if (o.require) {
_e = o.require;
for (_d = 0, _f = _e.length; _d < _f; _d++) {
file = _e[_d];
require(fs.realpathSync(file));
require(helpers.starts(file, '.') ? fs.realpathSync(file) : file);
}
}
try {
CoffeeScript.emit('compile', {
source: source,
code: code,
base: base,
t = (task = {
file: file,
input: input,
options: options
});
CoffeeScript.emit('compile', task);
if (o.tokens) {
return printTokens(CoffeeScript.tokens(code));
return printTokens(CoffeeScript.tokens(t.input));
} else if (o.nodes) {
return puts(CoffeeScript.nodes(code).toString());
return puts(CoffeeScript.nodes(t.input).toString());
} else if (o.run) {
return CoffeeScript.run(code, codeOpts);
return CoffeeScript.run(t.input, t.options);
} else {
js = CoffeeScript.compile(code, codeOpts);
CoffeeScript.emit('success', js);
t.output = CoffeeScript.compile(t.input, t.options);
CoffeeScript.emit('success', task);
if (o.print) {
return print(js);
return print(t.output);
} else if (o.compile) {
return writeJs(source, js, base);
return writeJs(t.file, t.output, base);
} else if (o.lint) {
return lint(js);
return lint(t.output);
}
}
} catch (err) {
CoffeeScript.emit('failure', err);
CoffeeScript.emit('failure', err, task);
if (CoffeeScript.listeners('failure').length) {
return null;
}
if (!(o.watch)) {
error(err.stack) && process.exit(1);
if (o.watch) {
return puts(err.message);
}
return puts(err.message);
error(err.stack);
return process.exit(1);
}
};
compileStdio = function() {
@@ -171,28 +172,29 @@
filename = path.basename(source, path.extname(source)) + '.js';
srcDir = path.dirname(source);
baseDir = srcDir.substring(base.length);
dir = options.output ? path.join(options.output, baseDir) : srcDir;
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
jsPath = path.join(dir, filename);
compile = function() {
if (js.length <= 0) {
js = ' ';
}
return fs.writeFile(jsPath, js, function(err) {
if (options.compile && options.watch) {
return puts(("Compiled " + (source)));
if (opts.compile && opts.watch) {
return puts("Compiled " + (source));
}
});
};
return path.exists(dir, function(exists) {
return exists ? compile() : exec(("mkdir -p " + (dir)), compile);
return exists ? compile() : exec("mkdir -p " + (dir), compile);
});
};
lint = function(js) {
var jsl, printIt;
var conf, jsl, printIt;
printIt = function(buffer) {
return print(buffer.toString());
return puts(buffer.toString().trim());
};
jsl = spawn('jsl', ['-nologo', '-stdin']);
conf = __dirname + '/../extras/jsl.conf';
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
jsl.stdout.on('data', printIt);
jsl.stderr.on('data', printIt);
jsl.stdin.write(js);
@@ -218,18 +220,18 @@
parseOptions = function() {
var o;
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
o = (options = optionParser.parse(process.argv.slice(2, process.argv.length)));
options.compile = options.compile || (!!o.output);
options.run = !(o.compile || o.print || o.lint);
options.print = !!(o.print || (o.eval || o.stdio && o.compile));
return (sources = options.arguments);
o = (opts = optionParser.parse(process.argv.slice(2, process.argv.length)));
o.compile || (o.compile = (!!o.output));
o.run = !(o.compile || o.print || o.lint);
o.print = !!(o.print || (o.eval || o.stdio && o.compile));
return (sources = o.arguments);
};
compileOptions = function(fileName) {
var o;
o = {
fileName: fileName
};
o.noWrap = options['no-wrap'];
o.noWrap = opts['no-wrap'];
return o;
};
usage = function() {
@@ -237,7 +239,7 @@
return process.exit(0);
};
version = function() {
puts(("CoffeeScript version " + (CoffeeScript.VERSION)));
puts("CoffeeScript version " + (CoffeeScript.VERSION));
return process.exit(0);
};
})();

View File

@@ -34,7 +34,7 @@
return new LiteralNode($1);
})
],
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Splat"), o("Existence"), o("Comment")],
Expression: [o("Value"), o("Call"), o("Code"), o("Operation"), o("Assign"), o("If"), o("Try"), o("While"), o("For"), o("Switch"), o("Extends"), o("Class"), o("Existence"), o("Comment")],
Block: [
o("INDENT Body OUTDENT", function() {
return $2;
@@ -307,6 +307,14 @@
return new RangeNode($2, $5);
}), o("INDEX_START Expression . . . Expression INDEX_END", function() {
return new RangeNode($2, $6, true);
}), o("INDEX_START Expression . . INDEX_END", function() {
return new RangeNode($2, null);
}), o("INDEX_START Expression . . . INDEX_END", function() {
return new RangeNode($2, null, true);
}), o("INDEX_START . . Expression INDEX_END", function() {
return new RangeNode(null, $4);
}), o("INDEX_START . . . Expression INDEX_END", function() {
return new RangeNode(null, $5, true);
})
],
Array: [
@@ -317,16 +325,17 @@
ArgList: [
o("", function() {
return [];
}), o("Expression", function() {
}), o("Arg", function() {
return [$1];
}), o("ArgList , Expression", function() {
}), o("ArgList , Arg", function() {
return $1.concat([$3]);
}), o("ArgList OptComma TERMINATOR Expression", function() {
}), o("ArgList OptComma TERMINATOR Arg", function() {
return $1.concat([$4]);
}), o("ArgList OptComma INDENT ArgList OptComma OUTDENT", function() {
return $1.concat($4);
})
],
Arg: [o("Expression"), o("Splat")],
SimpleArgs: [
o("Expression"), o("SimpleArgs , Expression", function() {
return $1 instanceof Array ? $1.concat([$3]) : [$1].concat([$3]);
@@ -354,6 +363,8 @@
Parenthetical: [
o("( Line )", function() {
return new ParentheticalNode($2);
}), o("( )", function() {
return new ParentheticalNode(new LiteralNode(''));
})
],
WhileSource: [
@@ -516,20 +527,20 @@
})
],
If: [
o("IfBlock"), o("Statement IF Expression", function() {
o("IfBlock"), o("Statement POST_IF Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), {
statement: true
});
}), o("Expression IF Expression", function() {
}), o("Expression POST_IF Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), {
statement: true
});
}), o("Statement UNLESS Expression", function() {
}), o("Statement POST_UNLESS Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), {
statement: true,
invert: true
});
}), o("Expression UNLESS Expression", function() {
}), o("Expression POST_UNLESS Expression", function() {
return new IfNode($3, Expressions.wrap([$1]), {
statement: true,
invert: true
@@ -537,102 +548,62 @@
})
],
Operation: [
o("! Expression", function() {
return new OpNode('!', $2);
}), o("!! Expression", function() {
return new OpNode('!!', $2);
}), o("- Expression", (function() {
o("UNARY Expression", function() {
return new OpNode($1, $2);
}), o("- Expression", function() {
return new OpNode('-', $2);
}), {
prec: 'UMINUS'
}), o("+ Expression", (function() {
}, {
prec: 'UNARY'
}), o("+ Expression", function() {
return new OpNode('+', $2);
}), {
prec: 'UPLUS'
}), o("~ Expression", function() {
return new OpNode('~', $2);
}, {
prec: 'UNARY'
}), o("-- Expression", function() {
return new OpNode('--', $2);
}), o("++ Expression", function() {
return new OpNode('++', $2);
}), o("DELETE Expression", function() {
return new OpNode('delete', $2);
}), o("TYPEOF Expression", function() {
return new OpNode('typeof', $2);
}), o("Expression --", function() {
return new OpNode('--', $1, null, true);
}), o("Expression ++", function() {
return new OpNode('++', $1, null, true);
}), o("Expression * Expression", function() {
return new OpNode('*', $1, $3);
}), o("Expression / Expression", function() {
return new OpNode('/', $1, $3);
}), o("Expression % Expression", function() {
return new OpNode('%', $1, $3);
}), o("Expression ? Expression", function() {
return new OpNode('?', $1, $3);
}), o("Expression + Expression", function() {
return new OpNode('+', $1, $3);
}), o("Expression - Expression", function() {
return new OpNode('-', $1, $3);
}), o("Expression << Expression", function() {
return new OpNode('<<', $1, $3);
}), o("Expression >> Expression", function() {
return new OpNode('>>', $1, $3);
}), o("Expression >>> Expression", function() {
return new OpNode('>>>', $1, $3);
}), o("Expression & Expression", function() {
return new OpNode('&', $1, $3);
}), o("Expression | Expression", function() {
return new OpNode('|', $1, $3);
}), o("Expression ^ Expression", function() {
return new OpNode('^', $1, $3);
}), o("Expression <= Expression", function() {
return new OpNode('<=', $1, $3);
}), o("Expression < Expression", function() {
return new OpNode('<', $1, $3);
}), o("Expression > Expression", function() {
return new OpNode('>', $1, $3);
}), o("Expression >= Expression", function() {
return new OpNode('>=', $1, $3);
}), o("Expression == Expression", function() {
return new OpNode('==', $1, $3);
}), o("Expression != Expression", function() {
return new OpNode('!=', $1, $3);
}), o("Expression && Expression", function() {
return new OpNode('&&', $1, $3);
}), o("Expression || Expression", function() {
return new OpNode('||', $1, $3);
}), o("Expression OP? Expression", function() {
return new OpNode('?', $1, $3);
}), o("Expression -= Expression", function() {
return new OpNode('-=', $1, $3);
}), o("Expression += Expression", function() {
return new OpNode('+=', $1, $3);
}), o("Expression /= Expression", function() {
return new OpNode('/=', $1, $3);
}), o("Expression *= Expression", function() {
return new OpNode('*=', $1, $3);
}), o("Expression %= Expression", function() {
return new OpNode('%=', $1, $3);
}), o("Expression ||= Expression", function() {
return new OpNode('||=', $1, $3);
}), o("Expression &&= Expression", function() {
return new OpNode('&&=', $1, $3);
}), o("Expression ?= Expression", function() {
return new OpNode('?=', $1, $3);
}), o("Expression INSTANCEOF Expression", function() {
return new OpNode('instanceof', $1, $3);
}), o("Expression MATH Expression", function() {
return new OpNode($2, $1, $3);
}), o("Expression SHIFT Expression", function() {
return new OpNode($2, $1, $3);
}), o("Expression COMPARE Expression", function() {
return new OpNode($2, $1, $3);
}), o("Expression LOGIC Expression", function() {
return new OpNode($2, $1, $3);
}), o("Value COMPOUND_ASSIGN Expression", function() {
return new OpNode($2, $1, $3);
}), o("Value COMPOUND_ASSIGN INDENT Expression OUTDENT", function() {
return new OpNode($2, $1, $4);
}), o("Expression IN Expression", function() {
return new InNode($1, $3);
}), o("Expression OF Expression", function() {
return new OpNode('in', $1, $3);
}), o("Expression ! IN Expression", function() {
return new OpNode('!', new InNode($1, $4));
}), o("Expression ! OF Expression", function() {
return new OpNode('!', new ParentheticalNode(new OpNode('in', $1, $4)));
}), o("Expression INSTANCEOF Expression", function() {
return new OpNode('instanceof', $1, $3);
}), o("Expression UNARY IN Expression", function() {
return new OpNode($2, new InNode($1, $4));
}), o("Expression UNARY OF Expression", function() {
return new OpNode($2, new ParentheticalNode(new OpNode('in', $1, $4)));
}), o("Expression UNARY INSTANCEOF Expression", function() {
return new OpNode($2, new ParentheticalNode(new OpNode('instanceof', $1, $4)));
})
]
};
operators = [["left", '?'], ["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--'], ["left", '*', '/', '%'], ["left", '+', '-'], ["left", '<<', '>>', '>>>'], ["left", '&', '|', '^'], ["left", '<=', '<', '>', '>='], ["right", 'DELETE', 'INSTANCEOF', 'TYPEOF'], ["left", '==', '!='], ["left", '&&', '||', 'OP?'], ["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?='], ["left", '.'], ["right", 'INDENT'], ["left", 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS'], ["left", 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']];
operators = [["right", '?', 'NEW'], ["nonassoc", '++', '--'], ["right", 'UNARY'], ["left", 'MATH'], ["left", '+', '-'], ["left", 'SHIFT'], ["left", 'COMPARE'], ["left", 'INSTANCEOF'], ["left", '==', '!='], ["left", 'LOGIC'], ["right", 'COMPOUND_ASSIGN'], ["left", '.'], ["nonassoc", 'INDENT', 'OUTDENT'], ["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW'], ["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'EXTENDS'], ["right", '=', ':', 'RETURN'], ["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']];
tokens = [];
_a = grammar;
for (name in _a) {

View File

@@ -1,6 +1,6 @@
(function() {
var compact, count, del, ends, extend, flatten, helpers, include, indexOf, merge, starts;
if (!((typeof process !== "undefined" && process !== null))) {
if (!(typeof process !== "undefined" && process !== null)) {
this.exports = this;
}
helpers = (exports.helpers = {});
@@ -36,7 +36,7 @@
item = _c[_b];
if (item) {
_a.push(item);
};
}
}
return _a;
});
@@ -72,7 +72,7 @@
_a = []; _b = properties;
for (key in _b) {
val = _b[key];
_a.push((object[key] = val));
_a.push(object[key] = val);
}
return _a;
});
@@ -86,7 +86,7 @@
memo = memo.concat(item);
} else {
memo.push(item);
};
}
}
return memo;
});

View File

@@ -1,7 +1,7 @@
(function() {
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, Lexer, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, STRING_NEWLINES, WHITESPACE, _a, _b, _c, compact, count, helpers, include, starts;
var ASSIGNED, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, CONVERSIONS, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS_CLEANER, JS_FORBIDDEN, JS_KEYWORDS, LAST_DENT, LAST_DENTS, LINE_BREAK, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NEXT_CHARACTER, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX_END, REGEX_ESCAPE, REGEX_INTERPOLATION, REGEX_START, RESERVED, Rewriter, SHIFT, UNARY, WHITESPACE, _a, _b, _c, compact, count, helpers, include, starts;
var __slice = Array.prototype.slice;
if ((typeof process !== "undefined" && process !== null)) {
if (typeof process !== "undefined" && process !== null) {
_a = require('./rewriter');
Rewriter = _a.Rewriter;
_b = require('./helpers');
@@ -86,6 +86,9 @@
if (id === 'all' && this.tag() === 'FOR') {
tag = 'ALL';
}
if (include(UNARY, tag)) {
tag = 'UNARY';
}
if (include(JS_FORBIDDEN, id)) {
if (forcedIdentifier) {
tag = 'STRING';
@@ -105,6 +108,12 @@
if (include(COFFEE_ALIASES, id)) {
tag = (id = CONVERSIONS[id]);
}
if (include(LOGIC, id)) {
tag = 'LOGIC';
}
if (id === '!') {
tag = 'UNARY';
}
}
this.token(tag, id);
if (close_index) {
@@ -132,7 +141,7 @@
if (!(string = this.balancedToken(['"', '"'], ['#{', '}']) || this.balancedToken(["'", "'"]))) {
return false;
}
this.interpolateString(string.replace(STRING_NEWLINES, " \\\n"));
this.interpolateString(string.replace(/\n/g, '\\\n'));
this.line += count(string, "\n");
this.i += string.length;
return true;
@@ -154,17 +163,17 @@
return true;
};
Lexer.prototype.commentToken = function() {
var comment, match;
var match;
if (!(match = this.chunk.match(COMMENT))) {
return false;
}
this.line += count(match[1], "\n");
this.i += match[1].length;
if (match[2]) {
comment = this.sanitizeHeredoc(match[2], {
herecomment: true
});
this.token('HERECOMMENT', comment.split(MULTILINER));
if (match[4]) {
this.token('HERECOMMENT', this.sanitizeHeredoc(match[4], {
herecomment: true,
indent: match[3]
}));
this.token('TERMINATOR', '\n');
}
return true;
@@ -182,8 +191,11 @@
return true;
};
Lexer.prototype.regexToken = function() {
var end, flags, regex, str;
if (!(this.chunk.match(REGEX_START))) {
var _d, end, first, flags, regex, str;
if (!(first = this.chunk.match(REGEX_START))) {
return false;
}
if (first[1] === ' ' && !('CALL_START' === (_d = this.tag()) || '=' === _d)) {
return false;
}
if (include(NOT_REGEX, this.tag())) {
@@ -204,7 +216,7 @@
return '\\' + escaped;
});
this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]);
this.interpolateString(("\"" + (str) + "\""), {
this.interpolateString("\"" + (str) + "\"", {
escapeQuotes: true
});
if (flags) {
@@ -242,10 +254,10 @@
if (noNewlines) {
return this.suppressNewlines();
}
this.outdebt = 0;
diff = size - this.indent;
diff = size - this.indent + this.outdebt;
this.token('INDENT', diff);
this.indents.push(diff);
this.outdebt = 0;
} else {
this.outdentToken(this.indent - size, noNewlines);
}
@@ -293,7 +305,7 @@
return true;
};
Lexer.prototype.newlineToken = function(newlines) {
if (!(this.tag() === 'TERMINATOR')) {
if (this.tag() !== 'TERMINATOR') {
this.token('TERMINATOR', "\n");
}
return true;
@@ -305,30 +317,41 @@
return true;
};
Lexer.prototype.literalToken = function() {
var _d, match, prevSpaced, space, tag, value;
var _d, match, space, spaced, tag, value;
match = this.chunk.match(OPERATOR);
value = match && match[1];
space = match && match[2];
if (value && value.match(CODE)) {
this.tagParameters();
}
value = value || this.chunk.substr(0, 1);
value || (value = this.chunk.substr(0, 1));
this.i += value.length;
prevSpaced = this.prev() && this.prev().spaced;
spaced = this.prev() && this.prev().spaced;
tag = value;
if (value === '=') {
if (include(JS_FORBIDDEN, this.value())) {
this.assignmentError();
}
if (('or' === (_d = this.value()) || 'and' === _d)) {
return this.tag(1, CONVERSIONS[this.value()] + '=');
this.tokens.splice(this.tokens.length - 1, 1, ['COMPOUND_ASSIGN', CONVERSIONS[this.value()] + '=', this.prev()[2]]);
return true;
}
}
if (value === ';') {
tag = 'TERMINATOR';
} else if (value === '?' && prevSpaced) {
tag = 'OP?';
} else if (include(CALLABLE, this.tag()) && !prevSpaced) {
} else if (include(LOGIC, value)) {
tag = 'LOGIC';
} else if (include(MATH, value)) {
tag = 'MATH';
} else if (include(COMPARE, value)) {
tag = 'COMPARE';
} else if (include(COMPOUND_ASSIGN, value)) {
tag = 'COMPOUND_ASSIGN';
} else if (include(UNARY, value)) {
tag = 'UNARY';
} else if (include(SHIFT, value)) {
tag = 'SHIFT';
} else if (include(CALLABLE, this.tag()) && !spaced) {
if (value === '(') {
tag = 'CALL_START';
} else if (value === '[') {
@@ -367,17 +390,23 @@
};
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
var _d, attempt, indent, match;
while ((match = HEREDOC_INDENT.exec(doc))) {
attempt = (typeof (_d = match[2]) !== "undefined" && _d !== null) ? match[2] : match[3];
if (!indent || attempt.length < indent.length) {
indent = attempt;
indent = options.indent || '';
if (options.herecomment && !include(doc, '\n')) {
return doc;
}
if (!(options.herecomment)) {
while (match = HEREDOC_INDENT.exec(doc)) {
attempt = (typeof (_d = match[2]) !== "undefined" && _d !== null) ? match[2] : match[3];
if (!indent || attempt.length < indent.length) {
indent = attempt;
}
}
}
doc = doc.replace(new RegExp("^" + indent, 'gm'), '');
if (options.herecomment) {
return doc;
}
return doc.replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), ("\\" + (options.quote)));
return doc.replace(MULTILINER, "\\n").replace(new RegExp(options.quote, 'g'), "\\" + (options.quote));
};
Lexer.prototype.tagParameters = function() {
var _d, i, tok;
@@ -405,14 +434,14 @@
return this.outdentToken(this.indent);
};
Lexer.prototype.identifierError = function(word) {
throw new Error(("SyntaxError: Reserved word \"" + (word) + "\" on line " + (this.line + 1)));
throw new Error("SyntaxError: Reserved word \"" + (word) + "\" on line " + (this.line + 1));
};
Lexer.prototype.assignmentError = function() {
throw new Error(("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned"));
throw new Error("SyntaxError: Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
};
Lexer.prototype.balancedString = function(str, delimited, options) {
var _d, _e, _f, _g, close, i, levels, open, pair, slash;
options = options || {};
options || (options = {});
slash = delimited[0][0] === '/';
levels = [];
i = 0;
@@ -449,13 +478,13 @@
if (slash) {
return false;
}
throw new Error(("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1)));
throw new Error("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1));
}
return !i ? false : str.substring(0, i);
};
Lexer.prototype.interpolateString = function(str, options) {
var _d, _e, _f, _g, _h, _i, escaped, expr, i, idx, inner, interpolated, lexer, nested, pi, quote, tag, tok, token, tokens, value;
options = options || {};
options || (options = {});
if (str.length < 3 || !starts(str, '"')) {
return this.token('STRING', str);
} else {
@@ -468,7 +497,7 @@
while (i < str.length - 1) {
if (starts(str, '\\', i)) {
i += 1;
} else if ((expr = this.balancedString(str.substring(i), [['#{', '}']]))) {
} else if (expr = this.balancedString(str.substring(i), [['#{', '}']])) {
if (pi < i) {
tokens.push(['STRING', quote + str.substring(pi, i) + quote]);
}
@@ -477,7 +506,7 @@
if (options.heredoc) {
inner = inner.replace(new RegExp('\\\\' + quote, 'g'), quote);
}
nested = lexer.tokenize(("(" + (inner) + ")"), {
nested = lexer.tokenize("(" + (inner) + ")", {
line: this.line
});
_e = nested;
@@ -485,7 +514,7 @@
tok = _e[idx];
if (tok[0] === 'CALL_END') {
(tok[0] = ')');
};
}
}
nested.pop();
tokens.push(['TOKENS', nested]);
@@ -500,7 +529,7 @@
if (pi < i && pi < str.length - 1) {
tokens.push(['STRING', quote + str.substring(pi, i) + quote]);
}
if (!(tokens[0][0] === 'STRING')) {
if (tokens[0][0] !== 'STRING') {
tokens.unshift(['STRING', '""']);
}
interpolated = tokens.length > 1;
@@ -517,7 +546,7 @@
this.tokens = this.tokens.concat(value);
} else if (tag === 'STRING' && options.escapeQuotes) {
escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"');
this.token(tag, ("\"" + (escaped) + "\""));
this.token(tag, "\"" + (escaped) + "\"");
} else {
this.token(tag, value);
}
@@ -539,7 +568,7 @@
if (!(tok = this.prev(index))) {
return null;
}
if ((typeof newTag !== "undefined" && newTag !== null)) {
if (typeof newTag !== "undefined" && newTag !== null) {
return (tok[0] = newTag);
}
return tok[0];
@@ -549,7 +578,7 @@
if (!(tok = this.prev(index))) {
return null;
}
if ((typeof val !== "undefined" && val !== null)) {
if (typeof val !== "undefined" && val !== null) {
return (tok[1] = val);
}
return tok[1];
@@ -579,24 +608,29 @@
IDENTIFIER = /^([a-zA-Z\$_](\w|\$)*)/;
NUMBER = /^(((\b0(x|X)[0-9a-fA-F]+)|((\b[0-9]+(\.[0-9]+)?|\.[0-9]+)(e[+\-]?[0-9]+)?)))\b/i;
HEREDOC = /^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/;
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>:!?]+)([ \t]*)/;
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>^:!?]+)([ \t]*)/;
WHITESPACE = /^([ \t]+)/;
COMMENT = /^(\s*\#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*\#{3}|(\s*#(?!##[^#])[^\n]*)+)/;
COMMENT = /^(([ \t]*\n)*([ \t]*)###([^#][\s\S]*?)(###[ \t]*\n|(###)?$)|(\s*#(?!##[^#])[^\n]*)+)/;
CODE = /^((-|=)>)/;
MULTI_DENT = /^((\n([ \t]*))+)(\.)?/;
LAST_DENTS = /\n([ \t]*)/g;
LAST_DENT = /\n([ \t]*)/;
REGEX_START = /^\/[^\/ ]/;
REGEX_START = /^\/([^\/])/;
REGEX_INTERPOLATION = /([^\\]#\{.*[^\\]\})/;
REGEX_END = /^(([imgy]{1,4})\b|\W|$)/;
REGEX_ESCAPE = /\\[^\$]/g;
JS_CLEANER = /(^`|`$)/g;
MULTILINER = /\n/g;
STRING_NEWLINES = /\n[ \t]*/g;
NO_NEWLINE = /^([+\*&|\/\-%=<>!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/;
HEREDOC_INDENT = /(\n+([ \t]*)|^([ \t]+))/g;
ASSIGNED = /^\s*([a-zA-Z\$_@]\w*[ \t]*?[:=][^=])/;
ASSIGNED = /^\s*(([a-zA-Z\$_@]\w*|["'][^\r\n]+?["']|\d+)[ \t]*?[:=][^=])/;
NEXT_CHARACTER = /^\s*(\S)/;
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
UNARY = ['UMINUS', 'UPLUS', '!', '!!', '~', 'TYPEOF', 'DELETE'];
LOGIC = ['&', '|', '^', '&&', '||'];
SHIFT = ['<<', '>>', '>>>'];
COMPARE = ['<=', '<', '>', '>='];
MATH = ['*', '/', '%'];
NOT_REGEX = ['NUMBER', 'REGEX', '++', '--', 'FALSE', 'NULL', 'TRUE', ']'];
CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', '::'];
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];

View File

@@ -6,9 +6,9 @@
child.prototype = new ctor();
child.prototype.constructor = child;
if (typeof parent.extended === "function") parent.extended(child);
child.__superClass__ = parent.prototype;
child.__super__ = parent.prototype;
};
if ((typeof process !== "undefined" && process !== null)) {
if (typeof process !== "undefined" && process !== null) {
Scope = require('./scope').Scope;
helpers = require('./helpers').helpers;
} else {
@@ -26,19 +26,19 @@
starts = _a.starts;
ends = _a.ends;
exports.BaseNode = (function() {
BaseNode = function() {};
BaseNode = function() {
this.tags = {};
return this;
};
BaseNode.prototype.compile = function(o) {
var closure, top;
this.options = merge(o || {});
this.tab = o.indent;
if (!(this instanceof ValueNode || this instanceof CallNode)) {
del(this.options, 'operation');
if (!(this instanceof AccessorNode || this instanceof IndexNode)) {
del(this.options, 'chainRoot');
}
if (!(this instanceof AccessorNode || this instanceof IndexNode)) {
del(this.options, 'chainRoot');
}
top = this.topSensitive() ? this.options.top : del(this.options, 'top');
closure = this.isStatement() && !this.isPureStatement() && !top && !this.options.asStatement && !(this instanceof CommentNode) && !this.containsPureStatement();
closure = this.isStatement(o) && !this.isPureStatement() && !top && !this.options.asStatement && !(this instanceof CommentNode) && !this.containsPureStatement();
return closure ? this.compileClosure(this.options) : this.compileNode(this.options);
};
BaseNode.prototype.compileClosure = function(o) {
@@ -48,7 +48,7 @@
};
BaseNode.prototype.compileReference = function(o, options) {
var compiled, pair, reference;
options = options || {};
options || (options = {});
pair = (function() {
if (!((this instanceof CallNode || this.contains(function(n) {
return n instanceof CallNode;
@@ -105,7 +105,7 @@
};
BaseNode.prototype.toString = function(idt, override) {
var _b, _c, _d, _e, child, children;
idt = idt || '';
idt || (idt = '');
children = (function() {
_b = []; _d = this.collectChildren();
for (_c = 0, _e = _d.length; _c < _e; _c++) {
@@ -170,6 +170,7 @@
})();
exports.Expressions = (function() {
Expressions = function(nodes) {
Expressions.__super__.constructor.call(this);
this.expressions = compact(flatten(nodes || []));
return this;
};
@@ -207,8 +208,8 @@
return this;
};
Expressions.prototype.compile = function(o) {
o = o || {};
return o.scope ? Expressions.__superClass__.compile.call(this, o) : this.compileRoot(o);
o || (o = {});
return o.scope ? Expressions.__super__.compile.call(this, o) : this.compileRoot(o);
};
Expressions.prototype.compileNode = function(o) {
var _b, _c, _d, _e, node;
@@ -246,7 +247,7 @@
compiledNode = node.compile(merge(o, {
top: true
}));
return node.isStatement() ? compiledNode : ("" + (this.idt()) + (compiledNode) + ";");
return node.isStatement(o) ? compiledNode : ("" + (this.idt()) + (compiledNode) + ";");
};
return Expressions;
})();
@@ -259,12 +260,13 @@
exports.LiteralNode = (function() {
LiteralNode = function(_b) {
this.value = _b;
LiteralNode.__super__.constructor.call(this);
return this;
};
__extends(LiteralNode, BaseNode);
LiteralNode.prototype["class"] = 'LiteralNode';
LiteralNode.prototype.makeReturn = function() {
return this.isStatement() ? this : LiteralNode.__superClass__.makeReturn.call(this);
return this.isStatement() ? this : LiteralNode.__super__.makeReturn.call(this);
};
LiteralNode.prototype.isStatement = function() {
return this.value === 'break' || this.value === 'continue';
@@ -272,8 +274,8 @@
LiteralNode.prototype.isPureStatement = LiteralNode.prototype.isStatement;
LiteralNode.prototype.compileNode = function(o) {
var end, idt;
idt = this.isStatement() ? this.idt() : '';
end = this.isStatement() ? ';' : '';
idt = this.isStatement(o) ? this.idt() : '';
end = this.isStatement(o) ? ';' : '';
return idt + this.value + end;
};
LiteralNode.prototype.toString = function(idt) {
@@ -284,6 +286,7 @@
exports.ReturnNode = (function() {
ReturnNode = function(_b) {
this.expression = _b;
ReturnNode.__super__.constructor.call(this);
return this;
};
__extends(ReturnNode, BaseNode);
@@ -304,10 +307,10 @@
if (!(expr instanceof ReturnNode)) {
return expr.compile(o);
}
return ReturnNode.__superClass__.compile.call(this, o);
return ReturnNode.__super__.compile.call(this, o);
};
ReturnNode.prototype.compileNode = function(o) {
if (this.expression.isStatement()) {
if (this.expression.isStatement(o)) {
o.asStatement = true;
}
return "" + (this.tab) + "return " + (this.expression.compile(o)) + ";";
@@ -318,11 +321,11 @@
ValueNode = function(_b, _c) {
this.properties = _c;
this.base = _b;
this.properties = this.properties || [];
ValueNode.__super__.constructor.call(this);
this.properties || (this.properties = []);
return this;
};
__extends(ValueNode, BaseNode);
ValueNode.prototype.SOAK = " == undefined ? undefined : ";
ValueNode.prototype["class"] = 'ValueNode';
ValueNode.prototype.children = ['base', 'properties'];
ValueNode.prototype.push = function(prop) {
@@ -342,28 +345,17 @@
return this.hasProperties() && this.properties[this.properties.length - 1] instanceof SliceNode;
};
ValueNode.prototype.makeReturn = function() {
return this.hasProperties() ? ValueNode.__superClass__.makeReturn.call(this) : this.base.makeReturn();
return this.hasProperties() ? ValueNode.__super__.makeReturn.call(this) : this.base.makeReturn();
};
ValueNode.prototype.unwrap = function() {
return this.properties.length ? this : this.base;
};
ValueNode.prototype.isStatement = function() {
return this.base.isStatement && this.base.isStatement() && !this.hasProperties();
ValueNode.prototype.isStatement = function(o) {
return this.base.isStatement && this.base.isStatement(o) && !this.hasProperties();
};
ValueNode.prototype.isNumber = function() {
return this.base instanceof LiteralNode && this.base.value.match(NUMBER);
};
ValueNode.prototype.isStart = function(o) {
var node;
if (this === o.chainRoot && this.properties[0] instanceof AccessorNode) {
return true;
}
node = o.chainRoot.base || o.chainRoot.variable;
while (node instanceof CallNode) {
node = node.variable;
}
return node === this;
};
ValueNode.prototype.cacheIndexes = function(o) {
var _b, _c, _d, copy, i;
copy = new ValueNode(this.base, this.properties.slice(0));
@@ -387,14 +379,17 @@
return [this, copy];
};
ValueNode.prototype.compile = function(o) {
return !o.top || this.properties.length ? ValueNode.__superClass__.compile.call(this, o) : this.base.compile(o);
return !o.top || this.properties.length ? ValueNode.__super__.compile.call(this, o) : this.base.compile(o);
};
ValueNode.prototype.compileNode = function(o) {
var _b, _c, _d, baseline, complete, i, only, op, props;
only = del(o, 'onlyFirst');
op = del(o, 'operation');
op = this.tags.operation;
props = only ? this.properties.slice(0, this.properties.length - 1) : this.properties;
o.chainRoot = o.chainRoot || this;
o.chainRoot || (o.chainRoot = this);
if (this.parenthetical && !props.length) {
this.base.parenthetical = true;
}
baseline = this.base.compile(o);
if (this.hasProperties() && (this.base instanceof ObjectNode || this.isNumber())) {
baseline = ("(" + (baseline) + ")");
@@ -414,10 +409,8 @@
temp = o.scope.freeVariable();
complete = ("(" + (baseline = temp) + " = (" + (complete) + "))");
}
if (i === 0 && this.isStart(o)) {
complete = ("typeof " + (complete) + " === \"undefined\" || " + (baseline));
}
return complete += this.SOAK + (baseline += prop.compile(o));
complete = i === 0 ? ("(typeof " + (complete) + " === \"undefined\" || " + (baseline) + " === null) ? undefined : ") : ("" + (complete) + " == null ? undefined : ");
return complete += (baseline += prop.compile(o));
} else {
part = prop.compile(o);
baseline += part;
@@ -432,7 +425,8 @@
})();
exports.CommentNode = (function() {
CommentNode = function(_b) {
this.lines = _b;
this.comment = _b;
CommentNode.__super__.constructor.call(this);
return this;
};
__extends(CommentNode, BaseNode);
@@ -444,19 +438,18 @@
return this;
};
CommentNode.prototype.compileNode = function(o) {
var sep;
sep = '\n' + this.tab;
return "" + (this.tab) + "/*" + (sep + this.lines.join(sep)) + "\n" + (this.tab) + "*/";
return this.tab + '/*' + this.comment.replace(/\r?\n/g, '\n' + this.tab) + '*/';
};
return CommentNode;
})();
exports.CallNode = (function() {
CallNode = function(variable, _b) {
this.args = _b;
CallNode.__super__.constructor.call(this);
this.isNew = false;
this.isSuper = variable === 'super';
this.variable = this.isSuper ? null : variable;
this.args = this.args || [];
this.args || (this.args = []);
this.compileSplatArguments = function(o) {
return SplatNode.compileSplattedArray.call(this, this.args, o);
};
@@ -477,9 +470,9 @@
methname = o.scope.method.name;
return (meth = (function() {
if (o.scope.method.proto) {
return "" + (o.scope.method.proto) + ".__superClass__." + (methname);
return "" + (o.scope.method.proto) + ".__super__." + (methname);
} else if (methname) {
return "" + (methname) + ".__superClass__.constructor";
return "" + (methname) + ".__super__.constructor";
} else {
throw new Error("cannot call super on an anonymous function.");
}
@@ -495,20 +488,23 @@
arg = _c[_b];
if (arg instanceof SplatNode) {
compilation = this.compileSplat(o);
};
}
}
if (!(compilation)) {
if (!compilation) {
args = (function() {
_e = []; _g = this.args;
for (_f = 0, _h = _g.length; _f < _h; _f++) {
arg = _g[_f];
_e.push(arg.compile(o));
_e.push((function() {
arg.parenthetical = true;
return arg.compile(o);
})());
}
return _e;
}).call(this).join(', ');
compilation = this.isSuper ? this.compileSuper(args, o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + (args) + ")");
}).call(this);
compilation = this.isSuper ? this.compileSuper(args.join(', '), o) : ("" + (this.prefix()) + (this.variable.compile(o)) + "(" + (args.join(', ')) + ")");
}
return o.operation && this.wrapped ? ("(" + (compilation) + ")") : compilation;
return compilation;
};
CallNode.prototype.compileSuper = function(args, o) {
return "" + (this.superReference(o)) + ".call(this" + (args.length ? ', ' : '') + (args) + ")";
@@ -535,6 +531,7 @@
ExtendsNode = function(_b, _c) {
this.parent = _c;
this.child = _b;
ExtendsNode.__super__.constructor.call(this);
return this;
};
__extends(ExtendsNode, BaseNode);
@@ -550,6 +547,7 @@
exports.AccessorNode = (function() {
AccessorNode = function(_b, tag) {
this.name = _b;
AccessorNode.__super__.constructor.call(this);
this.prototype = tag === 'prototype' ? '.prototype' : '';
this.soakNode = tag === 'soak';
return this;
@@ -560,7 +558,7 @@
AccessorNode.prototype.compileNode = function(o) {
var name, namePart;
name = this.name.compile(o);
o.chainRoot.wrapped = o.chainRoot.wrapped || this.soakNode;
o.chainRoot.wrapped || (o.chainRoot.wrapped = this.soakNode);
namePart = name.match(IS_STRING) ? ("[" + (name) + "]") : ("." + (name));
return this.prototype + namePart;
};
@@ -569,6 +567,7 @@
exports.IndexNode = (function() {
IndexNode = function(_b) {
this.index = _b;
IndexNode.__super__.constructor.call(this);
return this;
};
__extends(IndexNode, BaseNode);
@@ -576,7 +575,7 @@
IndexNode.prototype.children = ['index'];
IndexNode.prototype.compileNode = function(o) {
var idx, prefix;
o.chainRoot.wrapped = o.chainRoot.wrapped || this.soakNode;
o.chainRoot.wrapped || (o.chainRoot.wrapped = this.soakNode);
idx = this.index.compile(o);
prefix = this.proto ? '.prototype' : '';
return "" + (prefix) + "[" + (idx) + "]";
@@ -587,6 +586,7 @@
RangeNode = function(_b, _c, exclusive) {
this.to = _c;
this.from = _b;
RangeNode.__super__.constructor.call(this);
this.exclusive = !!exclusive;
this.equals = this.exclusive ? '' : '=';
return this;
@@ -645,7 +645,7 @@
to = _b[1];
idx = del(o, 'index');
step = del(o, 'step');
step = step && ("" + (idx) + " += " + (step.compile(o)));
step && (step = ("" + (idx) + " += " + (step.compile(o))));
return from <= to ? ("" + (idx) + " = " + (from) + "; " + (idx) + " <" + (this.equals) + " " + (to) + "; " + (step || ("" + (idx) + "++"))) : ("" + (idx) + " = " + (from) + "; " + (idx) + " >" + (this.equals) + " " + (to) + "; " + (step || ("" + (idx) + "--")));
};
RangeNode.prototype.compileArray = function(o) {
@@ -654,7 +654,7 @@
vars = this.compileVariables(merge(o, {
indent: idt
}));
if (this.fromNum && this.toNum && Math.abs(+this.fromNum - +this.toNum) <= 20) {
if (this.fromNum && this.toNum && (Math.abs(+this.fromNum - +this.toNum) <= 20)) {
range = (function() {
_c = [];
for (var _b = +this.fromNum; +this.fromNum <= +this.toNum ? _b <= +this.toNum : _b >= +this.toNum; +this.fromNum <= +this.toNum ? _b += 1 : _b -= 1){ _c.push(_b); }
@@ -683,22 +683,27 @@
exports.SliceNode = (function() {
SliceNode = function(_b) {
this.range = _b;
SliceNode.__super__.constructor.call(this);
return this;
};
__extends(SliceNode, BaseNode);
SliceNode.prototype["class"] = 'SliceNode';
SliceNode.prototype.children = ['range'];
SliceNode.prototype.compileNode = function(o) {
var from, plusPart, to;
from = this.range.from.compile(o);
to = this.range.to.compile(o);
plusPart = this.range.exclusive ? '' : ' + 1';
return ".slice(" + (from) + ", " + (to) + (plusPart) + ")";
var from, to;
from = this.range.from ? this.range.from.compile(o) : '0';
to = this.range.to ? this.range.to.compile(o) : '';
to += (!to || this.range.exclusive ? '' : ' + 1');
if (to) {
to = ', ' + to;
}
return ".slice(" + (from) + (to) + ")";
};
return SliceNode;
})();
exports.ObjectNode = (function() {
ObjectNode = function(props) {
ObjectNode.__super__.constructor.call(this);
this.objects = (this.properties = props || []);
return this;
};
@@ -718,7 +723,7 @@
prop = _d[_c];
if (!(prop instanceof CommentNode)) {
_b.push(prop);
};
}
}
return _b;
}).call(this);
@@ -753,7 +758,8 @@
exports.ArrayNode = (function() {
ArrayNode = function(_b) {
this.objects = _b;
this.objects = this.objects || [];
ArrayNode.__super__.constructor.call(this);
this.objects || (this.objects = []);
this.compileSplatLiteral = function(o) {
return SplatNode.compileSplattedArray.call(this, this.objects, o);
};
@@ -773,11 +779,11 @@
if (obj instanceof SplatNode) {
return this.compileSplatLiteral(o);
} else if (obj instanceof CommentNode) {
objects.push(("\n" + (code) + "\n" + (o.indent)));
objects.push("\n" + (code) + "\n" + (o.indent));
} else if (i === this.objects.length - 1) {
objects.push(code);
} else {
objects.push(("" + (code) + ", "));
objects.push("" + (code) + ", ");
}
}
objects = objects.join('');
@@ -790,7 +796,8 @@
this.properties = _d;
this.parent = _c;
this.variable = _b;
this.properties = this.properties || [];
ClassNode.__super__.constructor.call(this);
this.properties || (this.properties = []);
this.returns = false;
return this;
};
@@ -839,14 +846,18 @@
continue;
}
if (func instanceof CodeNode && func.bound) {
func.bound = false;
constScope = constScope || new Scope(o.scope, constructor.body, constructor);
me = me || constScope.freeVariable();
pname = pvar.compile(o);
if (constructor.body.empty()) {
constructor.body.push(new ReturnNode(literal('this')));
if (prop.context === 'this') {
func.context = className;
} else {
func.bound = false;
constScope || (constScope = new Scope(o.scope, constructor.body, constructor));
me || (me = constScope.freeVariable());
pname = pvar.compile(o);
if (constructor.body.empty()) {
constructor.body.push(new ReturnNode(literal('this')));
}
constructor.body.unshift(literal("this." + (pname) + " = function(){ return " + (className) + ".prototype." + (pname) + ".apply(" + (me) + ", arguments); }"));
}
constructor.body.unshift(literal(("this." + (pname) + " = function(){ return " + (className) + ".prototype." + (pname) + ".apply(" + (me) + ", arguments); }")));
}
if (pvar) {
access = prop.context === 'this' ? pvar.base.properties[0] : new AccessorNode(pvar, 'prototype');
@@ -856,7 +867,7 @@
props.push(prop);
}
if (me) {
constructor.body.unshift(literal(("" + (me) + " = this")));
constructor.body.unshift(literal("" + (me) + " = this"));
}
construct = this.idt() + (new AssignNode(this.variable, constructor)).compile(merge(o, {
sharedScope: constScope
@@ -873,6 +884,7 @@
this.context = _d;
this.value = _c;
this.variable = _b;
AssignNode.__super__.constructor.call(this);
return this;
};
__extends(AssignNode, BaseNode);
@@ -890,7 +902,7 @@
if (this.isStatement()) {
return new Expressions([this, new ReturnNode(this.variable)]);
} else {
return AssignNode.__superClass__.makeReturn.call(this);
return AssignNode.__super__.makeReturn.call(this);
}
};
AssignNode.prototype.isStatement = function() {
@@ -899,7 +911,7 @@
AssignNode.prototype.compileNode = function(o) {
var last, match, name, proto, stmt, top, val;
top = del(o, 'top');
if (this.isStatement()) {
if (this.isStatement(o)) {
return this.compilePatternMatch(o);
}
if (this.isValue() && this.variable.isSplice()) {
@@ -929,12 +941,12 @@
if (stmt) {
return ("" + (this.tab) + (val) + ";");
}
return top ? val : ("(" + (val) + ")");
return top || this.parenthetical ? val : ("(" + (val) + ")");
};
AssignNode.prototype.compilePatternMatch = function(o) {
var _b, _c, _d, accessClass, assigns, code, i, idx, isString, obj, oindex, olength, splat, val, valVar, value;
valVar = o.scope.freeVariable();
value = this.value.isStatement() ? ClosureNode.wrap(this.value) : this.value;
value = this.value.isStatement(o) ? ClosureNode.wrap(this.value) : this.value;
assigns = [("" + (this.tab) + (valVar) + " = " + (value.compile(o)) + ";")];
o.top = true;
o.asStatement = true;
@@ -958,7 +970,7 @@
isString = idx.value && idx.value.match(IS_STRING);
accessClass = isString || this.variable.isArray() ? IndexNode : AccessorNode;
if (obj instanceof SplatNode && !splat) {
val = literal(obj.compileValue(o, valVar, (oindex = indexOf(this.variable.base.objects, obj)), (olength = this.variable.base.objects.length) - oindex - 1));
val = literal(obj.compileValue(o, valVar, oindex = indexOf(this.variable.base.objects, obj), (olength = this.variable.base.objects.length) - oindex - 1));
splat = true;
} else {
if (typeof idx !== 'object') {
@@ -979,8 +991,8 @@
l = this.variable.properties.length;
range = this.variable.properties[l - 1].range;
plus = range.exclusive ? '' : ' + 1';
from = range.from.compile(o);
to = range.to.compile(o) + ' - ' + from + plus;
from = range.from ? range.from.compile(o) : '0';
to = range.to ? range.to.compile(o) + ' - ' + from + plus : ("" + (name) + ".length");
val = this.value.compile(o);
return "" + (name) + ".splice.apply(" + (name) + ", [" + (from) + ", " + (to) + "].concat(" + (val) + "))";
};
@@ -990,9 +1002,13 @@
CodeNode = function(_b, _c, tag) {
this.body = _c;
this.params = _b;
this.params = this.params || [];
this.body = this.body || new Expressions();
CodeNode.__super__.constructor.call(this);
this.params || (this.params = []);
this.body || (this.body = new Expressions());
this.bound = tag === 'boundfunc';
if (this.bound) {
this.context = 'this';
}
return this;
};
__extends(CodeNode, BaseNode);
@@ -1058,7 +1074,7 @@
code = this.body.expressions.length ? ("\n" + (this.body.compileWithDeclarations(o)) + "\n") : '';
func = ("function(" + (params.join(', ')) + ") {" + (code) + (code && this.tab) + "}");
if (this.bound) {
return ("" + (utility('bind')) + "(" + (func) + ", this)");
return ("" + (utility('bind')) + "(" + (func) + ", " + (this.context) + ")");
}
return top ? ("(" + (func) + ")") : func;
};
@@ -1067,12 +1083,12 @@
};
CodeNode.prototype.traverseChildren = function(crossScope, func) {
if (crossScope) {
return CodeNode.__superClass__.traverseChildren.call(this, crossScope, func);
return CodeNode.__super__.traverseChildren.call(this, crossScope, func);
}
};
CodeNode.prototype.toString = function(idt) {
var _b, _c, _d, _e, child, children;
idt = idt || '';
idt || (idt = '');
children = (function() {
_b = []; _d = this.collectChildren();
for (_c = 0, _e = _d.length; _c < _e; _c++) {
@@ -1090,6 +1106,7 @@
this.splat = _d;
this.attach = _c;
this.name = _b;
ParamNode.__super__.constructor.call(this);
this.value = literal(this.name);
return this;
};
@@ -1106,6 +1123,7 @@
})();
exports.SplatNode = (function() {
SplatNode = function(name) {
SplatNode.__super__.constructor.call(this);
if (!(name.compile)) {
name = literal(name);
}
@@ -1139,7 +1157,7 @@
assign.value = trailing;
}
pos = this.trailings.length - idx;
o.scope.assign(trailing.compile(o), ("arguments[" + (variadic) + " ? " + (len) + " - " + (pos) + " : " + (this.index + idx) + "]"));
o.scope.assign(trailing.compile(o), "arguments[" + (variadic) + " ? " + (len) + " - " + (pos) + " : " + (this.index + idx) + "]");
}
}
return "" + (name) + " = " + (utility('slice')) + ".call(arguments, " + (this.index) + (end) + ")";
@@ -1176,6 +1194,7 @@
}).call(this);
exports.WhileNode = (function() {
WhileNode = function(condition, opts) {
WhileNode.__super__.constructor.call(this);
if (opts && opts.invert) {
if (condition instanceof OpNode) {
condition = new ParentheticalNode(condition);
@@ -1208,6 +1227,7 @@
top = del(o, 'top') && !this.returns;
o.indent = this.idt(1);
o.top = true;
this.condition.parenthetical = true;
cond = this.condition.compile(o);
set = '';
if (!(top)) {
@@ -1227,7 +1247,7 @@
}));
} else {
post = '';
};
}
return "" + (pre) + " {\n" + (this.body.compile(o)) + "\n" + (this.tab) + "}" + (post);
};
return WhileNode;
@@ -1237,11 +1257,16 @@
this.second = _d;
this.first = _c;
this.operator = _b;
OpNode.__super__.constructor.call(this);
this.operator = this.CONVERSIONS[this.operator] || this.operator;
this.flip = !!flip;
if (this.first instanceof ValueNode && this.first.base instanceof ObjectNode) {
this.first = new ParentheticalNode(this.first);
};
}
this.first.tags.operation = true;
if (this.second) {
this.second.tags.operation = true;
}
return this;
};
__extends(OpNode, BaseNode);
@@ -1249,6 +1274,10 @@
'==': '===',
'!=': '!=='
};
OpNode.prototype.INVERSIONS = {
'!==': '===',
'===': '!=='
};
OpNode.prototype.CHAINABLE = ['<', '>', '>=', '<=', '===', '!=='];
OpNode.prototype.ASSIGNMENT = ['||=', '&&=', '?='];
OpNode.prototype.PREFIX_OPERATORS = ['typeof', 'delete'];
@@ -1257,14 +1286,24 @@
OpNode.prototype.isUnary = function() {
return !this.second;
};
OpNode.prototype.isInvertible = function() {
var _b;
return (('===' === (_b = this.operator) || '!==' === _b)) && !(this.first instanceof OpNode) && !(this.second instanceof OpNode);
};
OpNode.prototype.isMutator = function() {
var _b;
return ends(this.operator, '=') && !(('===' === (_b = this.operator) || '!==' === _b));
};
OpNode.prototype.isChainable = function() {
return indexOf(this.CHAINABLE, this.operator) >= 0;
return include(this.CHAINABLE, this.operator);
};
OpNode.prototype.invert = function() {
return (this.operator = this.INVERSIONS[this.operator]);
};
OpNode.prototype.toString = function(idt) {
return OpNode.__superClass__.toString.call(this, idt, this["class"] + ' ' + this.operator);
return OpNode.__super__.toString.call(this, idt, this["class"] + ' ' + this.operator);
};
OpNode.prototype.compileNode = function(o) {
o.operation = true;
if (this.isChainable() && this.first.unwrap() instanceof OpNode && this.first.unwrap().isChainable()) {
return this.compileChain(o);
}
@@ -1277,6 +1316,12 @@
if (this.operator === '?') {
return this.compileExistence(o);
}
if (this.first instanceof OpNode && this.first.isMutator()) {
this.first = new ParentheticalNode(this.first);
}
if (this.second instanceof OpNode && this.second.isMutator()) {
this.second = new ParentheticalNode(this.second);
}
return [this.first.compile(o), this.operator, this.second.compile(o)].join(' ');
};
OpNode.prototype.compileChain = function(o) {
@@ -1309,17 +1354,16 @@
o.scope.find(first);
}
if (this.operator === '?=') {
return ("" + (first) + " = " + (ExistenceNode.compileTest(o, literal(firstVar))) + " ? " + (firstVar) + " : " + (second));
return ("" + (first) + " = " + (ExistenceNode.compileTest(o, literal(firstVar))[0]) + " ? " + (firstVar) + " : " + (second));
}
return "" + (first) + " = " + (firstVar) + " " + (this.operator.substr(0, 2)) + " " + (second);
return "" + (first) + " " + (this.operator.substr(0, 2)) + " (" + (firstVar) + " = " + (second) + ")";
};
OpNode.prototype.compileExistence = function(o) {
var _b, first, second, test;
_b = [this.first.compile(o), this.second.compile(o)];
first = _b[0];
second = _b[1];
test = ExistenceNode.compileTest(o, this.first);
return "" + (test) + " ? " + (first) + " : " + (second);
var _b, ref, test;
_b = ExistenceNode.compileTest(o, this.first);
test = _b[0];
ref = _b[1];
return "" + (test) + " ? " + (ref) + " : " + (this.second.compile(o));
};
OpNode.prototype.compileUnary = function(o) {
var parts, space;
@@ -1336,6 +1380,7 @@
InNode = function(_b, _c) {
this.array = _c;
this.object = _b;
InNode.__super__.constructor.call(this);
return this;
};
__extends(InNode, BaseNode);
@@ -1359,7 +1404,7 @@
_b = []; _c = this.array.base.objects;
for (i = 0, _d = _c.length; i < _d; i++) {
item = _c[i];
_b.push(("" + (item.compile(o)) + " === " + (i ? this.obj2 : this.obj1)));
_b.push("" + (item.compile(o)) + " === " + (i ? this.obj2 : this.obj1));
}
return _b;
}).call(this);
@@ -1386,6 +1431,7 @@
this.recovery = _d;
this.error = _c;
this.attempt = _b;
TryNode.__super__.constructor.call(this);
return this;
};
__extends(TryNode, BaseNode);
@@ -1418,6 +1464,7 @@
exports.ThrowNode = (function() {
ThrowNode = function(_b) {
this.expression = _b;
ThrowNode.__super__.constructor.call(this);
return this;
};
__extends(ThrowNode, BaseNode);
@@ -1437,33 +1484,39 @@
exports.ExistenceNode = (function() {
ExistenceNode = function(_b) {
this.expression = _b;
ExistenceNode.__super__.constructor.call(this);
return this;
};
__extends(ExistenceNode, BaseNode);
ExistenceNode.prototype["class"] = 'ExistenceNode';
ExistenceNode.prototype.children = ['expression'];
ExistenceNode.prototype.compileNode = function(o) {
return ExistenceNode.compileTest(o, this.expression);
var test;
test = ExistenceNode.compileTest(o, this.expression)[0];
return this.parenthetical ? test.substring(1, test.length - 1) : test;
};
ExistenceNode.compileTest = function(o, variable) {
var _b, first, second;
_b = variable.compileReference(o);
_b = variable.compileReference(o, {
precompile: true
});
first = _b[0];
second = _b[1];
return "(typeof " + (first.compile(o)) + " !== \"undefined\" && " + (second.compile(o)) + " !== null)";
return [("(typeof " + (first) + " !== \"undefined\" && " + (second) + " !== null)"), second];
};
return ExistenceNode;
}).call(this);
exports.ParentheticalNode = (function() {
ParentheticalNode = function(_b) {
this.expression = _b;
ParentheticalNode.__super__.constructor.call(this);
return this;
};
__extends(ParentheticalNode, BaseNode);
ParentheticalNode.prototype["class"] = 'ParentheticalNode';
ParentheticalNode.prototype.children = ['expression'];
ParentheticalNode.prototype.isStatement = function() {
return this.expression.isStatement();
ParentheticalNode.prototype.isStatement = function(o) {
return this.expression.isStatement(o);
};
ParentheticalNode.prototype.makeReturn = function() {
return this.expression.makeReturn();
@@ -1472,17 +1525,17 @@
return true;
};
ParentheticalNode.prototype.compileNode = function(o) {
var code, l, top;
var code, top;
top = del(o, 'top');
this.expression.parenthetical = true;
code = this.expression.compile(o);
if (this.isStatement()) {
return (top ? this.tab + code + ';' : code);
if (top && this.expression.isPureStatement(o)) {
return code;
}
l = code.length;
if (code.substr(l - 1, 1) === ';') {
code = code.substr(o, l - 1);
if (this.parenthetical || this.isStatement(o)) {
return top ? this.tab + code + ';' : code;
}
return this.expression instanceof AssignNode ? code : ("(" + (code) + ")");
return "(" + (code) + ")";
};
return ParentheticalNode;
})();
@@ -1492,7 +1545,8 @@
this.index = _d;
this.name = _c;
this.body = _b;
this.index = this.index || null;
ForNode.__super__.constructor.call(this);
this.index || (this.index = null);
this.source = source.source;
this.guard = source.guard;
this.step = source.step;
@@ -1574,7 +1628,7 @@
svar = scope.freeVariable();
sourcePart = ("" + (svar) + " = " + (this.source.compile(o)) + ";");
if (this.pattern) {
namePart = new AssignNode(this.name, literal(("" + (svar) + "[" + (ivar) + "]"))).compile(merge(o, {
namePart = new AssignNode(this.name, literal("" + (svar) + "[" + (ivar) + "]")).compile(merge(o, {
indent: this.idt(1),
top: true
})) + '\n';
@@ -1597,16 +1651,16 @@
}
if (this.guard) {
body = Expressions.wrap([new IfNode(this.guard, body)]);
};
}
if (codeInBody) {
if (range) {
body.unshift(literal(("var " + (name) + " = " + (ivar))));
body.unshift(literal("var " + (name) + " = " + (ivar)));
}
if (namePart) {
body.unshift(literal(("var " + (namePart))));
body.unshift(literal("var " + (namePart)));
}
if (index) {
body.unshift(literal(("var " + (index) + " = " + (ivar))));
body.unshift(literal("var " + (index) + " = " + (ivar)));
}
body = ClosureNode.wrap(body, true);
} else {
@@ -1632,9 +1686,13 @@
this.tags = _d;
this.body = _c;
this.condition = _b;
this.tags = this.tags || {};
this.tags || (this.tags = {});
if (this.tags.invert) {
this.condition = new OpNode('!', new ParentheticalNode(this.condition));
if (this.condition instanceof OpNode && this.condition.isInvertible()) {
this.condition.invert();
} else {
this.condition = new OpNode('!', new ParentheticalNode(this.condition));
}
}
this.elseBody = null;
this.isChain = false;
@@ -1647,10 +1705,10 @@
return true;
};
IfNode.prototype.bodyNode = function() {
return this.body == undefined ? undefined : this.body.unwrap();
return this.body == null ? undefined : this.body.unwrap();
};
IfNode.prototype.elseBodyNode = function() {
return this.elseBody == undefined ? undefined : this.elseBody.unwrap();
return this.elseBody == null ? undefined : this.elseBody.unwrap();
};
IfNode.prototype.forceStatement = function() {
this.tags.statement = true;
@@ -1663,7 +1721,7 @@
IfNode.prototype.rewriteSwitch = function(o) {
var _b, _c, _d, cond, i, variable;
this.assigner = this.switchSubject;
if (!((this.switchSubject.unwrap() instanceof LiteralNode))) {
if (!(this.switchSubject.unwrap() instanceof LiteralNode)) {
variable = literal(o.scope.freeVariable());
this.assigner = new AssignNode(variable, this.switchSubject);
this.switchSubject = variable;
@@ -1676,7 +1734,7 @@
if (cond instanceof OpNode) {
cond = new ParentheticalNode(cond);
}
return new OpNode('==', (i === 0 ? this.assigner : this.switchSubject), cond);
return new OpNode('==', i === 0 ? this.assigner : this.switchSubject, cond);
}).call(this));
}
return _b;
@@ -1696,27 +1754,31 @@
}
return this;
};
IfNode.prototype.isStatement = function() {
return this.statement = this.statement || (!!(this.tags.statement || this.bodyNode().isStatement() || (this.elseBody && this.elseBodyNode().isStatement())));
IfNode.prototype.isStatement = function(o) {
return this.statement || (this.statement = (!!((o && o.top) || this.tags.statement || this.bodyNode().isStatement(o) || (this.elseBody && this.elseBodyNode().isStatement(o)))));
};
IfNode.prototype.compileCondition = function(o) {
var _b, _c, _d, _e, cond;
var _b, _c, _d, _e, cond, conditions;
conditions = flatten([this.condition]);
if (conditions.length === 1) {
conditions[0].parenthetical = true;
}
return (function() {
_b = []; _d = flatten([this.condition]);
_b = []; _d = conditions;
for (_c = 0, _e = _d.length; _c < _e; _c++) {
cond = _d[_c];
_b.push(cond.compile(o));
}
return _b;
}).call(this).join(' || ');
})().join(' || ');
};
IfNode.prototype.compileNode = function(o) {
return o.top || this.isStatement() ? this.compileStatement(o) : this.compileTernary(o);
return this.isStatement(o) ? this.compileStatement(o) : this.compileTernary(o);
};
IfNode.prototype.makeReturn = function() {
if (this.isStatement()) {
this.body = this.body && this.ensureExpressions(this.body.makeReturn());
this.elseBody = this.elseBody && this.ensureExpressions(this.elseBody.makeReturn());
this.body && (this.body = this.ensureExpressions(this.body.makeReturn()));
this.elseBody && (this.elseBody = this.ensureExpressions(this.elseBody.makeReturn()));
return this;
} else {
return new ReturnNode(this);
@@ -1735,7 +1797,7 @@
condO = merge(o);
o.indent = this.idt(1);
o.top = true;
ifDent = child || (top && !this.isStatement()) ? '' : this.idt();
ifDent = child || (top && !this.isStatement(o)) ? '' : this.idt();
comDent = child ? this.idt() : '';
body = this.body.compile(o);
ifPart = ("" + (ifDent) + "if (" + (this.compileCondition(condO)) + ") {\n" + (body) + "\n" + (this.tab) + "}");
@@ -1749,11 +1811,15 @@
return "" + (ifPart) + (elsePart);
};
IfNode.prototype.compileTernary = function(o) {
var elsePart, ifPart;
o.operation = true;
var code, elsePart, ifPart;
this.bodyNode().tags.operation = (this.condition.tags.operation = true);
if (this.elseBody) {
this.elseBodyNode().tags.operation = true;
}
ifPart = this.condition.compile(o) + ' ? ' + this.bodyNode().compile(o);
elsePart = this.elseBody ? this.elseBodyNode().compile(o) : 'null';
return "" + (ifPart) + " : " + (elsePart);
code = ("" + (ifPart) + " : " + (elsePart));
return this.tags.operation ? ("(" + (code) + ")") : code;
};
return IfNode;
})();
@@ -1794,7 +1860,7 @@
}
});
UTILITIES = {
"extends": "function(child, parent) {\n var ctor = function(){};\n ctor.prototype = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n if (typeof parent.extended === \"function\") parent.extended(child);\n child.__superClass__ = parent.prototype;\n }",
"extends": "function(child, parent) {\n var ctor = function(){};\n ctor.prototype = parent.prototype;\n child.prototype = new ctor();\n child.prototype.constructor = child;\n if (typeof parent.extended === \"function\") parent.extended(child);\n child.__super__ = parent.prototype;\n }",
bind: "function(func, context) {\n return function(){ return func.apply(context, arguments); };\n }",
hasProp: 'Object.prototype.hasOwnProperty',
slice: 'Array.prototype.slice'

View File

@@ -28,7 +28,7 @@
}
}
if (isOption && !matchedRule) {
throw new Error(("unrecognized option: " + (arg)));
throw new Error("unrecognized option: " + (arg));
}
if (!isOption) {
options.arguments = args.slice(i, args.length);
@@ -41,7 +41,7 @@
var _a, _b, _c, _d, i, letPart, lines, rule, spaces;
lines = ['Available options:'];
if (this.banner) {
lines.unshift(("" + (this.banner) + "\n"));
lines.unshift("" + (this.banner) + "\n");
}
_b = this.rules;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
@@ -83,7 +83,7 @@
var match;
match = longFlag.match(OPTIONAL);
longFlag = longFlag.match(LONG_FLAG)[1];
options = options || {};
options || (options = {});
return {
name: longFlag.substr(2),
shortFlag: shortFlag,
@@ -100,7 +100,7 @@
_b = args;
for (_a = 0, _c = _b.length; _a < _c; _a++) {
arg = _b[_a];
if ((match = arg.match(MULTI_FLAG))) {
if (match = arg.match(MULTI_FLAG)) {
_e = match[1].split('');
for (_d = 0, _f = _e.length; _d < _f; _d++) {
l = _e[_d];

File diff suppressed because one or more lines are too long

View File

@@ -1,9 +1,7 @@
(function() {
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, helpers, include, pair;
var __bind = function(func, context) {
return function(){ return func.apply(context, arguments); };
}, __hasProp = Object.prototype.hasOwnProperty;
if ((typeof process !== "undefined" && process !== null)) {
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, helpers, include, pair;
var __hasProp = Object.prototype.hasOwnProperty;
if (typeof process !== "undefined" && process !== null) {
_a = require('./helpers');
helpers = _a.helpers;
} else {
@@ -23,6 +21,7 @@
this.closeOpenIndexes();
this.addImplicitIndentation();
this.addImplicitBraces();
this.tagPostfixConditionals();
this.addImplicitParentheses();
this.ensureBalance(BALANCED_PAIRS);
this.rewriteClosingParens();
@@ -35,7 +34,7 @@
if (!(this.tokens[i])) {
break;
}
move = block(this.tokens[i], i);
move = block.call(this, this.tokens[i], i);
i += move;
}
return true;
@@ -62,9 +61,9 @@
return i - 1;
};
Rewriter.prototype.adjustComments = function() {
return this.scanTokens(__bind(function(token, i) {
return this.scanTokens(function(token, i) {
var _c, _d, after, before, post, prev;
if (!(token[0] === 'HERECOMMENT')) {
if (token[0] !== 'HERECOMMENT') {
return 1;
}
_c = [this.tokens[i - 2], this.tokens[i - 1], this.tokens[i + 1], this.tokens[i + 2]];
@@ -78,20 +77,20 @@
this.tokens.splice(i - 2, 1);
} else {
this.tokens.splice(i, 0, after);
};
}
} else if (prev && !('TERMINATOR' === (_d = prev[0]) || 'INDENT' === _d || 'OUTDENT' === _d)) {
if (post && post[0] === 'TERMINATOR' && after && after[0] === 'OUTDENT') {
this.tokens.splice.apply(this.tokens, [i + 2, 0].concat(this.tokens.splice(i, 2)));
if (this.tokens[i + 2][0] !== 'TERMINATOR') {
this.tokens.splice(i + 2, 0, ['TERMINATOR', "\n", prev[2]]);
};
}
} else {
this.tokens.splice(i, 0, ['TERMINATOR', "\n", prev[2]]);
}
return 2;
}
return 1;
}, this));
});
};
Rewriter.prototype.removeLeadingNewlines = function() {
var _c;
@@ -102,16 +101,16 @@
return _c;
};
Rewriter.prototype.removeMidExpressionNewlines = function() {
return this.scanTokens(__bind(function(token, i) {
return this.scanTokens(function(token, i) {
if (!(include(EXPRESSION_CLOSE, this.tag(i + 1)) && token[0] === 'TERMINATOR')) {
return 1;
}
this.tokens.splice(i, 1);
return 0;
}, this));
});
};
Rewriter.prototype.closeOpenCalls = function() {
return this.scanTokens(__bind(function(token, i) {
return this.scanTokens(function(token, i) {
var action, condition;
if (token[0] === 'CALL_START') {
condition = function(token, i) {
@@ -124,10 +123,10 @@
this.detectEnd(i + 1, condition, action);
}
return 1;
}, this));
});
};
Rewriter.prototype.closeOpenIndexes = function() {
return this.scanTokens(__bind(function(token, i) {
return this.scanTokens(function(token, i) {
var action, condition;
if (token[0] === 'INDEX_START') {
condition = function(token, i) {
@@ -140,24 +139,26 @@
this.detectEnd(i + 1, condition, action);
}
return 1;
}, this));
});
};
Rewriter.prototype.addImplicitBraces = function() {
var stack;
stack = [];
return this.scanTokens(__bind(function(token, i) {
var action, condition, idx, last;
return this.scanTokens(function(token, i) {
var action, condition, idx, last, tok;
if (include(EXPRESSION_START, token[0])) {
stack.push((token[0] === 'INDENT' && (this.tag(i - 1) === '{')) ? '{' : token[0]);
};
}
if (include(EXPRESSION_END, token[0])) {
stack.pop();
};
}
last = stack[stack.length - 1];
if (token[0] === ':' && (!last || last[0] !== '{')) {
stack.push('{');
idx = this.tag(i - 2) === '@' ? i - 2 : i - 1;
this.tokens.splice(idx, 0, ['{', '{', token[2]]);
tok = ['{', '{', token[2]];
tok.generated = true;
this.tokens.splice(idx, 0, tok);
condition = function(token, i) {
var _c, _d, _e, one, three, two;
_c = this.tokens.slice(i + 1, i + 4);
@@ -176,36 +177,49 @@
return 2;
}
return 1;
}, this));
});
};
Rewriter.prototype.addImplicitParentheses = function() {
return this.scanTokens(__bind(function(token, i) {
var _c, action, condition, prev;
var classLine;
classLine = false;
return this.scanTokens(function(token, i) {
var _c, action, callObject, condition, idx, next, prev;
if (token[0] === 'CLASS') {
classLine = true;
}
prev = this.tokens[i - 1];
if (prev && prev.spaced && include(IMPLICIT_FUNC, prev[0]) && include(IMPLICIT_CALL, token[0]) && !(token[0] === '!' && (('IN' === (_c = this.tag(i + 1)) || 'OF' === _c)))) {
next = this.tokens[i + 1];
idx = 1;
callObject = !classLine && token[0] === 'INDENT' && next && next.generated && next[0] === '{' && prev && include(IMPLICIT_FUNC, prev[0]);
if (callObject) {
idx = 2;
}
if (include(LINEBREAKS, token[0])) {
classLine = false;
}
if (prev && (prev.spaced && include(IMPLICIT_FUNC, prev[0]) && include(IMPLICIT_CALL, token[0]) && !(token[0] === 'UNARY' && (('IN' === (_c = this.tag(i + 1)) || 'OF' === _c || 'INSTANCEOF' === _c)))) || callObject) {
this.tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
condition = function(token, i) {
return (!token.generated && this.tokens[i - 1][0] !== ',' && include(IMPLICIT_END, token[0]) && !(token[0] === 'INDENT' && (include(IMPLICIT_BLOCK, this.tag(i - 1)) || this.tag(i - 2) === 'CLASS'))) || token[0] === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT';
};
action = function(token, i) {
var idx;
idx = token[0] === 'OUTDENT' ? i + 1 : i;
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
};
this.detectEnd(i + 1, condition, action);
this.detectEnd(i + idx, condition, action);
return 2;
}
return 1;
}, this));
});
};
Rewriter.prototype.addImplicitIndentation = function() {
return this.scanTokens(__bind(function(token, i) {
return this.scanTokens(function(token, i) {
var _c, action, condition, indent, outdent, starter;
if (token[0] === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
this.tokens.splice.apply(this.tokens, [i, 0].concat(this.indentation(token)));
return 2;
}
if (token[0] === 'CATCH' && (this.tokens[i + 2][0] === 'TERMINATOR' || this.tokens[i + 2][0] === 'FINALLY')) {
if (token[0] === 'CATCH' && (this.tag(i + 2) === 'TERMINATOR' || this.tag(i + 2) === 'FINALLY')) {
this.tokens.splice.apply(this.tokens, [i + 2, 0].concat(this.indentation(token)));
return 4;
}
@@ -231,13 +245,33 @@
return 2;
}
return 1;
}, this));
});
};
Rewriter.prototype.tagPostfixConditionals = function() {
return this.scanTokens(function(token, i) {
var _c, action, condition, original;
if (('IF' === (_c = token[0]) || 'UNLESS' === _c)) {
original = token;
condition = function(token, i) {
var _c;
return ('TERMINATOR' === (_c = token[0]) || 'INDENT' === _c);
};
action = function(token, i) {
if (token[0] !== 'INDENT') {
return (original[0] = 'POST_' + original[0]);
}
};
this.detectEnd(i + 1, condition, action);
return 1;
}
return 1;
});
};
Rewriter.prototype.ensureBalance = function(pairs) {
var _c, _d, key, levels, line, open, openLine, unclosed, value;
levels = {};
openLine = {};
this.scanTokens(__bind(function(token, i) {
this.scanTokens(function(token, i) {
var _c, _d, _e, _f, close, open, pair;
_d = pairs;
for (_c = 0, _e = _d.length; _c < _e; _c++) {
@@ -245,7 +279,7 @@
_f = pair;
open = _f[0];
close = _f[1];
levels[open] = levels[open] || 0;
levels[open] || (levels[open] = 0);
if (token[0] === open) {
if (levels[open] === 0) {
openLine[open] = token[2];
@@ -256,11 +290,11 @@
levels[open] -= 1;
}
if (levels[open] < 0) {
throw new Error(("too many " + (token[1]) + " on line " + (token[2] + 1)));
throw new Error("too many " + (token[1]) + " on line " + (token[2] + 1));
}
}
return 1;
}, this));
});
unclosed = (function() {
_c = []; _d = levels;
for (key in _d) {
@@ -268,14 +302,14 @@
value = _d[key];
if (value > 0) {
_c.push(key);
};
}
}
return _c;
})();
if (unclosed.length) {
open = unclosed[0];
line = openLine[open] + 1;
throw new Error(("unclosed " + (open) + " on line " + (line)));
throw new Error("unclosed " + (open) + " on line " + (line));
}
};
Rewriter.prototype.rewriteClosingParens = function() {
@@ -288,7 +322,7 @@
val = _c[key];
(debt[key] = 0);
}
return this.scanTokens(__bind(function(token, i) {
return this.scanTokens(function(token, i) {
var inv, match, mtag, oppos, tag;
tag = token[0];
inv = INVERSES[token[0]];
@@ -309,7 +343,7 @@
}
debt[mtag] += 1;
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
if ((this.tokens[i + 2] == undefined ? undefined : this.tokens[i + 2][0]) === mtag) {
if ((this.tokens[i + 2] == null ? undefined : this.tokens[i + 2][0]) === mtag) {
this.tokens.splice(i + 3, 0, val);
stack.push(match);
} else {
@@ -320,7 +354,7 @@
} else {
return 1;
}
}, this));
});
};
Rewriter.prototype.indentation = function(token) {
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
@@ -356,9 +390,10 @@
})();
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'THIS', 'NULL', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '!', '!!', '@', '->', '=>', '[', '(', '{'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY', 'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF', '@', '->', '=>', '[', '(', '{'];
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'];
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT'];
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN'];
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
})();

View File

@@ -1,7 +1,7 @@
(function() {
var Scope;
var __hasProp = Object.prototype.hasOwnProperty;
if (!((typeof process !== "undefined" && process !== null))) {
if (!(typeof process !== "undefined" && process !== null)) {
this.exports = this;
}
exports.Scope = (function() {
@@ -44,7 +44,7 @@
return (this.variables[name] = 'param');
};
Scope.prototype.check = function(name) {
if (this.variables.hasOwnProperty(name)) {
if (Object.prototype.hasOwnProperty.call(this.variables, name)) {
return true;
}
return !!(this.parent && this.parent.check(name));
@@ -83,7 +83,7 @@
val = _b[key];
if (val === 'var') {
_a.push(key);
};
}
}
return _a;
}).call(this).sort();
@@ -95,8 +95,8 @@
if (!__hasProp.call(_b, key)) continue;
val = _b[key];
if (val.assigned) {
_a.push(("" + (key) + " = " + (val.value)));
};
_a.push("" + (key) + " = " + (val.value));
}
}
return _a;
};

View File

@@ -3,7 +3,7 @@
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language", "coffeescript", "compiler"],
"author": "Jeremy Ashkenas",
"version": "0.9.1",
"version": "0.9.2",
"licenses": [{
"type": "MIT",
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
@@ -11,6 +11,10 @@
"engines": {
"node": ">=0.1.99"
},
"directories" : {
"lib" : "./lib"
},
"main" : "./lib/coffee-script",
"bin": {
"coffee": "./bin/coffee",
"cake": "./bin/cake"

33
src/coffee-script.coffee Normal file → Executable file
View File

@@ -22,7 +22,7 @@ else
helpers = this.helpers
# The current CoffeeScript version number.
exports.VERSION = '0.9.1'
exports.VERSION = '0.9.2'
# Instantiate a Lexer for our use here.
lexer = new Lexer
@@ -71,14 +71,27 @@ parser.lexer =
upcomingInput: -> ""
# Activate CoffeeScript in the browser by having it compile and evaluate
# all script tags with a content-type of `text/coffeescript`. This happens
# on page load. Unfortunately, the text contents of remote scripts cannot be
# accessed from the browser, so only inline script tags will work.
if document? and document.getElementsByTagName
# all script tags with a content-type of `text/coffeescript`.
# This happens on page load.
if document?.getElementsByTagName
grind = (coffee) ->
setTimeout exports.compile coffee
grindRemote = (url) ->
xhr = new (window.ActiveXObject or XMLHttpRequest)('Microsoft.XMLHTTP')
xhr.open 'GET', url, true
xhr.overrideMimeType 'text/plain' if 'overrideMimeType' of xhr
xhr.onreadystatechange = ->
grind xhr.responseText if xhr.readyState is 4
xhr.send null
processScripts = ->
for tag in document.getElementsByTagName('script') when tag.type is 'text/coffeescript'
eval exports.compile tag.innerHTML
for script in document.getElementsByTagName 'script'
if script.type is 'text/coffeescript'
if script.src
grindRemote script.src
else
grind script.innerHTML
null
if window.addEventListener
window.addEventListener 'load', processScripts, false
else if window.attachEvent
window.attachEvent 'onload', processScripts
addEventListener 'DOMContentLoaded', processScripts, false
else
attachEvent 'onload', processScripts

View File

@@ -44,7 +44,7 @@ SWITCHES = [
]
# Top-level objects shared by all the functions.
options = {}
opts = {}
sources = []
optionParser = null
@@ -53,18 +53,18 @@ optionParser = null
# `--` will be passed verbatim to your script as arguments in `process.argv`
exports.run = ->
parseOptions()
return usage() if options.help
return version() if options.version
return require './repl' if options.interactive
return compileStdio() if options.stdio
return compileScript 'console', sources[0] if options.eval
return usage() if opts.help
return version() if opts.version
return require './repl' if opts.interactive
return compileStdio() if opts.stdio
return compileScript 'console', sources[0] if opts.eval
return require './repl' unless sources.length
separator = sources.indexOf '--'
flags = []
if separator >= 0
flags = sources[(separator + 1)...sources.length]
sources = sources[0...separator]
if options.run
if opts.run
flags = sources[1..sources.length].concat flags
sources = [sources[0]]
process.ARGV = process.argv = flags
@@ -86,35 +86,37 @@ compileScripts = ->
compile path.join(source, file)
else if topLevel or path.extname(source) is '.coffee'
fs.readFile source, (err, code) -> compileScript(source, code.toString(), base)
watch source, base if options.watch
watch source, base if opts.watch
compile source, true
# Compile a single source script, containing the given code, according to the
# requested options. If evaluating the script directly sets `__filename`,
# `__dirname` and `module.filename` to be correct relative to the script's path.
compileScript = (source, code, base) ->
o = options
codeOpts = compileOptions source
compileScript = (file, input, base) ->
o = opts
options = compileOptions file
if o.require
require fs.realpathSync file for file in o.require
require(if helpers.starts(file, '.') then fs.realpathSync(file) else file) for file in o.require
try
CoffeeScript.emit 'compile', {source, code, base, options}
if o.tokens then printTokens CoffeeScript.tokens code
else if o.nodes then puts CoffeeScript.nodes(code).toString()
else if o.run then CoffeeScript.run code, codeOpts
t = task = {file, input, options}
CoffeeScript.emit 'compile', task
if o.tokens then printTokens CoffeeScript.tokens t.input
else if o.nodes then puts CoffeeScript.nodes(t.input).toString()
else if o.run then CoffeeScript.run t.input, t.options
else
js = CoffeeScript.compile code, codeOpts
CoffeeScript.emit 'success', js
if o.print then print js
else if o.compile then writeJs source, js, base
else if o.lint then lint js
t.output = CoffeeScript.compile t.input, t.options
CoffeeScript.emit 'success', task
if o.print then print t.output
else if o.compile then writeJs t.file, t.output, base
else if o.lint then lint t.output
catch err
# Avoid using 'error' as it is a special event -- if there is no handler,
# node will print a stack trace and exit the program.
CoffeeScript.emit 'failure', err
CoffeeScript.emit 'failure', err, task
return if CoffeeScript.listeners('failure').length
error(err.stack) and process.exit 1 unless o.watch
puts err.message
return puts err.message if o.watch
error err.stack
process.exit 1
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
# and write them back to **stdout**.
@@ -141,20 +143,21 @@ writeJs = (source, js, base) ->
filename = path.basename(source, path.extname(source)) + '.js'
srcDir = path.dirname source
baseDir = srcDir.substring base.length
dir = if options.output then path.join options.output, baseDir else srcDir
dir = if opts.output then path.join opts.output, baseDir else srcDir
jsPath = path.join dir, filename
compile = ->
js = ' ' if js.length <= 0
fs.writeFile jsPath, js, (err) ->
puts "Compiled #{source}" if options.compile and options.watch
puts "Compiled #{source}" if opts.compile and opts.watch
path.exists dir, (exists) ->
if exists then compile() else exec "mkdir -p #{dir}", compile
# Pipe compiled JS through JSLint (requires a working `jsl` command), printing
# any errors or warnings that arise.
lint = (js) ->
printIt = (buffer) -> print buffer.toString()
jsl = spawn 'jsl', ['-nologo', '-stdin']
printIt = (buffer) -> puts buffer.toString().trim()
conf = __dirname + '/../extras/jsl.conf'
jsl = spawn 'jsl', ['-nologo', '-stdin', '-conf', conf]
jsl.stdout.on 'data', printIt
jsl.stderr.on 'data', printIt
jsl.stdin.write js
@@ -170,17 +173,17 @@ printTokens = (tokens) ->
# Use the [OptionParser module](optparse.html) to extract all options from
# `process.argv` that are specified in `SWITCHES`.
parseOptions = ->
optionParser = new optparse.OptionParser SWITCHES, BANNER
o = options = optionParser.parse(process.argv[2...process.argv.length])
options.compile or= !!o.output
options.run = not (o.compile or o.print or o.lint)
options.print = !! (o.print or (o.eval or o.stdio and o.compile))
sources = options.arguments
optionParser = new optparse.OptionParser SWITCHES, BANNER
o = opts = optionParser.parse(process.argv[2...process.argv.length])
o.compile or= !!o.output
o.run = not (o.compile or o.print or o.lint)
o.print = !! (o.print or (o.eval or o.stdio and o.compile))
sources = o.arguments
# The compile-time options to pass to the CoffeeScript compiler.
compileOptions = (fileName) ->
o = {fileName}
o.noWrap = options['no-wrap']
o.noWrap = opts['no-wrap']
o
# Print the `--help` usage message and exit.

View File

@@ -97,7 +97,6 @@ grammar =
o "Switch"
o "Extends"
o "Class"
o "Splat"
o "Existence"
o "Comment"
]
@@ -349,6 +348,10 @@ grammar =
Slice: [
o "INDEX_START Expression . . Expression INDEX_END", -> new RangeNode $2, $5
o "INDEX_START Expression . . . Expression INDEX_END", -> new RangeNode $2, $6, true
o "INDEX_START Expression . . INDEX_END", -> new RangeNode $2, null
o "INDEX_START Expression . . . INDEX_END", -> new RangeNode $2, null, true
o "INDEX_START . . Expression INDEX_END", -> new RangeNode null, $4
o "INDEX_START . . . Expression INDEX_END", -> new RangeNode null, $5, true
]
# The array literal.
@@ -361,12 +364,18 @@ grammar =
# (i.e. comma-separated expressions). Newlines work as well.
ArgList: [
o "", -> []
o "Expression", -> [$1]
o "ArgList , Expression", -> $1.concat [$3]
o "ArgList OptComma TERMINATOR Expression", -> $1.concat [$4]
o "Arg", -> [$1]
o "ArgList , Arg", -> $1.concat [$3]
o "ArgList OptComma TERMINATOR Arg", -> $1.concat [$4]
o "ArgList OptComma INDENT ArgList OptComma OUTDENT", -> $1.concat $4
]
# Valid arguments are Expressions or Splats.
Arg: [
o "Expression"
o "Splat"
]
# Just simple, comma-separated, required arguments (no fancy syntax). We need
# this to be separate from the **ArgList** for use in **Switch** blocks, where
# having the newlines wouldn't make sense.
@@ -399,6 +408,7 @@ grammar =
# the trick.
Parenthetical: [
o "( Line )", -> new ParentheticalNode $2
o "( )", -> new ParentheticalNode new LiteralNode ''
]
# The condition portion of a while loop.
@@ -507,10 +517,10 @@ grammar =
# *if* and *unless*.
If: [
o "IfBlock"
o "Statement IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
o "Expression IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
o "Statement UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
o "Expression UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
o "Statement POST_IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
o "Expression POST_IF Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true
o "Statement POST_UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
o "Expression POST_UNLESS Expression", -> new IfNode $3, Expressions.wrap([$1]), statement: true, invert: true
]
# Arithmetic and logical operators, working on one or more operands.
@@ -520,58 +530,34 @@ grammar =
# -type rule, but in order to make the precedence binding possible, separate
# rules are necessary.
Operation: [
o "! Expression", -> new OpNode '!', $2
o "!! Expression", -> new OpNode '!!', $2
o("- Expression", (-> new OpNode('-', $2)), {prec: 'UMINUS'})
o("+ Expression", (-> new OpNode('+', $2)), {prec: 'UPLUS'})
o "~ Expression", -> new OpNode '~', $2
o "UNARY Expression", -> new OpNode $1, $2
o("- Expression", (-> new OpNode('-', $2)), {prec: 'UNARY'})
o("+ Expression", (-> new OpNode('+', $2)), {prec: 'UNARY'})
o "-- Expression", -> new OpNode '--', $2
o "++ Expression", -> new OpNode '++', $2
o "DELETE Expression", -> new OpNode 'delete', $2
o "TYPEOF Expression", -> new OpNode 'typeof', $2
o "Expression --", -> new OpNode '--', $1, null, true
o "Expression ++", -> new OpNode '++', $1, null, true
o "Expression * Expression", -> new OpNode '*', $1, $3
o "Expression / Expression", -> new OpNode '/', $1, $3
o "Expression % Expression", -> new OpNode '%', $1, $3
o "Expression ? Expression", -> new OpNode '?', $1, $3
o "Expression + Expression", -> new OpNode '+', $1, $3
o "Expression - Expression", -> new OpNode '-', $1, $3
o "Expression << Expression", -> new OpNode '<<', $1, $3
o "Expression >> Expression", -> new OpNode '>>', $1, $3
o "Expression >>> Expression", -> new OpNode '>>>', $1, $3
o "Expression & Expression", -> new OpNode '&', $1, $3
o "Expression | Expression", -> new OpNode '|', $1, $3
o "Expression ^ Expression", -> new OpNode '^', $1, $3
o "Expression <= Expression", -> new OpNode '<=', $1, $3
o "Expression < Expression", -> new OpNode '<', $1, $3
o "Expression > Expression", -> new OpNode '>', $1, $3
o "Expression >= Expression", -> new OpNode '>=', $1, $3
o "Expression == Expression", -> new OpNode '==', $1, $3
o "Expression != Expression", -> new OpNode '!=', $1, $3
o "Expression && Expression", -> new OpNode '&&', $1, $3
o "Expression || Expression", -> new OpNode '||', $1, $3
o "Expression OP? Expression", -> new OpNode '?', $1, $3
o "Expression MATH Expression", -> new OpNode $2, $1, $3
o "Expression SHIFT Expression", -> new OpNode $2, $1, $3
o "Expression COMPARE Expression", -> new OpNode $2, $1, $3
o "Expression LOGIC Expression", -> new OpNode $2, $1, $3
o "Value COMPOUND_ASSIGN Expression", -> new OpNode $2, $1, $3
o "Value COMPOUND_ASSIGN INDENT Expression OUTDENT", -> new OpNode $2, $1, $4
o "Expression -= Expression", -> new OpNode '-=', $1, $3
o "Expression += Expression", -> new OpNode '+=', $1, $3
o "Expression /= Expression", -> new OpNode '/=', $1, $3
o "Expression *= Expression", -> new OpNode '*=', $1, $3
o "Expression %= Expression", -> new OpNode '%=', $1, $3
o "Expression ||= Expression", -> new OpNode '||=', $1, $3
o "Expression &&= Expression", -> new OpNode '&&=', $1, $3
o "Expression ?= Expression", -> new OpNode '?=', $1, $3
o "Expression INSTANCEOF Expression", -> new OpNode 'instanceof', $1, $3
o "Expression IN Expression", -> new InNode $1, $3
o "Expression OF Expression", -> new OpNode 'in', $1, $3
o "Expression ! IN Expression", -> new OpNode '!', new InNode $1, $4
o "Expression ! OF Expression", -> new OpNode '!', new ParentheticalNode new OpNode 'in', $1, $4
o "Expression INSTANCEOF Expression", -> new OpNode 'instanceof', $1, $3
o "Expression UNARY IN Expression", -> new OpNode $2, new InNode $1, $4
o "Expression UNARY OF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'in', $1, $4
o "Expression UNARY INSTANCEOF Expression", -> new OpNode $2, new ParentheticalNode new OpNode 'instanceof', $1, $4
]
@@ -587,25 +573,23 @@ grammar =
#
# (2 + 3) * 4
operators = [
["left", '?']
["nonassoc", 'UMINUS', 'UPLUS', '!', '!!', '~', '++', '--']
["left", '*', '/', '%']
["right", '?', 'NEW']
["nonassoc", '++', '--']
["right", 'UNARY']
["left", 'MATH']
["left", '+', '-']
["left", '<<', '>>', '>>>']
["left", '&', '|', '^']
["left", '<=', '<', '>', '>=']
["right", 'DELETE', 'INSTANCEOF', 'TYPEOF']
["left", 'SHIFT']
["left", 'COMPARE']
["left", 'INSTANCEOF']
["left", '==', '!=']
["left", '&&', '||', 'OP?']
["right", '-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=']
["left", 'LOGIC']
["right", 'COMPOUND_ASSIGN']
["left", '.']
["right", 'INDENT']
["left", 'OUTDENT']
["nonassoc", 'INDENT', 'OUTDENT']
["right", 'WHEN', 'LEADING_WHEN', 'IN', 'OF', 'BY', 'THROW']
["right", 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'NEW', 'SUPER', 'CLASS']
["left", 'EXTENDS']
["right", 'IF', 'UNLESS', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS', 'EXTENDS']
["right", '=', ':', 'RETURN']
["right", '->', '=>', 'UNLESS', 'IF', 'ELSE']
["right", '->', '=>', 'UNLESS', 'POST_IF', 'POST_UNLESS']
]
# Wrapping Up
@@ -627,9 +611,8 @@ for name, alternatives of grammar
# rules, and the name of the root. Reverse the operators because Jison orders
# precedence from low to high, and we have it high to low
# (as in [Yacc](http://dinosaur.compilertools.net/yacc/index.html)).
exports.parser = new Parser {
exports.parser = new Parser
tokens: tokens.join ' '
bnf: grammar
operators: operators.reverse()
startSymbol: 'Root'
}

View File

@@ -50,7 +50,7 @@ exports.Lexer = class Lexer
@indents = [] # The stack of all current indentation levels.
@tokens = [] # Stream of parsed tokens in the form ['TYPE', value, line]
while @i < @code.length
@chunk = @code.slice @i
@chunk = @code[@i..]
@extractNextToken()
@closeIndentation()
return @tokens if o.rewrite is off
@@ -88,6 +88,7 @@ exports.Lexer = class Lexer
tag = id.toUpperCase() if include(JS_KEYWORDS, id) or (not forcedIdentifier and include(COFFEE_KEYWORDS, id))
tag = 'LEADING_WHEN' if tag is 'WHEN' and include LINE_BREAK, @tag()
tag = 'ALL' if id is 'all' and @tag() is 'FOR'
tag = 'UNARY' if include UNARY, tag
if include(JS_FORBIDDEN, id)
if forcedIdentifier
tag = 'STRING'
@@ -100,6 +101,8 @@ exports.Lexer = class Lexer
@identifierError id
unless forcedIdentifier
tag = id = CONVERSIONS[id] if include COFFEE_ALIASES, id
tag = 'LOGIC' if include LOGIC, id
tag = 'UNARY' if id is '!'
@token tag, id
@token ']', ']' if close_index
true
@@ -120,7 +123,7 @@ exports.Lexer = class Lexer
return false unless string =
@balancedToken(['"', '"'], ['#{', '}']) or
@balancedToken ["'", "'"]
@interpolateString string.replace STRING_NEWLINES, " \\\n"
@interpolateString string.replace /\n/g, '\\\n'
@line += count string, "\n"
@i += string.length
true
@@ -141,9 +144,8 @@ exports.Lexer = class Lexer
return false unless match = @chunk.match(COMMENT)
@line += count match[1], "\n"
@i += match[1].length
if match[2]
comment = @sanitizeHeredoc match[2], herecomment: true
@token 'HERECOMMENT', comment.split MULTILINER
if match[4]
@token 'HERECOMMENT', @sanitizeHeredoc match[4], herecomment: true, indent: match[3]
@token 'TERMINATOR', '\n'
true
@@ -160,7 +162,8 @@ exports.Lexer = class Lexer
# JavaScript and Ruby, borrow slash balancing from `@balancedToken`, and
# borrow interpolation from `@interpolateString`.
regexToken: ->
return false unless @chunk.match REGEX_START
return false unless first = @chunk.match REGEX_START
return false if first[1] is ' ' and @tag() not in ['CALL_START', '=']
return false if include NOT_REGEX, @tag()
return false unless regex = @balancedToken ['/', '/']
return false unless end = @chunk.substr(regex.length).match REGEX_END
@@ -205,10 +208,10 @@ exports.Lexer = class Lexer
return @newlineToken indent
else if size > @indent
return @suppressNewlines() if noNewlines
@outdebt = 0
diff = size - @indent
diff = size - @indent + @outdebt
@token 'INDENT', diff
@indents.push diff
@outdebt = 0
else
@outdentToken @indent - size, noNewlines
@indent = size
@@ -269,17 +272,21 @@ exports.Lexer = class Lexer
@tagParameters() if value and value.match CODE
value or= @chunk.substr 0, 1
@i += value.length
prevSpaced = @prev() and @prev().spaced
spaced = @prev() and @prev().spaced
tag = value
if value is '='
@assignmentError() if include JS_FORBIDDEN, @value()
if @value() in ['or', 'and']
return @tag 1, CONVERSIONS[@value()] + '='
if value is ';'
tag = 'TERMINATOR'
else if value is '?' and prevSpaced
tag = 'OP?'
else if include(CALLABLE, @tag()) and not prevSpaced
@tokens.splice(@tokens.length - 1, 1, ['COMPOUND_ASSIGN', CONVERSIONS[@value()] + '=', @prev()[2]])
return true
if value is ';' then tag = 'TERMINATOR'
else if include(LOGIC, value) then tag = 'LOGIC'
else if include(MATH, value) then tag = 'MATH'
else if include(COMPARE, value) then tag = 'COMPARE'
else if include(COMPOUND_ASSIGN, value) then tag = 'COMPOUND_ASSIGN'
else if include(UNARY, value) then tag = 'UNARY'
else if include(SHIFT, value) then tag = 'SHIFT'
else if include(CALLABLE, @tag()) and not spaced
if value is '('
tag = 'CALL_START'
else if value is '['
@@ -312,10 +319,13 @@ exports.Lexer = class Lexer
# Sanitize a heredoc or herecomment by escaping internal double quotes and
# erasing all external indentation on the left-hand side.
sanitizeHeredoc: (doc, options) ->
while (match = HEREDOC_INDENT.exec(doc))
attempt = if match[2]? then match[2] else match[3]
indent = attempt if not indent or attempt.length < indent.length
doc = doc.replace(new RegExp("^" +indent, 'gm'), '')
indent = options.indent or ''
return doc if options.herecomment and not include doc, '\n'
unless options.herecomment
while match = HEREDOC_INDENT.exec(doc)
attempt = if match[2]? then match[2] else match[3]
indent = attempt if not indent or attempt.length < indent.length
doc = doc.replace(new RegExp("^" + indent, 'gm'), '')
return doc if options.herecomment
doc.replace(MULTILINER, "\\n")
.replace(new RegExp(options.quote, 'g'), "\\#{options.quote}")
@@ -511,16 +521,16 @@ JS_FORBIDDEN = JS_KEYWORDS.concat RESERVED
IDENTIFIER = /^([a-zA-Z\$_](\w|\$)*)/
NUMBER = /^(((\b0(x|X)[0-9a-fA-F]+)|((\b[0-9]+(\.[0-9]+)?|\.[0-9]+)(e[+\-]?[0-9]+)?)))\b/i
HEREDOC = /^("{6}|'{6}|"{3}\n?([\s\S]*?)\n?([ \t]*)"{3}|'{3}\n?([\s\S]*?)\n?([ \t]*)'{3})/
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>:!?]+)([ \t]*)/
OPERATOR = /^(-[\-=>]?|\+[+=]?|[*&|\/%=<>^:!?]+)([ \t]*)/
WHITESPACE = /^([ \t]+)/
COMMENT = /^(\s*\#{3}(?!#)[ \t]*\n+([\s\S]*?)[ \t]*\n+[ \t]*\#{3}|(\s*#(?!##[^#])[^\n]*)+)/
COMMENT = /^(([ \t]*\n)*([ \t]*)###([^#][\s\S]*?)(###[ \t]*\n|(###)?$)|(\s*#(?!##[^#])[^\n]*)+)/
CODE = /^((-|=)>)/
MULTI_DENT = /^((\n([ \t]*))+)(\.)?/
LAST_DENTS = /\n([ \t]*)/g
LAST_DENT = /\n([ \t]*)/
# Regex-matching-regexes.
REGEX_START = /^\/[^\/ ]/
REGEX_START = /^\/([^\/])/
REGEX_INTERPOLATION = /([^\\]#\{.*[^\\]\})/
REGEX_END = /^(([imgy]{1,4})\b|\W|$)/
REGEX_ESCAPE = /\\[^\$]/g
@@ -528,12 +538,29 @@ REGEX_ESCAPE = /\\[^\$]/g
# Token cleaning regexes.
JS_CLEANER = /(^`|`$)/g
MULTILINER = /\n/g
STRING_NEWLINES = /\n[ \t]*/g
NO_NEWLINE = /^([+\*&|\/\-%=<>!.\\][<>=&|]*|and|or|is|isnt|not|delete|typeof|instanceof)$/
HEREDOC_INDENT = /(\n+([ \t]*)|^([ \t]+))/g
ASSIGNED = /^\s*([a-zA-Z\$_@]\w*[ \t]*?[:=][^=])/
ASSIGNED = /^\s*(([a-zA-Z\$_@]\w*|["'][^\r\n]+?["']|\d+)[ \t]*?[:=][^=])/
NEXT_CHARACTER = /^\s*(\S)/
# Compound assignment tokens.
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|=']
# Unary tokens.
UNARY = ['UMINUS', 'UPLUS', '!', '!!', '~', 'TYPEOF', 'DELETE']
# Logical tokens.
LOGIC = ['&', '|', '^', '&&', '||']
# Bit-shifting tokens.
SHIFT = ['<<', '>>', '>>>']
# Comparison tokens.
COMPARE = ['<=', '<', '>', '>=']
# Mathmatical tokens.
MATH = ['*', '/', '%']
# Tokens which a regular expression will never immediately follow, but which
# a division operator might.
#
@@ -553,11 +580,10 @@ CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING', '@', 'THIS', '?', ':
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']
# Conversions from CoffeeScript operators into JavaScript ones.
CONVERSIONS = {
CONVERSIONS =
'and': '&&'
'or': '||'
'is': '=='
'isnt': '!='
'not': '!'
'===': '=='
}

View File

@@ -29,6 +29,9 @@ else
# scope, and indentation level.
exports.BaseNode = class BaseNode
constructor: ->
@tags = {}
# 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
# *statement*, and it's not a *pureStatement*, and we're not at
@@ -42,12 +45,10 @@ exports.BaseNode = class BaseNode
compile: (o) ->
@options = merge o or {}
@tab = o.indent
unless this instanceof ValueNode or this instanceof CallNode
del @options, 'operation'
del @options, 'chainRoot' unless this instanceof AccessorNode or this instanceof IndexNode
del @options, 'chainRoot' unless this instanceof AccessorNode or this instanceof IndexNode
top = if @topSensitive() then @options.top else del @options, 'top'
closure = @isStatement() and not @isPureStatement() and not top and
not @options.asStatement and not (this instanceof CommentNode) and
closure = @isStatement(o) and not @isPureStatement() and not top and
not @options.asStatement and this not instanceof CommentNode and
not @containsPureStatement()
if closure then @compileClosure(@options) else @compileNode(@options)
@@ -157,6 +158,7 @@ exports.Expressions = class Expressions extends BaseNode
isStatement: -> yes
constructor: (nodes) ->
super()
@expressions = compact flatten nodes or []
# Tack an expression on to the end of this expression list.
@@ -221,7 +223,7 @@ exports.Expressions = class Expressions extends BaseNode
compileExpression: (node, o) ->
@tab = o.indent
compiledNode = node.compile merge o, top: true
if node.isStatement() then compiledNode else "#{@idt()}#{compiledNode};"
if node.isStatement(o) then compiledNode else "#{@idt()}#{compiledNode};"
# Wrap up the given nodes as an **Expressions**, unless it already happens
# to be one.
@@ -239,6 +241,7 @@ exports.LiteralNode = class LiteralNode extends BaseNode
class: 'LiteralNode'
constructor: (@value) ->
super()
makeReturn: ->
if @isStatement() then this else super()
@@ -250,8 +253,8 @@ exports.LiteralNode = class LiteralNode extends BaseNode
isPureStatement: LiteralNode::isStatement
compileNode: (o) ->
idt = if @isStatement() then @idt() else ''
end = if @isStatement() then ';' else ''
idt = if @isStatement(o) then @idt() else ''
end = if @isStatement(o) then ';' else ''
idt + @value + end
toString: (idt) ->
@@ -269,6 +272,7 @@ exports.ReturnNode = class ReturnNode extends BaseNode
children: ['expression']
constructor: (@expression) ->
super()
makeReturn: ->
this
@@ -279,7 +283,7 @@ exports.ReturnNode = class ReturnNode extends BaseNode
super o
compileNode: (o) ->
o.asStatement = true if @expression.isStatement()
o.asStatement = true if @expression.isStatement(o)
"#{@tab}return #{@expression.compile(o)};"
#### ValueNode
@@ -288,13 +292,12 @@ exports.ReturnNode = class ReturnNode extends BaseNode
# or vanilla.
exports.ValueNode = class ValueNode extends BaseNode
SOAK: " == undefined ? undefined : "
class: 'ValueNode'
children: ['base', 'properties']
# A **ValueNode** has a base and a list of property accesses.
constructor: (@base, @properties) ->
super()
@properties or= []
# Add a property access to the list.
@@ -325,24 +328,17 @@ exports.ValueNode = class ValueNode extends BaseNode
if @properties.length then this else @base
# Values are considered to be statements if their base is a statement.
isStatement: ->
@base.isStatement and @base.isStatement() and not @hasProperties()
isStatement: (o) ->
@base.isStatement and @base.isStatement(o) and not @hasProperties()
isNumber: ->
@base instanceof LiteralNode and @base.value.match NUMBER
# Works out if the value is the start of a chain.
isStart: (o) ->
return true if this is o.chainRoot and @properties[0] instanceof AccessorNode
node = o.chainRoot.base or o.chainRoot.variable
while node instanceof CallNode then node = node.variable
node is this
# If the value node has indexes containing function calls, and the value node
# needs to be used twice, in compound assignment ... then we need to cache
# the value of the indexes.
cacheIndexes: (o) ->
copy = new ValueNode @base, @properties.slice 0
copy = new ValueNode @base, @properties[0..]
for prop, i in copy.properties
if prop instanceof IndexNode and prop.contains((n) -> n instanceof CallNode)
[index, indexVar] = prop.index.compileReference o
@@ -360,9 +356,10 @@ exports.ValueNode = class ValueNode extends BaseNode
# evaluate a anything twice when building the soak chain.
compileNode: (o) ->
only = del o, 'onlyFirst'
op = del o, 'operation'
op = @tags.operation
props = if only then @properties[0...@properties.length - 1] else @properties
o.chainRoot or= this
@base.parenthetical = yes if @parenthetical and not props.length
baseline = @base.compile o
baseline = "(#{baseline})" if @hasProperties() and (@base instanceof ObjectNode or @isNumber())
complete = @last = baseline
@@ -373,8 +370,11 @@ exports.ValueNode = class ValueNode extends BaseNode
if @base instanceof CallNode or @base.contains((n) -> n instanceof CallNode) and i is 0
temp = o.scope.freeVariable()
complete = "(#{ baseline = temp } = (#{complete}))"
complete = "typeof #{complete} === \"undefined\" || #{baseline}" if i is 0 and @isStart(o)
complete += @SOAK + (baseline += prop.compile(o))
complete = if i is 0
"(typeof #{complete} === \"undefined\" || #{baseline} === null) ? undefined : "
else
"#{complete} == null ? undefined : "
complete += (baseline += prop.compile(o))
else
part = prop.compile(o)
baseline += part
@@ -392,14 +392,14 @@ exports.CommentNode = class CommentNode extends BaseNode
class: 'CommentNode'
isStatement: -> yes
constructor: (@lines) ->
constructor: (@comment) ->
super()
makeReturn: ->
this
compileNode: (o) ->
sep = '\n' + @tab
"#{@tab}/*#{sep + @lines.join(sep) }\n#{@tab}*/"
@tab + '/*' + @comment.replace(/\r?\n/g, '\n' + @tab) + '*/'
#### CallNode
@@ -411,6 +411,7 @@ exports.CallNode = class CallNode extends BaseNode
children: ['variable', 'args']
constructor: (variable, @args) ->
super()
@isNew = false
@isSuper = variable is 'super'
@variable = if @isSuper then null else variable
@@ -430,9 +431,9 @@ exports.CallNode = class CallNode extends BaseNode
superReference: (o) ->
methname = o.scope.method.name
meth = if o.scope.method.proto
"#{o.scope.method.proto}.__superClass__.#{methname}"
"#{o.scope.method.proto}.__super__.#{methname}"
else if methname
"#{methname}.__superClass__.constructor"
"#{methname}.__super__.constructor"
else throw new Error "cannot call super on an anonymous function."
# Compile a vanilla function call.
@@ -440,11 +441,15 @@ exports.CallNode = class CallNode extends BaseNode
o.chainRoot = this unless o.chainRoot
for arg in @args when arg instanceof SplatNode
compilation = @compileSplat(o)
unless compilation
args = (arg.compile(o) for arg in @args).join(', ')
compilation = if @isSuper then @compileSuper(args, o)
else "#{@prefix()}#{@variable.compile(o)}(#{args})"
if o.operation and @wrapped then "(#{compilation})" else compilation
if not compilation
args = for arg in @args
arg.parenthetical = true
arg.compile o
compilation = if @isSuper
@compileSuper(args.join(', '), o)
else
"#{@prefix()}#{@variable.compile(o)}(#{ args.join(', ') })"
compilation
# `super()` is converted into a call against the superclass's implementation
# of the current function.
@@ -485,6 +490,7 @@ exports.ExtendsNode = class ExtendsNode extends BaseNode
children: ['child', 'parent']
constructor: (@child, @parent) ->
super()
# Hooks one constructor into another's prototype chain.
compileNode: (o) ->
@@ -501,6 +507,7 @@ exports.AccessorNode = class AccessorNode extends BaseNode
children: ['name']
constructor: (@name, tag) ->
super()
@prototype = if tag is 'prototype' then '.prototype' else ''
@soakNode = tag is 'soak'
@@ -519,6 +526,7 @@ exports.IndexNode = class IndexNode extends BaseNode
children: ['index']
constructor: (@index) ->
super()
compileNode: (o) ->
o.chainRoot.wrapped or= @soakNode
@@ -537,6 +545,7 @@ exports.RangeNode = class RangeNode extends BaseNode
children: ['from', 'to']
constructor: (@from, @to, exclusive) ->
super()
@exclusive = !!exclusive
@equals = if @exclusive then '' else '='
@@ -608,12 +617,14 @@ exports.SliceNode = class SliceNode extends BaseNode
children: ['range']
constructor: (@range) ->
super()
compileNode: (o) ->
from = @range.from.compile(o)
to = @range.to.compile(o)
plusPart = if @range.exclusive then '' else ' + 1'
".slice(#{from}, #{to}#{plusPart})"
from = if @range.from then @range.from.compile(o) else '0'
to = if @range.to then @range.to.compile(o) else ''
to += if not to or @range.exclusive then '' else ' + 1'
to = ', ' + to if to
".slice(#{from}#{to})"
#### ObjectNode
@@ -626,12 +637,13 @@ exports.ObjectNode = class ObjectNode extends BaseNode
topSensitive: -> true
constructor: (props) ->
super()
@objects = @properties = props or []
compileNode: (o) ->
top = del o, 'top'
o.indent = @idt 1
nonComments = prop for prop in @properties when not (prop instanceof CommentNode)
nonComments = prop for prop in @properties when (prop not instanceof CommentNode)
lastNoncom = nonComments[nonComments.length - 1]
props = for prop, i in @properties
join = ",\n"
@@ -653,6 +665,7 @@ exports.ArrayNode = class ArrayNode extends BaseNode
children: ['objects']
constructor: (@objects) ->
super()
@objects or= []
@compileSplatLiteral = (o) ->
SplatNode.compileSplattedArray.call(this, @objects, o)
@@ -688,6 +701,7 @@ exports.ClassNode = class ClassNode extends BaseNode
# Initialize a **ClassNode** with its name, an optional superclass, and a
# list of prototype property assignments.
constructor: (@variable, @parent, @properties) ->
super()
@properties or= []
@returns = false
@@ -726,12 +740,15 @@ exports.ClassNode = class ClassNode extends BaseNode
constructor = func
continue
if func instanceof CodeNode and func.bound
func.bound = false
constScope or= new Scope(o.scope, constructor.body, constructor)
me or= constScope.freeVariable()
pname = pvar.compile(o)
constructor.body.push new ReturnNode literal 'this' if constructor.body.empty()
constructor.body.unshift literal "this.#{pname} = function(){ return #{className}.prototype.#{pname}.apply(#{me}, arguments); }"
if prop.context is 'this'
func.context = className
else
func.bound = false
constScope or= new Scope(o.scope, constructor.body, constructor)
me or= constScope.freeVariable()
pname = pvar.compile(o)
constructor.body.push new ReturnNode literal 'this' if constructor.body.empty()
constructor.body.unshift literal "this.#{pname} = function(){ return #{className}.prototype.#{pname}.apply(#{me}, arguments); }"
if pvar
access = if prop.context is 'this' then pvar.base.properties[0] else new AccessorNode(pvar, 'prototype')
val = new ValueNode(@variable, [access])
@@ -759,6 +776,7 @@ exports.AssignNode = class AssignNode extends BaseNode
children: ['variable', 'value']
constructor: (@variable, @value, @context) ->
super()
topSensitive: ->
true
@@ -781,7 +799,7 @@ exports.AssignNode = class AssignNode extends BaseNode
# has not been seen yet within the current scope, declare it.
compileNode: (o) ->
top = del o, 'top'
return @compilePatternMatch(o) if @isStatement()
return @compilePatternMatch(o) if @isStatement(o)
return @compileSplice(o) if @isValue() and @variable.isSplice()
stmt = del o, 'asStatement'
name = @variable.compile(o)
@@ -796,7 +814,7 @@ exports.AssignNode = class AssignNode extends BaseNode
o.scope.find name unless @isValue() and (@variable.hasProperties() or @variable.namespaced)
val = "#{name} = #{val}"
return "#{@tab}#{val};" if stmt
if top then val else "(#{val})"
if top or @parenthetical then val else "(#{val})"
# Brief implementation of recursive pattern matching, when assigning array or
# object literals to a value. Peeks at their properties to assign inner names.
@@ -804,7 +822,7 @@ exports.AssignNode = class AssignNode extends BaseNode
# for details.
compilePatternMatch: (o) ->
valVar = o.scope.freeVariable()
value = if @value.isStatement() then ClosureNode.wrap(@value) else @value
value = if @value.isStatement(o) then ClosureNode.wrap(@value) else @value
assigns = ["#{@tab}#{valVar} = #{ value.compile(o) };"]
o.top = true
o.asStatement = true
@@ -842,8 +860,8 @@ exports.AssignNode = class AssignNode extends BaseNode
l = @variable.properties.length
range = @variable.properties[l - 1].range
plus = if range.exclusive then '' else ' + 1'
from = range.from.compile(o)
to = range.to.compile(o) + ' - ' + from + plus
from = if range.from then range.from.compile(o) else '0'
to = if range.to then range.to.compile(o) + ' - ' + from + plus else "#{name}.length"
val = @value.compile(o)
"#{name}.splice.apply(#{name}, [#{from}, #{to}].concat(#{val}))"
@@ -858,9 +876,11 @@ exports.CodeNode = class CodeNode extends BaseNode
children: ['params', 'body']
constructor: (@params, @body, tag) ->
@params or= []
@body or= new Expressions
@bound = tag is 'boundfunc'
super()
@params or= []
@body or= new Expressions
@bound = tag is 'boundfunc'
@context = 'this' if @bound
# Compilation creates a new scope unless explicitly asked to share with the
# outer scope. Handles splat parameters in the parameter list by peeking at
@@ -902,7 +922,7 @@ exports.CodeNode = class CodeNode extends BaseNode
(o.scope.parameter(param)) for param in params
code = if @body.expressions.length then "\n#{ @body.compileWithDeclarations(o) }\n" else ''
func = "function(#{ params.join(', ') }) {#{code}#{ code and @tab }}"
return "#{utility('bind')}(#{func}, this)" if @bound
return "#{utility('bind')}(#{func}, #{@context})" if @bound
if top then "(#{func})" else func
topSensitive: ->
@@ -928,6 +948,7 @@ exports.ParamNode = class ParamNode extends BaseNode
children: ['name']
constructor: (@name, @attach, @splat) ->
super()
@value = literal @name
compileNode: (o) ->
@@ -946,6 +967,7 @@ exports.SplatNode = class SplatNode extends BaseNode
children: ['name']
constructor: (name) ->
super()
name = literal(name) unless name.compile
@name = name
@@ -986,7 +1008,7 @@ exports.SplatNode = class SplatNode extends BaseNode
for arg, i in list
code = arg.compile o
prev = args[last = args.length - 1]
if not (arg instanceof SplatNode)
if arg not instanceof SplatNode
if prev and starts(prev, '[') and ends(prev, ']')
args[last] = "#{prev.substr(0, prev.length - 1)}, #{code}]"
continue
@@ -1010,6 +1032,7 @@ exports.WhileNode = class WhileNode extends BaseNode
isStatement: -> yes
constructor: (condition, opts) ->
super()
if opts and opts.invert
condition = new ParentheticalNode condition if condition instanceof OpNode
condition = new OpNode('!', condition)
@@ -1034,6 +1057,7 @@ exports.WhileNode = class WhileNode extends BaseNode
top = del(o, 'top') and not @returns
o.indent = @idt 1
o.top = true
@condition.parenthetical = yes
cond = @condition.compile(o)
set = ''
unless top
@@ -1055,10 +1079,14 @@ exports.WhileNode = class WhileNode extends BaseNode
exports.OpNode = class OpNode extends BaseNode
# The map of conversions from CoffeeScript to JavaScript symbols.
CONVERSIONS: {
CONVERSIONS:
'==': '==='
'!=': '!=='
}
# The map of invertible operators.
INVERSIONS:
'!==': '==='
'===': '!=='
# The list of operators for which we perform
# [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin).
@@ -1074,26 +1102,41 @@ exports.OpNode = class OpNode extends BaseNode
children: ['first', 'second']
constructor: (@operator, @first, @second, flip) ->
super()
@operator = @CONVERSIONS[@operator] or @operator
@flip = !!flip
if @first instanceof ValueNode and @first.base instanceof ObjectNode
@first = new ParentheticalNode @first
@first.tags.operation = yes
@second.tags.operation = yes if @second
isUnary: ->
not @second
isInvertible: ->
(@operator in ['===', '!==']) and
not (@first instanceof OpNode) and not (@second instanceof OpNode)
isMutator: ->
ends(@operator, '=') and not (@operator in ['===', '!=='])
isChainable: ->
indexOf(@CHAINABLE, @operator) >= 0
include(@CHAINABLE, @operator)
invert: ->
@operator = @INVERSIONS[@operator]
toString: (idt) ->
super(idt, @class + ' ' + @operator)
compileNode: (o) ->
o.operation = true
return @compileChain(o) if @isChainable() and @first.unwrap() instanceof OpNode and @first.unwrap().isChainable()
return @compileAssignment(o) if indexOf(@ASSIGNMENT, @operator) >= 0
return @compileUnary(o) if @isUnary()
return @compileExistence(o) if @operator is '?'
@first = new ParentheticalNode(@first) if @first instanceof OpNode and @first.isMutator()
@second = new ParentheticalNode(@second) if @second instanceof OpNode and @second.isMutator()
[@first.compile(o), @operator, @second.compile(o)].join ' '
# Mimic Python's chained comparisons when multiple comparison operators are
@@ -1115,15 +1158,14 @@ exports.OpNode = class OpNode extends BaseNode
second = @second.compile o
second = "(#{second})" if @second instanceof OpNode
o.scope.find(first) if first.match(IDENTIFIER)
return "#{first} = #{ ExistenceNode.compileTest(o, literal(firstVar)) } ? #{firstVar} : #{second}" if @operator is '?='
"#{first} = #{firstVar} #{ @operator.substr(0, 2) } #{second}"
return "#{first} = #{ ExistenceNode.compileTest(o, literal(firstVar))[0] } ? #{firstVar} : #{second}" if @operator is '?='
"#{first} #{ @operator.substr(0, 2) } (#{firstVar} = #{second})"
# If this is an existence operator, we delegate to `ExistenceNode.compileTest`
# to give us the safe references for the variables.
compileExistence: (o) ->
[first, second] = [@first.compile(o), @second.compile(o)]
test = ExistenceNode.compileTest(o, @first)
"#{test} ? #{first} : #{second}"
[test, ref] = ExistenceNode.compileTest(o, @first)
"#{test} ? #{ref} : #{ @second.compile(o) }"
# Compile a unary **OpNode**.
compileUnary: (o) ->
@@ -1139,6 +1181,7 @@ exports.InNode = class InNode extends BaseNode
children: ['object', 'array']
constructor: (@object, @array) ->
super()
isArray: ->
@array instanceof ValueNode and @array.isArray()
@@ -1168,6 +1211,7 @@ exports.TryNode = class TryNode extends BaseNode
isStatement: -> yes
constructor: (@attempt, @error, @recovery, @ensure) ->
super()
makeReturn: ->
@attempt = @attempt.makeReturn() if @attempt
@@ -1195,6 +1239,7 @@ exports.ThrowNode = class ThrowNode extends BaseNode
isStatement: -> yes
constructor: (@expression) ->
super()
# A **ThrowNode** is already a return, of sorts...
makeReturn: ->
@@ -1214,16 +1259,18 @@ exports.ExistenceNode = class ExistenceNode extends BaseNode
children: ['expression']
constructor: (@expression) ->
super()
compileNode: (o) ->
ExistenceNode.compileTest(o, @expression)
test = ExistenceNode.compileTest(o, @expression)[0]
if @parenthetical then test.substring(1, test.length - 1) else test
# The meat of the **ExistenceNode** is in this static `compileTest` method
# because other nodes like to check the existence of their variables as well.
# Be careful not to double-evaluate anything.
@compileTest: (o, variable) ->
[first, second] = variable.compileReference o
"(typeof #{first.compile(o)} !== \"undefined\" && #{second.compile(o)} !== null)"
[first, second] = variable.compileReference o, precompile: yes
["(typeof #{first} !== \"undefined\" && #{second} !== null)", second]
#### ParentheticalNode
@@ -1238,9 +1285,10 @@ exports.ParentheticalNode = class ParentheticalNode extends BaseNode
children: ['expression']
constructor: (@expression) ->
super()
isStatement: ->
@expression.isStatement()
isStatement: (o) ->
@expression.isStatement(o)
makeReturn: ->
@expression.makeReturn()
@@ -1250,12 +1298,12 @@ exports.ParentheticalNode = class ParentheticalNode extends BaseNode
compileNode: (o) ->
top = del o, 'top'
@expression.parenthetical = true
code = @expression.compile(o)
if @isStatement()
return (if top then @tab + code + ';' else code)
l = code.length
code = code.substr(o, l-1) if code.substr(l-1, 1) is ';'
if @expression instanceof AssignNode then code else "(#{code})"
return code if top and @expression.isPureStatement o
if @parenthetical or @isStatement o
return if top then @tab + code + ';' else code
"(#{code})"
#### ForNode
@@ -1273,6 +1321,7 @@ exports.ForNode = class ForNode extends BaseNode
isStatement: -> yes
constructor: (@body, source, @name, @index) ->
super()
@index or= null
@source = source.source
@guard = source.guard
@@ -1365,8 +1414,12 @@ exports.IfNode = class IfNode extends BaseNode
topSensitive: -> true
constructor: (@condition, @body, @tags) ->
@tags or= {}
@condition = new OpNode('!', new ParentheticalNode(@condition)) if @tags.invert
@tags or= {}
if @tags.invert
if @condition instanceof OpNode and @condition.isInvertible()
@condition.invert()
else
@condition = new OpNode '!', new ParentheticalNode @condition
@elseBody = null
@isChain = false
@@ -1410,14 +1463,16 @@ exports.IfNode = class IfNode extends BaseNode
# The **IfNode** only compiles into a statement if either of its bodies needs
# to be a statement. Otherwise a ternary is safe.
isStatement: ->
@statement or= !!(@tags.statement or @bodyNode().isStatement() or (@elseBody and @elseBodyNode().isStatement()))
isStatement: (o) ->
@statement or= !!((o and o.top) or @tags.statement or @bodyNode().isStatement(o) or (@elseBody and @elseBodyNode().isStatement(o)))
compileCondition: (o) ->
(cond.compile(o) for cond in flatten([@condition])).join(' || ')
conditions = flatten [@condition]
conditions[0].parenthetical = yes if conditions.length is 1
(cond.compile(o) for cond in conditions).join(' || ')
compileNode: (o) ->
if o.top or @isStatement() then @compileStatement(o) else @compileTernary(o)
if @isStatement(o) then @compileStatement(o) else @compileTernary(o)
makeReturn: ->
if @isStatement()
@@ -1439,7 +1494,7 @@ exports.IfNode = class IfNode extends BaseNode
condO = merge o
o.indent = @idt 1
o.top = true
ifDent = if child or (top and not @isStatement()) then '' else @idt()
ifDent = if child or (top and not @isStatement(o)) then '' else @idt()
comDent = if child then @idt() else ''
body = @body.compile(o)
ifPart = "#{ifDent}if (#{ @compileCondition(condO) }) {\n#{body}\n#{@tab}}"
@@ -1452,10 +1507,12 @@ exports.IfNode = class IfNode extends BaseNode
# Compile the IfNode as a ternary operator.
compileTernary: (o) ->
o.operation = true
@bodyNode().tags.operation = @condition.tags.operation = yes
@elseBodyNode().tags.operation = yes if @elseBody
ifPart = @condition.compile(o) + ' ? ' + @bodyNode().compile(o)
elsePart = if @elseBody then @elseBodyNode().compile(o) else 'null'
"#{ifPart} : #{elsePart}"
code = "#{ifPart} : #{elsePart}"
if @tags.operation then "(#{code})" else code
# Faux-Nodes
# ----------
@@ -1466,8 +1523,7 @@ exports.IfNode = class IfNode extends BaseNode
# generation to generate other combinations of nodes. The **PushNode** creates
# the tree for `array.push(value)`, which is helpful for recording the result
# arrays from comprehensions.
PushNode = exports.PushNode = {
PushNode = exports.PushNode =
wrap: (array, expressions) ->
expr = expressions.unwrap()
return expressions if expr.isPureStatement() or expr.containsPureStatement()
@@ -1475,12 +1531,10 @@ PushNode = exports.PushNode = {
new ValueNode(literal(array), [new AccessorNode(literal('push'))]), [expr]
)])
}
#### ClosureNode
# A faux-node used to wrap an expressions body in a closure.
ClosureNode = exports.ClosureNode = {
ClosureNode = exports.ClosureNode =
# Wrap the expressions body, unless it contains a pure statement,
# in which case, no dice. If the body mentions `this` or `arguments`,
@@ -1502,12 +1556,10 @@ ClosureNode = exports.ClosureNode = {
call = new CallNode(func, args)
if statement then Expressions.wrap([call]) else call
}
# Utility Functions
# -----------------
UTILITIES = {
UTILITIES =
# Correctly set up a prototype chain for inheritance, including a reference
# to the superclass for `super()` calls. See:
@@ -1519,7 +1571,7 @@ UTILITIES = {
child.prototype = new ctor();
child.prototype.constructor = child;
if (typeof parent.extended === "function") parent.extended(child);
child.__superClass__ = parent.prototype;
child.__super__ = parent.prototype;
}
"""
@@ -1534,8 +1586,6 @@ UTILITIES = {
hasProp: 'Object.prototype.hasOwnProperty'
slice: 'Array.prototype.slice'
}
# Constants
# ---------

View File

@@ -36,6 +36,7 @@ exports.Rewriter = class Rewriter
@closeOpenIndexes()
@addImplicitIndentation()
@addImplicitBraces()
@tagPostfixConditionals()
@addImplicitParentheses()
@ensureBalance BALANCED_PAIRS
@rewriteClosingParens()
@@ -50,7 +51,7 @@ exports.Rewriter = class Rewriter
i = 0
loop
break unless @tokens[i]
move = block @tokens[i], i
move = block.call this, @tokens[i], i
i += move
true
@@ -68,7 +69,7 @@ exports.Rewriter = class Rewriter
# Massage newlines and indentations so that comments don't have to be
# correctly indented, or appear on a line of their own.
adjustComments: ->
@scanTokens (token, i) =>
@scanTokens (token, i) ->
return 1 unless token[0] is 'HERECOMMENT'
[before, prev, post, after] = [@tokens[i - 2], @tokens[i - 1], @tokens[i + 1], @tokens[i + 2]]
if after and after[0] is 'INDENT'
@@ -95,7 +96,7 @@ exports.Rewriter = class Rewriter
# Some blocks occur in the middle of expressions -- when we're expecting
# this, remove their trailing newlines.
removeMidExpressionNewlines: ->
@scanTokens (token, i) =>
@scanTokens (token, i) ->
return 1 unless include(EXPRESSION_CLOSE, @tag(i + 1)) and token[0] is 'TERMINATOR'
@tokens.splice i, 1
return 0
@@ -103,7 +104,7 @@ exports.Rewriter = class Rewriter
# The lexer has tagged the opening parenthesis of a method call. Match it with
# its paired close.
closeOpenCalls: ->
@scanTokens (token, i) =>
@scanTokens (token, i) ->
if token[0] is 'CALL_START'
condition = (token, i) -> token[0] in [')', 'CALL_END']
action = (token, i) -> token[0] = 'CALL_END'
@@ -113,7 +114,7 @@ exports.Rewriter = class Rewriter
# The lexer has tagged the opening parenthesis of an indexing operation call.
# Match it with its paired close.
closeOpenIndexes: ->
@scanTokens (token, i) =>
@scanTokens (token, i) ->
if token[0] is 'INDEX_START'
condition = (token, i) -> token[0] in [']', 'INDEX_END']
action = (token, i) -> token[0] = 'INDEX_END'
@@ -124,7 +125,7 @@ exports.Rewriter = class Rewriter
# Insert the missing braces here, so that the parser doesn't have to.
addImplicitBraces: ->
stack = []
@scanTokens (token, i) =>
@scanTokens (token, i) ->
if include EXPRESSION_START, token[0]
stack.push(if (token[0] is 'INDENT' and (@tag(i - 1) is '{')) then '{' else token[0])
if include EXPRESSION_END, token[0]
@@ -133,7 +134,9 @@ exports.Rewriter = class Rewriter
if token[0] is ':' and (not last or last[0] isnt '{')
stack.push '{'
idx = if @tag(i - 2) is '@' then i - 2 else i - 1
@tokens.splice idx, 0, ['{', '{', token[2]]
tok = ['{', '{', token[2]]
tok.generated = yes
@tokens.splice idx, 0, tok
condition = (token, i) ->
[one, two, three] = @tokens.slice(i + 1, i + 4)
return false if 'HERECOMMENT' in [@tag(i + 1), @tag(i - 1)]
@@ -150,10 +153,17 @@ exports.Rewriter = class Rewriter
# Insert the implicit parentheses here, so that the parser doesn't have to
# deal with them.
addImplicitParentheses: ->
@scanTokens (token, i) =>
prev = @tokens[i - 1]
if prev and prev.spaced and include(IMPLICIT_FUNC, prev[0]) and include(IMPLICIT_CALL, token[0]) and
not (token[0] is '!' and (@tag(i + 1) in ['IN', 'OF']))
classLine = no
@scanTokens (token, i) ->
classLine = yes if token[0] is 'CLASS'
prev = @tokens[i - 1]
next = @tokens[i + 1]
idx = 1
callObject = not classLine and token[0] is 'INDENT' and next and next.generated and next[0] is '{' and prev and include(IMPLICIT_FUNC, prev[0])
idx = 2 if callObject
classLine = no if include(LINEBREAKS, token[0])
if prev and (prev.spaced and include(IMPLICIT_FUNC, prev[0]) and include(IMPLICIT_CALL, token[0]) and
not (token[0] is 'UNARY' and (@tag(i + 1) in ['IN', 'OF', 'INSTANCEOF']))) or callObject
@tokens.splice i, 0, ['CALL_START', '(', token[2]]
condition = (token, i) ->
(not token.generated and @tokens[i - 1][0] isnt ',' and include(IMPLICIT_END, token[0]) and
@@ -162,7 +172,7 @@ exports.Rewriter = class Rewriter
action = (token, i) ->
idx = if token[0] is 'OUTDENT' then i + 1 else i
@tokens.splice idx, 0, ['CALL_END', ')', token[2]]
@detectEnd i + 1, condition, action
@detectEnd i + idx, condition, action
return 2
return 1
@@ -171,12 +181,12 @@ exports.Rewriter = class Rewriter
# blocks, so it doesn't need to. ')' can close a single-line block,
# but we need to make sure it's balanced.
addImplicitIndentation: ->
@scanTokens (token, i) =>
@scanTokens (token, i) ->
if token[0] is 'ELSE' and @tag(i - 1) isnt 'OUTDENT'
@tokens.splice i, 0, @indentation(token)...
return 2
if token[0] is 'CATCH' and
(@tokens[i + 2][0] is 'TERMINATOR' or @tokens[i + 2][0] is 'FINALLY')
(@tag(i + 2) is 'TERMINATOR' or @tag(i + 2) is 'FINALLY')
@tokens.splice i + 2, 0, @indentation(token)...
return 4
if include(SINGLE_LINERS, token[0]) and @tag(i + 1) isnt 'INDENT' and
@@ -196,12 +206,26 @@ exports.Rewriter = class Rewriter
return 2
return 1
# Tag postfix conditionals as such, so that we can parse them with a
# different precedence.
tagPostfixConditionals: ->
@scanTokens (token, i) ->
if token[0] in ['IF', 'UNLESS']
original = token
condition = (token, i) ->
token[0] in ['TERMINATOR', 'INDENT']
action = (token, i) ->
original[0] = 'POST_' + original[0] if token[0] isnt 'INDENT'
@detectEnd i + 1, condition, action
return 1
return 1
# Ensure that all listed pairs of tokens are correctly balanced throughout
# the course of the token stream.
ensureBalance: (pairs) ->
levels = {}
openLine = {}
@scanTokens (token, i) =>
@scanTokens (token, i) ->
for pair in pairs
[open, close] = pair
levels[open] or= 0
@@ -237,7 +261,7 @@ exports.Rewriter = class Rewriter
stack = []
debt = {}
(debt[key] = 0) for key, val of INVERSES
@scanTokens (token, i) =>
@scanTokens (token, i) ->
tag = token[0]
inv = INVERSES[token[0]]
if include EXPRESSION_START, tag
@@ -301,18 +325,21 @@ IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@
# If preceded by an `IMPLICIT_FUNC`, indicates a function invocation.
IMPLICIT_CALL = [
'IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS',
'TRY', 'DELETE', 'TYPEOF', 'SWITCH', 'THIS', 'NULL',
'IF', 'UNLESS', 'TRY', 'SWITCH', 'THIS', 'NULL', 'UNARY'
'TRUE', 'FALSE', 'YES', 'NO', 'ON', 'OFF',
'!', '!!', '@', '->', '=>', '[', '(', '{'
'@', '->', '=>', '[', '(', '{'
]
# Tokens indicating that the implicit call must enclose a block of expressions.
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']
# Tokens that always mark the end of an implicit call for single-liners.
IMPLICIT_END = ['IF', 'UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT']
IMPLICIT_END = ['POST_IF', 'POST_UNLESS', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'TERMINATOR', 'INDENT']
# Single-line flavors of block expressions that have unclosed endings.
# The grammar can't disambiguate them, so we insert the implicit indentation.
SINGLE_LINERS = ['ELSE', "->", "=>", 'TRY', 'FINALLY', 'THEN']
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN']
# Tokens that end a line.
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']

View File

@@ -46,7 +46,7 @@ exports.Scope = class Scope
# Just check to see if a variable has already been declared, without reserving.
check: (name) ->
return true if @variables.hasOwnProperty name
return true if Object::hasOwnProperty.call @variables, name
!!(@parent and @parent.check(name))
# If we need to store an intermediate result, find an available name for a

View File

@@ -8,11 +8,10 @@ ok results.join(' ') is '1 4 9'
# Chained blocks, with proper indentation levels:
results = []
counter = {
counter =
tick: (func) ->
results.push func()
this
}
counter
.tick ->
@@ -53,3 +52,17 @@ obj
)
ok result is 3
# Test newline-supressed call chains with nested functions.
obj =
call: -> this
func = ->
obj
.call ->
one two
.call ->
three four
101
ok func() is 101

View File

@@ -131,6 +131,7 @@ ok instance.name() is 'class'
# Classes with methods that are pre-bound to the instance.
# ... or statically, to the class.
class Dog
constructor: (name) ->
@@ -139,12 +140,19 @@ class Dog
bark: =>
"#{@name} woofs!"
@static: =>
new this('Dog')
spark = new Dog('Spark')
fido = new Dog('Fido')
fido.bark = spark.bark
ok fido.bark() is 'Spark woofs!'
obj = func: Dog.static
ok obj.func().name is 'Dog'
# Testing a bound function in a bound function.
class Mini
@@ -199,13 +207,13 @@ class Element extends Base
@node = node
ok Element.extended is Base.extended
ok Element.__superClass__ is Base.prototype
ok Element.__super__ is Base.prototype
class MyElement extends Element
ok MyElement.extended is Base.extended
ok MyElement.fromHTML is Element.fromHTML
ok MyElement.__superClass__ is Element.prototype
ok MyElement.__super__ is Element.prototype
# Test classes wrapped in decorators.

View File

@@ -17,9 +17,15 @@ ok a is 10 and b is 10
# The existential operator.
z = null
x = z ? "EX"
ok z is null and x is "EX"
i = 9
func = -> i += 1
result = func() ? 101
ok result is 10
ok (non ? existent ? variables ? 1) is 1
# Only evaluate once.
counter = 0
@@ -70,6 +76,11 @@ result = value?.toString().toLowerCase()
ok result is '10'
# Soaks inner values.
ident = (obj) -> obj
ok ident(non?.existent().method()) is undefined
# Soaks constructor invocations.
a = 0
class Foo

View File

@@ -64,10 +64,20 @@ ok result is undefined
# Return an if with no else.
func = ->
return (if false then callback())
return if false then callback()
ok func() is null
func = ->
return unless false then 100 else -100
ok func() is 100
ident = (x) -> x
result = ident if false then 300 else 100
ok result is 100
# If-to-ternary with instanceof requires parentheses (no comment).
if {} instanceof Object
@@ -80,3 +90,22 @@ try
ok yes
catch e
ok no
# If-to-ternary as part of a larger operation requires parens.
x = 1
result = x + if false then 10 else 1
ok result is 2
# If/else indented within an assignment.
func = ->
a =
if false
3
else
5
101
a
ok func() is 5

View File

@@ -60,8 +60,8 @@ ok money$ is '\(\(\(dollars\)\)\)'
multiline = "one
two
three"
two
three"
ok multiline is 'one two three'
@@ -165,9 +165,31 @@ ok obj.options.value is yes
ok obj.fn() is null
# Implicit arguments to function calls:
func = (obj) -> obj.a
result = func
a: 10
ok result is 10
result = func
"a": 20
ok result is 20
third = (a, b, c) -> c
obj =
one: 'one'
two: third 'one', 'two', 'three'
ok obj.one is 'one'
ok obj.two is 'three'
# Implicit objects with wacky indentation:
obj =
reverse: (obj) ->
'reverse': (obj) ->
Array.prototype.reverse.call obj
abc: ->
@reverse(
@@ -197,11 +219,12 @@ ok obj.misdent.toString() is ',,,'
second = (x, y) -> y
obj = then second 'the',
one: 1
1: 1
two:
three: ->
four five,
six: seven
three: 3
ok obj[1] is 1
ok obj.three is 3

View File

@@ -100,3 +100,46 @@ ok list.join(' ') is '0 100 5 10'
a = b = false
a and= b or true
ok a is false
# Bitwise operators:
ok (10 & 3) is 2
ok (10 | 3) is 11
ok (10 ^ 3) is 9
ok (10 << 3) is 80
ok (10 >> 3) is 1
ok (10 >>> 3) is 1
num = 10; ok (num <<= 3) is 80
num = 10; ok (num >>= 3) is 1
num = 10; ok (num >>>= 3) is 1
num = 10; ok (num &= 3) is 2
num = 10; ok (num ^= 3) is 9
num = 10; ok (num |= 3) is 11
# Compound assignment with implicit objects.
obj = undefined
obj ?=
one: 1
ok obj.one is 1
obj and=
two: 2
ok not obj.one
ok obj.two is 2
# Compound assignment as a sub expression.
[a, b, c] = [1, 2, 3]
ok (a + b += c) is 6
ok a is 1
ok b is 5
ok c is 3
# Instanceof.
ok new String instanceof String
ok new Number not instanceof String

View File

@@ -56,3 +56,20 @@ array[5..10] = [0, 0, 0]
ok array.join(' ') is '0 1 2 3 4 0 0 0'
# Slices and splices that omit their beginning or end.
array = [0..10]
ok array[7..].join(' ') is '7 8 9 10'
ok array[-2..].join(' ') is '9 10'
ok array[...3].join(' ') is '0 1 2'
ok array[..-5].join(' ') is '0 1 2 3 4 5 6'
array[3..] = [9, 8, 7]
ok array.join(' ') is '0 1 2 9 8 7'
array[...3] = [7, 8, 9]
ok array.join(' ') is '7 8 9 9 8 7'

View File

@@ -20,4 +20,9 @@ obj = {
}
id = 2
ok ' '.match(/ /)[0] is ' '
regexp = / /
ok ' '.match regexp
ok (obj.width()/id - obj.height()/id) is -5