mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
Merge branch 'master' of git://github.com/jashkenas/coffee-script into interpolation_3
This commit is contained in:
7
Cakefile
7
Cakefile
@@ -28,6 +28,13 @@ task 'build', 'build the CoffeeScript language from source', ->
|
||||
run ['-c', '-o', 'lib'].concat(files)
|
||||
|
||||
|
||||
task 'build:full', 'checkout /lib, rebuild the source twice, and run the tests', ->
|
||||
exec 'git co lib && bin/cake build && bin/cake build && bin/cake test', (err, stdout, stderr) ->
|
||||
print stdout if stdout
|
||||
print stderr if stderr
|
||||
throw err if err
|
||||
|
||||
|
||||
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
|
||||
require.paths.unshift 'vendor/jison/lib'
|
||||
parser: require('grammar').parser
|
||||
|
||||
2
documentation/coffee/interpolation.coffee
Normal file
2
documentation/coffee/interpolation.coffee
Normal file
@@ -0,0 +1,2 @@
|
||||
author: "Wittgenstein"
|
||||
quote: "A picture is a fact. -- $author"
|
||||
4
documentation/coffee/interpolation_expression.coffee
Normal file
4
documentation/coffee/interpolation_expression.coffee
Normal file
@@ -0,0 +1,4 @@
|
||||
sentence: "${ 22 / 7 } is a decent approximation of π"
|
||||
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ div.code {
|
||||
#error {
|
||||
position: absolute;
|
||||
-webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px;
|
||||
right: 15px; top: 15px; left: 565px;
|
||||
right: 15px; top: 15px; left: 722px;
|
||||
height: 15px;
|
||||
padding: 2px 5px;
|
||||
background: #fdcdcc;
|
||||
@@ -142,14 +142,14 @@ div.code {
|
||||
float: left;
|
||||
padding: 0 20px;
|
||||
border: 1px solid #bbb;
|
||||
border-top: 0; border-bottom: 0;
|
||||
border-top: 0; border-bottom: 0; border-left-width: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
body.full_screen .navigation {
|
||||
position: static;
|
||||
}
|
||||
.navigation.try {
|
||||
border-left: 0;
|
||||
.navigation.toc {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
.navigation:hover,
|
||||
.navigation.active {
|
||||
@@ -206,7 +206,7 @@ div.code {
|
||||
}
|
||||
.navigation .contents a {
|
||||
display: block;
|
||||
width: 300px;
|
||||
width: 290px;
|
||||
text-transform: none;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
|
||||
@@ -12,7 +12,7 @@ execute all scripts present in <code>text/coffeescript</code> tags.</p>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">lexer: </span><span class="k">new</span> <span class="nx">Lexer</span><span class="p">()</span>
|
||||
<span class="nv">parser: </span><span class="nx">exports</span><span class="p">.</span><span class="nx">parser</span>
|
||||
<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></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">'0.5.4'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
<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></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">'0.5.5'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-4">#</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: </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">-></span>
|
||||
<span class="k">try</span>
|
||||
<span class="p">(</span><span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="nx">code</span><span class="p">).</span><span class="nx">compile</span> <span class="nx">options</span>
|
||||
|
||||
@@ -56,23 +56,23 @@ and <code>module.filename</code> to be correct relative to the script's path.</p
|
||||
<span class="nv">o: </span><span class="nx">options</span>
|
||||
<span class="nv">code_opts: </span><span class="nx">compile_options</span> <span class="nx">source</span>
|
||||
<span class="k">try</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">print_tokens</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">code_opts</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">print_tokens</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">code_opts</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">code_opts</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">write_js</span> <span class="nx">source</span><span class="p">,</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">lint</span> <span class="k">then</span> <span class="nx">lint</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">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="k">then</span> <span class="nx">print</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">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">write</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">write_js</span> <span class="nx">source</span><span class="p">,</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">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">js</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">else</span> <span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span> <span class="k">then</span> <span class="nx">puts</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">else</span> <span class="k">throw</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-9">#</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">compile_stdio: </span><span class="o">-></span>
|
||||
<span class="nv">code: </span><span class="s1">''</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">open</span><span class="p">()</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">string</span> <span class="k">if</span> <span class="nx">string</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'close'</span><span class="p">,</span> <span class="o">-></span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">stdio</span><span class="p">.</span><span class="nx">write</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">compile_options</span><span class="p">(</span><span class="s1">'stdio'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Watch a list of source CoffeeScript files using <code>fs.watchFile</code>, recompiling
|
||||
<span class="nx">compile_script</span> <span class="s1">'stdio'</span><span class="p">,</span> <span class="nx">code</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-10">#</a> </div> <p>Watch a list of source CoffeeScript files using <code>fs.watchFile</code>, recompiling
|
||||
them every time the files are updated. May be used in combination with other
|
||||
options, such as <code>--lint</code> or <code>--print</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">watch_scripts: </span><span class="o">-></span>
|
||||
<span class="nv">watch: </span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">-></span>
|
||||
@@ -101,10 +101,11 @@ any errors or warnings that arise.</p> </td> <td class="
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parse_options: </span><span class="o">-></span>
|
||||
<span class="nv">option_parser: </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">option_parser</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="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="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nb">eval</span><span class="p">)</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><span class="p">[</span><span class="mi">2</span><span class="p">...</span><span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-15">#</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">compile_options: </span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o: </span><span class="p">{</span><span class="nv">source: </span><span class="nx">source</span><span class="p">}</span>
|
||||
<span class="nx">o</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span><span class="o">:</span> <span class="nx">options</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span>
|
||||
<span class="nx">o</span><span class="p">[</span><span class="s1">'no_wrap'</span><span class="p">]</span><span class="o">:</span> <span class="nx">options</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span>
|
||||
<span class="nx">o</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-16">#</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">-></span>
|
||||
<span class="nx">puts</span> <span class="nx">option_parser</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-17"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-17">#</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">-></span>
|
||||
|
||||
@@ -265,12 +265,15 @@ token stream.</p> </td> <td class="code">
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="nx">interp</span><span class="p">]</span>
|
||||
<span class="nx">i</span> <span class="o">+=</span> <span class="nx">group</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">pi: </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nv">expr: </span><span class="err">@</span><span class="nx">balanced_string</span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">i</span><span class="p">),</span> <span class="p">[</span><span class="s1">'${'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">])</span> <span class="o">and</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">3</span>
|
||||
<span class="nv">inner: </span><span class="nx">expr</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nx">expr</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">nested: </span><span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="s2">"($inner)"</span><span class="p">,</span> <span class="p">{</span><span class="nv">rewrite: </span><span class="kc">no</span><span class="p">,</span> <span class="nv">line: </span><span class="err">@</span><span class="nx">line</span><span class="p">}</span>
|
||||
<span class="nx">nested</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nv">expr: </span><span class="err">@</span><span class="nx">balanced_string</span> <span class="nx">str</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">i</span><span class="p">),</span> <span class="p">[</span><span class="s1">'${'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">])</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote${ str.substring(pi, i) }$quote"</span><span class="p">]</span> <span class="k">if</span> <span class="nx">pi</span> <span class="o"><</span> <span class="nx">i</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'TOKENS'</span><span class="p">,</span> <span class="nx">nested</span><span class="p">]</span>
|
||||
<span class="nv">inner: </span><span class="nx">expr</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nx">expr</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="nx">inner</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">nested: </span><span class="nx">lexer</span><span class="p">.</span><span class="nx">tokenize</span> <span class="s2">"($inner)"</span><span class="p">,</span> <span class="p">{</span><span class="nv">rewrite: </span><span class="kc">no</span><span class="p">,</span> <span class="nv">line: </span><span class="err">@</span><span class="nx">line</span><span class="p">}</span>
|
||||
<span class="nx">nested</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'TOKENS'</span><span class="p">,</span> <span class="nx">nested</span><span class="p">]</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'STRING'</span><span class="p">,</span> <span class="s2">"$quote$quote"</span><span class="p">]</span>
|
||||
<span class="nx">i</span> <span class="o">+=</span> <span class="nx">expr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nv">pi: </span><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>
|
||||
|
||||
@@ -609,7 +609,11 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
|
||||
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_unary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_unary</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="err">@</span><span class="nx">compile_existence</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">operator</span> <span class="o">is</span> <span class="s1">'?'</span>
|
||||
<span class="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">operator</span><span class="p">,</span> <span class="err">@</span><span class="nx">second</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)].</span><span class="nx">join</span> <span class="s1">' '</span></pre></div> </td> </tr> <tr id="section-99"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-99">#</a> </div> <p>Mimic Python's chained comparisons when multiple comparison operators are
|
||||
used sequentially. For example: <code>50 < 65 > 10</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_chain: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
used sequentially. For example:</p>
|
||||
|
||||
<pre><code>bin/coffee -e "puts 50 < 65 > 10"
|
||||
true
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_chain: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">shared: </span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">().</span><span class="nx">second</span>
|
||||
<span class="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">second</span><span class="p">,</span> <span class="nx">shared</span><span class="p">]</span><span class="o">:</span> <span class="nx">shared</span><span class="p">.</span><span class="nx">compile_reference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="nx">shared</span> <span class="k">instanceof</span> <span class="nx">CallNode</span>
|
||||
<span class="p">[</span><span class="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="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">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">shared</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span>
|
||||
@@ -619,26 +623,22 @@ more than once.</p> </td> <td class="code">
|
||||
<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="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">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">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">"$first = ${ ExistenceNode.compile_test(o, @first) } ? $first : $second"</span> <span class="k">if</span> <span class="err">@</span><span class="nx">operator</span> <span class="o">is</span> <span class="s1">'?='</span>
|
||||
<span class="s2">"$first = $first ${ @operator.substr(0, 2) } $second"</span>
|
||||
|
||||
<span class="nv">compile_existence: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="s2">"$first = $first ${ @operator.substr(0, 2) } $second"</span></pre></div> </td> </tr> <tr id="section-101"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-101">#</a> </div> <p>If this is an existence operator, we delegate to <code>ExistenceNode.compile_test</code>
|
||||
to give us the safe references for the variables.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_existence: </span><span class="p">(</span><span class="nx">o</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">second</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="err">@</span><span class="nx">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">compile_test</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="err">@</span><span class="nx">first</span><span class="p">)</span>
|
||||
<span class="s2">"$test ? $first : $second"</span>
|
||||
|
||||
<span class="nv">compile_unary: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="s2">"$test ? $first : $second"</span></pre></div> </td> </tr> <tr id="section-102"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-102">#</a> </div> <p>Compile a unary <strong>OpNode</strong>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_unary: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">space: </span><span class="k">if</span> <span class="err">@</span><span class="nx">PREFIX_OPERATORS</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="err">@</span><span class="nx">operator</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">0</span> <span class="k">then</span> <span class="s1">' '</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">parts: </span><span class="p">[</span><span class="err">@</span><span class="nx">operator</span><span class="p">,</span> <span class="nx">space</span><span class="p">,</span> <span class="err">@</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span>
|
||||
<span class="nv">parts: </span><span class="nx">parts</span><span class="p">.</span><span class="nx">reverse</span><span class="p">()</span> <span class="k">if</span> <span class="err">@</span><span class="nx">flip</span>
|
||||
<span class="nx">parts</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">''</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-101"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-101">#</a> </div> <p>A try/catch/finally block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.TryNode: </span><span class="nx">class</span> <span class="nx">TryNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nx">parts</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">''</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> <h3>TryNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-104"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-104">#</a> </div> <p>A classic <em>try/catch/finally</em> block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.TryNode: </span><span class="nx">class</span> <span class="nx">TryNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nv">type: </span><span class="s1">'Try'</span>
|
||||
|
||||
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">attempt</span><span class="p">,</span> <span class="nx">error</span><span class="p">,</span> <span class="nx">recovery</span><span class="p">,</span> <span class="nx">ensure</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="err">@</span><span class="nv">children: </span><span class="nx">compact</span> <span class="p">[</span><span class="err">@</span><span class="nv">attempt: </span><span class="nx">attempt</span><span class="p">,</span> <span class="err">@</span><span class="nv">recovery: </span><span class="nx">recovery</span><span class="p">,</span> <span class="err">@</span><span class="nv">ensure: </span><span class="nx">ensure</span><span class="p">]</span>
|
||||
<span class="err">@</span><span class="nv">error: </span><span class="nx">error</span>
|
||||
<span class="k">this</span>
|
||||
|
||||
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-105"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-105">#</a> </div> <p>Compilation is more or less as you would expect -- the <em>finally</em> clause
|
||||
is optional, the <em>catch</em> is not.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">o.indent: </span> <span class="err">@</span><span class="nx">idt</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||||
<span class="nv">o.top: </span> <span class="kc">true</span>
|
||||
<span class="nv">attempt_part: </span><span class="err">@</span><span class="nx">attempt</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
||||
@@ -647,7 +647,7 @@ more than once.</p> </td> <td class="code">
|
||||
<span class="nv">finally_part: </span><span class="p">(</span><span class="err">@</span><span class="nx">ensure</span> <span class="o">or</span> <span class="s1">''</span><span class="p">)</span> <span class="o">and</span> <span class="s1">' finally {\n'</span> <span class="o">+</span> <span class="err">@</span><span class="nx">ensure</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">returns: </span><span class="kc">null</span><span class="p">}))</span> <span class="o">+</span> <span class="s2">"\n$@tab}"</span>
|
||||
<span class="s2">"${@tab}try {\n$attempt_part\n$@tab}$catch_part$finally_part"</span>
|
||||
|
||||
<span class="nx">statement</span> <span class="nx">TryNode</span></pre></div> </td> </tr> <tr id="section-102"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-102">#</a> </div> <p>Throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ThrowNode: </span><span class="nx">class</span> <span class="nx">ThrowNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nx">statement</span> <span class="nx">TryNode</span></pre></div> </td> </tr> <tr id="section-106"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-106">#</a> </div> <h3>ThrowNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-107"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-107">#</a> </div> <p>Simple node to throw an exception.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ThrowNode: </span><span class="nx">class</span> <span class="nx">ThrowNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nv">type: </span><span class="s1">'Throw'</span>
|
||||
|
||||
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-></span>
|
||||
@@ -656,21 +656,27 @@ more than once.</p> </td> <td class="code">
|
||||
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="s2">"${@tab}throw ${@expression.compile(o)};"</span>
|
||||
|
||||
<span class="nx">statement</span> <span class="nx">ThrowNode</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-103"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-103">#</a> </div> <p>Check an expression for existence (meaning not null or undefined).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ExistenceNode: </span><span class="nx">class</span> <span class="nx">ExistenceNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nx">statement</span> <span class="nx">ThrowNode</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-108">#</a> </div> <h3>ExistenceNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-109"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-109">#</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="nv">exports.ExistenceNode: </span><span class="nx">class</span> <span class="nx">ExistenceNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nv">type: </span><span class="s1">'Existence'</span>
|
||||
|
||||
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="err">@</span><span class="nv">children: </span><span class="p">[</span><span class="err">@</span><span class="nv">expression: </span><span class="nx">expression</span><span class="p">]</span>
|
||||
|
||||
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">ExistenceNode</span><span class="p">.</span><span class="nx">compile_test</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="err">@</span><span class="nx">expression</span><span class="p">)</span>
|
||||
|
||||
<span class="nv">ExistenceNode.compile_test: </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">-></span>
|
||||
<span class="nx">ExistenceNode</span><span class="p">.</span><span class="nx">compile_test</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="err">@</span><span class="nx">expression</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-110"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-110">#</a> </div> <p>The meat of the <strong>ExistenceNode</strong> is in this static <code>compile_test</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><span class="nv">ExistenceNode.compile_test: </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">-></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">variable</span><span class="p">,</span> <span class="nx">variable</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">CallNode</span> <span class="o">or</span> <span class="p">(</span><span class="nx">variable</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="nx">variable</span><span class="p">.</span><span class="nx">has_properties</span><span class="p">())</span>
|
||||
<span class="p">[</span><span class="nx">first</span><span class="p">,</span> <span class="nx">second</span><span class="p">]</span><span class="o">:</span> <span class="nx">variable</span><span class="p">.</span><span class="nx">compile_reference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
||||
<span class="p">[</span><span class="nx">first</span><span class="p">,</span> <span class="nx">second</span><span class="p">]</span><span class="o">:</span> <span class="p">[</span><span class="nx">first</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">),</span> <span class="nx">second</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)]</span>
|
||||
<span class="s2">"(typeof $first !== \"undefined\" && $second !== null)"</span></pre></div> </td> </tr> <tr id="section-104"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-104">#</a> </div> <p>An extra set of parentheses, specified explicitly in the source.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ParentheticalNode: </span><span class="nx">class</span> <span class="nx">ParentheticalNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="s2">"(typeof $first !== \"undefined\" && $second !== null)"</span></pre></div> </td> </tr> <tr id="section-111"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-111">#</a> </div> <h3>ParentheticalNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-112"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-112">#</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>
|
||||
|
||||
<p>Parentheses are a good way to force any statement to become an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ParentheticalNode: </span><span class="nx">class</span> <span class="nx">ParentheticalNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nv">type: </span><span class="s1">'Paren'</span>
|
||||
|
||||
<span class="nv">constructor: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-></span>
|
||||
@@ -684,10 +690,13 @@ more than once.</p> </td> <td class="code">
|
||||
<span class="k">return</span> <span class="nx">code</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span>
|
||||
<span class="nv">l: </span> <span class="nx">code</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">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">';'</span>
|
||||
<span class="s2">"($code)"</span></pre></div> </td> </tr> <tr id="section-105"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-105">#</a> </div> <p>The replacement for the for loop is an array comprehension (that compiles)
|
||||
into a for loop. Also acts as an expression, able to return the result
|
||||
of the comprehenion. Unlike Python array comprehensions, it's able to pass
|
||||
the current index of the loop as a second parameter.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ForNode: </span><span class="nx">class</span> <span class="nx">ForNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="s2">"($code)"</span></pre></div> </td> </tr> <tr id="section-113"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-113">#</a> </div> <h3>ForNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-114"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-114">#</a> </div> <p>CoffeeScript's replacement for the <em>for</em> loop is our array and object
|
||||
comprehensions, that compile into <em>for</em> loops here. They also act as an
|
||||
expression, able to return the result of each filtered iteration.</p>
|
||||
|
||||
<p>Unlike Python array comprehensions, they can be multi-line, and you can pass
|
||||
the current index of the loop as a second parameter. Unlike Ruby blocks,
|
||||
you can map and filter in a single pass.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ForNode: </span><span class="nx">class</span> <span class="nx">ForNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nv">type: </span><span class="s1">'For'</span>
|
||||
|
||||
<span class="nv">constructor: </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">-></span>
|
||||
@@ -702,9 +711,10 @@ the current index of the loop as a second parameter.</p> </td>
|
||||
<span class="err">@</span><span class="nv">children: </span><span class="nx">compact</span> <span class="p">[</span><span class="err">@</span><span class="nx">body</span><span class="p">,</span> <span class="err">@</span><span class="nx">source</span><span class="p">,</span> <span class="err">@</span><span class="nx">filter</span><span class="p">]</span>
|
||||
|
||||
<span class="nv">top_sensitive: </span><span class="o">-></span>
|
||||
<span class="kc">true</span>
|
||||
|
||||
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="kc">true</span></pre></div> </td> </tr> <tr id="section-115"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-115">#</a> </div> <p>Welcome to the hairiest method in all of CoffeeScript. Handles the inner
|
||||
loop, filtering, stepping, and result saving for array, object, and range
|
||||
comprehensions. Some of the generated code can be shared in common, and
|
||||
some cannot.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">top_level: </span> <span class="nx">del</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="s1">'top'</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">returns</span>
|
||||
<span class="nv">range: </span> <span class="err">@</span><span class="nx">source</span> <span class="k">instanceof</span> <span class="nx">ValueNode</span> <span class="o">and</span> <span class="err">@</span><span class="nx">source</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">RangeNode</span> <span class="o">and</span> <span class="o">not</span> <span class="err">@</span><span class="nx">source</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">source: </span> <span class="k">if</span> <span class="nx">range</span> <span class="k">then</span> <span class="err">@</span><span class="nx">source</span><span class="p">.</span><span class="nx">base</span> <span class="k">else</span> <span class="err">@</span><span class="nx">source</span>
|
||||
@@ -751,10 +761,11 @@ the current index of the loop as a second parameter.</p> </td>
|
||||
<span class="nv">close: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">object</span> <span class="k">then</span> <span class="s1">'}}\n'</span> <span class="k">else</span> <span class="s1">'}\n'</span>
|
||||
<span class="s2">"$set_result${source_part}for ($for_part) {\n$var_part$body\n$@tab$close$@tab$return_result"</span>
|
||||
|
||||
<span class="nx">statement</span> <span class="nx">ForNode</span></pre></div> </td> </tr> <tr id="section-106"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-106">#</a> </div> <p>If/else statements. Switch/whens get compiled into these. Acts as an
|
||||
expression by pushing down requested returns to the expression bodies.
|
||||
Single-expression IfNodes are compiled into ternary operators if possible,
|
||||
because ternaries are first-class returnable assignable expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.IfNode: </span><span class="nx">class</span> <span class="nx">IfNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nx">statement</span> <span class="nx">ForNode</span></pre></div> </td> </tr> <tr id="section-116"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-116">#</a> </div> <h3>IfNode</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-117"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-117">#</a> </div> <p><em>If/else</em> statements. Our <em>switch/when</em> will be compiled into this. Acts as an
|
||||
expression by pushing down requested returns to the last line of each clause.</p>
|
||||
|
||||
<p>Single-expression <strong>IfNodes</strong> are compiled into ternary operators if possible,
|
||||
because ternaries are already proper expressions, and don't need conversion.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.IfNode: </span><span class="nx">class</span> <span class="nx">IfNode</span> <span class="k">extends</span> <span class="nx">BaseNode</span>
|
||||
<span class="nv">type: </span><span class="s1">'If'</span>
|
||||
|
||||
<span class="nv">constructor: </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">else_body</span><span class="p">,</span> <span class="nx">tags</span><span class="p">)</span> <span class="o">-></span>
|
||||
@@ -764,18 +775,19 @@ because ternaries are first-class returnable assignable expressions.</p>
|
||||
<span class="err">@</span><span class="nv">children: </span> <span class="nx">compact</span> <span class="p">[</span><span class="err">@</span><span class="nx">condition</span><span class="p">,</span> <span class="err">@</span><span class="nx">body</span><span class="p">,</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">]</span>
|
||||
<span class="err">@</span><span class="nv">tags: </span> <span class="nx">tags</span> <span class="o">or</span> <span class="p">{}</span>
|
||||
<span class="err">@</span><span class="nv">multiple: </span> <span class="kc">true</span> <span class="k">if</span> <span class="err">@</span><span class="nx">condition</span> <span class="k">instanceof</span> <span class="nb">Array</span>
|
||||
<span class="err">@</span><span class="nv">condition: </span><span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'!'</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="err">@</span><span class="nx">condition</span><span class="p">))</span> <span class="k">if</span> <span class="err">@</span><span class="nx">tags</span><span class="p">.</span><span class="nx">invert</span>
|
||||
|
||||
<span class="nv">push: </span><span class="p">(</span><span class="nx">else_body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="err">@</span><span class="nv">condition: </span><span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'!'</span><span class="p">,</span> <span class="k">new</span> <span class="nx">ParentheticalNode</span><span class="p">(</span><span class="err">@</span><span class="nx">condition</span><span class="p">))</span> <span class="k">if</span> <span class="err">@</span><span class="nx">tags</span><span class="p">.</span><span class="nx">invert</span></pre></div> </td> </tr> <tr id="section-118"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-118">#</a> </div> <p>Add a new <em>else</em> clause to this <strong>IfNode</strong>, or push it down to the bottom
|
||||
of the chain recursively.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">push: </span><span class="p">(</span><span class="nx">else_body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">eb: </span><span class="nx">else_body</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">then</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">eb</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nv">else_body: </span><span class="nx">eb</span>
|
||||
<span class="k">this</span>
|
||||
|
||||
<span class="nv">force_statement: </span><span class="o">-></span>
|
||||
<span class="err">@</span><span class="nv">tags.statement: </span><span class="kc">true</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-107"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-107">#</a> </div> <p>Tag a chain of IfNodes with their switch condition for equality.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_condition: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-119"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-119">#</a> </div> <p>Tag a chain of <strong>IfNodes</strong> with their object(s) to switch on for equality
|
||||
tests. <code>rewrite_switch</code> will perform the actual change at compile time.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_condition: </span><span class="p">(</span><span class="nx">expression</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="err">@</span><span class="nv">switcher: </span><span class="nx">expression</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-108">#</a> </div> <p>Rewrite a chain of IfNodes with their switch condition for equality.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_switch: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-120"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-120">#</a> </div> <p>Rewrite a chain of <strong>IfNodes</strong> with their switch condition for equality.
|
||||
Ensure that the switch expression isn't evaluated more than once.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">rewrite_switch: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">assigner: </span><span class="err">@</span><span class="nx">switcher</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="p">(</span><span class="err">@</span><span class="nx">switcher</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">LiteralNode</span><span class="p">)</span>
|
||||
<span class="nv">variable: </span><span class="nx">literal</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">free_variable</span><span class="p">())</span>
|
||||
@@ -787,23 +799,23 @@ because ternaries are first-class returnable assignable expressions.</p>
|
||||
<span class="k">else</span>
|
||||
<span class="k">new</span> <span class="nx">OpNode</span><span class="p">(</span><span class="s1">'is'</span><span class="p">,</span> <span class="nx">assigner</span><span class="p">,</span> <span class="err">@</span><span class="nx">condition</span><span class="p">)</span>
|
||||
<span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">rewrite_condition</span><span class="p">(</span><span class="err">@</span><span class="nx">switcher</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-109"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-109">#</a> </div> <p>Rewrite a chain of IfNodes to add a default case as the final else.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">add_else: </span><span class="p">(</span><span class="nx">exprs</span><span class="p">,</span> <span class="nx">statement</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-121"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-121">#</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="nv">add_else: </span><span class="p">(</span><span class="nx">exprs</span><span class="p">,</span> <span class="nx">statement</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="err">@</span><span class="nx">is_chain</span><span class="p">()</span>
|
||||
<span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">add_else</span> <span class="nx">exprs</span><span class="p">,</span> <span class="nx">statement</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">exprs: </span><span class="nx">exprs</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">statement</span>
|
||||
<span class="err">@</span><span class="nx">children</span><span class="p">.</span><span class="nx">push</span> <span class="err">@</span><span class="nv">else_body: </span><span class="nx">exprs</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-110"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-110">#</a> </div> <p>If the else_body is an IfNode itself, then we've got an if-else chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_chain: </span><span class="o">-></span>
|
||||
<span class="err">@</span><span class="nx">chain</span> <span class="o">||=</span> <span class="err">@</span><span class="nx">else_body</span> <span class="o">and</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">instanceof</span> <span class="nx">IfNode</span></pre></div> </td> </tr> <tr id="section-111"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-111">#</a> </div> <p>The IfNode only compiles into a statement if either of the bodies needs
|
||||
to be a statement.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-></span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-122"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-122">#</a> </div> <p>If the <code>else_body</code> is an <strong>IfNode</strong> itself, then we've got an <em>if-else</em> chain.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_chain: </span><span class="o">-></span>
|
||||
<span class="err">@</span><span class="nx">chain</span> <span class="o">||=</span> <span class="err">@</span><span class="nx">else_body</span> <span class="o">and</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">instanceof</span> <span class="nx">IfNode</span></pre></div> </td> </tr> <tr id="section-123"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-123">#</a> </div> <p>The <strong>IfNode</strong> only compiles into a statement if either of its bodies needs
|
||||
to be a statement. Otherwise a ternary is safe.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">is_statement: </span><span class="o">-></span>
|
||||
<span class="err">@</span><span class="nx">statement</span> <span class="o">||=</span> <span class="o">!!</span><span class="p">(</span><span class="err">@</span><span class="nx">comment</span> <span class="o">or</span> <span class="err">@</span><span class="nx">tags</span><span class="p">.</span><span class="nx">statement</span> <span class="o">or</span> <span class="err">@</span><span class="nx">body</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()</span> <span class="o">or</span> <span class="p">(</span><span class="err">@</span><span class="nx">else_body</span> <span class="o">and</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">is_statement</span><span class="p">()))</span>
|
||||
|
||||
<span class="nv">compile_condition: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">(</span><span class="nx">cond</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">for</span> <span class="nx">cond</span> <span class="k">in</span> <span class="nx">flatten</span><span class="p">([</span><span class="err">@</span><span class="nx">condition</span><span class="p">])).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' || '</span><span class="p">)</span>
|
||||
|
||||
<span class="nv">compile_node: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_statement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_ternary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-112"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-112">#</a> </div> <p>Compile the IfNode as a regular if-else statement. Flattened chains
|
||||
force sub-else bodies into statement form.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_statement: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="err">@</span><span class="nx">is_statement</span><span class="p">()</span> <span class="k">then</span> <span class="err">@</span><span class="nx">compile_statement</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="err">@</span><span class="nx">compile_ternary</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-124"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-124">#</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="nv">compile_statement: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="err">@</span><span class="nx">rewrite_switch</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">if</span> <span class="err">@</span><span class="nx">switcher</span>
|
||||
<span class="nv">child: </span> <span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">'chain_child'</span>
|
||||
<span class="nv">cond_o: </span> <span class="nx">merge</span> <span class="nx">o</span>
|
||||
@@ -820,22 +832,26 @@ force sub-else bodies into statement form.</p> </td> <td
|
||||
<span class="s1">' else '</span> <span class="o">+</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="p">{</span><span class="nv">indent: </span><span class="err">@</span><span class="nx">idt</span><span class="p">(),</span> <span class="nv">chain_child: </span><span class="kc">true</span><span class="p">}))</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s2">" else {\n${ Expressions.wrap([@else_body]).compile(o) }\n$@tab}"</span>
|
||||
<span class="s2">"$if_part$else_part"</span></pre></div> </td> </tr> <tr id="section-113"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-113">#</a> </div> <p>Compile the IfNode into a ternary operator.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_ternary: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="s2">"$if_part$else_part"</span></pre></div> </td> </tr> <tr id="section-125"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-125">#</a> </div> <p>Compile the IfNode as a ternary operator.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">compile_ternary: </span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">if_part: </span> <span class="err">@</span><span class="nx">condition</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">' ? '</span> <span class="o">+</span> <span class="err">@</span><span class="nx">body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
||||
<span class="nv">else_part: </span> <span class="k">if</span> <span class="err">@</span><span class="nx">else_body</span> <span class="k">then</span> <span class="err">@</span><span class="nx">else_body</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="s1">'null'</span>
|
||||
<span class="s2">"$if_part : $else_part"</span></pre></div> </td> </tr> <tr id="section-114"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-114">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-115"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-115">#</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB: </span><span class="s1">' '</span>
|
||||
<span class="nv">TRAILING_WHITESPACE: </span><span class="sr">/\s+$/gm</span></pre></div> </td> </tr> <tr id="section-116"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-116">#</a> </div> <p>Keep the identifier regex in sync with the Lexer.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER: </span> <span class="sr">/^[a-zA-Z$_](\w|\$)*$/</span></pre></div> </td> </tr> <tr id="section-117"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-117">#</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-118"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-118">#</a> </div> <p>Merge objects.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">merge: </span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">overrides</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="s2">"$if_part : $else_part"</span></pre></div> </td> </tr> <tr id="section-126"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-126">#</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-127"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-127">#</a> </div> <p>Tabs are two spaces for pretty printing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">TAB: </span><span class="s1">' '</span></pre></div> </td> </tr> <tr id="section-128"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-128">#</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">TRAILING_WHITESPACE: </span><span class="sr">/\s+$/gm</span></pre></div> </td> </tr> <tr id="section-129"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-129">#</a> </div> <p>Keep this identifier regex in sync with the Lexer.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IDENTIFIER: </span><span class="sr">/^[a-zA-Z$_](\w|\$)*$/</span></pre></div> </td> </tr> <tr id="section-130"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-130">#</a> </div> <h2>Utility Functions</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-131"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-131">#</a> </div> <p>Merge objects, returning a fresh copy with attributes from both sides.
|
||||
Used every time <code>compile</code> is called, to allow properties in the options hash
|
||||
to propagate down the tree without polluting other branches.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">merge: </span><span class="p">(</span><span class="nx">options</span><span class="p">,</span> <span class="nx">overrides</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">fresh: </span><span class="p">{}</span>
|
||||
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">options</span>
|
||||
<span class="p">(</span><span class="nx">fresh</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">:</span> <span class="nx">val</span><span class="p">)</span> <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">overrides</span> <span class="k">if</span> <span class="nx">overrides</span>
|
||||
<span class="nx">fresh</span></pre></div> </td> </tr> <tr id="section-119"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-119">#</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compact: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span> <span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-120"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-120">#</a> </div> <p>Return a completely flattened version of an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">flatten: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">fresh</span></pre></div> </td> </tr> <tr id="section-132"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-132">#</a> </div> <p>Trim out all falsy values from an array.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compact: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span> <span class="nx">item</span> <span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span> <span class="k">when</span> <span class="nx">item</span></pre></div> </td> </tr> <tr id="section-133"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-133">#</a> </div> <p>Return a completely flattened version of an array. Handy for getting a
|
||||
list of <code>children</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">flatten: </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">memo: </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">item</span> <span class="k">in</span> <span class="nx">array</span>
|
||||
<span class="k">if</span> <span class="nx">item</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="k">then</span> <span class="nv">memo: </span><span class="nx">memo</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span> <span class="k">else</span> <span class="nx">memo</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>
|
||||
<span class="nx">memo</span></pre></div> </td> </tr> <tr id="section-121"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-121">#</a> </div> <p>Delete a key from an object, returning the value.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">del: </span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">memo</span></pre></div> </td> </tr> <tr id="section-134"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-134">#</a> </div> <p>Delete a key from an object, returning the value. Useful when a node is
|
||||
looking for a particular method in an options hash.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">del: </span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">val: </span><span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
<span class="k">delete</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
|
||||
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-122"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-122">#</a> </div> <p>Quickie helper for a generated LiteralNode.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">literal: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">val</span></pre></div> </td> </tr> <tr id="section-135"> <td class="docs"> <div class="octowrap"> <a class="octothorpe" href="#section-135">#</a> </div> <p>Handy helper for a generating LiteralNode.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">literal: </span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">new</span> <span class="nx">LiteralNode</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<div id="flybar">
|
||||
<a id="logo" href="#top"> </a>
|
||||
<div class="navigation">
|
||||
<div class="navigation toc">
|
||||
<div class="button">
|
||||
Table of Contents
|
||||
</div>
|
||||
@@ -60,6 +60,7 @@
|
||||
<a href="#try">Try/Catch/Finally</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#strings">Multiline Strings and Heredocs</a>
|
||||
<a href="#interpolation">String Interpolation</a>
|
||||
<a href="#cake">Cake, and Cakefiles</a>
|
||||
<a href="#scripts">"text/coffeescript" Script Tags</a>
|
||||
<a href="#resources">Resources</a>
|
||||
@@ -75,7 +76,7 @@
|
||||
<div id="repl_source_wrap"><textarea id="repl_source">reverse: (string) ->
|
||||
string.split('').reverse().join ''
|
||||
|
||||
alert reverse '!tpircseeffoC'</textarea></div>
|
||||
alert reverse '.eeffoC yrT'</textarea></div>
|
||||
<pre id="repl_results"></pre>
|
||||
<button class="full_screen">go full screen</button>
|
||||
<button class="minimize">minimize</button>
|
||||
@@ -84,6 +85,23 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navigation annotated">
|
||||
<div class="button">
|
||||
Annotated Source
|
||||
</div>
|
||||
<div class="contents">
|
||||
<a href="documentation/docs/grammar.html">Grammar Rules — src/grammar</a>
|
||||
<a href="documentation/docs/lexer.html">Lexing Tokens — src/lexer</a>
|
||||
<a href="documentation/docs/rewriter.html">The Rewriter — src/rewriter</a>
|
||||
<a href="documentation/docs/nodes.html">The Syntax Tree — src/nodes</a>
|
||||
<a href="documentation/docs/scope.html">Lexical Scope — src/scope</a>
|
||||
<a href="documentation/docs/coffee-script.html">The CoffeeScript Module — src/coffee-script</a>
|
||||
<a href="documentation/docs/cake.html">Cake & Cakefiles — src/cake</a>
|
||||
<a href="documentation/docs/command.html">"coffee" Command-Line Utility — src/command</a>
|
||||
<a href="documentation/docs/optparse.html">Option Parsing — src/optparse</a>
|
||||
<a href="documentation/docs/repl.html">Interactive REPL — src/repl</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="error" style="display:none;"></div>
|
||||
</div>
|
||||
|
||||
@@ -111,7 +129,7 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.5.4">0.5.4</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.5.5">0.5.5</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -143,7 +161,7 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
|
||||
<p>
|
||||
The CoffeeScript compiler is written in pure CoffeeScript, using a
|
||||
<a href="http://github.com/jashkenas/coffee-script/blob/master/src/grammar.coffee">small DSL</a>
|
||||
<a href="documentation/docs/grammar.html">small DSL</a>
|
||||
on top of the <a href="http://github.com/zaach/jison">Jison parser generator</a>, and is available
|
||||
as a <a href="http://nodejs.org/">Node.js</a> utility. The core compiler however,
|
||||
does not depend on Node, and can be run in other server-side-JavaScript environments,
|
||||
@@ -153,11 +171,11 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
|
||||
<p>
|
||||
To install, first make sure you have a working version of
|
||||
<a href="http://nodejs.org/">Node.js</a> version 0.1.31 or higher.
|
||||
<a href="http://nodejs.org/">Node.js</a> version 0.1.31 or higher.
|
||||
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.5.4">0.5.4</a>.
|
||||
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.5.5">0.5.5</a>.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
</p>
|
||||
@@ -185,8 +203,8 @@ sudo bin/cake install</pre>
|
||||
<tr>
|
||||
<td width="25%"><code>-i, --interactive</code></td>
|
||||
<td>
|
||||
Launch an interactive CoffeeScript session to try short snippets.
|
||||
More pleasant if wrapped with
|
||||
Launch an interactive CoffeeScript session to try short snippets.
|
||||
More pleasant if wrapped with
|
||||
<a href="http://utopia.knoware.nl/~hlub/uck/rlwrap/rlwrap.html">rlwrap</a>.
|
||||
</td>
|
||||
</tr>
|
||||
@@ -226,14 +244,14 @@ sudo bin/cake install</pre>
|
||||
<td>
|
||||
Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT.
|
||||
Good for use with processes written in other languages. An example:<br />
|
||||
<tt>cat src/cake.coffee | coffee -s</tt>
|
||||
<tt>cat src/cake.coffee | coffee -sc</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-e, --eval</code></td>
|
||||
<td>
|
||||
Compile and print a little snippet of CoffeeScript directly from the
|
||||
command line. For example:<br /><tt>coffee -e "square: (x) -> x * x"</tt>
|
||||
command line. For example:<br /><tt>coffee -e "puts num for num in [10..1]"</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -619,7 +637,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<p>
|
||||
If structuring your prototypes classically isn't your cup of tea, CoffeeScript
|
||||
provides a couple of lower-level conveniences. The <tt>extends</tt> operator
|
||||
helps with proper prototype setup, as seen above, <tt>::</tt> gives you
|
||||
helps with proper prototype setup, <tt>::</tt> gives you
|
||||
quick access to an object's prototype, and <tt>super()</tt>
|
||||
is converted into a call against the immediate ancestor's method of the same name.
|
||||
</p>
|
||||
@@ -654,7 +672,7 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
|
||||
object that the current function is attached to. If you pass a function as
|
||||
as callback, or attach it to a different object, the original value of <tt>this</tt>
|
||||
will be lost. If you're not familiar with this behavior,
|
||||
will be lost. If you're not familiar with this behavior,
|
||||
<a href="http://www.digital-web.com/articles/scope_in_javascript/">this Digital Web article</a>
|
||||
gives a good overview of the quirks.
|
||||
</p>
|
||||
@@ -669,8 +687,8 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<%= code_for('fat_arrow') %>
|
||||
<p>
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
have referred to the undefined "customer" property of the DOM element,
|
||||
and trying to call <tt>purchase()</tt> on it would have raised an exception.
|
||||
have referred to the undefined "customer" property of the DOM element,
|
||||
and trying to call <tt>purchase()</tt> on it would have raised an exception.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -732,6 +750,19 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
</p>
|
||||
<%= code_for('heredocs') %>
|
||||
|
||||
<p>
|
||||
<span id="interpolation" class="bookmark"></span>
|
||||
<b class="header">String 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 marking
|
||||
them with a dollar sign.
|
||||
</p>
|
||||
<%= code_for('interpolation', 'quote') %>
|
||||
<p>
|
||||
And arbitrary expressions can be interpolated by using brackets <tt>${ ... }</tt>
|
||||
</p>
|
||||
<%= code_for('interpolation_expression', 'sentence') %>
|
||||
|
||||
<h2>
|
||||
<span id="cake" class="bookmark"></span>
|
||||
Cake, and Cakefiles
|
||||
@@ -794,9 +825,9 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<tt>bin/cake build</tt> to rebuild the CoffeeScript compiler, and <br />
|
||||
<tt>bin/cake build:parser</tt> to regenerate the Jison parser if you're
|
||||
working on the grammar. <br /><br />
|
||||
<tt>git checkout lib && bin/cake build && bin/cake build && bin/cake test</tt>
|
||||
is a good command to run when you're working on the core language. It'll refresh the lib directory
|
||||
(in case you broke something), build your altered compiler, use that to
|
||||
<tt>bin/cake build:full</tt> is a good command to run when you're working
|
||||
on the core language. It'll refresh the lib directory
|
||||
(in case you broke something), build your altered compiler, use that to
|
||||
rebuild itself (a good sanity test) and then run all of the tests. If
|
||||
they pass, there's a good chance you've made a successful change.
|
||||
</li>
|
||||
@@ -812,12 +843,12 @@ coffee --print app/scripts/*.coffee > concatenation.js</pre>
|
||||
<li>
|
||||
<b>defunkt</b>'s <a href="http://github.com/defunkt/coffee-mode">CoffeeScript Major Mode</a>
|
||||
— a Emacs major mode that provides syntax highlighting, indentation
|
||||
support, and some bonus commands. (For Vim and TextMate highlighters,
|
||||
support, and some bonus commands. (For Vim and TextMate highlighters,
|
||||
see the <tt>extras</tt> directory of the main repository.)
|
||||
</li>
|
||||
<li>
|
||||
<b>mattly</b>'s <a href="http://github.com/mattly/rack-coffee">rack-coffee</a>
|
||||
— a small Rack middleware for serving CoffeeScript files as
|
||||
— a small Rack middleware for serving CoffeeScript files as
|
||||
compiled JavaScript on the fly.
|
||||
</li>
|
||||
</ul>
|
||||
@@ -826,17 +857,26 @@ 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.5.5</b>
|
||||
String interpolation, contributed by
|
||||
<a href="http://github.com/StanAngeloff">Stan Angeloff</a>.
|
||||
Since <tt>--run</tt> has been the default since <b>0.5.3</b>, updating
|
||||
<tt>--stdio</tt> and <tt>--eval</tt> to run by default, pass <tt>--compile</tt>
|
||||
as well if you'd like to print the result.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.4</b>
|
||||
Bugfix that corrects the Node.js global constants <tt>__filename</tt> and
|
||||
<tt>__dirname</tt>. Tweaks for more flexible parsing of nested function
|
||||
literals and improperly-indented comments. Updates for the latest Node.js API.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.3</b>
|
||||
CoffeeScript now has a syntax for defining classes. Many of the core
|
||||
CoffeeScript now has a syntax for defining classes. Many of the core
|
||||
components (Nodes, Lexer, Rewriter, Scope, Optparse) are using them.
|
||||
Cakefiles can use <tt>optparse.coffee</tt> to define options for tasks.
|
||||
<tt>--run</tt> is now the default flag for the <tt>coffee</tt> command,
|
||||
|
||||
5
documentation/js/interpolation.js
Normal file
5
documentation/js/interpolation.js
Normal file
@@ -0,0 +1,5 @@
|
||||
(function(){
|
||||
var author, quote;
|
||||
author = "Wittgenstein";
|
||||
quote = "A picture is a fact. -- " + author;
|
||||
})();
|
||||
4
documentation/js/interpolation_expression.js
Normal file
4
documentation/js/interpolation_expression.js
Normal file
@@ -0,0 +1,4 @@
|
||||
(function(){
|
||||
var sentence;
|
||||
sentence = (22 / 7) + " is a decent approximation of π";
|
||||
})();
|
||||
@@ -1,5 +1,6 @@
|
||||
# Contributed by Jason Huggins
|
||||
|
||||
process.mixin require 'sys'
|
||||
http: require 'http'
|
||||
|
||||
server: http.createServer (req, res) ->
|
||||
|
||||
24
extras/CoffeeScript.tmbundle/CoffeeScript.tmPreferences
Normal file
24
extras/CoffeeScript.tmbundle/CoffeeScript.tmPreferences
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>comments</string>
|
||||
<key>scope</key>
|
||||
<string>source.coffee</string>
|
||||
<key>settings</key>
|
||||
<dict>
|
||||
<key>shellVariables</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>TM_COMMENT_START</string>
|
||||
<key>value</key>
|
||||
<string># </string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>uuid</key>
|
||||
<string>0A92C6F6-4D73-4859-B38C-4CC19CBC191F</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>commands</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>command</key>
|
||||
<string>moveRightAndModifySelection:</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>argument</key>
|
||||
<dict>
|
||||
<key>action</key>
|
||||
<string>replaceAll</string>
|
||||
<key>findInProjectIgnoreCase</key>
|
||||
<false/>
|
||||
<key>findString</key>
|
||||
<string>((?m:.){2,})|\}|([^}])</string>
|
||||
<key>ignoreCase</key>
|
||||
<false/>
|
||||
<key>regularExpression</key>
|
||||
<true/>
|
||||
<key>replaceAllScope</key>
|
||||
<string>selection</string>
|
||||
<key>replaceString</key>
|
||||
<string>$1}$2</string>
|
||||
<key>wrapAround</key>
|
||||
<false/>
|
||||
</dict>
|
||||
<key>command</key>
|
||||
<string>findWithOptions:</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>command</key>
|
||||
<string>moveLeft:</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>command</key>
|
||||
<string>moveRight:</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>keyEquivalent</key>
|
||||
<string>}</string>
|
||||
<key>name</key>
|
||||
<string>Overwrite '}' in ${ .. }</string>
|
||||
<key>scope</key>
|
||||
<string>source.coffee string.quoted.double source.coffee.embedded</string>
|
||||
<key>scopeType</key>
|
||||
<string>local</string>
|
||||
<key>uuid</key>
|
||||
<string>D7ADBF4B-B25B-4CF6-8FC0-C4FB0C3DBE64</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>content</key>
|
||||
<string>\${${1:$TM_SELECTED_TEXT}}</string>
|
||||
<key>keyEquivalent</key>
|
||||
<string>$</string>
|
||||
<key>name</key>
|
||||
<string>Embedded Code — ${…}</string>
|
||||
<key>scope</key>
|
||||
<string>string.quoted.double.coffee - string source</string>
|
||||
<key>uuid</key>
|
||||
<string>17C8BFF6-25F2-4F00-8E7E-768D3D186A23</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Symbol List: Method</string>
|
||||
<key>scope</key>
|
||||
<string>source.coffee entity.name.type.instance</string>
|
||||
<key>settings</key>
|
||||
<dict>
|
||||
<key>showInSymbolList</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>uuid</key>
|
||||
<string>B087AF2F-8946-4EA9-8409-49E7C4A2EEF0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -7,19 +7,20 @@
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>coffee</string>
|
||||
<string>Cakefile</string>
|
||||
</array>
|
||||
<key>name</key>
|
||||
<string>CoffeeScript</string>
|
||||
<key>foldingStartMarker</key>
|
||||
<string>^.*[:=] \{[^\}]*$</string>
|
||||
<key>foldingStopMarker</key>
|
||||
<string>\s*\}</string>
|
||||
<key>name</key>
|
||||
<string>CoffeeScript</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.parameter.function.coffee</string>
|
||||
@@ -43,7 +44,7 @@
|
||||
<key>comment</key>
|
||||
<string>match stuff like: a -> … </string>
|
||||
<key>match</key>
|
||||
<string>(\()([a-zA-Z0-9_?.$]*(,\s*[a-zA-Z0-9_?.$]+)*)(\))\s*((=|-)>)</string>
|
||||
<string>(\()([a-zA-Z0-9_?.\$]*(,\s*[a-zA-Z0-9_?.\$]+)*)(\))\s*((=|-)>)</string>
|
||||
<key>name</key>
|
||||
<string>meta.inline.function.coffee</string>
|
||||
</dict>
|
||||
@@ -66,45 +67,9 @@
|
||||
<key>name</key>
|
||||
<string>meta.class.instance.constructor</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?))\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(@)([a-zA-Z_$]\w*)?</string>
|
||||
<key>name</key>
|
||||
<string>variable.other.readwrite.instance.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.heredoc.coffee</string>
|
||||
<key>begin</key>
|
||||
<string>("""|''')</string>
|
||||
<key>end</key>
|
||||
<string>("""|''')</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>'</string>
|
||||
<string>("""|''')</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
@@ -114,7 +79,7 @@
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>'</string>
|
||||
<string>("""|''')</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
@@ -124,49 +89,7 @@
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.single.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>"</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>"</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.double.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
<string>string.quoted.heredoc.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
@@ -255,10 +178,67 @@
|
||||
<string>keyword.control.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.assignment.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>\b([a-zA-Z$_](\w|\$|:|\.)*\s*(?=\:))</string>
|
||||
<string>(?=[a-zA-Z\$_])([a-zA-Z\$_](\w|\$|\.)*\s*(?=(?!\::)\:(?!(\s*\(.*\))?\s*((=|-)>))))</string>
|
||||
<key>name</key>
|
||||
<string>variable.assignment.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(\[)(?=.*?\]\s*:)</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>(\]\s*:)</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>meta.variable.assignment.destructured.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#variable_name</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#instance_variable</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#single_quoted_string</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#double_quoted_string</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#numeric</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
@@ -267,6 +247,16 @@
|
||||
<string>entity.name.function.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(?=[a-zA-Z\$_])([a-zA-Z\$_](\w|\$|:|\.)*\s*(?=\:(\s*\(.*\))?\s*((=|-)>)))</string>
|
||||
<key>name</key>
|
||||
<string>meta.function.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(=|-)></string>
|
||||
<key>name</key>
|
||||
<string>storage.type.function.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
@@ -288,22 +278,45 @@
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(super|this|extends|class)\b</string>
|
||||
<string>\b(super|this|extends)\b</string>
|
||||
<key>name</key>
|
||||
<string>variable.language.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>storage.type.class.coffee</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.name.type.class.coffee</string>
|
||||
</dict>
|
||||
<key>3</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.other.inherited-class.coffee</string>
|
||||
</dict>
|
||||
<key>4</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.control.inheritance.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(class)\s+([a-zA-Z\$_]\w+)(\s+(extends)\s+[a-zA-Z\$_]\w*)?</string>
|
||||
<key>name</key>
|
||||
<string>meta.class.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(debugger|\\)\b</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(=|-)></string>
|
||||
<key>name</key>
|
||||
<string>storage.type.function.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>!|%|&|\*|\/|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\?|\|\||\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(instanceof|new|delete|typeof|and|or|is|isnt|not)\b</string>
|
||||
@@ -348,11 +361,213 @@
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\[|\]</string>
|
||||
<string>\[|\]\s*</string>
|
||||
<key>name</key>
|
||||
<string>meta.brace.square.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#instance_variable</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#single_quoted_string</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#double_quoted_string</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#numeric</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>repository</key>
|
||||
<dict>
|
||||
<key>double_quoted_string</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>"</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>"</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.double.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#interpolated_coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>instance_variable</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(@)([a-zA-Z_\$]\w*)?</string>
|
||||
<key>name</key>
|
||||
<string>variable.other.readwrite.instance.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>interpolated_coffee</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>\$\{</string>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.section.embedded.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>\}</string>
|
||||
<key>name</key>
|
||||
<string>source.coffee.embedded.source</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>$self</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.variable.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(\$)@[a-zA-Z_]\w*(\.\w+)*</string>
|
||||
<key>name</key>
|
||||
<string>variable.other.readwrite.coffee</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.variable.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(\$)(?!@)[a-zA-Z_]\w*(\.\w+)*</string>
|
||||
<key>name</key>
|
||||
<string>source.coffee.embedded.source</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>numeric</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(?<!\$)\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?(e[+\-]?[0-9]+)?))\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>single_quoted_string</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>'</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>'</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.single.coffee</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>variable_name</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.assignment.coffee</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>([a-zA-Z\$_]\w*(\.\w+)*)</string>
|
||||
<key>name</key>
|
||||
<string>variable.assignment.coffee</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>scopeName</key>
|
||||
<string>source.coffee</string>
|
||||
<key>uuid</key>
|
||||
|
||||
File diff suppressed because one or more lines are too long
230
index.html
230
index.html
@@ -16,7 +16,7 @@
|
||||
|
||||
<div id="flybar">
|
||||
<a id="logo" href="#top"> </a>
|
||||
<div class="navigation">
|
||||
<div class="navigation toc">
|
||||
<div class="button">
|
||||
Table of Contents
|
||||
</div>
|
||||
@@ -46,6 +46,7 @@
|
||||
<a href="#try">Try/Catch/Finally</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
<a href="#strings">Multiline Strings and Heredocs</a>
|
||||
<a href="#interpolation">String Interpolation</a>
|
||||
<a href="#cake">Cake, and Cakefiles</a>
|
||||
<a href="#scripts">"text/coffeescript" Script Tags</a>
|
||||
<a href="#resources">Resources</a>
|
||||
@@ -61,7 +62,7 @@
|
||||
<div id="repl_source_wrap"><textarea id="repl_source">reverse: (string) ->
|
||||
string.split('').reverse().join ''
|
||||
|
||||
alert reverse '!tpircseeffoC'</textarea></div>
|
||||
alert reverse '.eeffoC yrT'</textarea></div>
|
||||
<pre id="repl_results"></pre>
|
||||
<button class="full_screen">go full screen</button>
|
||||
<button class="minimize">minimize</button>
|
||||
@@ -70,6 +71,23 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navigation annotated">
|
||||
<div class="button">
|
||||
Annotated Source
|
||||
</div>
|
||||
<div class="contents">
|
||||
<a href="documentation/docs/grammar.html">Grammar Rules — src/grammar</a>
|
||||
<a href="documentation/docs/lexer.html">Lexing Tokens — src/lexer</a>
|
||||
<a href="documentation/docs/rewriter.html">The Rewriter — src/rewriter</a>
|
||||
<a href="documentation/docs/nodes.html">The Syntax Tree — src/nodes</a>
|
||||
<a href="documentation/docs/scope.html">Lexical Scope — src/scope</a>
|
||||
<a href="documentation/docs/coffee-script.html">The CoffeeScript Module — src/coffee-script</a>
|
||||
<a href="documentation/docs/cake.html">Cake & Cakefiles — src/cake</a>
|
||||
<a href="documentation/docs/command.html">"coffee" Command-Line Utility — src/command</a>
|
||||
<a href="documentation/docs/optparse.html">Option Parsing — src/optparse</a>
|
||||
<a href="documentation/docs/repl.html">Interactive REPL — src/repl</a>
|
||||
</div>
|
||||
</div>
|
||||
<div id="error" style="display:none;"></div>
|
||||
</div>
|
||||
|
||||
@@ -97,7 +115,7 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.5.4">0.5.4</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.5.5">0.5.5</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -108,22 +126,22 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
<p><i>CoffeeScript on the left, compiled JavaScript output on the right.</i></p>
|
||||
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> Assignment:</span>
|
||||
<span class="FunctionName">number</span><span class="Keyword">:</span> <span class="Number">42</span>
|
||||
<span class="FunctionName">opposite_day</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
|
||||
number<span class="Keyword">:</span> <span class="Number">42</span>
|
||||
opposite_day<span class="Keyword">:</span> <span class="BuiltInConstant">true</span>
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Conditions:</span>
|
||||
<span class="FunctionName">number</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">42</span> <span class="Keyword">if</span> opposite_day
|
||||
number<span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">42</span> <span class="Keyword">if</span> opposite_day
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Functions:</span>
|
||||
<span class="FunctionName">square</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">x</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> x <span class="Keyword">*</span> x
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Arrays:</span>
|
||||
<span class="FunctionName">list</span><span class="Keyword">:</span> [<span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>]
|
||||
list<span class="Keyword">:</span> [<span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>]
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Objects:</span>
|
||||
<span class="FunctionName">math</span><span class="Keyword">:</span> {
|
||||
<span class="FunctionName">root</span><span class="Keyword">:</span> Math.sqrt
|
||||
<span class="FunctionName">square</span><span class="Keyword">:</span> square
|
||||
math<span class="Keyword">:</span> {
|
||||
root<span class="Keyword">:</span> Math.sqrt
|
||||
square<span class="Keyword">:</span> square
|
||||
<span class="FunctionName">cube</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">x</span><span class="FunctionArgument">)</span> <span class="Storage">-></span> x <span class="Keyword">*</span> square x
|
||||
}
|
||||
|
||||
@@ -135,7 +153,7 @@ alert reverse '!tpircseeffoC'</textarea></div>
|
||||
alert <span class="String"><span class="String">"</span>I knew it!<span class="String">"</span></span> <span class="Keyword">if</span> elvis<span class="Keyword">?</span>
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Array comprehensions:</span>
|
||||
<span class="FunctionName">cubed_list</span><span class="Keyword">:</span> math.cube num <span class="Keyword">for</span> num <span class="Keyword">in</span> list
|
||||
cubed_list<span class="Keyword">:</span> math.cube num <span class="Keyword">for</span> num <span class="Keyword">in</span> list
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, _d, cubed_list, list, math, num, number, opposite_day, race, square;
|
||||
<span class="Comment"><span class="Comment">//</span> Assignment:</span>
|
||||
number <span class="Keyword">=</span> <span class="Number">42</span>;
|
||||
@@ -240,7 +258,7 @@ cubed_list = (function() {
|
||||
|
||||
<p>
|
||||
The CoffeeScript compiler is written in pure CoffeeScript, using a
|
||||
<a href="http://github.com/jashkenas/coffee-script/blob/master/src/grammar.coffee">small DSL</a>
|
||||
<a href="documentation/docs/grammar.html">small DSL</a>
|
||||
on top of the <a href="http://github.com/zaach/jison">Jison parser generator</a>, and is available
|
||||
as a <a href="http://nodejs.org/">Node.js</a> utility. The core compiler however,
|
||||
does not depend on Node, and can be run in other server-side-JavaScript environments,
|
||||
@@ -250,11 +268,11 @@ cubed_list = (function() {
|
||||
|
||||
<p>
|
||||
To install, first make sure you have a working version of
|
||||
<a href="http://nodejs.org/">Node.js</a> version 0.1.31 or higher.
|
||||
<a href="http://nodejs.org/">Node.js</a> version 0.1.31 or higher.
|
||||
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.5.4">0.5.4</a>.
|
||||
release: <a href="http://github.com/jashkenas/coffee-script/tarball/0.5.5">0.5.5</a>.
|
||||
To install the CoffeeScript compiler system-wide
|
||||
under <tt>/usr/local</tt>, open the directory and run:
|
||||
</p>
|
||||
@@ -282,8 +300,8 @@ sudo bin/cake install</pre>
|
||||
<tr>
|
||||
<td width="25%"><code>-i, --interactive</code></td>
|
||||
<td>
|
||||
Launch an interactive CoffeeScript session to try short snippets.
|
||||
More pleasant if wrapped with
|
||||
Launch an interactive CoffeeScript session to try short snippets.
|
||||
More pleasant if wrapped with
|
||||
<a href="http://utopia.knoware.nl/~hlub/uck/rlwrap/rlwrap.html">rlwrap</a>.
|
||||
</td>
|
||||
</tr>
|
||||
@@ -323,14 +341,14 @@ sudo bin/cake install</pre>
|
||||
<td>
|
||||
Pipe in CoffeeScript to STDIN and get back JavaScript over STDOUT.
|
||||
Good for use with processes written in other languages. An example:<br />
|
||||
<tt>cat src/cake.coffee | coffee -s</tt>
|
||||
<tt>cat src/cake.coffee | coffee -sc</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>-e, --eval</code></td>
|
||||
<td>
|
||||
Compile and print a little snippet of CoffeeScript directly from the
|
||||
command line. For example:<br /><tt>coffee -e "square: (x) -> x * x"</tt>
|
||||
command line. For example:<br /><tt>coffee -e "puts num for num in [10..1]"</tt>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -457,8 +475,8 @@ cube = function cube(x) {
|
||||
mathy things. While colons are preferred, the two may be used interchangeably,
|
||||
even within object literals.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">greeting</span><span class="Keyword">:</span> <span class="String"><span class="String">"</span>Hello CoffeeScript<span class="String">"</span></span>
|
||||
<span class="FunctionName">difficulty</span><span class="Keyword">:</span> <span class="Number">0.5</span>
|
||||
<div class='code'><pre class="idle">greeting<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Hello CoffeeScript<span class="String">"</span></span>
|
||||
difficulty<span class="Keyword">:</span> <span class="Number">0.5</span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> difficulty, greeting;
|
||||
greeting <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Hello CoffeeScript<span class="String">"</span></span>;
|
||||
difficulty <span class="Keyword">=</span> <span class="Number">0.5</span>;
|
||||
@@ -480,15 +498,15 @@ difficulty = 0.5;
|
||||
assigning local variables, and can be moved around freely. Feel free to mix
|
||||
and match the two styles.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">song</span><span class="Keyword">:</span> [<span class="String"><span class="String">"</span>do<span class="String">"</span></span>, <span class="String"><span class="String">"</span>re<span class="String">"</span></span>, <span class="String"><span class="String">"</span>mi<span class="String">"</span></span>, <span class="String"><span class="String">"</span>fa<span class="String">"</span></span>, <span class="String"><span class="String">"</span>so<span class="String">"</span></span>]
|
||||
<div class='code'><pre class="idle">song<span class="Keyword">:</span> [<span class="String"><span class="String">"</span>do<span class="String">"</span></span>, <span class="String"><span class="String">"</span>re<span class="String">"</span></span>, <span class="String"><span class="String">"</span>mi<span class="String">"</span></span>, <span class="String"><span class="String">"</span>fa<span class="String">"</span></span>, <span class="String"><span class="String">"</span>so<span class="String">"</span></span>]
|
||||
|
||||
<span class="FunctionName">ages</span><span class="Keyword">:</span> {
|
||||
<span class="FunctionName">max</span><span class="Keyword">:</span> <span class="Number">10</span>
|
||||
<span class="FunctionName">ida</span><span class="Keyword">:</span> <span class="Number">9</span>
|
||||
<span class="FunctionName">tim</span><span class="Keyword">:</span> <span class="Number">11</span>
|
||||
ages<span class="Keyword">:</span> {
|
||||
max<span class="Keyword">:</span> <span class="Number">10</span>
|
||||
ida<span class="Keyword">:</span> <span class="Number">9</span>
|
||||
tim<span class="Keyword">:</span> <span class="Number">11</span>
|
||||
}
|
||||
|
||||
<span class="FunctionName">matrix</span><span class="Keyword">:</span> [
|
||||
matrix<span class="Keyword">:</span> [
|
||||
<span class="Number">1</span>, <span class="Number">0</span>, <span class="Number">1</span>
|
||||
<span class="Number">0</span>, <span class="Number">0</span>, <span class="Number">1</span>
|
||||
<span class="Number">1</span>, <span class="Number">1</span>, <span class="Number">0</span>
|
||||
@@ -518,11 +536,11 @@ matrix = [1, 0, 1, 0, 0, 1, 1, 1, 0];
|
||||
are properly declared within lexical scope — you never need to write
|
||||
<tt>var</tt> yourself.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">num</span><span class="Keyword">:</span> <span class="Number">1</span>
|
||||
<div class='code'><pre class="idle">num<span class="Keyword">:</span> <span class="Number">1</span>
|
||||
<span class="FunctionName">change_numbers</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="FunctionName">new_num</span><span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">1</span>
|
||||
<span class="FunctionName">num</span><span class="Keyword">:</span> <span class="Number">10</span>
|
||||
<span class="FunctionName">new_num</span><span class="Keyword">:</span> change_numbers()
|
||||
new_num<span class="Keyword">:</span> <span class="Keyword">-</span><span class="Number">1</span>
|
||||
num<span class="Keyword">:</span> <span class="Number">10</span>
|
||||
new_num<span class="Keyword">:</span> change_numbers()
|
||||
</pre><pre class="idle"><span class="Storage">var</span> change_numbers, new_num, num;
|
||||
num <span class="Keyword">=</span> <span class="Number">1</span>;
|
||||
change_numbers <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">change_numbers</span>() {
|
||||
@@ -575,13 +593,13 @@ new_num = change_numbers();
|
||||
CoffeeScript will compile <b>if</b> statements using the ternary operator
|
||||
when possible, to make it easier to use the result as an expression.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">mood</span><span class="Keyword">:</span> greatly_improved <span class="Keyword">if</span> singing
|
||||
<div class='code'><pre class="idle">mood<span class="Keyword">:</span> greatly_improved <span class="Keyword">if</span> singing
|
||||
|
||||
<span class="Keyword">if</span> happy <span class="Keyword">and</span> knows_it
|
||||
claps_hands()
|
||||
cha_cha_cha()
|
||||
|
||||
<span class="FunctionName">date</span><span class="Keyword">:</span> <span class="Keyword">if</span> friday <span class="Keyword">then</span> sue <span class="Keyword">else</span> jill
|
||||
date<span class="Keyword">:</span> <span class="Keyword">if</span> friday <span class="Keyword">then</span> sue <span class="Keyword">else</span> jill
|
||||
|
||||
expensive <span class="Keyword">||</span><span class="Keyword">=</span> do_the_math()
|
||||
</pre><pre class="idle"><span class="Storage">var</span> date, expensive, mood;
|
||||
@@ -636,7 +654,7 @@ expensive <span class="Keyword">=</span> expensive <span class="Keyword">||</spa
|
||||
</p>
|
||||
<div class='code'><pre class="idle">launch() <span class="Keyword">if</span> ignition <span class="Keyword">is</span> <span class="BuiltInConstant">on</span>
|
||||
|
||||
<span class="FunctionName">volume</span><span class="Keyword">:</span> <span class="Number">10</span> <span class="Keyword">if</span> band <span class="Keyword">isnt</span> spinal_tap
|
||||
volume<span class="Keyword">:</span> <span class="Number">10</span> <span class="Keyword">if</span> band <span class="Keyword">isnt</span> spinal_tap
|
||||
|
||||
let_the_wild_rumpus_begin() <span class="Keyword">unless</span> answer <span class="Keyword">is</span> <span class="BuiltInConstant">no</span>
|
||||
|
||||
@@ -665,14 +683,14 @@ car.speed <span class="Keyword"><</span> speed_limit ? accelerate() : <span c
|
||||
splats <tt>...</tt>, both for function definition as well as invocation,
|
||||
making variable numbers of arguments a little bit more palatable.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">gold</span><span class="Keyword">:</span> <span class="FunctionName">silver</span><span class="Keyword">:</span> <span class="FunctionName">the_field</span><span class="Keyword">:</span> <span class="String"><span class="String">"</span>unknown<span class="String">"</span></span>
|
||||
<div class='code'><pre class="idle">gold<span class="Keyword">:</span> silver<span class="Keyword">:</span> the_field<span class="Keyword">:</span> <span class="String"><span class="String">"</span>unknown<span class="String">"</span></span>
|
||||
|
||||
<span class="FunctionName">award_medals</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">first, second, rest...</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="FunctionName">gold</span><span class="Keyword">:</span> first
|
||||
<span class="FunctionName">silver</span><span class="Keyword">:</span> second
|
||||
<span class="FunctionName">the_field</span><span class="Keyword">:</span> rest
|
||||
gold<span class="Keyword">:</span> first
|
||||
silver<span class="Keyword">:</span> second
|
||||
the_field<span class="Keyword">:</span> rest
|
||||
|
||||
<span class="FunctionName">contenders</span><span class="Keyword">:</span> [
|
||||
contenders<span class="Keyword">:</span> [
|
||||
<span class="String"><span class="String">"</span>Michael Phelps<span class="String">"</span></span>
|
||||
<span class="String"><span class="String">"</span>Liu Xiang<span class="String">"</span></span>
|
||||
<span class="String"><span class="String">"</span>Yao Ming<span class="String">"</span></span>
|
||||
@@ -760,8 +778,8 @@ backwards("stairway", "to", "heaven");
|
||||
<span class="Keyword">while</span> supply <span class="Keyword"><</span> demand <span class="Keyword">then</span> sell()
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Nursery Rhyme</span>
|
||||
<span class="FunctionName">num</span><span class="Keyword">:</span> <span class="Number">6</span>
|
||||
<span class="FunctionName">lyrics</span><span class="Keyword">:</span> <span class="Keyword">while</span> num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>
|
||||
num<span class="Keyword">:</span> <span class="Number">6</span>
|
||||
lyrics<span class="Keyword">:</span> <span class="Keyword">while</span> num <span class="Keyword">-</span><span class="Keyword">=</span> <span class="Number">1</span>
|
||||
num <span class="Keyword">+</span> <span class="String"><span class="String">"</span> little monkeys, jumping on the bed.</span>
|
||||
<span class="String"> One fell out and bumped his head.<span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, lyrics, num;
|
||||
@@ -823,7 +841,7 @@ One fell out and bumped his head.");
|
||||
would use a loop, <b>each</b>/<b>forEach</b>, <b>map</b>, or <b>select</b>/<b>filter</b>.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> Eat lunch.</span>
|
||||
<span class="FunctionName">lunch</span><span class="Keyword">:</span> eat food <span class="Keyword">for</span> food <span class="Keyword">in</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>]
|
||||
lunch<span class="Keyword">:</span> eat food <span class="Keyword">for</span> food <span class="Keyword">in</span> [<span class="String"><span class="String">'</span>toast<span class="String">'</span></span>, <span class="String"><span class="String">'</span>cheese<span class="String">'</span></span>, <span class="String"><span class="String">'</span>wine<span class="String">'</span></span>]
|
||||
|
||||
<span class="Comment"><span class="Comment">#</span> Naive collision detection.</span>
|
||||
<span class="Keyword">for</span> roid <span class="Keyword">in</span> asteroids
|
||||
@@ -860,11 +878,11 @@ _e <span class="Keyword">=</span> asteroids;
|
||||
end of your comprehension. (The long line-breaking "for" definitions in
|
||||
the compiled JS below allow ranges to count downwards, as well as upwards).
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">countdown</span><span class="Keyword">:</span> num <span class="Keyword">for</span> num <span class="Keyword">in</span> [<span class="Number">10</span>..<span class="Number">1</span>]
|
||||
<div class='code'><pre class="idle">countdown<span class="Keyword">:</span> num <span class="Keyword">for</span> num <span class="Keyword">in</span> [<span class="Number">10</span>..<span class="Number">1</span>]
|
||||
|
||||
<span class="FunctionName">egg_delivery</span><span class="Keyword">:</span> <span class="Storage">-></span>
|
||||
<span class="Keyword">for</span> i <span class="Keyword">in</span> [<span class="Number">0</span>...eggs.length] <span class="Keyword">by</span> <span class="Number">12</span>
|
||||
<span class="FunctionName">dozen_eggs</span><span class="Keyword">:</span> eggs[i...i<span class="Keyword">+</span><span class="Number">12</span>]
|
||||
dozen_eggs<span class="Keyword">:</span> eggs[i...i<span class="Keyword">+</span><span class="Number">12</span>]
|
||||
deliver <span class="Keyword">new</span> <span class="TypeName">egg_carton</span>(dozen)
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, _d, _e, countdown, egg_delivery, num;
|
||||
countdown <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
@@ -910,9 +928,9 @@ egg_delivery = function egg_delivery() {
|
||||
an object. Use <tt>of</tt> to signal comprehension over the properties of
|
||||
an object instead of the values in an array.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">years_old</span><span class="Keyword">:</span> {<span class="FunctionName">max</span><span class="Keyword">:</span> <span class="Number">10</span>, <span class="FunctionName">ida</span><span class="Keyword">:</span> <span class="Number">9</span>, <span class="FunctionName">tim</span><span class="Keyword">:</span> <span class="Number">11</span>}
|
||||
<div class='code'><pre class="idle">years_old<span class="Keyword">:</span> {max<span class="Keyword">:</span> <span class="Number">10</span>, ida<span class="Keyword">:</span> <span class="Number">9</span>, tim<span class="Keyword">:</span> <span class="Number">11</span>}
|
||||
|
||||
<span class="FunctionName">ages</span><span class="Keyword">:</span> <span class="Keyword">for</span> child, age <span class="Keyword">of</span> years_old
|
||||
ages<span class="Keyword">:</span> <span class="Keyword">for</span> child, age <span class="Keyword">of</span> years_old
|
||||
child <span class="Keyword">+</span> <span class="String"><span class="String">"</span> is <span class="String">"</span></span> <span class="Keyword">+</span> age
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, age, ages, child, years_old;
|
||||
<span class="Storage">var</span> __hasProp <span class="Keyword">=</span> <span class="LibraryClassType">Object</span>.<span class="LibraryConstant">prototype</span>.hasOwnProperty;
|
||||
@@ -956,11 +974,11 @@ ages = (function() {
|
||||
the slice, and the second is the index of the last one. Three dots signify
|
||||
a range that excludes the end.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">numbers</span><span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
|
||||
<div class='code'><pre class="idle">numbers<span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
|
||||
|
||||
<span class="FunctionName">three_to_six</span><span class="Keyword">:</span> numbers[<span class="Number">3</span>..<span class="Number">6</span>]
|
||||
three_to_six<span class="Keyword">:</span> numbers[<span class="Number">3</span>..<span class="Number">6</span>]
|
||||
|
||||
<span class="FunctionName">numbers_copy</span><span class="Keyword">:</span> numbers[<span class="Number">0</span>...numbers.length]
|
||||
numbers_copy<span class="Keyword">:</span> numbers[<span class="Number">0</span>...numbers.length]
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> numbers, numbers_copy, three_to_six;
|
||||
numbers <span class="Keyword">=</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>];
|
||||
@@ -975,9 +993,9 @@ numbers_copy = numbers.slice(0, numbers.length);
|
||||
The same syntax can be used with assignment to replace a segment of an
|
||||
array with new values (to splice it).
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">numbers</span><span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
|
||||
<div class='code'><pre class="idle">numbers<span class="Keyword">:</span> [<span class="Number">0</span>, <span class="Number">1</span>, <span class="Number">2</span>, <span class="Number">3</span>, <span class="Number">4</span>, <span class="Number">5</span>, <span class="Number">6</span>, <span class="Number">7</span>, <span class="Number">8</span>, <span class="Number">9</span>]
|
||||
|
||||
numbers[<span class="Number">3</span>..<span class="Number">6</span>]<span class="Keyword">:</span> [<span class="Keyword">-</span><span class="Number">3</span>, <span class="Keyword">-</span><span class="Number">4</span>, <span class="Keyword">-</span><span class="Number">5</span>, <span class="Keyword">-</span><span class="Number">6</span>]
|
||||
numbers<span class="Keyword">[</span><span class="Number">3</span>..<span class="Number">6</span><span class="Keyword">]:</span> [<span class="Keyword">-</span><span class="Number">3</span>, <span class="Keyword">-</span><span class="Number">4</span>, <span class="Keyword">-</span><span class="Number">5</span>, <span class="Keyword">-</span><span class="Number">6</span>]
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> numbers;
|
||||
@@ -1006,7 +1024,7 @@ numbers.splice.apply(numbers, [3, 6 - 3 + 1].concat([-3, -4, -5, -6]));
|
||||
<span class="Keyword">else</span>
|
||||
<span class="String"><span class="String">"</span>C<span class="String">"</span></span>
|
||||
|
||||
<span class="FunctionName">eldest</span><span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Number">24</span> <span class="Keyword">></span> <span class="Number">21</span> <span class="Keyword">then</span> <span class="String"><span class="String">"</span>Liz<span class="String">"</span></span> <span class="Keyword">else</span> <span class="String"><span class="String">"</span>Ike<span class="String">"</span></span>
|
||||
eldest<span class="Keyword">:</span> <span class="Keyword">if</span> <span class="Number">24</span> <span class="Keyword">></span> <span class="Number">21</span> <span class="Keyword">then</span> <span class="String"><span class="String">"</span>Liz<span class="String">"</span></span> <span class="Keyword">else</span> <span class="String"><span class="String">"</span>Ike<span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> eldest, grade;
|
||||
grade <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">grade</span>(<span class="FunctionArgument">student</span>) {
|
||||
<span class="Keyword">if</span> (student.excellent_work) {
|
||||
@@ -1039,7 +1057,7 @@ eldest = 24 > 21 ? "Liz" : "Ike";
|
||||
Because variable declarations occur at the top of scope, assignment can
|
||||
be used within expressions, even for variables that haven't been seen before:
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">six</span><span class="Keyword">:</span> (<span class="FunctionName">one</span><span class="Keyword">:</span> <span class="Number">1</span>) <span class="Keyword">+</span> (<span class="FunctionName">two</span><span class="Keyword">:</span> <span class="Number">2</span>) <span class="Keyword">+</span> (<span class="FunctionName">three</span><span class="Keyword">:</span> <span class="Number">3</span>)
|
||||
<div class='code'><pre class="idle">six<span class="Keyword">:</span> (one<span class="Keyword">:</span> <span class="Number">1</span>) <span class="Keyword">+</span> (two<span class="Keyword">:</span> <span class="Number">2</span>) <span class="Keyword">+</span> (three<span class="Keyword">:</span> <span class="Number">3</span>)
|
||||
</pre><pre class="idle"><span class="Storage">var</span> one, six, three, two;
|
||||
six <span class="Keyword">=</span> ((one <span class="Keyword">=</span> <span class="Number">1</span>)) <span class="Keyword">+</span> ((two <span class="Keyword">=</span> <span class="Number">2</span>)) <span class="Keyword">+</span> ((three <span class="Keyword">=</span> <span class="Number">3</span>));
|
||||
</pre><button onclick='javascript: var one, six, three, two;
|
||||
@@ -1053,7 +1071,7 @@ six = ((one = 1)) + ((two = 2)) + ((three = 3));
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">#</span> The first ten global properties.</span>
|
||||
|
||||
<span class="FunctionName">globals</span><span class="Keyword">:</span> (name <span class="Keyword">for</span> name <span class="Keyword">of</span> window)[<span class="Number">0</span>...<span class="Number">10</span>]
|
||||
globals<span class="Keyword">:</span> (name <span class="Keyword">for</span> name <span class="Keyword">of</span> window)[<span class="Number">0</span>...<span class="Number">10</span>]
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, globals, name;
|
||||
<span class="Storage">var</span> __hasProp <span class="Keyword">=</span> <span class="LibraryClassType">Object</span>.<span class="LibraryConstant">prototype</span>.hasOwnProperty;
|
||||
<span class="Comment"><span class="Comment">//</span> The first ten global properties.</span>
|
||||
@@ -1120,7 +1138,7 @@ globals = (function() {
|
||||
It can also be used for safer conditional assignment than <tt>||=</tt>
|
||||
provides, for cases where you may be handling numbers or strings.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">solipsism</span><span class="Keyword">:</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> mind<span class="Keyword">?</span> <span class="Keyword">and</span> <span class="Keyword">not</span> world<span class="Keyword">?</span>
|
||||
<div class='code'><pre class="idle">solipsism<span class="Keyword">:</span> <span class="BuiltInConstant">true</span> <span class="Keyword">if</span> mind<span class="Keyword">?</span> <span class="Keyword">and</span> <span class="Keyword">not</span> world<span class="Keyword">?</span>
|
||||
|
||||
speed <span class="Keyword">?</span><span class="Keyword">=</span> <span class="Number">140</span>
|
||||
|
||||
@@ -1179,11 +1197,11 @@ speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;
|
||||
set the superclass, assign prototypal properties, and define the constructor,
|
||||
in a single assignable expression.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Variable">class</span> Animal
|
||||
<div class='code'><pre class="idle"><span class="Storage">class</span> <span class="TypeName">Animal</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">-></span>
|
||||
alert <span class="Variable">@name</span> <span class="Keyword">+</span> <span class="String"><span class="String">"</span> moved <span class="String">"</span></span> <span class="Keyword">+</span> meters <span class="Keyword">+</span> <span class="String"><span class="String">"</span>m.<span class="String">"</span></span>
|
||||
|
||||
<span class="Variable">class</span> Snake <span class="Variable">extends</span> Animal
|
||||
<span class="Storage">class</span> <span class="TypeName">Snake</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
|
||||
<span class="FunctionName">constructor</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="Variable">@name</span><span class="Keyword">:</span> name
|
||||
|
||||
@@ -1191,7 +1209,7 @@ speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;
|
||||
alert <span class="String"><span class="String">"</span>Slithering...<span class="String">"</span></span>
|
||||
<span class="Variable">super</span> <span class="Number">5</span>
|
||||
|
||||
<span class="Variable">class</span> Horse <span class="Variable">extends</span> Animal
|
||||
<span class="Storage">class</span> <span class="TypeName">Horse</span><span class="InheritedClass"> <span class="Keyword">extends</span> Animal</span>
|
||||
<span class="FunctionName">constructor</span><span class="Keyword">:</span> <span class="FunctionArgument">(</span><span class="FunctionArgument">name</span><span class="FunctionArgument">)</span> <span class="Storage">-></span>
|
||||
<span class="Variable">@name</span><span class="Keyword">:</span> name
|
||||
|
||||
@@ -1199,8 +1217,8 @@ speed = (typeof speed !== "undefined" && speed !== null) ? speed : 140;
|
||||
alert <span class="String"><span class="String">"</span>Galloping...<span class="String">"</span></span>
|
||||
<span class="Variable">super</span> <span class="Number">45</span>
|
||||
|
||||
<span class="FunctionName">sam</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Snake</span> <span class="String"><span class="String">"</span>Sammy the Python<span class="String">"</span></span>
|
||||
<span class="FunctionName">tom</span><span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Horse</span> <span class="String"><span class="String">"</span>Tommy the Palomino<span class="String">"</span></span>
|
||||
sam<span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Snake</span> <span class="String"><span class="String">"</span>Sammy the Python<span class="String">"</span></span>
|
||||
tom<span class="Keyword">:</span> <span class="Keyword">new</span> <span class="TypeName">Horse</span> <span class="String"><span class="String">"</span>Tommy the Palomino<span class="String">"</span></span>
|
||||
|
||||
sam.move()
|
||||
tom.move()
|
||||
@@ -1280,7 +1298,7 @@ tom.move();
|
||||
<p>
|
||||
If structuring your prototypes classically isn't your cup of tea, CoffeeScript
|
||||
provides a couple of lower-level conveniences. The <tt>extends</tt> operator
|
||||
helps with proper prototype setup, as seen above, <tt>::</tt> gives you
|
||||
helps with proper prototype setup, <tt>::</tt> gives you
|
||||
quick access to an object's prototype, and <tt>super()</tt>
|
||||
is converted into a call against the immediate ancestor's method of the same name.
|
||||
</p>
|
||||
@@ -1305,10 +1323,10 @@ tom.move();
|
||||
on the right to the variables on the left. In the simplest case, it can be
|
||||
used for parallel assignment:
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">bait</span><span class="Keyword">:</span> <span class="Number">1000</span>
|
||||
<span class="FunctionName">and_switch</span><span class="Keyword">:</span> <span class="Number">0</span>
|
||||
<div class='code'><pre class="idle">bait<span class="Keyword">:</span> <span class="Number">1000</span>
|
||||
and_switch<span class="Keyword">:</span> <span class="Number">0</span>
|
||||
|
||||
[bait, and_switch]<span class="Keyword">:</span> [and_switch, bait]
|
||||
<span class="Keyword">[</span>bait, and_switch<span class="Keyword">]:</span> [and_switch, bait]
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, and_switch, bait;
|
||||
bait <span class="Keyword">=</span> <span class="Number">1000</span>;
|
||||
and_switch <span class="Keyword">=</span> <span class="Number">0</span>;
|
||||
@@ -1330,7 +1348,7 @@ and_switch = _a[1];
|
||||
<span class="Comment"><span class="Comment">#</span> Make an Ajax request to fetch the weather...</span>
|
||||
[location, <span class="Number">72</span>, <span class="String"><span class="String">"</span>Mostly Sunny<span class="String">"</span></span>]
|
||||
|
||||
[city, temp, forecast]<span class="Keyword">:</span> weather_report <span class="String"><span class="String">"</span>Berkeley, CA<span class="String">"</span></span>
|
||||
<span class="Keyword">[</span>city, temp, forecast<span class="Keyword">]:</span> weather_report <span class="String"><span class="String">"</span>Berkeley, CA<span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, city, forecast, temp, weather_report;
|
||||
weather_report <span class="Keyword">=</span> <span class="Storage">function</span> <span class="FunctionName">weather_report</span>(<span class="FunctionArgument">location</span>) {
|
||||
<span class="Comment"><span class="Comment">//</span> Make an Ajax request to fetch the weather...</span>
|
||||
@@ -1354,19 +1372,19 @@ forecast = _a[2];
|
||||
Pattern matching can be used with any depth of array and object nesting,
|
||||
to help pull out deeply nested properties.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">futurists</span><span class="Keyword">:</span> {
|
||||
<span class="FunctionName">sculptor</span><span class="Keyword">:</span> <span class="String"><span class="String">"</span>Umberto Boccioni<span class="String">"</span></span>
|
||||
<span class="FunctionName">painter</span><span class="Keyword">:</span> <span class="String"><span class="String">"</span>Vladimir Burliuk<span class="String">"</span></span>
|
||||
<span class="FunctionName">poet</span><span class="Keyword">:</span> {
|
||||
<span class="FunctionName">name</span><span class="Keyword">:</span> <span class="String"><span class="String">"</span>F.T. Marinetti<span class="String">"</span></span>
|
||||
<span class="FunctionName">address</span><span class="Keyword">:</span> [
|
||||
<div class='code'><pre class="idle">futurists<span class="Keyword">:</span> {
|
||||
sculptor<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Umberto Boccioni<span class="String">"</span></span>
|
||||
painter<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Vladimir Burliuk<span class="String">"</span></span>
|
||||
poet<span class="Keyword">:</span> {
|
||||
name<span class="Keyword">:</span> <span class="String"><span class="String">"</span>F.T. Marinetti<span class="String">"</span></span>
|
||||
address<span class="Keyword">:</span> [
|
||||
<span class="String"><span class="String">"</span>Via Roma 42R<span class="String">"</span></span>
|
||||
<span class="String"><span class="String">"</span>Bellagio, Italy 22021<span class="String">"</span></span>
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
{<span class="FunctionName">poet</span><span class="Keyword">:</span> {<span class="FunctionName">name</span><span class="Keyword">:</span> poet, <span class="FunctionName">address</span><span class="Keyword">:</span> [street, city]}}<span class="Keyword">:</span> futurists
|
||||
{poet<span class="Keyword">:</span> {name<span class="Keyword">:</span> poet, address<span class="Keyword">:</span> [street, city]}}<span class="Keyword">:</span> futurists
|
||||
</pre><pre class="idle"><span class="Storage">var</span> _a, _b, _c, city, futurists, poet, street;
|
||||
futurists <span class="Keyword">=</span> {
|
||||
sculptor: <span class="String"><span class="String">"</span>Umberto Boccioni<span class="String">"</span></span>,
|
||||
@@ -1405,7 +1423,7 @@ city = _c[1];
|
||||
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
|
||||
object that the current function is attached to. If you pass a function as
|
||||
as callback, or attach it to a different object, the original value of <tt>this</tt>
|
||||
will be lost. If you're not familiar with this behavior,
|
||||
will be lost. If you're not familiar with this behavior,
|
||||
<a href="http://www.digital-web.com/articles/scope_in_javascript/">this Digital Web article</a>
|
||||
gives a good overview of the quirks.
|
||||
</p>
|
||||
@@ -1439,8 +1457,8 @@ Account <span class="Keyword">=</span> <span class="Storage">function</span> <sp
|
||||
</pre><br class='clear' /></div>
|
||||
<p>
|
||||
If we had used <tt>-></tt> in the callback above, <tt>@customer</tt> would
|
||||
have referred to the undefined "customer" property of the DOM element,
|
||||
and trying to call <tt>purchase()</tt> on it would have raised an exception.
|
||||
have referred to the undefined "customer" property of the DOM element,
|
||||
and trying to call <tt>purchase()</tt> on it would have raised an exception.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -1450,7 +1468,7 @@ Account <span class="Keyword">=</span> <span class="Storage">function</span> <sp
|
||||
snippets of JavaScript within your CoffeeScript, you can
|
||||
use backticks to pass it straight through.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">hi</span><span class="Keyword">:</span> <span class="String"><span class="String">`</span>function() {</span>
|
||||
<div class='code'><pre class="idle">hi<span class="Keyword">:</span> <span class="String"><span class="String">`</span>function() {</span>
|
||||
<span class="String"> return [document.title, "Hello JavaScript"].join(": ");</span>
|
||||
<span class="String">}<span class="String">`</span></span>
|
||||
|
||||
@@ -1540,9 +1558,9 @@ return [document.title, "Hello JavaScript"].join(": ");
|
||||
from Python — making it easy to test if a value falls within a
|
||||
certain range.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">cholesterol</span><span class="Keyword">:</span> <span class="Number">127</span>
|
||||
<div class='code'><pre class="idle">cholesterol<span class="Keyword">:</span> <span class="Number">127</span>
|
||||
|
||||
<span class="FunctionName">healthy</span><span class="Keyword">:</span> <span class="Number">200</span> <span class="Keyword">></span> cholesterol <span class="Keyword">></span> <span class="Number">60</span>
|
||||
healthy<span class="Keyword">:</span> <span class="Number">200</span> <span class="Keyword">></span> cholesterol <span class="Keyword">></span> <span class="Number">60</span>
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> cholesterol, healthy;
|
||||
@@ -1558,7 +1576,7 @@ healthy = (200 > cholesterol) && (cholesterol > 60);
|
||||
<b class="header">Multiline Strings and Heredocs</b>
|
||||
Multiline strings are allowed in CoffeeScript.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">moby_dick</span><span class="Keyword">:</span> <span class="String"><span class="String">"</span>Call me Ishmael. Some years ago --</span>
|
||||
<div class='code'><pre class="idle">moby_dick<span class="Keyword">:</span> <span class="String"><span class="String">"</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>
|
||||
@@ -1587,7 +1605,7 @@ world...";
|
||||
indentation level that begins the heredoc is maintained throughout, so
|
||||
you can keep it all aligned with the body of your code.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="FunctionName">html</span><span class="Keyword">:</span> <span class="String"><span class="String">'''</span></span>
|
||||
<div class='code'><pre class="idle">html<span class="Keyword">:</span> <span class="String"><span class="String">'''</span></span>
|
||||
<span class="String"> <strong></span>
|
||||
<span class="String"> cup of coffeescript</span>
|
||||
<span class="String"> </strong></span>
|
||||
@@ -1596,6 +1614,35 @@ world...";
|
||||
html <span class="Keyword">=</span> <span class="String"><span class="String">"</span><strong><span class="UserDefinedConstant">\n</span> cup of coffeescript<span class="UserDefinedConstant">\n</span></strong><span class="String">"</span></span>;
|
||||
</pre><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="interpolation" class="bookmark"></span>
|
||||
<b class="header">String 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 marking
|
||||
them with a dollar sign.
|
||||
</p>
|
||||
<div class='code'><pre class="idle">author<span class="Keyword">:</span> <span class="String"><span class="String">"</span>Wittgenstein<span class="String">"</span></span>
|
||||
quote<span class="Keyword">:</span> <span class="String"><span class="String">"</span>A picture is a fact. -- <span class="String"><span class="String">$</span>author</span><span class="String">"</span></span>
|
||||
</pre><pre class="idle"><span class="Storage">var</span> author, quote;
|
||||
author <span class="Keyword">=</span> <span class="String"><span class="String">"</span>Wittgenstein<span class="String">"</span></span>;
|
||||
quote <span class="Keyword">=</span> <span class="String"><span class="String">"</span>A picture is a fact. -- <span class="String">"</span></span> <span class="Keyword">+</span> author;
|
||||
</pre><button onclick='javascript: var author, quote;
|
||||
author = "Wittgenstein";
|
||||
quote = "A picture is a fact. -- " + author;
|
||||
;alert(quote);'>run: quote</button><br class='clear' /></div>
|
||||
<p>
|
||||
And arbitrary expressions can be interpolated by using brackets <tt>${ ... }</tt>
|
||||
</p>
|
||||
<div class='code'><pre class="idle">sentence<span class="Keyword">:</span> <span class="String"><span class="String">"</span><span class="String"><span class="String">${</span> <span class="Number">22</span> <span class="Keyword">/</span> <span class="Number">7</span> <span class="String">}</span></span> is a decent approximation of π<span class="String">"</span></span>
|
||||
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> sentence;
|
||||
sentence <span class="Keyword">=</span> (<span class="Number">22</span> / <span class="Number">7</span>) <span class="Keyword">+</span> <span class="String"><span class="String">"</span> is a decent approximation of π<span class="String">"</span></span>;
|
||||
</pre><button onclick='javascript: var sentence;
|
||||
sentence = (22 / 7) + " is a decent approximation of π";
|
||||
;alert(sentence);'>run: sentence</button><br class='clear' /></div>
|
||||
|
||||
<h2>
|
||||
<span id="cake" class="bookmark"></span>
|
||||
Cake, and Cakefiles
|
||||
@@ -1675,9 +1722,9 @@ task(<span class="String"><span class="String">'</span>test<span class="String">
|
||||
<tt>bin/cake build</tt> to rebuild the CoffeeScript compiler, and <br />
|
||||
<tt>bin/cake build:parser</tt> to regenerate the Jison parser if you're
|
||||
working on the grammar. <br /><br />
|
||||
<tt>git checkout lib && bin/cake build && bin/cake build && bin/cake test</tt>
|
||||
is a good command to run when you're working on the core language. It'll refresh the lib directory
|
||||
(in case you broke something), build your altered compiler, use that to
|
||||
<tt>bin/cake build:full</tt> is a good command to run when you're working
|
||||
on the core language. It'll refresh the lib directory
|
||||
(in case you broke something), build your altered compiler, use that to
|
||||
rebuild itself (a good sanity test) and then run all of the tests. If
|
||||
they pass, there's a good chance you've made a successful change.
|
||||
</li>
|
||||
@@ -1693,12 +1740,12 @@ task(<span class="String"><span class="String">'</span>test<span class="String">
|
||||
<li>
|
||||
<b>defunkt</b>'s <a href="http://github.com/defunkt/coffee-mode">CoffeeScript Major Mode</a>
|
||||
— a Emacs major mode that provides syntax highlighting, indentation
|
||||
support, and some bonus commands. (For Vim and TextMate highlighters,
|
||||
support, and some bonus commands. (For Vim and TextMate highlighters,
|
||||
see the <tt>extras</tt> directory of the main repository.)
|
||||
</li>
|
||||
<li>
|
||||
<b>mattly</b>'s <a href="http://github.com/mattly/rack-coffee">rack-coffee</a>
|
||||
— a small Rack middleware for serving CoffeeScript files as
|
||||
— a small Rack middleware for serving CoffeeScript files as
|
||||
compiled JavaScript on the fly.
|
||||
</li>
|
||||
</ul>
|
||||
@@ -1707,17 +1754,26 @@ task(<span class="String"><span class="String">'</span>test<span class="String">
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.5</b>
|
||||
String interpolation, contributed by
|
||||
<a href="http://github.com/StanAngeloff">Stan Angeloff</a>.
|
||||
Since <tt>--run</tt> has been the default since <b>0.5.3</b>, updating
|
||||
<tt>--stdio</tt> and <tt>--eval</tt> to run by default, pass <tt>--compile</tt>
|
||||
as well if you'd like to print the result.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.4</b>
|
||||
Bugfix that corrects the Node.js global constants <tt>__filename</tt> and
|
||||
<tt>__dirname</tt>. Tweaks for more flexible parsing of nested function
|
||||
literals and improperly-indented comments. Updates for the latest Node.js API.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.3</b>
|
||||
CoffeeScript now has a syntax for defining classes. Many of the core
|
||||
CoffeeScript now has a syntax for defining classes. Many of the core
|
||||
components (Nodes, Lexer, Rewriter, Scope, Optparse) are using them.
|
||||
Cakefiles can use <tt>optparse.coffee</tt> to define options for tasks.
|
||||
<tt>--run</tt> is now the default flag for the <tt>coffee</tt> command,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
this.exports = (this.CoffeeScript = {});
|
||||
}
|
||||
// The current CoffeeScript version number.
|
||||
exports.VERSION = '0.5.4';
|
||||
exports.VERSION = '0.5.5';
|
||||
// Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
// compiler.
|
||||
exports.compile = function compile(code, options) {
|
||||
|
||||
@@ -92,12 +92,12 @@
|
||||
return CoffeeScript.run(code, code_opts);
|
||||
} else {
|
||||
js = CoffeeScript.compile(code, code_opts);
|
||||
if (o.compile) {
|
||||
if (o.print) {
|
||||
return process.stdio.write(js);
|
||||
} else if (o.compile) {
|
||||
return write_js(source, js);
|
||||
} else if (o.lint) {
|
||||
return lint(js);
|
||||
} else if (o.print || o.eval) {
|
||||
return print(js);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -120,7 +120,7 @@
|
||||
}
|
||||
});
|
||||
return process.stdio.addListener('close', function() {
|
||||
return process.stdio.write(CoffeeScript.compile(code, compile_options('stdio')));
|
||||
return compile_script('stdio', code);
|
||||
});
|
||||
};
|
||||
// Watch a list of source CoffeeScript files using `fs.watchFile`, recompiling
|
||||
@@ -200,7 +200,8 @@
|
||||
var o;
|
||||
option_parser = new optparse.OptionParser(SWITCHES, BANNER);
|
||||
o = (options = option_parser.parse(process.argv));
|
||||
options.run = !(o.compile || o.print || o.lint || o.eval);
|
||||
options.run = !(o.compile || o.print || o.lint);
|
||||
options.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
return sources = options.arguments.slice(2, options.arguments.length);
|
||||
};
|
||||
// The compile-time options to pass to the CoffeeScript compiler.
|
||||
@@ -209,7 +210,7 @@
|
||||
o = {
|
||||
source: source
|
||||
};
|
||||
o['no-wrap'] = options['no-wrap'];
|
||||
o['no_wrap'] = options['no-wrap'];
|
||||
return o;
|
||||
};
|
||||
// Print the `--help` usage message and exit.
|
||||
|
||||
117
lib/nodes.js
117
lib/nodes.js
@@ -1009,7 +1009,7 @@ idt += TAB
|
||||
}).call(this);
|
||||
//### SplatNode
|
||||
// A splat, either as a parameter to a function, an argument to a call,
|
||||
// or in a destructuring assignment.
|
||||
// or as part of a destructuring assignment.
|
||||
exports.SplatNode = (function() {
|
||||
SplatNode = function SplatNode(name) {
|
||||
if (!(name.compile)) {
|
||||
@@ -1024,19 +1024,25 @@ idt += TAB
|
||||
var _a;
|
||||
return (typeof (_a = this.index) !== "undefined" && _a !== null) ? this.compile_param(o) : this.name.compile(o);
|
||||
};
|
||||
// Compiling a parameter splat means recovering the parameters that succeed
|
||||
// the splat in the parameter list, by slicing the arguments object.
|
||||
SplatNode.prototype.compile_param = function compile_param(o) {
|
||||
var name;
|
||||
name = this.name.compile(o);
|
||||
o.scope.find(name);
|
||||
return name + " = Array.prototype.slice.call(arguments, " + this.index + ")";
|
||||
};
|
||||
// A compiling a splat as a destructuring assignment means slicing arguments
|
||||
// from the right-hand-side's corresponding array.
|
||||
SplatNode.prototype.compile_value = function compile_value(o, name, index) {
|
||||
return "Array.prototype.slice.call(" + name + ", " + index + ")";
|
||||
};
|
||||
return SplatNode;
|
||||
}).call(this);
|
||||
//### WhileNode
|
||||
// A while loop, the only sort of low-level loop exposed by CoffeeScript. From
|
||||
// it, all other loops can be manufactured.
|
||||
// it, all other loops can be manufactured. Useful in cases where you need more
|
||||
// flexibility or more speed than a comprehension can provide.
|
||||
exports.WhileNode = (function() {
|
||||
WhileNode = function WhileNode(condition, opts) {
|
||||
this.children = [(this.condition = condition)];
|
||||
@@ -1052,6 +1058,9 @@ idt += TAB
|
||||
WhileNode.prototype.top_sensitive = function top_sensitive() {
|
||||
return true;
|
||||
};
|
||||
// The main difference from a JavaScript *while* is that the CoffeeScript
|
||||
// *while* can be used as a part of a larger expression -- while loops may
|
||||
// return an array containing the computed result of each iteration.
|
||||
WhileNode.prototype.compile_node = function compile_node(o) {
|
||||
var cond, post, pre, returns, rvar, set, top;
|
||||
returns = del(o, 'returns');
|
||||
@@ -1080,6 +1089,7 @@ idt += TAB
|
||||
return WhileNode;
|
||||
}).call(this);
|
||||
statement(WhileNode);
|
||||
//### OpNode
|
||||
// Simple Arithmetic and logical operations. Performs some conversion from
|
||||
// CoffeeScript operations into their JavaScript equivalents.
|
||||
exports.OpNode = (function() {
|
||||
@@ -1092,6 +1102,7 @@ idt += TAB
|
||||
};
|
||||
__extends(OpNode, BaseNode);
|
||||
OpNode.prototype.type = 'Op';
|
||||
// The map of conversions from CoffeeScript to JavaScript symbols.
|
||||
OpNode.prototype.CONVERSIONS = {
|
||||
'==': '===',
|
||||
'!=': '!==',
|
||||
@@ -1101,8 +1112,12 @@ idt += TAB
|
||||
'isnt': '!==',
|
||||
'not': '!'
|
||||
};
|
||||
// The list of operators for which we perform
|
||||
// [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin).
|
||||
OpNode.prototype.CHAINABLE = ['<', '>', '>=', '<=', '===', '!=='];
|
||||
// Our assignment operators that have no JavaScript equivalent.
|
||||
OpNode.prototype.ASSIGNMENT = ['||=', '&&=', '?='];
|
||||
// Operators must come before their operands with a space.
|
||||
OpNode.prototype.PREFIX_OPERATORS = ['typeof', 'delete'];
|
||||
OpNode.prototype.is_unary = function is_unary() {
|
||||
return !this.second;
|
||||
@@ -1126,8 +1141,10 @@ idt += TAB
|
||||
}
|
||||
return [this.first.compile(o), this.operator, this.second.compile(o)].join(' ');
|
||||
};
|
||||
// Mimic Python's chained comparisons. See:
|
||||
// http://docs.python.org/reference/expressions.html#notin
|
||||
// Mimic Python's chained comparisons when multiple comparison operators are
|
||||
// used sequentially. For example:
|
||||
// bin/coffee -e "puts 50 < 65 > 10"
|
||||
// true
|
||||
OpNode.prototype.compile_chain = function compile_chain(o) {
|
||||
var _a, _b, first, second, shared;
|
||||
shared = this.first.unwrap().second;
|
||||
@@ -1142,6 +1159,9 @@ idt += TAB
|
||||
shared = _b[2];
|
||||
return "(" + first + ") && (" + shared + " " + this.operator + " " + second + ")";
|
||||
};
|
||||
// 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.
|
||||
OpNode.prototype.compile_assignment = function compile_assignment(o) {
|
||||
var _a, first, second;
|
||||
_a = [this.first.compile(o), this.second.compile(o)];
|
||||
@@ -1155,6 +1175,8 @@ idt += TAB
|
||||
}
|
||||
return first + " = " + first + " " + (this.operator.substr(0, 2)) + " " + second;
|
||||
};
|
||||
// If this is an existence operator, we delegate to `ExistenceNode.compile_test`
|
||||
// to give us the safe references for the variables.
|
||||
OpNode.prototype.compile_existence = function compile_existence(o) {
|
||||
var _a, first, second, test;
|
||||
_a = [this.first.compile(o), this.second.compile(o)];
|
||||
@@ -1163,6 +1185,7 @@ idt += TAB
|
||||
test = ExistenceNode.compile_test(o, this.first);
|
||||
return test + " ? " + first + " : " + second;
|
||||
};
|
||||
// Compile a unary **OpNode**.
|
||||
OpNode.prototype.compile_unary = function compile_unary(o) {
|
||||
var parts, space;
|
||||
space = this.PREFIX_OPERATORS.indexOf(this.operator) >= 0 ? ' ' : '';
|
||||
@@ -1174,7 +1197,8 @@ idt += TAB
|
||||
};
|
||||
return OpNode;
|
||||
}).call(this);
|
||||
// A try/catch/finally block.
|
||||
//### TryNode
|
||||
// A classic *try/catch/finally* block.
|
||||
exports.TryNode = (function() {
|
||||
TryNode = function TryNode(attempt, error, recovery, ensure) {
|
||||
this.children = compact([(this.attempt = attempt), (this.recovery = recovery), (this.ensure = ensure)]);
|
||||
@@ -1184,6 +1208,8 @@ idt += TAB
|
||||
};
|
||||
__extends(TryNode, BaseNode);
|
||||
TryNode.prototype.type = 'Try';
|
||||
// Compilation is more or less as you would expect -- the *finally* clause
|
||||
// is optional, the *catch* is not.
|
||||
TryNode.prototype.compile_node = function compile_node(o) {
|
||||
var attempt_part, catch_part, error_part, finally_part;
|
||||
o.indent = this.idt(1);
|
||||
@@ -1199,7 +1225,8 @@ idt += TAB
|
||||
return TryNode;
|
||||
}).call(this);
|
||||
statement(TryNode);
|
||||
// Throw an exception.
|
||||
//### ThrowNode
|
||||
// Simple node to throw an exception.
|
||||
exports.ThrowNode = (function() {
|
||||
ThrowNode = function ThrowNode(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
@@ -1212,8 +1239,11 @@ idt += TAB
|
||||
};
|
||||
return ThrowNode;
|
||||
}).call(this);
|
||||
statement(ThrowNode, true);
|
||||
// Check an expression for existence (meaning not null or undefined).
|
||||
statement(ThrowNode);
|
||||
//### ExistenceNode
|
||||
// Checks a variable for existence -- not *null* and not *undefined*. This is
|
||||
// similar to `.nil?` in Ruby, and avoids having to consult a JavaScript truth
|
||||
// table.
|
||||
exports.ExistenceNode = (function() {
|
||||
ExistenceNode = function ExistenceNode(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
@@ -1226,6 +1256,9 @@ idt += TAB
|
||||
};
|
||||
return ExistenceNode;
|
||||
}).call(this);
|
||||
// The meat of the **ExistenceNode** is in this static `compile_test` method
|
||||
// because other nodes like to check the existence of their variables as well.
|
||||
// Be careful not to double-evaluate anything.
|
||||
ExistenceNode.compile_test = function compile_test(o, variable) {
|
||||
var _a, _b, _c, first, second;
|
||||
_a = [variable, variable];
|
||||
@@ -1241,7 +1274,11 @@ idt += TAB
|
||||
second = _c[1];
|
||||
return "(typeof " + first + " !== \"undefined\" && " + second + " !== null)";
|
||||
};
|
||||
// An extra set of parentheses, specified explicitly in the source.
|
||||
//### ParentheticalNode
|
||||
// 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.
|
||||
// Parentheses are a good way to force any statement to become an expression.
|
||||
exports.ParentheticalNode = (function() {
|
||||
ParentheticalNode = function ParentheticalNode(expression) {
|
||||
this.children = [(this.expression = expression)];
|
||||
@@ -1266,10 +1303,13 @@ idt += TAB
|
||||
};
|
||||
return ParentheticalNode;
|
||||
}).call(this);
|
||||
// The replacement for the for loop is an array comprehension (that compiles)
|
||||
// into a for loop. Also acts as an expression, able to return the result
|
||||
// of the comprehenion. Unlike Python array comprehensions, it's able to pass
|
||||
// the current index of the loop as a second parameter.
|
||||
//### ForNode
|
||||
// CoffeeScript's replacement for the *for* loop is our array and object
|
||||
// comprehensions, that compile into *for* loops here. They also act as an
|
||||
// expression, able to return the result of each filtered iteration.
|
||||
// Unlike Python array comprehensions, they can be multi-line, and you can pass
|
||||
// the current index of the loop as a second parameter. Unlike Ruby blocks,
|
||||
// you can map and filter in a single pass.
|
||||
exports.ForNode = (function() {
|
||||
ForNode = function ForNode(body, source, name, index) {
|
||||
var _a;
|
||||
@@ -1293,6 +1333,10 @@ idt += TAB
|
||||
ForNode.prototype.top_sensitive = function top_sensitive() {
|
||||
return true;
|
||||
};
|
||||
// Welcome to the hairiest method in all of CoffeeScript. Handles the inner
|
||||
// loop, filtering, stepping, and result saving for array, object, and range
|
||||
// comprehensions. Some of the generated code can be shared in common, and
|
||||
// some cannot.
|
||||
ForNode.prototype.compile_node = function compile_node(o) {
|
||||
var body, body_dent, close, for_part, index, index_found, index_var, ivar, lvar, name, name_found, range, return_result, rvar, scope, set_result, source, source_part, step_part, svar, top_level, var_part, vars;
|
||||
top_level = del(o, 'top') && !o.returns;
|
||||
@@ -1370,10 +1414,11 @@ idt += TAB
|
||||
return ForNode;
|
||||
}).call(this);
|
||||
statement(ForNode);
|
||||
// If/else statements. Switch/whens get compiled into these. Acts as an
|
||||
// expression by pushing down requested returns to the expression bodies.
|
||||
// Single-expression IfNodes are compiled into ternary operators if possible,
|
||||
// because ternaries are first-class returnable assignable expressions.
|
||||
//### IfNode
|
||||
// *If/else* statements. Our *switch/when* will be compiled into this. Acts as an
|
||||
// expression by pushing down requested returns to the last line of each clause.
|
||||
// Single-expression **IfNodes** are compiled into ternary operators if possible,
|
||||
// because ternaries are already proper expressions, and don't need conversion.
|
||||
exports.IfNode = (function() {
|
||||
IfNode = function IfNode(condition, body, else_body, tags) {
|
||||
this.condition = condition;
|
||||
@@ -1391,6 +1436,8 @@ idt += TAB
|
||||
};
|
||||
__extends(IfNode, BaseNode);
|
||||
IfNode.prototype.type = 'If';
|
||||
// Add a new *else* clause to this **IfNode**, or push it down to the bottom
|
||||
// of the chain recursively.
|
||||
IfNode.prototype.push = function push(else_body) {
|
||||
var eb;
|
||||
eb = else_body.unwrap();
|
||||
@@ -1401,12 +1448,14 @@ idt += TAB
|
||||
this.tags.statement = true;
|
||||
return this;
|
||||
};
|
||||
// Tag a chain of IfNodes with their switch condition for equality.
|
||||
// Tag a chain of **IfNodes** with their object(s) to switch on for equality
|
||||
// tests. `rewrite_switch` will perform the actual change at compile time.
|
||||
IfNode.prototype.rewrite_condition = function rewrite_condition(expression) {
|
||||
this.switcher = expression;
|
||||
return this;
|
||||
};
|
||||
// Rewrite a chain of IfNodes with their switch condition for equality.
|
||||
// Rewrite a chain of **IfNodes** with their switch condition for equality.
|
||||
// Ensure that the switch expression isn't evaluated more than once.
|
||||
IfNode.prototype.rewrite_switch = function rewrite_switch(o) {
|
||||
var _a, _b, _c, assigner, cond, i, variable;
|
||||
assigner = this.switcher;
|
||||
@@ -1432,7 +1481,7 @@ idt += TAB
|
||||
}
|
||||
return this;
|
||||
};
|
||||
// Rewrite a chain of IfNodes to add a default case as the final else.
|
||||
// Rewrite a chain of **IfNodes** to add a default case as the final *else*.
|
||||
IfNode.prototype.add_else = function add_else(exprs, statement) {
|
||||
if (this.is_chain()) {
|
||||
this.else_body.add_else(exprs, statement);
|
||||
@@ -1444,12 +1493,12 @@ idt += TAB
|
||||
}
|
||||
return this;
|
||||
};
|
||||
// If the else_body is an IfNode itself, then we've got an if-else chain.
|
||||
// If the `else_body` is an **IfNode** itself, then we've got an *if-else* chain.
|
||||
IfNode.prototype.is_chain = function is_chain() {
|
||||
return this.chain = this.chain || this.else_body && this.else_body instanceof IfNode;
|
||||
};
|
||||
// The IfNode only compiles into a statement if either of the bodies needs
|
||||
// to be a statement.
|
||||
// The **IfNode** only compiles into a statement if either of its bodies needs
|
||||
// to be a statement. Otherwise a ternary is safe.
|
||||
IfNode.prototype.is_statement = function is_statement() {
|
||||
return this.statement = this.statement || !!(this.comment || this.tags.statement || this.body.is_statement() || (this.else_body && this.else_body.is_statement()));
|
||||
};
|
||||
@@ -1467,8 +1516,8 @@ idt += TAB
|
||||
IfNode.prototype.compile_node = function compile_node(o) {
|
||||
return this.is_statement() ? this.compile_statement(o) : this.compile_ternary(o);
|
||||
};
|
||||
// Compile the IfNode as a regular if-else statement. Flattened chains
|
||||
// force sub-else bodies into statement form.
|
||||
// Compile the **IfNode** as a regular *if-else* statement. Flattened chains
|
||||
// force inner *else* bodies into statement form.
|
||||
IfNode.prototype.compile_statement = function compile_statement(o) {
|
||||
var body, child, com_dent, cond_o, else_part, if_dent, if_part, prefix;
|
||||
if (this.switcher) {
|
||||
@@ -1493,7 +1542,7 @@ idt += TAB
|
||||
})) : " else {\n" + (Expressions.wrap([this.else_body]).compile(o)) + "\n" + this.tab + "}";
|
||||
return if_part + else_part;
|
||||
};
|
||||
// Compile the IfNode into a ternary operator.
|
||||
// Compile the IfNode as a ternary operator.
|
||||
IfNode.prototype.compile_ternary = function compile_ternary(o) {
|
||||
var else_part, if_part;
|
||||
if_part = this.condition.compile(o) + ' ? ' + this.body.compile(o);
|
||||
@@ -1506,12 +1555,16 @@ idt += TAB
|
||||
// ---------
|
||||
// Tabs are two spaces for pretty printing.
|
||||
TAB = ' ';
|
||||
// Trim out all trailing whitespace, so that the generated code plays nice
|
||||
// with Git.
|
||||
TRAILING_WHITESPACE = /\s+$/gm;
|
||||
// Keep the identifier regex in sync with the Lexer.
|
||||
// Keep this identifier regex in sync with the Lexer.
|
||||
IDENTIFIER = /^[a-zA-Z$_](\w|\$)*$/;
|
||||
// Utility Functions
|
||||
// -----------------
|
||||
// Merge objects.
|
||||
// Merge objects, returning a fresh copy with attributes from both sides.
|
||||
// Used every time `compile` is called, to allow properties in the options hash
|
||||
// to propagate down the tree without polluting other branches.
|
||||
merge = function merge(options, overrides) {
|
||||
var _a, _b, fresh, key, val;
|
||||
fresh = {};
|
||||
@@ -1541,7 +1594,8 @@ idt += TAB
|
||||
}
|
||||
return _a;
|
||||
};
|
||||
// Return a completely flattened version of an array.
|
||||
// Return a completely flattened version of an array. Handy for getting a
|
||||
// list of `children`.
|
||||
flatten = function flatten(array) {
|
||||
var _a, _b, _c, item, memo;
|
||||
memo = [];
|
||||
@@ -1552,14 +1606,15 @@ idt += TAB
|
||||
}
|
||||
return memo;
|
||||
};
|
||||
// Delete a key from an object, returning the value.
|
||||
// Delete a key from an object, returning the value. Useful when a node is
|
||||
// looking for a particular method in an options hash.
|
||||
del = function del(obj, key) {
|
||||
var val;
|
||||
val = obj[key];
|
||||
delete obj[key];
|
||||
return val;
|
||||
};
|
||||
// Quickie helper for a generated LiteralNode.
|
||||
// Handy helper for a generating LiteralNode.
|
||||
literal = function literal(name) {
|
||||
return new LiteralNode(name);
|
||||
};
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": ["javascript", "language"],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "0.5.4"
|
||||
"version": "0.5.5"
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ else
|
||||
this.exports: this.CoffeeScript: {}
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION: '0.5.4'
|
||||
exports.VERSION: '0.5.5'
|
||||
|
||||
# Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
# compiler.
|
||||
|
||||
@@ -77,16 +77,16 @@ compile_script: (source, code) ->
|
||||
o: options
|
||||
code_opts: compile_options source
|
||||
try
|
||||
if o.tokens then print_tokens CoffeeScript.tokens code
|
||||
else if o.nodes then puts CoffeeScript.nodes(code).toString()
|
||||
else if o.run then CoffeeScript.run code, code_opts
|
||||
if o.tokens then print_tokens CoffeeScript.tokens code
|
||||
else if o.nodes then puts CoffeeScript.nodes(code).toString()
|
||||
else if o.run then CoffeeScript.run code, code_opts
|
||||
else
|
||||
js: CoffeeScript.compile code, code_opts
|
||||
if o.compile then write_js source, js
|
||||
else if o.lint then lint js
|
||||
else if o.print or o.eval then print js
|
||||
if o.print then process.stdio.write js
|
||||
else if o.compile then write_js source, js
|
||||
else if o.lint then lint js
|
||||
catch err
|
||||
if o.watch then puts err.message else throw err
|
||||
if o.watch then puts err.message else throw err
|
||||
|
||||
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
|
||||
# and write them back to **stdout**.
|
||||
@@ -96,7 +96,7 @@ compile_stdio: ->
|
||||
process.stdio.addListener 'data', (string) ->
|
||||
code += string if string
|
||||
process.stdio.addListener 'close', ->
|
||||
process.stdio.write CoffeeScript.compile code, compile_options('stdio')
|
||||
compile_script 'stdio', code
|
||||
|
||||
# Watch a list of source CoffeeScript files using `fs.watchFile`, recompiling
|
||||
# them every time the files are updated. May be used in combination with other
|
||||
@@ -140,13 +140,14 @@ print_tokens: (tokens) ->
|
||||
parse_options: ->
|
||||
option_parser: new optparse.OptionParser SWITCHES, BANNER
|
||||
o: options: option_parser.parse(process.argv)
|
||||
options.run: not (o.compile or o.print or o.lint or o.eval)
|
||||
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[2...options.arguments.length]
|
||||
|
||||
# The compile-time options to pass to the CoffeeScript compiler.
|
||||
compile_options: (source) ->
|
||||
o: {source: source}
|
||||
o['no-wrap']: options['no-wrap']
|
||||
o['no_wrap']: options['no-wrap']
|
||||
o
|
||||
|
||||
# Print the `--help` usage message and exit.
|
||||
|
||||
100
src/nodes.coffee
100
src/nodes.coffee
@@ -881,7 +881,10 @@ exports.OpNode: class OpNode extends BaseNode
|
||||
[@first.compile(o), @operator, @second.compile(o)].join ' '
|
||||
|
||||
# Mimic Python's chained comparisons when multiple comparison operators are
|
||||
# used sequentially. For example: `50 < 65 > 10`
|
||||
# used sequentially. For example:
|
||||
#
|
||||
# bin/coffee -e "puts 50 < 65 > 10"
|
||||
# true
|
||||
compile_chain: (o) ->
|
||||
shared: @first.unwrap().second
|
||||
[@first.second, shared]: shared.compile_reference(o) if shared instanceof CallNode
|
||||
@@ -897,19 +900,23 @@ exports.OpNode: class OpNode extends BaseNode
|
||||
return "$first = ${ ExistenceNode.compile_test(o, @first) } ? $first : $second" if @operator is '?='
|
||||
"$first = $first ${ @operator.substr(0, 2) } $second"
|
||||
|
||||
# If this is an existence operator, we delegate to `ExistenceNode.compile_test`
|
||||
# to give us the safe references for the variables.
|
||||
compile_existence: (o) ->
|
||||
[first, second]: [@first.compile(o), @second.compile(o)]
|
||||
test: ExistenceNode.compile_test(o, @first)
|
||||
"$test ? $first : $second"
|
||||
|
||||
# Compile a unary **OpNode**.
|
||||
compile_unary: (o) ->
|
||||
space: if @PREFIX_OPERATORS.indexOf(@operator) >= 0 then ' ' else ''
|
||||
parts: [@operator, space, @first.compile(o)]
|
||||
parts: parts.reverse() if @flip
|
||||
parts.join('')
|
||||
|
||||
#### TryNode
|
||||
|
||||
# A try/catch/finally block.
|
||||
# A classic *try/catch/finally* block.
|
||||
exports.TryNode: class TryNode extends BaseNode
|
||||
type: 'Try'
|
||||
|
||||
@@ -918,6 +925,8 @@ exports.TryNode: class TryNode extends BaseNode
|
||||
@error: error
|
||||
this
|
||||
|
||||
# Compilation is more or less as you would expect -- the *finally* clause
|
||||
# is optional, the *catch* is not.
|
||||
compile_node: (o) ->
|
||||
o.indent: @idt(1)
|
||||
o.top: true
|
||||
@@ -929,8 +938,9 @@ exports.TryNode: class TryNode extends BaseNode
|
||||
|
||||
statement TryNode
|
||||
|
||||
#### ThrowNode
|
||||
|
||||
# Throw an exception.
|
||||
# Simple node to throw an exception.
|
||||
exports.ThrowNode: class ThrowNode extends BaseNode
|
||||
type: 'Throw'
|
||||
|
||||
@@ -940,10 +950,13 @@ exports.ThrowNode: class ThrowNode extends BaseNode
|
||||
compile_node: (o) ->
|
||||
"${@tab}throw ${@expression.compile(o)};"
|
||||
|
||||
statement ThrowNode, true
|
||||
statement ThrowNode
|
||||
|
||||
#### ExistenceNode
|
||||
|
||||
# Check an expression for existence (meaning not null or undefined).
|
||||
# Checks a variable for existence -- not *null* and not *undefined*. This is
|
||||
# similar to `.nil?` in Ruby, and avoids having to consult a JavaScript truth
|
||||
# table.
|
||||
exports.ExistenceNode: class ExistenceNode extends BaseNode
|
||||
type: 'Existence'
|
||||
|
||||
@@ -953,6 +966,9 @@ exports.ExistenceNode: class ExistenceNode extends BaseNode
|
||||
compile_node: (o) ->
|
||||
ExistenceNode.compile_test(o, @expression)
|
||||
|
||||
# The meat of the **ExistenceNode** is in this static `compile_test` method
|
||||
# because other nodes like to check the existence of their variables as well.
|
||||
# Be careful not to double-evaluate anything.
|
||||
ExistenceNode.compile_test: (o, variable) ->
|
||||
[first, second]: [variable, variable]
|
||||
if variable instanceof CallNode or (variable instanceof ValueNode and variable.has_properties())
|
||||
@@ -960,8 +976,13 @@ ExistenceNode.compile_test: (o, variable) ->
|
||||
[first, second]: [first.compile(o), second.compile(o)]
|
||||
"(typeof $first !== \"undefined\" && $second !== null)"
|
||||
|
||||
#### ParentheticalNode
|
||||
|
||||
# An extra set of parentheses, specified explicitly in the source.
|
||||
# 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.
|
||||
#
|
||||
# Parentheses are a good way to force any statement to become an expression.
|
||||
exports.ParentheticalNode: class ParentheticalNode extends BaseNode
|
||||
type: 'Paren'
|
||||
|
||||
@@ -978,11 +999,15 @@ exports.ParentheticalNode: class ParentheticalNode extends BaseNode
|
||||
code: code.substr(o, l-1) if code.substr(l-1, 1) is ';'
|
||||
"($code)"
|
||||
|
||||
#### ForNode
|
||||
|
||||
# The replacement for the for loop is an array comprehension (that compiles)
|
||||
# into a for loop. Also acts as an expression, able to return the result
|
||||
# of the comprehenion. Unlike Python array comprehensions, it's able to pass
|
||||
# the current index of the loop as a second parameter.
|
||||
# CoffeeScript's replacement for the *for* loop is our array and object
|
||||
# comprehensions, that compile into *for* loops here. They also act as an
|
||||
# expression, able to return the result of each filtered iteration.
|
||||
#
|
||||
# Unlike Python array comprehensions, they can be multi-line, and you can pass
|
||||
# the current index of the loop as a second parameter. Unlike Ruby blocks,
|
||||
# you can map and filter in a single pass.
|
||||
exports.ForNode: class ForNode extends BaseNode
|
||||
type: 'For'
|
||||
|
||||
@@ -1000,6 +1025,10 @@ exports.ForNode: class ForNode extends BaseNode
|
||||
top_sensitive: ->
|
||||
true
|
||||
|
||||
# Welcome to the hairiest method in all of CoffeeScript. Handles the inner
|
||||
# loop, filtering, stepping, and result saving for array, object, and range
|
||||
# comprehensions. Some of the generated code can be shared in common, and
|
||||
# some cannot.
|
||||
compile_node: (o) ->
|
||||
top_level: del(o, 'top') and not o.returns
|
||||
range: @source instanceof ValueNode and @source.base instanceof RangeNode and not @source.properties.length
|
||||
@@ -1049,11 +1078,13 @@ exports.ForNode: class ForNode extends BaseNode
|
||||
|
||||
statement ForNode
|
||||
|
||||
#### IfNode
|
||||
|
||||
# If/else statements. Switch/whens get compiled into these. Acts as an
|
||||
# expression by pushing down requested returns to the expression bodies.
|
||||
# Single-expression IfNodes are compiled into ternary operators if possible,
|
||||
# because ternaries are first-class returnable assignable expressions.
|
||||
# *If/else* statements. Our *switch/when* will be compiled into this. Acts as an
|
||||
# expression by pushing down requested returns to the last line of each clause.
|
||||
#
|
||||
# Single-expression **IfNodes** are compiled into ternary operators if possible,
|
||||
# because ternaries are already proper expressions, and don't need conversion.
|
||||
exports.IfNode: class IfNode extends BaseNode
|
||||
type: 'If'
|
||||
|
||||
@@ -1066,6 +1097,8 @@ exports.IfNode: class IfNode extends BaseNode
|
||||
@multiple: true if @condition instanceof Array
|
||||
@condition: new OpNode('!', new ParentheticalNode(@condition)) if @tags.invert
|
||||
|
||||
# Add a new *else* clause to this **IfNode**, or push it down to the bottom
|
||||
# of the chain recursively.
|
||||
push: (else_body) ->
|
||||
eb: else_body.unwrap()
|
||||
if @else_body then @else_body.push(eb) else @else_body: eb
|
||||
@@ -1075,12 +1108,14 @@ exports.IfNode: class IfNode extends BaseNode
|
||||
@tags.statement: true
|
||||
this
|
||||
|
||||
# Tag a chain of IfNodes with their switch condition for equality.
|
||||
# Tag a chain of **IfNodes** with their object(s) to switch on for equality
|
||||
# tests. `rewrite_switch` will perform the actual change at compile time.
|
||||
rewrite_condition: (expression) ->
|
||||
@switcher: expression
|
||||
this
|
||||
|
||||
# Rewrite a chain of IfNodes with their switch condition for equality.
|
||||
# Rewrite a chain of **IfNodes** with their switch condition for equality.
|
||||
# Ensure that the switch expression isn't evaluated more than once.
|
||||
rewrite_switch: (o) ->
|
||||
assigner: @switcher
|
||||
if not (@switcher.unwrap() instanceof LiteralNode)
|
||||
@@ -1095,7 +1130,7 @@ exports.IfNode: class IfNode extends BaseNode
|
||||
@else_body.rewrite_condition(@switcher) if @is_chain()
|
||||
this
|
||||
|
||||
# Rewrite a chain of IfNodes to add a default case as the final else.
|
||||
# Rewrite a chain of **IfNodes** to add a default case as the final *else*.
|
||||
add_else: (exprs, statement) ->
|
||||
if @is_chain()
|
||||
@else_body.add_else exprs, statement
|
||||
@@ -1104,12 +1139,12 @@ exports.IfNode: class IfNode extends BaseNode
|
||||
@children.push @else_body: exprs
|
||||
this
|
||||
|
||||
# If the else_body is an IfNode itself, then we've got an if-else chain.
|
||||
# If the `else_body` is an **IfNode** itself, then we've got an *if-else* chain.
|
||||
is_chain: ->
|
||||
@chain ||= @else_body and @else_body instanceof IfNode
|
||||
|
||||
# The IfNode only compiles into a statement if either of the bodies needs
|
||||
# to be a statement.
|
||||
# The **IfNode** only compiles into a statement if either of its bodies needs
|
||||
# to be a statement. Otherwise a ternary is safe.
|
||||
is_statement: ->
|
||||
@statement ||= !!(@comment or @tags.statement or @body.is_statement() or (@else_body and @else_body.is_statement()))
|
||||
|
||||
@@ -1119,8 +1154,8 @@ exports.IfNode: class IfNode extends BaseNode
|
||||
compile_node: (o) ->
|
||||
if @is_statement() then @compile_statement(o) else @compile_ternary(o)
|
||||
|
||||
# Compile the IfNode as a regular if-else statement. Flattened chains
|
||||
# force sub-else bodies into statement form.
|
||||
# Compile the **IfNode** as a regular *if-else* statement. Flattened chains
|
||||
# force inner *else* bodies into statement form.
|
||||
compile_statement: (o) ->
|
||||
@rewrite_switch(o) if @switcher
|
||||
child: del o, 'chain_child'
|
||||
@@ -1140,7 +1175,7 @@ exports.IfNode: class IfNode extends BaseNode
|
||||
" else {\n${ Expressions.wrap([@else_body]).compile(o) }\n$@tab}"
|
||||
"$if_part$else_part"
|
||||
|
||||
# Compile the IfNode into a ternary operator.
|
||||
# Compile the IfNode as a ternary operator.
|
||||
compile_ternary: (o) ->
|
||||
if_part: @condition.compile(o) + ' ? ' + @body.compile(o)
|
||||
else_part: if @else_body then @else_body.compile(o) else 'null'
|
||||
@@ -1151,15 +1186,20 @@ exports.IfNode: class IfNode extends BaseNode
|
||||
|
||||
# Tabs are two spaces for pretty printing.
|
||||
TAB: ' '
|
||||
|
||||
# Trim out all trailing whitespace, so that the generated code plays nice
|
||||
# with Git.
|
||||
TRAILING_WHITESPACE: /\s+$/gm
|
||||
|
||||
# Keep the identifier regex in sync with the Lexer.
|
||||
IDENTIFIER: /^[a-zA-Z$_](\w|\$)*$/
|
||||
# Keep this identifier regex in sync with the Lexer.
|
||||
IDENTIFIER: /^[a-zA-Z$_](\w|\$)*$/
|
||||
|
||||
# Utility Functions
|
||||
# -----------------
|
||||
|
||||
# Merge objects.
|
||||
# Merge objects, returning a fresh copy with attributes from both sides.
|
||||
# Used every time `compile` is called, to allow properties in the options hash
|
||||
# to propagate down the tree without polluting other branches.
|
||||
merge: (options, overrides) ->
|
||||
fresh: {}
|
||||
(fresh[key]: val) for key, val of options
|
||||
@@ -1169,19 +1209,21 @@ merge: (options, overrides) ->
|
||||
# Trim out all falsy values from an array.
|
||||
compact: (array) -> item for item in array when item
|
||||
|
||||
# Return a completely flattened version of an array.
|
||||
# Return a completely flattened version of an array. Handy for getting a
|
||||
# list of `children`.
|
||||
flatten: (array) ->
|
||||
memo: []
|
||||
for item in array
|
||||
if item instanceof Array then memo: memo.concat(item) else memo.push(item)
|
||||
memo
|
||||
|
||||
# Delete a key from an object, returning the value.
|
||||
# Delete a key from an object, returning the value. Useful when a node is
|
||||
# looking for a particular method in an options hash.
|
||||
del: (obj, key) ->
|
||||
val: obj[key]
|
||||
delete obj[key]
|
||||
val
|
||||
|
||||
# Quickie helper for a generated LiteralNode.
|
||||
# Handy helper for a generating LiteralNode.
|
||||
literal: (name) ->
|
||||
new LiteralNode(name)
|
||||
|
||||
Reference in New Issue
Block a user