mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 01:07:55 -05:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa53a4c057 | ||
|
|
edd0c5af5a | ||
|
|
2fb269a938 | ||
|
|
3eac6aeb99 | ||
|
|
ec64646fee | ||
|
|
2decb30d4e | ||
|
|
c0bbc609be | ||
|
|
f6be426aa0 | ||
|
|
17b5c8ac6f | ||
|
|
b18d0d75fd | ||
|
|
77e13e459b | ||
|
|
06647bdd0a | ||
|
|
24183d9a39 | ||
|
|
dc5854689b | ||
|
|
ed70b9d4d0 | ||
|
|
c7a9801db7 | ||
|
|
85521f88b2 | ||
|
|
75ca0f23ac | ||
|
|
67c20c0715 | ||
|
|
c50cb65019 | ||
|
|
23b4d2fd1d | ||
|
|
dd18703b50 | ||
|
|
b1ba298ffc | ||
|
|
992324b425 | ||
|
|
56e10f9bce | ||
|
|
69664a1bb3 | ||
|
|
1f5727fe9d | ||
|
|
b52a1ed60a | ||
|
|
c3f1820ebc | ||
|
|
4afa6a2887 | ||
|
|
1254efaddb | ||
|
|
adeace8f62 | ||
|
|
4447180d5a | ||
|
|
41beccbe3c | ||
|
|
a4958e76c1 | ||
|
|
a9e264dd84 | ||
|
|
51988dba09 | ||
|
|
39c4c23200 | ||
|
|
63cbb64341 | ||
|
|
c0cb0c35e2 | ||
|
|
9db6d6f4ef | ||
|
|
57bd6bc2cd |
6
Cakefile
6
Cakefile
@@ -146,12 +146,15 @@ task 'loc', 'count the lines of source code in the CoffeeScript compiler', ->
|
||||
runTests = (CoffeeScript) ->
|
||||
startTime = Date.now()
|
||||
passedTests = failedTests = 0
|
||||
for all name, func of require 'assert'
|
||||
|
||||
for name, func of require 'assert'
|
||||
global[name] = ->
|
||||
passedTests += 1
|
||||
func arguments...
|
||||
|
||||
global.eq = global.strictEqual
|
||||
global.CoffeeScript = CoffeeScript
|
||||
|
||||
process.on 'exit', ->
|
||||
time = ((Date.now() - startTime) / 1000).toFixed(2)
|
||||
message = "passed #{passedTests} tests in #{time} seconds#{reset}"
|
||||
@@ -159,6 +162,7 @@ runTests = (CoffeeScript) ->
|
||||
log "failed #{failedTests} and #{message}", red
|
||||
else
|
||||
log message, green
|
||||
|
||||
fs.readdir 'test', (err, files) ->
|
||||
files.forEach (file) ->
|
||||
return unless file.match(/\.coffee$/i)
|
||||
|
||||
57
Rakefile
57
Rakefile
@@ -1,6 +1,8 @@
|
||||
require 'rubygems'
|
||||
require 'erb'
|
||||
require 'fileutils'
|
||||
require 'rake/testtask'
|
||||
require 'json'
|
||||
|
||||
desc "Build the documentation page"
|
||||
task :doc do
|
||||
@@ -19,3 +21,58 @@ task :doc do
|
||||
end
|
||||
end
|
||||
|
||||
desc "Build coffee-script-source gem"
|
||||
task :gem do
|
||||
require 'rubygems'
|
||||
require 'rubygems/package'
|
||||
|
||||
gemspec = Gem::Specification.new do |s|
|
||||
s.name = 'coffee-script-source'
|
||||
s.version = JSON.parse(File.read('package.json'))["version"]
|
||||
s.date = Time.now.strftime("%Y-%m-%d")
|
||||
|
||||
s.homepage = "http://jashkenas.github.com/coffee-script/"
|
||||
s.summary = "The CoffeeScript Compiler"
|
||||
s.description = <<-EOS
|
||||
CoffeeScript is a little language that compiles into JavaScript.
|
||||
Underneath all of those embarrassing braces and semicolons,
|
||||
JavaScript has always had a gorgeous object model at its heart.
|
||||
CoffeeScript is an attempt to expose the good parts of JavaScript
|
||||
in a simple way.
|
||||
EOS
|
||||
|
||||
s.files = [
|
||||
'lib/coffee_script/coffee-script.js',
|
||||
'lib/coffee_script/source.rb'
|
||||
]
|
||||
|
||||
s.authors = ['Jeremy Ashkenas']
|
||||
s.email = 'jashkenas@gmail.com'
|
||||
s.rubyforge_project = 'coffee-script-source'
|
||||
end
|
||||
|
||||
file = File.open("coffee-script-source.gem", "w")
|
||||
Gem::Package.open(file, 'w') do |pkg|
|
||||
pkg.metadata = gemspec.to_yaml
|
||||
|
||||
path = "lib/coffee_script/source.rb"
|
||||
contents = <<-ERUBY
|
||||
module CoffeeScript
|
||||
module Source
|
||||
def self.bundled_path
|
||||
File.expand_path("../coffee-script.js", __FILE__)
|
||||
end
|
||||
end
|
||||
end
|
||||
ERUBY
|
||||
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
|
||||
tar_io.write(contents)
|
||||
end
|
||||
|
||||
contents = File.read("extras/coffee-script.js")
|
||||
path = "lib/coffee_script/coffee-script.js"
|
||||
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
|
||||
tar_io.write(contents)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,2 @@
|
||||
# Eat lunch.
|
||||
lunch = eat food for food in ['toast', 'cheese', 'wine']
|
||||
|
||||
# Naive collision detection.
|
||||
for roid, pos in asteroids
|
||||
for roid2 in asteroids when roid isnt roid2
|
||||
roid.explode() if roid.overlaps roid2
|
||||
eat food for food in ['toast', 'cheese', 'wine']
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
###
|
||||
CoffeeScript Compiler v0.9.5
|
||||
CoffeeScript Compiler v0.9.6
|
||||
Released under the MIT License
|
||||
###
|
||||
6
documentation/coffee/slices.coffee
Normal file
6
documentation/coffee/slices.coffee
Normal file
@@ -0,0 +1,6 @@
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
copy = numbers[0...numbers.length]
|
||||
|
||||
middle = copy[3..6]
|
||||
|
||||
5
documentation/coffee/splices.coffee
Normal file
5
documentation/coffee/splices.coffee
Normal file
@@ -0,0 +1,5 @@
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
numbers[3..6] = [-3, -4, -5, -6]
|
||||
|
||||
|
||||
@@ -76,6 +76,11 @@ code, pre, tt, textarea {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
.timestamp {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: black;
|
||||
}
|
||||
div.code {
|
||||
position: relative;
|
||||
border: 1px solid #cacaca;
|
||||
|
||||
@@ -31,7 +31,7 @@ If no tasks are passed, print the help screen.</p> </td>
|
||||
<span class="nv">options = </span><span class="nx">oparse</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span>
|
||||
<span class="nx">invoke</span> <span class="nx">arg</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">options</span><span class="p">.</span><span class="nx">arguments</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTasks = </span><span class="o">-></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s1">''</span>
|
||||
<span class="k">for</span> <span class="nx">all</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">task</span> <span class="k">of</span> <span class="nx">tasks</span>
|
||||
<span class="nv">spaces = </span><span class="mi">20</span> <span class="o">-</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">spaces = </span><span class="k">if</span> <span class="nx">spaces</span> <span class="o">></span> <span class="mi">0</span> <span class="k">then</span> <span class="nb">Array</span><span class="p">(</span><span class="nx">spaces</span> <span class="o">+</span> <span class="mi">1</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="nv">desc = </span><span class="k">if</span> <span class="nx">task</span><span class="p">.</span><span class="nx">description</span> <span class="k">then</span> <span class="s2">"# #{task.description}"</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
|
||||
@@ -12,7 +12,7 @@ execute all scripts present in <code>text/coffeescript</code> tags.</p>
|
||||
<span class="nv">content = </span><span class="nx">compile</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span> <span class="nx">filename</span><span class="p">,</span> <span class="s1">'utf8'</span>
|
||||
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">content</span><span class="p">,</span> <span class="nx">filename</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span>
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">'.coffee'</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile</span> <span class="nx">content</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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.9.5'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
<span class="nx">require</span><span class="p">.</span><span class="nx">registerExtension</span> <span class="s1">'.coffee'</span><span class="p">,</span> <span class="p">(</span><span class="nx">content</span><span class="p">)</span> <span class="o">-></span> <span class="nx">compile</span> <span class="nx">content</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" 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.9.6'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Expose helpers for testing.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
|
||||
compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nv">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>
|
||||
|
||||
@@ -4,11 +4,15 @@ into various forms: saved into <code>.js</code> files or printed to stdout, pipe
|
||||
saved, printed as a token stream or as the syntax tree, or launch an
|
||||
interactive REPL.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>External dependencies.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s1">'fs'</span>
|
||||
<span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
||||
<span class="nv">util = </span><span class="nx">require</span> <span class="s1">'util'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span>
|
||||
<span class="nv">optparse = </span><span class="nx">require</span> <span class="s1">'./optparse'</span>
|
||||
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'child_process'</span>
|
||||
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'events'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Allow CoffeeScript to emit Node.js events.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s1">'''</span>
|
||||
<span class="p">{</span><span class="nx">EventEmitter</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'events'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Allow CoffeeScript to emit Node.js events.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">CoffeeScript</span><span class="p">,</span> <span class="k">new</span> <span class="nx">EventEmitter</span>
|
||||
|
||||
<span class="nv">printLine = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">write</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">'\n'</span>
|
||||
<span class="nv">printWarn = </span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">binding</span><span class="p">(</span><span class="s1">'stdio'</span><span class="p">).</span><span class="nx">writeError</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">'\n'</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>The help banner that is printed when <code>coffee</code> is called without arguments.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BANNER = </span><span class="s1">'''</span>
|
||||
<span class="s1"> Usage: coffee [options] path/to/script.coffee</span>
|
||||
<span class="s1"> '''</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SWITCHES = </span><span class="p">[</span>
|
||||
<span class="p">[</span><span class="s1">'-c'</span><span class="p">,</span> <span class="s1">'--compile'</span><span class="p">,</span> <span class="s1">'compile to JavaScript and save as .js files'</span><span class="p">]</span>
|
||||
@@ -76,19 +80,19 @@ requested options. If evaluating the script directly sets <code>__filename</code
|
||||
<span class="nv">t = task = </span><span class="p">{</span><span class="nx">file</span><span class="p">,</span> <span class="nx">input</span><span class="p">,</span> <span class="nx">options</span><span class="p">}</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'compile'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">tokens</span> <span class="k">then</span> <span class="nx">printTokens</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">tokens</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">nodes</span> <span class="k">then</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">).</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</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">nodes</span> <span class="k">then</span> <span class="nx">printLine</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">nodes</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">).</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">run</span> <span class="k">then</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">t.output = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">options</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'success'</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</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">printLine</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">trim</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">compile</span> <span class="k">then</span> <span class="nx">writeJs</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">base</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="k">then</span> <span class="nx">lint</span> <span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">,</span> <span class="nx">t</span><span class="p">.</span><span class="nx">output</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s1">'failure'</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s1">'failure'</span><span class="p">).</span><span class="nx">length</span>
|
||||
<span class="k">return</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span>
|
||||
<span class="k">return</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span> <span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">watch</span>
|
||||
<span class="nx">printWarn</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
|
||||
and write them back to <strong>stdout</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileStdio = </span><span class="o">-></span>
|
||||
<span class="nv">code = </span><span class="s1">''</span>
|
||||
@@ -114,12 +118,12 @@ directory can be customized with <code>--output</code>.</p> </td>
|
||||
<span class="nv">compile = </span><span class="o">-></span>
|
||||
<span class="nv">js = </span><span class="s1">' '</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o"><=</span> <span class="mi">0</span>
|
||||
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">err</span> <span class="k">then</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="k">then</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"Compiled #{source}"</span>
|
||||
<span class="k">if</span> <span class="nx">err</span> <span class="k">then</span> <span class="nx">printLine</span> <span class="nx">err</span><span class="p">.</span><span class="nx">message</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span> <span class="o">and</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span> <span class="k">then</span> <span class="nx">util</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"compiled #{source}"</span>
|
||||
<span class="nx">path</span><span class="p">.</span><span class="nx">exists</span> <span class="nx">dir</span><span class="p">,</span> <span class="p">(</span><span class="nx">exists</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">exists</span> <span class="k">then</span> <span class="nx">compile</span><span class="p">()</span> <span class="k">else</span> <span class="nx">exec</span> <span class="s2">"mkdir -p #{dir}"</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
|
||||
any errors or warnings that arise.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lint = </span><span class="p">(</span><span class="nx">file</span><span class="p">,</span> <span class="nx">js</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">file</span> <span class="o">+</span> <span class="s1">':\t'</span> <span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">printIt = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">printLine</span> <span class="nx">file</span> <span class="o">+</span> <span class="s1">':\t'</span> <span class="o">+</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">trim</span><span class="p">()</span>
|
||||
<span class="nv">conf = </span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">'/../extras/jsl.conf'</span>
|
||||
<span class="nv">jsl = </span><span class="nx">spawn</span> <span class="s1">'jsl'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'-nologo'</span><span class="p">,</span> <span class="s1">'-stdin'</span><span class="p">,</span> <span class="s1">'-conf'</span><span class="p">,</span> <span class="nx">conf</span><span class="p">]</span>
|
||||
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nx">printIt</span>
|
||||
@@ -129,7 +133,7 @@ any errors or warnings that arise.</p> </td> <td class="
|
||||
<span class="nv">strings = </span><span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">tokens</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">token</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nx">toString</span><span class="p">().</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\n/</span><span class="p">,</span> <span class="s1">'\\n'</span><span class="p">)]</span>
|
||||
<span class="s2">"[#{tag} #{value}]"</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">strings</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-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<span class="nx">printLine</span> <span class="nx">strings</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-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parseOptions = </span><span class="o">-></span>
|
||||
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">ALL_SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
|
||||
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">2</span>
|
||||
@@ -138,11 +142,11 @@ any errors or warnings that arise.</p> </td> <td class="
|
||||
<span class="nv">o.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
|
||||
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span>
|
||||
<span class="k">if</span> <span class="nx">opts</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">warn</span> <span class="s1">'--no-wrap is deprecated; please use --bare instead.'</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">fileName</span><span class="p">)</span> <span class="o">-></span> <span class="p">{</span><span class="nx">fileName</span><span class="p">,</span> <span class="nx">bare</span><span class="o">:</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span> <span class="o">or</span> <span class="nx">opts</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]}</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
<span class="nx">printWarn</span> <span class="s1">'--no-wrap is deprecated; please use --bare instead.'</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>The compile-time options to pass to the CoffeeScript compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compileOptions = </span><span class="p">(</span><span class="nx">fileName</span><span class="p">)</span> <span class="o">-></span> <span class="p">{</span><span class="nx">fileName</span><span class="p">,</span> <span class="nx">bare</span><span class="o">:</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span> <span class="o">or</span> <span class="nx">opts</span><span class="p">[</span><span class="s1">'no-wrap'</span><span class="p">]}</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
shown.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">usage = </span><span class="o">-></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="p">(</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="p">).</span><span class="nx">help</span><span class="p">()</span>
|
||||
<span class="nx">printLine</span> <span class="p">(</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="p">).</span><span class="nx">help</span><span class="p">()</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Print the <code>--version</code> message and exit.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">version = </span><span class="o">-></span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"CoffeeScript version #{CoffeeScript.VERSION}"</span>
|
||||
<span class="nx">printLine</span> <span class="s2">"CoffeeScript version #{CoffeeScript.VERSION}"</span>
|
||||
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">0</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -99,7 +99,6 @@ the ordinary <strong>Assign</strong> is that these allow numbers and strings as
|
||||
<span class="nx">ObjAssignable</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
<span class="nx">o</span> <span class="s1">'AlphaNumeric'</span>
|
||||
<span class="nx">o</span> <span class="s1">'Parenthetical'</span>
|
||||
<span class="nx">o</span> <span class="s1">'ThisProperty'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>A return statement from a function body.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Return</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'RETURN Expression'</span><span class="p">,</span> <span class="o">-></span> <span class="k">new</span> <span class="nx">Return</span> <span class="nx">$2</span>
|
||||
@@ -270,12 +269,12 @@ or postfix, with a single expression.</p> </td> <td clas
|
||||
|
||||
<span class="nx">ForBody</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR Range'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">source</span><span class="o">:</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$2</span><span class="p">),</span> <span class="nx">vars</span><span class="o">:</span> <span class="p">[]</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForStart ForSource'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$2.raw = </span><span class="nx">$1</span><span class="p">.</span><span class="nx">raw</span><span class="p">;</span> <span class="nv">$2.vars = </span><span class="nx">$1</span><span class="p">;</span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'ForStart ForSource'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$2.own = </span><span class="nx">$1</span><span class="p">.</span><span class="nx">own</span><span class="p">;</span> <span class="nv">$2.vars = </span><span class="nx">$1</span><span class="p">;</span> <span class="nx">$2</span>
|
||||
<span class="p">]</span>
|
||||
|
||||
<span class="nx">ForStart</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR ForVariables'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">$2</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR ALL ForVariables'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$3.raw = </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$3</span>
|
||||
<span class="nx">o</span> <span class="s1">'FOR OWN ForVariables'</span><span class="p">,</span> <span class="o">-></span> <span class="nv">$3.own = </span><span class="kc">yes</span><span class="p">;</span> <span class="nx">$3</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>An array of all accepted values for a variable inside the loop.
|
||||
This enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ForValue</span><span class="o">:</span> <span class="p">[</span>
|
||||
<span class="nx">o</span> <span class="s1">'Identifier'</span>
|
||||
@@ -388,7 +387,7 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
our <strong>Jison.Parser</strong>. We do this by processing all of our rules, recording all
|
||||
terminals (every symbol which does not appear as the name of a rule above)
|
||||
as "tokens".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">tokens = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">all</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">alternatives</span> <span class="k">of</span> <span class="nx">grammar</span>
|
||||
<span class="k">for</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">alternatives</span> <span class="k">of</span> <span class="nx">grammar</span>
|
||||
<span class="nx">grammar</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="k">for</span> <span class="nx">alt</span> <span class="k">in</span> <span class="nx">alternatives</span>
|
||||
<span class="k">for</span> <span class="nx">token</span> <span class="k">in</span> <span class="nx">alt</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">split</span> <span class="s1">' '</span>
|
||||
<span class="nx">tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span> <span class="nx">unless</span> <span class="nx">grammar</span><span class="p">[</span><span class="nx">token</span><span class="p">]</span>
|
||||
|
||||
@@ -11,7 +11,7 @@ arrays, count characters, that sort of thing.</p> </td>
|
||||
Used every time <code>Base#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">exports.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="nx">extend</span> <span class="p">(</span><span class="nx">extend</span> <span class="p">{},</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">overrides</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Extend a source object with the properties of another object (shallow copy).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">extend = exports.extend = </span><span class="p">(</span><span class="nx">object</span><span class="p">,</span> <span class="nx">properties</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">all</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">val</span> <span class="k">of</span> <span class="nx">properties</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">properties</span>
|
||||
<span class="nx">object</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="nx">object</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Return a flattened version of an array.
|
||||
Handy for getting a list of <code>children</code> from the nodes.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.flatten = flatten = </span><span class="p">(</span><span class="nx">array</span><span class="p">)</span> <span class="o">-></span>
|
||||
|
||||
@@ -53,8 +53,8 @@ though <code>is</code> means <code>===</code> otherwise.</p> </td>
|
||||
<span class="k">return</span> <span class="mi">0</span> <span class="nx">unless</span> <span class="nv">match = </span><span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">@chunk</span>
|
||||
<span class="p">[</span><span class="nx">input</span><span class="p">,</span> <span class="nx">id</span><span class="p">,</span> <span class="nx">colon</span><span class="p">]</span> <span class="o">=</span> <span class="nx">match</span>
|
||||
|
||||
<span class="k">if</span> <span class="nx">id</span> <span class="o">is</span> <span class="s1">'all'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'FOR'</span>
|
||||
<span class="nx">@token</span> <span class="s1">'ALL'</span><span class="p">,</span> <span class="nx">id</span>
|
||||
<span class="k">if</span> <span class="nx">id</span> <span class="o">is</span> <span class="s1">'own'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">()</span> <span class="o">is</span> <span class="s1">'FOR'</span>
|
||||
<span class="nx">@token</span> <span class="s1">'OWN'</span><span class="p">,</span> <span class="nx">id</span>
|
||||
<span class="k">return</span> <span class="nx">id</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nv">forcedIdentifier = </span><span class="nx">colon</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nv">prev = </span><span class="nx">last</span> <span class="nx">@tokens</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">prev</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'.'</span><span class="p">,</span> <span class="s1">'?.'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'::'</span><span class="p">]</span>
|
||||
@@ -385,7 +385,7 @@ token stream.</p> </td> <td class="code">
|
||||
<span class="s1">'if'</span><span class="p">,</span> <span class="s1">'else'</span><span class="p">,</span> <span class="s1">'switch'</span><span class="p">,</span> <span class="s1">'for'</span><span class="p">,</span> <span class="s1">'while'</span><span class="p">,</span> <span class="s1">'try'</span><span class="p">,</span> <span class="s1">'catch'</span><span class="p">,</span> <span class="s1">'finally'</span>
|
||||
<span class="s1">'class'</span><span class="p">,</span> <span class="s1">'extends'</span><span class="p">,</span> <span class="s1">'super'</span>
|
||||
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-39"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-39">¶</a> </div> <p>CoffeeScript-only keywords.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">COFFEE_KEYWORDS = </span><span class="p">[</span><span class="s1">'undefined'</span><span class="p">,</span> <span class="s1">'then'</span><span class="p">,</span> <span class="s1">'unless'</span><span class="p">,</span> <span class="s1">'until'</span><span class="p">,</span> <span class="s1">'loop'</span><span class="p">,</span> <span class="s1">'of'</span><span class="p">,</span> <span class="s1">'by'</span><span class="p">,</span> <span class="s1">'when'</span><span class="p">]</span>
|
||||
<span class="nx">COFFEE_KEYWORDS</span><span class="p">.</span><span class="nx">push</span> <span class="nx">op</span> <span class="k">for</span> <span class="nx">all</span> <span class="nx">op</span> <span class="k">of</span> <span class="nv">COFFEE_ALIASES =</span>
|
||||
<span class="nx">COFFEE_KEYWORDS</span><span class="p">.</span><span class="nx">push</span> <span class="nx">op</span> <span class="k">for</span> <span class="nx">op</span> <span class="k">of</span> <span class="nv">COFFEE_ALIASES =</span>
|
||||
<span class="o">and</span> <span class="o">:</span> <span class="s1">'&&'</span>
|
||||
<span class="o">or</span> <span class="o">:</span> <span class="s1">'||'</span>
|
||||
<span class="o">is</span> <span class="o">:</span> <span class="s1">'=='</span>
|
||||
|
||||
@@ -160,10 +160,11 @@ declarations of all inner variables pushed up to the top.</p> </td>
|
||||
<span class="vi">@expressions = </span><span class="nx">rest</span>
|
||||
<span class="nv">post = </span><span class="nx">@compileNode</span> <span class="nx">o</span>
|
||||
<span class="p">{</span><span class="nx">scope</span><span class="p">}</span> <span class="o">=</span> <span class="nx">o</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">globals</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">hasDeclarations</span> <span class="k">this</span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">"#{@tab}var #{ scope.compiledDeclarations() };\n"</span>
|
||||
<span class="k">if</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">hasAssignments</span> <span class="k">this</span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">"#{@tab}var #{ multident scope.compiledAssignments(), @tab };\n"</span>
|
||||
<span class="k">if</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">expressions</span> <span class="o">is</span> <span class="k">this</span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">o</span><span class="p">.</span><span class="nx">globals</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">hasDeclarations</span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">"#{@tab}var #{ scope.declaredVariables().join(', ') };\n"</span>
|
||||
<span class="k">if</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">hasAssignments</span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">"#{@tab}var #{ multident scope.assignedVariables().join(', '), @tab };\n"</span>
|
||||
<span class="nx">code</span> <span class="o">+</span> <span class="nx">post</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>Wrap up the given nodes as an <strong>Expressions</strong>, unless it already happens
|
||||
to be one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">@wrap</span><span class="o">:</span> <span class="p">(</span><span class="nx">nodes</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="nx">nodes</span><span class="p">.</span><span class="nx">length</span> <span class="o">is</span> <span class="mi">1</span> <span class="o">and</span> <span class="nx">nodes</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nx">Expressions</span>
|
||||
@@ -297,7 +298,11 @@ calls against the prototype's function of the same name.</p> </td>
|
||||
<span class="vi">@variable = </span><span class="k">if</span> <span class="nx">@isSuper</span> <span class="k">then</span> <span class="kc">null</span> <span class="k">else</span> <span class="nx">variable</span>
|
||||
|
||||
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">'variable'</span><span class="p">,</span> <span class="s1">'args'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-48"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-48">¶</a> </div> <p>Tag this invocation as creating a new instance.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">newInstance</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="vi">@isNew = </span><span class="kc">true</span>
|
||||
<span class="nv">base = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">base</span> <span class="o">or</span> <span class="nx">@variable</span>
|
||||
<span class="k">if</span> <span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Call</span>
|
||||
<span class="nx">base</span><span class="p">.</span><span class="nx">newInstance</span><span class="p">()</span>
|
||||
<span class="k">else</span>
|
||||
<span class="vi">@isNew = </span><span class="kc">true</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">¶</a> </div> <p>Grab the reference to the superclass's implementation of the current
|
||||
method.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">superReference</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">{</span><span class="nx">method</span><span class="p">}</span> <span class="o">=</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span>
|
||||
@@ -342,7 +347,7 @@ method.</p> </td> <td class="code"> <div c
|
||||
<span class="k">return</span> <span class="nx">@compileSplat</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">code</span>
|
||||
<span class="nv">args = </span><span class="p">(</span><span class="nx">arg</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span> <span class="k">for</span> <span class="nx">arg</span> <span class="k">in</span> <span class="nx">@args</span><span class="p">).</span><span class="nx">join</span> <span class="s1">', '</span>
|
||||
<span class="k">if</span> <span class="nx">@isSuper</span>
|
||||
<span class="nx">@compileSuper</span> <span class="nx">args</span><span class="p">,</span> <span class="nx">o</span>
|
||||
<span class="nx">@superReference</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s2">".call(this#{ args and ', ' + args })"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="p">(</span><span class="k">if</span> <span class="nx">@isNew</span> <span class="k">then</span> <span class="s1">'new '</span> <span class="k">else</span> <span class="s1">''</span><span class="p">)</span> <span class="o">+</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span><span class="p">)</span> <span class="o">+</span> <span class="s2">"(#{args})"</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">¶</a> </div> <p><code>super()</code> is converted into a call against the superclass's implementation
|
||||
of the current function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSuper</span><span class="o">:</span> <span class="p">(</span><span class="nx">args</span><span class="p">,</span> <span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
@@ -351,21 +356,25 @@ of the current function.</p> </td> <td class="code">
|
||||
If it's a constructor, then things get real tricky. We have to inject an
|
||||
inner constructor in order to be able to pass the varargs.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSplat</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">splatArgs</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="s2">"#{ @superReference o }.apply(this, #{splatArgs})"</span> <span class="k">if</span> <span class="nx">@isSuper</span>
|
||||
<span class="nx">unless</span> <span class="nx">@isNew</span>
|
||||
<span class="nv">base = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@variable</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nv">name = </span><span class="nx">base</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">pop</span><span class="p">())</span> <span class="o">and</span> <span class="nx">base</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
||||
<span class="nv">ref = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">'this'</span>
|
||||
<span class="nv">fun = </span><span class="s2">"(#{ref} = #{ base.compile o, LEVEL_LIST })#{ name.compile o }"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">fun = ref = </span><span class="nx">base</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span>
|
||||
<span class="nx">fun</span> <span class="o">+=</span> <span class="nx">name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="k">if</span> <span class="nx">name</span>
|
||||
<span class="k">return</span> <span class="s2">"#{fun}.apply(#{ref}, #{splatArgs})"</span>
|
||||
<span class="nv">idt = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
|
||||
<span class="s2">"""</span>
|
||||
<span class="s2"> (function(func, args, ctor) {</span>
|
||||
<span class="k">if</span> <span class="nx">@isNew</span>
|
||||
<span class="nv">idt = </span><span class="nx">@tab</span> <span class="o">+</span> <span class="nx">TAB</span>
|
||||
<span class="k">return</span> <span class="s2">"""</span>
|
||||
<span class="s2"> (function(func, args, ctor) {</span>
|
||||
|
||||
<span class="s2">#DIVIDER</span>
|
||||
<span class="s2"> """</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>{idt}ctor.prototype = func.prototype;
|
||||
<span class="s2"> """</span>
|
||||
<span class="nv">base = </span><span class="k">new</span> <span class="nx">Value</span> <span class="nx">@variable</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nv">name = </span><span class="nx">base</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">pop</span><span class="p">())</span> <span class="o">and</span> <span class="nx">base</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
||||
<span class="nv">ref = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">'ref'</span>
|
||||
<span class="nv">fun = </span><span class="s2">"(#{ref} = #{ base.compile o, LEVEL_LIST })#{ name.compile o }"</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">fun = </span><span class="nx">base</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_ACCESS</span>
|
||||
<span class="k">if</span> <span class="nx">name</span>
|
||||
<span class="nv">ref = </span><span class="nx">fun</span>
|
||||
<span class="nx">fun</span> <span class="o">+=</span> <span class="nx">name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">ref = </span><span class="s1">'null'</span>
|
||||
<span class="s2">"#{fun}.apply(#{ref}, #{splatArgs})"</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">¶</a> </div> <p>{idt}ctor.prototype = func.prototype;
|
||||
{idt}var child = new ctor, result = func.apply(child, args);
|
||||
{idt}return typeof result === "object" ? result : child;
|
||||
{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">¶</a> </div> <h3>Extends</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Extends = </span><span class="nx">class</span> <span class="nx">Extends</span> <span class="k">extends</span> <span class="nx">Base</span>
|
||||
@@ -472,10 +481,6 @@ is the index of the beginning.</p> </td> <td class="code
|
||||
<span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">props = </span><span class="nx">@properties</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="k">if</span> <span class="nx">@front</span> <span class="k">then</span> <span class="s1">'({})'</span> <span class="k">else</span> <span class="s1">'{}'</span><span class="p">)</span> <span class="nx">unless</span> <span class="nx">props</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">props</span>
|
||||
<span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Splat</span> <span class="o">or</span> <span class="p">(</span><span class="nx">prop</span><span class="p">.</span><span class="nx">variable</span> <span class="o">or</span> <span class="nx">prop</span><span class="p">).</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Parens</span>
|
||||
<span class="nv">rest = </span><span class="nx">props</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mi">0</span>
|
||||
<span class="k">break</span>
|
||||
<span class="nv">idt = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
||||
<span class="nv">nonComments = </span><span class="p">(</span><span class="nx">prop</span> <span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="nx">prop</span> <span class="o">not</span> <span class="k">instanceof</span> <span class="nx">Comment</span><span class="p">)</span>
|
||||
<span class="nv">lastNoncom = </span><span class="nx">last</span> <span class="nx">nonComments</span>
|
||||
@@ -494,31 +499,8 @@ is the index of the beginning.</p> </td> <td class="code
|
||||
<span class="nx">indent</span> <span class="o">+</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span><span class="p">)</span> <span class="o">+</span> <span class="nx">join</span>
|
||||
<span class="nv">props = </span><span class="nx">props</span><span class="p">.</span><span class="nx">join</span> <span class="s1">''</span>
|
||||
<span class="nv">obj = </span><span class="s2">"{#{ props and '\n' + props + '\n' + @tab }}"</span>
|
||||
<span class="k">return</span> <span class="nx">@compileDynamic</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">obj</span><span class="p">,</span> <span class="nx">rest</span> <span class="k">if</span> <span class="nx">rest</span>
|
||||
<span class="k">if</span> <span class="nx">@front</span> <span class="k">then</span> <span class="s2">"(#{obj})"</span> <span class="k">else</span> <span class="nx">obj</span>
|
||||
|
||||
<span class="nx">compileDynamic</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">props</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">code = </span><span class="s2">"#{ oref = o.scope.freeVariable 'obj' } = #{code}, "</span>
|
||||
<span class="k">for</span> <span class="nx">prop</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">props</span>
|
||||
<span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Comment</span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">)</span> <span class="o">+</span> <span class="s1">' '</span>
|
||||
<span class="k">continue</span>
|
||||
<span class="k">if</span> <span class="nx">prop</span> <span class="k">instanceof</span> <span class="nx">Assign</span>
|
||||
<span class="nv">acc = </span><span class="nx">prop</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="nx">base</span>
|
||||
<span class="nv">key = </span><span class="nx">acc</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_PAREN</span>
|
||||
<span class="nv">val = </span><span class="nx">prop</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">acc = </span><span class="nx">prop</span><span class="p">.</span><span class="nx">base</span>
|
||||
<span class="p">[</span><span class="nx">key</span><span class="p">,</span> <span class="nx">val</span><span class="p">]</span> <span class="o">=</span> <span class="nx">acc</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span><span class="p">,</span> <span class="nx">ref</span>
|
||||
<span class="nv">ref = </span><span class="nx">val</span> <span class="k">if</span> <span class="nx">key</span> <span class="o">isnt</span> <span class="nx">val</span>
|
||||
<span class="nv">key = </span><span class="k">if</span> <span class="nx">acc</span> <span class="k">instanceof</span> <span class="nx">Literal</span> <span class="o">and</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">key</span>
|
||||
<span class="s1">'.'</span> <span class="o">+</span> <span class="nx">key</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s1">'['</span> <span class="o">+</span> <span class="nx">key</span> <span class="o">+</span> <span class="s1">']'</span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="s2">"#{oref}#{key} = #{val}, "</span>
|
||||
<span class="nx">code</span> <span class="o">+=</span> <span class="nx">oref</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><=</span> <span class="nx">LEVEL_PAREN</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">"(#{code})"</span>
|
||||
|
||||
<span class="nx">assigns</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">prop</span> <span class="k">in</span> <span class="nx">@properties</span> <span class="k">when</span> <span class="nx">prop</span><span class="p">.</span><span class="nx">assigns</span> <span class="nx">name</span> <span class="k">then</span> <span class="k">return</span> <span class="kc">yes</span>
|
||||
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-71"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-71">¶</a> </div> <p>An object literal, nothing fancy.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-72"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-72">¶</a> </div> <h3>Arr</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Arr = </span><span class="nx">class</span> <span class="nx">Arr</span> <span class="k">extends</span> <span class="nx">Base</span>
|
||||
@@ -576,10 +558,9 @@ constructor.</p> </td> <td class="code"> <
|
||||
<span class="k">if</span> <span class="nx">func</span><span class="p">.</span><span class="nx">bound</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s1">'cannot define a constructor as a bound function'</span>
|
||||
<span class="k">if</span> <span class="nx">func</span> <span class="k">instanceof</span> <span class="nx">Code</span>
|
||||
<span class="vi">@ctor = </span><span class="nx">func</span>
|
||||
<span class="nv">assign = </span><span class="vi">@ctor = </span><span class="nx">func</span>
|
||||
<span class="k">else</span>
|
||||
<span class="vi">@ctor = </span><span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">name</span><span class="p">),</span> <span class="nx">func</span><span class="p">)</span>
|
||||
<span class="nv">assign = </span><span class="kc">null</span>
|
||||
<span class="nv">assign = </span><span class="vi">@ctor = </span><span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span> <span class="nx">name</span><span class="p">),</span> <span class="nx">func</span><span class="p">)</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">unless</span> <span class="nx">assign</span><span class="p">.</span><span class="nx">variable</span><span class="p">.</span><span class="k">this</span>
|
||||
<span class="nv">assign.variable = </span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="nx">name</span><span class="p">),</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="nx">base</span><span class="p">,</span> <span class="s1">'proto'</span><span class="p">)])</span>
|
||||
@@ -589,14 +570,16 @@ constructor.</p> </td> <td class="code"> <
|
||||
<span class="nx">assign</span></pre></div> </td> </tr> <tr id="section-79"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-79">¶</a> </div> <p>Merge the properties from a top-level object as prototypal properties
|
||||
on the class.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">walkBody</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@traverseChildren</span> <span class="kc">false</span><span class="p">,</span> <span class="p">(</span><span class="nx">child</span><span class="p">)</span> <span class="o">=></span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="nx">child</span> <span class="k">instanceof</span> <span class="nx">Class</span>
|
||||
<span class="k">if</span> <span class="nx">child</span> <span class="k">instanceof</span> <span class="nx">Expressions</span>
|
||||
<span class="k">for</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nv">exps = </span><span class="nx">child</span><span class="p">.</span><span class="nx">expressions</span>
|
||||
<span class="k">if</span> <span class="nx">node</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">node</span><span class="p">.</span><span class="nx">isObject</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span>
|
||||
<span class="nx">exps</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">compact</span> <span class="nx">@addProperties</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">name</span>
|
||||
<span class="nv">child.expressions = exps = </span><span class="nx">compact</span> <span class="nx">flatten</span> <span class="nx">exps</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-80">¶</a> </div> <p>Walk the body of the class, looking for prototype properties to be converted.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ensureConstructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">exps</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@addProperties</span> <span class="nx">node</span><span class="p">,</span> <span class="nx">name</span>
|
||||
<span class="nv">child.expressions = exps = </span><span class="nx">flatten</span> <span class="nx">exps</span></pre></div> </td> </tr> <tr id="section-80"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-80">¶</a> </div> <p>Walk the body of the class, looking for prototype properties to be converted.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">ensureConstructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="o">not</span> <span class="nx">@ctor</span>
|
||||
<span class="vi">@ctor = </span><span class="k">new</span> <span class="nx">Code</span>
|
||||
<span class="nx">@ctor</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">Call</span> <span class="s1">'super'</span><span class="p">,</span> <span class="p">[</span><span class="k">new</span> <span class="nx">Splat</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'arguments'</span><span class="p">]</span> <span class="k">if</span> <span class="nx">@parent</span>
|
||||
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@ctor</span>
|
||||
<span class="vi">@ctor.ctor = @ctor.name = </span><span class="nx">name</span>
|
||||
<span class="vi">@ctor.klass = </span><span class="kc">null</span>
|
||||
<span class="vi">@ctor.noReturn = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-81"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-81">¶</a> </div> <p>Make sure that a constructor is defined for the class, and properly
|
||||
@@ -607,14 +590,12 @@ configured.</p> </td> <td class="code"> <d
|
||||
|
||||
<span class="nx">@setContext</span> <span class="nx">name</span>
|
||||
<span class="nx">@walkBody</span> <span class="nx">name</span>
|
||||
<span class="nx">@ensureConstructor</span> <span class="nx">name</span>
|
||||
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Extends</span> <span class="nx">lname</span><span class="p">,</span> <span class="nx">@parent</span> <span class="k">if</span> <span class="nx">@parent</span>
|
||||
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">@ctor</span>
|
||||
<span class="nx">@ensureConstructor</span> <span class="nx">name</span>
|
||||
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">push</span> <span class="nx">lname</span>
|
||||
<span class="nx">@addBoundFunctions</span> <span class="nx">o</span>
|
||||
|
||||
<span class="nv">klass = </span><span class="k">new</span> <span class="nx">Parens</span> <span class="k">new</span> <span class="nx">Call</span><span class="p">(</span><span class="k">new</span> <span class="nx">Code</span> <span class="p">[],</span> <span class="nx">@body</span><span class="p">),</span> <span class="kc">true</span>
|
||||
<span class="nv">klass = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">lname</span><span class="p">),</span> <span class="nx">klass</span> <span class="k">if</span> <span class="nx">decl</span> <span class="o">and</span> <span class="nx">@variable</span><span class="o">?</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
||||
<span class="nv">klass = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="nx">@variable</span><span class="p">,</span> <span class="nx">klass</span> <span class="k">if</span> <span class="nx">@variable</span>
|
||||
<span class="nx">klass</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span></pre></div> </td> </tr> <tr id="section-82"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-82">¶</a> </div> <p>Instead of generating the JavaScript string directly, we build up the
|
||||
equivalent syntax tree and compile that, in pieces. You can see the
|
||||
@@ -712,13 +693,17 @@ for details.</p> </td> <td class="code"> <
|
||||
operands are only evaluated once, even though we have to reference them
|
||||
more than once.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileSplice</span><span class="o">:</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">range</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@variable</span><span class="p">.</span><span class="nx">properties</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="nv">name = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
|
||||
<span class="nv">plus = </span><span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">exclusive</span> <span class="k">then</span> <span class="s1">''</span> <span class="k">else</span> <span class="s1">' + 1'</span>
|
||||
<span class="nv">from = </span><span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span> <span class="k">then</span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="s1">'0'</span>
|
||||
<span class="nv">to = </span><span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">to</span> <span class="k">then</span> <span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">' - '</span> <span class="o">+</span> <span class="nx">from</span> <span class="o">+</span> <span class="nx">plus</span> <span class="k">else</span> <span class="s2">"#{name}.length"</span>
|
||||
<span class="nv">ref = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">'ref'</span>
|
||||
<span class="nv">val = </span><span class="nx">@value</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
||||
<span class="s2">"([].splice.apply(#{name}, [#{from}, #{to}].concat(#{ref} = #{val})), #{ref})"</span></pre></div> </td> </tr> <tr id="section-93"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-93">¶</a> </div> <p>Compile the assignment from an array splice literal, using JavaScript's
|
||||
<span class="nv">name = </span><span class="nx">@variable</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span>
|
||||
<span class="nv">plus = </span><span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">exclusive</span> <span class="k">then</span> <span class="s1">''</span> <span class="k">else</span> <span class="s1">' + 1'</span>
|
||||
<span class="nv">from = </span><span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span> <span class="k">then</span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="k">else</span> <span class="s1">'0'</span>
|
||||
<span class="nv">to = </span><span class="s2">"#{name}.length"</span> <span class="nx">unless</span> <span class="nx">range</span><span class="p">.</span><span class="nx">to</span>
|
||||
<span class="nx">unless</span> <span class="nx">to</span>
|
||||
<span class="k">if</span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span> <span class="o">and</span> <span class="nx">range</span><span class="p">.</span><span class="nx">from</span><span class="p">.</span><span class="nx">isSimpleNumber</span><span class="p">()</span> <span class="o">and</span> <span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">isSimpleNumber</span><span class="p">()</span>
|
||||
<span class="nv">to = </span><span class="p">(</span><span class="o">+</span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">))</span> <span class="o">-</span> <span class="o">+</span><span class="nx">from</span> <span class="o">+</span> <span class="o">+</span><span class="nx">plus</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">to = </span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">+</span> <span class="s1">' - '</span> <span class="o">+</span> <span class="nx">from</span> <span class="o">+</span> <span class="nx">plus</span>
|
||||
<span class="nv">val = </span><span class="nx">@value</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span>
|
||||
<span class="s2">"[].splice.apply(#{name}, [#{from}, #{to}].concat(#{val}))"</span></pre></div> </td> </tr> <tr id="section-93"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-93">¶</a> </div> <p>Compile the assignment from an array splice literal, using JavaScript's
|
||||
<code>Array#splice</code> method.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-94"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-94">¶</a> </div> <h3>Code</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.Code = </span><span class="nx">class</span> <span class="nx">Code</span> <span class="k">extends</span> <span class="nx">Base</span>
|
||||
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">params</span><span class="p">,</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">tag</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@params = </span><span class="nx">params</span> <span class="o">or</span> <span class="p">[]</span>
|
||||
@@ -731,9 +716,10 @@ more than once.</p> </td> <td class="code">
|
||||
<span class="nx">isStatement</span><span class="o">:</span> <span class="o">-></span> <span class="o">!!</span><span class="nx">@ctor</span></pre></div> </td> </tr> <tr id="section-95"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-95">¶</a> </div> <p>A function definition. This is the only node that creates a new Scope.
|
||||
When for the purposes of walking the contents of a function body, the Code
|
||||
has no <em>children</em> -- they're within the inner scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileNode</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">sharedScope = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">'sharedScope'</span>
|
||||
<span class="nv">o.scope = scope = </span><span class="nx">sharedScope</span> <span class="o">or</span> <span class="k">new</span> <span class="nx">Scope</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">@body</span><span class="p">,</span> <span class="k">this</span>
|
||||
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
||||
<span class="nv">sharedScope = </span><span class="nx">del</span> <span class="nx">o</span><span class="p">,</span> <span class="s1">'sharedScope'</span>
|
||||
<span class="nv">o.scope = </span><span class="nx">sharedScope</span> <span class="o">or</span> <span class="k">new</span> <span class="nx">Scope</span> <span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">,</span> <span class="nx">@body</span><span class="p">,</span> <span class="k">this</span>
|
||||
<span class="nv">o.scope.shared = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">sharedScope</span>
|
||||
<span class="nx">o</span><span class="p">.</span><span class="nx">indent</span> <span class="o">+=</span> <span class="nx">TAB</span>
|
||||
<span class="k">delete</span> <span class="nx">o</span><span class="p">.</span><span class="nx">bare</span>
|
||||
<span class="k">delete</span> <span class="nx">o</span><span class="p">.</span><span class="nx">globals</span>
|
||||
<span class="nv">vars = </span><span class="p">[]</span>
|
||||
@@ -754,11 +740,10 @@ has no <em>children</em> -- they're within the inner scope.</p> </td
|
||||
<span class="nv">val = </span><span class="k">new</span> <span class="nx">Assign</span> <span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">param</span><span class="p">.</span><span class="nx">name</span><span class="p">),</span> <span class="nx">param</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span> <span class="s1">'='</span>
|
||||
<span class="nx">exprs</span><span class="p">.</span><span class="nx">push</span> <span class="k">new</span> <span class="nx">If</span> <span class="nx">lit</span><span class="p">,</span> <span class="nx">val</span>
|
||||
<span class="nx">vars</span><span class="p">.</span><span class="nx">push</span> <span class="nx">ref</span> <span class="nx">unless</span> <span class="nx">splats</span>
|
||||
<span class="nx">scope</span><span class="p">.</span><span class="nx">startLevel</span><span class="p">()</span>
|
||||
<span class="nv">wasEmpty = </span><span class="nx">@body</span><span class="p">.</span><span class="nx">isEmpty</span><span class="p">()</span>
|
||||
<span class="nx">exprs</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">splats</span> <span class="k">if</span> <span class="nx">splats</span>
|
||||
<span class="nx">@body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">.</span><span class="nx">unshift</span> <span class="nx">exprs</span><span class="p">...</span> <span class="k">if</span> <span class="nx">exprs</span><span class="p">.</span><span class="nx">length</span>
|
||||
<span class="nx">scope</span><span class="p">.</span><span class="nx">parameter</span> <span class="nx">vars</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="k">for</span> <span class="nx">v</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">vars</span> <span class="nx">unless</span> <span class="nx">splats</span>
|
||||
<span class="nx">o</span><span class="p">.</span><span class="nx">scope</span><span class="p">.</span><span class="nx">parameter</span> <span class="nx">vars</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span> <span class="k">for</span> <span class="nx">v</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">vars</span> <span class="nx">unless</span> <span class="nx">splats</span>
|
||||
<span class="nx">@body</span><span class="p">.</span><span class="nx">makeReturn</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">wasEmpty</span> <span class="o">or</span> <span class="nx">@noReturn</span>
|
||||
<span class="nv">idt = </span><span class="nx">o</span><span class="p">.</span><span class="nx">indent</span>
|
||||
<span class="nv">code = </span><span class="s1">'function'</span>
|
||||
@@ -888,10 +873,6 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
|
||||
<span class="s1">'of'</span><span class="o">:</span> <span class="s1">'in'</span></pre></div> </td> </tr> <tr id="section-108"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-108">¶</a> </div> <p>The map of conversions from CoffeeScript to JavaScript symbols.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">INVERSIONS =</span>
|
||||
<span class="s1">'!=='</span><span class="o">:</span> <span class="s1">'==='</span>
|
||||
<span class="s1">'==='</span><span class="o">:</span> <span class="s1">'!=='</span>
|
||||
<span class="s1">'>'</span><span class="o">:</span> <span class="s1">'<='</span>
|
||||
<span class="s1">'<='</span><span class="o">:</span> <span class="s1">'>'</span>
|
||||
<span class="s1">'<'</span><span class="o">:</span> <span class="s1">'>='</span>
|
||||
<span class="s1">'>='</span><span class="o">:</span> <span class="s1">'<'</span>
|
||||
|
||||
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">'first'</span><span class="p">,</span> <span class="s1">'second'</span><span class="p">]</span>
|
||||
|
||||
@@ -900,8 +881,23 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
|
||||
<span class="nx">@operator</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'<'</span><span class="p">,</span> <span class="s1">'>'</span><span class="p">,</span> <span class="s1">'>='</span><span class="p">,</span> <span class="s1">'<='</span><span class="p">,</span> <span class="s1">'==='</span><span class="p">,</span> <span class="s1">'!=='</span><span class="p">]</span>
|
||||
|
||||
<span class="nx">invert</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nv">op = </span><span class="nx">INVERSIONS</span><span class="p">[</span><span class="nx">@operator</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nx">@isChainable</span><span class="p">()</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isChainable</span><span class="p">()</span>
|
||||
<span class="nv">allInvertable = </span><span class="kc">yes</span>
|
||||
<span class="nv">curr = </span><span class="k">this</span>
|
||||
<span class="k">while</span> <span class="nx">curr</span> <span class="o">and</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span>
|
||||
<span class="nx">allInvertable</span> <span class="o">and=</span> <span class="p">(</span><span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span> <span class="k">of</span> <span class="nx">INVERSIONS</span><span class="p">)</span>
|
||||
<span class="nv">curr = </span><span class="nx">curr</span><span class="p">.</span><span class="nx">first</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nx">Parens</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">allInvertable</span>
|
||||
<span class="nv">curr = </span><span class="k">this</span>
|
||||
<span class="k">while</span> <span class="nx">curr</span> <span class="o">and</span> <span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span>
|
||||
<span class="nv">curr.invert = </span><span class="o">!</span><span class="nx">curr</span><span class="p">.</span><span class="nx">invert</span>
|
||||
<span class="nv">curr.operator = </span><span class="nx">INVERSIONS</span><span class="p">[</span><span class="nx">curr</span><span class="p">.</span><span class="nx">operator</span><span class="p">]</span>
|
||||
<span class="nv">curr = </span><span class="nx">curr</span><span class="p">.</span><span class="nx">first</span>
|
||||
<span class="k">this</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nv">op = </span><span class="nx">INVERSIONS</span><span class="p">[</span><span class="nx">@operator</span><span class="p">]</span>
|
||||
<span class="vi">@operator = </span><span class="nx">op</span>
|
||||
<span class="k">if</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Op</span>
|
||||
<span class="nx">@first</span><span class="p">.</span><span class="nx">invert</span><span class="p">()</span>
|
||||
<span class="k">this</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">@second</span>
|
||||
<span class="k">new</span> <span class="nx">Parens</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span>
|
||||
@@ -924,10 +920,10 @@ CoffeeScript operations into their JavaScript equivalents.</p> </td>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><=</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">"(#{code})"</span></pre></div> </td> </tr> <tr id="section-110"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-110">¶</a> </div> <p>Am I capable of
|
||||
<a href="http://docs.python.org/reference/expressions.html#notin">Python-style comparison chaining</a>?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compileChain</span><span class="o">:</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="nx">shared</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">second</span><span class="p">.</span><span class="nx">cache</span> <span class="nx">o</span>
|
||||
<span class="nv">fst = </span><span class="nx">@first</span> <span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
|
||||
<span class="nv">fst = </span><span class="nx">fst</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span> <span class="k">if</span> <span class="nx">fst</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'('</span>
|
||||
<span class="nv">code = </span><span class="s2">"#{fst} && #{ shared.compile o } #{@operator} #{ @second.compile o, LEVEL_OP }"</span>
|
||||
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">level</span> <span class="o"><</span> <span class="nx">LEVEL_OP</span> <span class="k">then</span> <span class="nx">code</span> <span class="k">else</span> <span class="s2">"(#{code})"</span>
|
||||
<span class="nv">fst = </span><span class="nx">@first</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_OP</span>
|
||||
<span class="nv">fst = </span><span class="nx">fst</span><span class="p">.</span><span class="nx">slice</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span> <span class="k">if</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">unwrap</span><span class="p">()</span> <span class="k">instanceof</span> <span class="nx">Op</span> <span class="o">and</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isChainable</span><span class="p">()</span> <span class="o">and</span> <span class="nx">fst</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'('</span>
|
||||
<span class="nv">code = </span><span class="s2">"#{fst} #{if @invert then '&&' else '||'} #{ shared.compile o } #{@operator} #{ @second.compile o, LEVEL_OP }"</span>
|
||||
<span class="s2">"(#{code})"</span>
|
||||
|
||||
<span class="nx">compileExistence</span><span class="o">:</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">@first</span><span class="p">.</span><span class="nx">isComplex</span><span class="p">()</span>
|
||||
@@ -1054,13 +1050,14 @@ parentheses, but no longer -- you can put in as many as you please.</p>
|
||||
<span class="nx">constructor</span><span class="o">:</span> <span class="p">(</span><span class="nx">body</span><span class="p">,</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">@name</span><span class="p">,</span> <span class="nx">@index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">{</span><span class="nx">@source</span><span class="p">,</span> <span class="nx">@guard</span><span class="p">,</span> <span class="nx">@step</span><span class="p">}</span> <span class="o">=</span> <span class="nx">source</span>
|
||||
<span class="vi">@body = </span><span class="nx">Expressions</span><span class="p">.</span><span class="nx">wrap</span> <span class="p">[</span><span class="nx">body</span><span class="p">]</span>
|
||||
<span class="vi">@raw = </span><span class="o">!!</span><span class="nx">source</span><span class="p">.</span><span class="nx">raw</span>
|
||||
<span class="vi">@own = </span><span class="o">!!</span><span class="nx">source</span><span class="p">.</span><span class="nx">own</span>
|
||||
<span class="vi">@object = </span><span class="o">!!</span><span class="nx">source</span><span class="p">.</span><span class="nx">object</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> <span class="p">[</span><span class="nx">@index</span><span class="p">,</span> <span class="nx">@name</span><span class="p">]</span> <span class="k">if</span> <span class="nx">@object</span>
|
||||
<span class="k">throw</span> <span class="nx">SyntaxError</span> <span class="s1">'index cannot be a pattern matching expression'</span> <span class="k">if</span> <span class="nx">@index</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
||||
<span class="vi">@range = </span><span class="nx">@source</span> <span class="k">instanceof</span> <span class="nx">Value</span> <span class="o">and</span> <span class="nx">@source</span><span class="p">.</span><span class="nx">base</span> <span class="k">instanceof</span> <span class="nx">Range</span> <span class="o">and</span> <span class="o">not</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="vi">@pattern = </span><span class="nx">@name</span> <span class="k">instanceof</span> <span class="nx">Value</span>
|
||||
<span class="k">throw</span> <span class="nx">SyntaxError</span> <span class="s1">'cannot pattern match a range loop'</span> <span class="k">if</span> <span class="nx">@range</span> <span class="o">and</span> <span class="nx">@pattern</span>
|
||||
<span class="k">throw</span> <span class="nx">SyntaxError</span> <span class="s1">'indexes do not apply to range loops'</span> <span class="k">if</span> <span class="nx">@range</span> <span class="o">and</span> <span class="nx">@index</span>
|
||||
<span class="k">throw</span> <span class="nx">SyntaxError</span> <span class="s1">'cannot pattern match over range loops'</span> <span class="k">if</span> <span class="nx">@range</span> <span class="o">and</span> <span class="nx">@pattern</span>
|
||||
<span class="vi">@returns = </span><span class="kc">false</span>
|
||||
|
||||
<span class="nx">children</span><span class="o">:</span> <span class="p">[</span><span class="s1">'body'</span><span class="p">,</span> <span class="s1">'source'</span><span class="p">,</span> <span class="s1">'guard'</span><span class="p">,</span> <span class="s1">'step'</span><span class="p">]</span>
|
||||
@@ -1079,9 +1076,8 @@ parentheses, but no longer -- you can put in as many as you please.</p>
|
||||
<span class="nv">scope = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span>
|
||||
<span class="nv">name = </span><span class="nx">@name</span> <span class="o">and</span> <span class="nx">@name</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
||||
<span class="nv">index = </span><span class="nx">@index</span> <span class="o">and</span> <span class="nx">@index</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_LIST</span>
|
||||
<span class="nx">unless</span> <span class="nx">hasCode</span>
|
||||
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">immediate</span><span class="o">:</span> <span class="kc">yes</span><span class="p">)</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@pattern</span>
|
||||
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">immediate</span><span class="o">:</span> <span class="kc">yes</span><span class="p">)</span> <span class="k">if</span> <span class="nx">index</span>
|
||||
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">immediate</span><span class="o">:</span> <span class="kc">yes</span><span class="p">)</span> <span class="k">if</span> <span class="nx">name</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@pattern</span>
|
||||
<span class="nx">scope</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span> <span class="nx">immediate</span><span class="o">:</span> <span class="kc">yes</span><span class="p">)</span> <span class="k">if</span> <span class="nx">index</span>
|
||||
<span class="nv">rvar = </span><span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">'results'</span> <span class="k">if</span> <span class="nx">@returns</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">hasPure</span>
|
||||
<span class="nv">ivar = </span><span class="p">(</span><span class="k">if</span> <span class="nx">@range</span> <span class="k">then</span> <span class="nx">name</span> <span class="k">else</span> <span class="nx">index</span><span class="p">)</span> <span class="o">or</span> <span class="nx">scope</span><span class="p">.</span><span class="nx">freeVariable</span> <span class="s1">'i'</span>
|
||||
<span class="nv">varPart = </span><span class="s1">''</span>
|
||||
@@ -1092,7 +1088,7 @@ parentheses, but no longer -- you can put in as many as you please.</p>
|
||||
<span class="nv">forPart = </span><span class="nx">source</span><span class="p">.</span><span class="nx">compile</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="nx">index</span><span class="o">:</span> <span class="nx">ivar</span><span class="p">,</span> <span class="nx">@step</span><span class="p">})</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nv">svar = </span><span class="nx">@source</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">LEVEL_TOP</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">name</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">@raw</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">svar</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">name</span> <span class="o">or</span> <span class="nx">@own</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">IDENTIFIER</span><span class="p">.</span><span class="nx">test</span> <span class="nx">svar</span>
|
||||
<span class="nv">defPart = </span><span class="s2">"#{@tab}#{ref = scope.freeVariable 'ref'} = #{svar};\n"</span>
|
||||
<span class="nv">svar = </span><span class="nx">ref</span>
|
||||
<span class="nv">namePart = </span><span class="k">if</span> <span class="nx">@pattern</span>
|
||||
@@ -1114,7 +1110,7 @@ parentheses, but no longer -- you can put in as many as you please.</p>
|
||||
<span class="nv">varPart = </span><span class="s2">"\n#{idt1}#{namePart};"</span> <span class="k">if</span> <span class="nx">namePart</span>
|
||||
<span class="k">if</span> <span class="nx">@object</span>
|
||||
<span class="nv">forPart = </span><span class="s2">"#{ivar} in #{svar}"</span>
|
||||
<span class="nv">guardPart = </span><span class="s2">"\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;"</span> <span class="nx">unless</span> <span class="nx">@raw</span>
|
||||
<span class="nv">guardPart = </span><span class="s2">"\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;"</span> <span class="k">if</span> <span class="nx">@own</span>
|
||||
<span class="nx">defPart</span> <span class="o">+=</span> <span class="nx">@pluckDirectCall</span> <span class="nx">o</span><span class="p">,</span> <span class="nx">body</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">index</span> <span class="nx">unless</span> <span class="nx">@pattern</span>
|
||||
<span class="nv">body = </span><span class="nx">body</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="nx">indent</span><span class="o">:</span> <span class="nx">idt1</span><span class="p">),</span> <span class="nx">LEVEL_TOP</span>
|
||||
<span class="nv">body = </span><span class="s1">'\n'</span> <span class="o">+</span> <span class="nx">body</span> <span class="o">+</span> <span class="s1">'\n'</span> <span class="k">if</span> <span class="nx">body</span>
|
||||
@@ -1145,6 +1141,7 @@ parentheses, but no longer -- you can put in as many as you please.</p>
|
||||
<span class="p">[</span><span class="nx">val</span><span class="p">.</span><span class="nx">base</span><span class="p">,</span> <span class="nx">base</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">base</span><span class="p">,</span> <span class="nx">val</span><span class="p">]</span>
|
||||
<span class="nx">args</span><span class="p">.</span><span class="nx">unshift</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s1">'this'</span>
|
||||
<span class="nx">body</span><span class="p">.</span><span class="nx">expressions</span><span class="p">[</span><span class="nx">idx</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Call</span> <span class="nx">base</span><span class="p">,</span> <span class="nx">args</span>
|
||||
<span class="nv">o.sharedScope = </span><span class="nx">o</span><span class="p">.</span><span class="nx">scope</span>
|
||||
<span class="nx">defs</span> <span class="o">+=</span> <span class="nx">@tab</span> <span class="o">+</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="nx">ref</span><span class="p">,</span> <span class="nx">fn</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">LEVEL_TOP</span><span class="p">)</span> <span class="o">+</span> <span class="s1">';\n'</span>
|
||||
<span class="nx">defs</span></pre></div> </td> </tr> <tr id="section-126"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-126">¶</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
|
||||
|
||||
@@ -5,15 +5,16 @@ Using it looks like this:</p>
|
||||
<pre><code>coffee> console.log "#{num} bottles of beer" for num in [99..1]
|
||||
</code></pre> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <p>Require the <strong>coffee-script</strong> module to get access to the compiler.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s1">'./coffee-script'</span>
|
||||
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s1">'./helpers'</span>
|
||||
<span class="nv">readline = </span><span class="nx">require</span> <span class="s1">'readline'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Start by opening up <strong>stdio</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdio = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Quick alias for quitting the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span> <span class="nx">quit</span><span class="o">:</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
|
||||
<span class="nv">readline = </span><span class="nx">require</span> <span class="s1">'readline'</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Start by opening up <strong>stdio</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">stdio = </span><span class="nx">process</span><span class="p">.</span><span class="nx">openStdin</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Log an error.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">error = </span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">stdio</span><span class="p">.</span><span class="nx">write</span> <span class="p">(</span><span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">())</span> <span class="o">+</span> <span class="s1">'\n\n'</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Quick alias for quitting the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">helpers</span><span class="p">.</span><span class="nx">extend</span> <span class="nx">global</span><span class="p">,</span> <span class="nx">quit</span><span class="o">:</span> <span class="o">-></span> <span class="nx">process</span><span class="p">.</span><span class="nx">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
|
||||
Attempt to evaluate the command. If there's an exception, print it out instead
|
||||
of exiting.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">run = </span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">try</span>
|
||||
<span class="nv">val = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nb">eval</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">toString</span><span class="p">(),</span> <span class="nx">bare</span><span class="o">:</span> <span class="kc">on</span><span class="p">,</span> <span class="nx">globals</span><span class="o">:</span> <span class="kc">on</span><span class="p">,</span> <span class="nx">fileName</span><span class="o">:</span> <span class="s1">'repl'</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="nx">val</span> <span class="k">if</span> <span class="nx">val</span> <span class="o">isnt</span> <span class="kc">undefined</span>
|
||||
<span class="k">catch</span> <span class="nx">err</span>
|
||||
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="nx">err</span><span class="p">.</span><span class="nx">stack</span> <span class="o">or</span> <span class="nx">err</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdio</span>
|
||||
<span class="nx">error</span> <span class="nx">err</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">prompt</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Make sure that uncaught exceptions don't kill the REPL.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">process</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'uncaughtException'</span><span class="p">,</span> <span class="nx">error</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Create the REPL by listening to <strong>stdin</strong>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">repl = </span><span class="nx">readline</span><span class="p">.</span><span class="nx">createInterface</span> <span class="nx">stdio</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="nx">setPrompt</span> <span class="s1">'coffee> '</span>
|
||||
<span class="nx">stdio</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'data'</span><span class="p">,</span> <span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="o">-></span> <span class="nx">repl</span><span class="p">.</span><span class="nx">write</span> <span class="nx">buffer</span>
|
||||
<span class="nx">repl</span><span class="p">.</span><span class="kc">on</span> <span class="s1">'close'</span><span class="p">,</span> <span class="o">-></span> <span class="nx">stdio</span><span class="p">.</span><span class="nx">destroy</span><span class="p">()</span>
|
||||
|
||||
@@ -71,13 +71,13 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
|
||||
<span class="nv">start = </span><span class="kc">null</span>
|
||||
<span class="nv">startIndent = </span><span class="mi">0</span>
|
||||
<span class="nv">condition = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="p">{(</span><span class="nx">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:</span> <span class="nx">one</span><span class="p">,</span> <span class="p">(</span><span class="nx">i</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span><span class="o">:</span> <span class="nx">two</span><span class="p">,</span> <span class="p">(</span><span class="nx">i</span><span class="o">+</span><span class="mi">3</span><span class="p">)</span><span class="o">:</span> <span class="nx">three</span><span class="p">}</span> <span class="o">=</span> <span class="nx">@tokens</span>
|
||||
<span class="p">[</span><span class="nx">one</span><span class="p">,</span> <span class="nx">two</span><span class="p">,</span> <span class="nx">three</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">..</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span>
|
||||
<span class="k">return</span> <span class="kc">false</span> <span class="k">if</span> <span class="s1">'HERECOMMENT'</span> <span class="o">is</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="p">[</span><span class="nx">tag</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">]</span> <span class="o">and</span>
|
||||
<span class="o">not</span> <span class="p">(</span><span class="nx">two</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">or</span> <span class="nx">one</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="o">and</span> <span class="nx">three</span><span class="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">':'</span><span class="p">))</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s1">','</span> <span class="o">and</span> <span class="nx">one</span> <span class="o">and</span>
|
||||
<span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">,</span> <span class="s1">'('</span><span class="p">])</span>
|
||||
<span class="nx">one</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'IDENTIFIER'</span><span class="p">,</span> <span class="s1">'NUMBER'</span><span class="p">,</span> <span class="s1">'STRING'</span><span class="p">,</span> <span class="s1">'@'</span><span class="p">,</span> <span class="s1">'TERMINATOR'</span><span class="p">,</span> <span class="s1">'OUTDENT'</span><span class="p">])</span>
|
||||
<span class="nv">action = </span><span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span> <span class="o">-></span> <span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[</span><span class="s1">'}'</span><span class="p">,</span> <span class="s1">'}'</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">in</span> <span class="nx">EXPRESSION_START</span>
|
||||
@@ -87,17 +87,10 @@ Insert the missing braces here, so that the parser doesn't have to.</p>
|
||||
<span class="nv">start = </span><span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="mi">1</span>
|
||||
<span class="k">return</span> <span class="mi">1</span> <span class="nx">unless</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">and</span>
|
||||
<span class="p">((</span><span class="nv">ago2 = </span><span class="nx">@tag</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">or</span>
|
||||
<span class="p">(</span><span class="nv">ago1 = </span><span class="nx">@tag</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">')'</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">start</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">or</span>
|
||||
<span class="nx">stack</span><span class="p">[</span><span class="nx">stack</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="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="p">((</span><span class="nv">ago = </span><span class="nx">@tag</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">':'</span> <span class="o">or</span> <span class="nx">stack</span><span class="p">[</span><span class="nx">stack</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="o">?</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">isnt</span> <span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s1">'{'</span><span class="p">]</span>
|
||||
<span class="nv">idx = </span><span class="k">if</span> <span class="nx">ago1</span> <span class="o">is</span> <span class="s1">')'</span>
|
||||
<span class="nx">start</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">ago2</span> <span class="o">is</span> <span class="s1">'@'</span>
|
||||
<span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">idx</span> <span class="o">-=</span> <span class="mi">2</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'HERECOMMENT'</span>
|
||||
<span class="nv">idx = </span> <span class="k">if</span> <span class="nx">ago</span> <span class="o">is</span> <span class="s1">'@'</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
|
||||
<span class="nx">idx</span> <span class="o">-=</span> <span class="mi">2</span> <span class="k">while</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'HERECOMMENT'</span>
|
||||
<span class="nv">value = </span><span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="s1">'{'</span><span class="p">)</span>
|
||||
<span class="nv">value.generated = </span><span class="kc">yes</span>
|
||||
<span class="nv">tok = </span><span class="p">[</span><span class="s1">'{'</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]]</span>
|
||||
@@ -114,7 +107,7 @@ deal with them.</p> </td> <td class="code">
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
||||
<span class="nv">noCall = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'CLASS'</span><span class="p">,</span> <span class="s1">'IF'</span><span class="p">,</span> <span class="s1">'UNLESS'</span><span class="p">]</span>
|
||||
<span class="p">{(</span><span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">:</span> <span class="nx">prev</span><span class="p">,</span> <span class="p">(</span><span class="nx">i</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">:</span> <span class="nx">next</span><span class="p">}</span> <span class="o">=</span> <span class="nx">tokens</span>
|
||||
<span class="p">[</span><span class="nx">prev</span><span class="p">,</span> <span class="nx">current</span><span class="p">,</span> <span class="nx">next</span><span class="p">]</span> <span class="o">=</span> <span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="p">..</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
|
||||
<span class="nv">callObject = </span><span class="o">not</span> <span class="nx">noCall</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s1">'INDENT'</span> <span class="o">and</span>
|
||||
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s1">'{'</span> <span class="o">and</span>
|
||||
<span class="nx">prev</span> <span class="o">and</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span>
|
||||
@@ -186,7 +179,7 @@ the course of the token stream.</p> </td> <td class="cod
|
||||
<span class="nx">openLine</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o">=</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="k">if</span> <span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span><span class="o">++</span> <span class="o">is</span> <span class="mi">0</span>
|
||||
<span class="k">else</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="nx">close</span> <span class="o">and</span> <span class="o">--</span><span class="nx">levels</span><span class="p">[</span><span class="nx">open</span><span class="p">]</span> <span class="o"><</span> <span class="mi">0</span>
|
||||
<span class="k">throw</span> <span class="nb">Error</span> <span class="s2">"too many #{token[1]} on line #{token[2] + 1}"</span>
|
||||
<span class="k">for</span> <span class="nx">all</span> <span class="nx">open</span><span class="p">,</span> <span class="nx">level</span> <span class="k">of</span> <span class="nx">levels</span> <span class="k">when</span> <span class="nx">level</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="k">for</span> <span class="nx">open</span><span class="p">,</span> <span class="nx">level</span> <span class="k">of</span> <span class="nx">levels</span> <span class="k">when</span> <span class="nx">level</span> <span class="o">></span> <span class="mi">0</span>
|
||||
<span class="k">throw</span> <span class="nb">Error</span> <span class="s2">"unclosed #{ open } on line #{openLine[open] + 1}"</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>We'd like to support syntax like this:</p>
|
||||
|
||||
@@ -209,7 +202,7 @@ rewriting.</li>
|
||||
</ol> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">rewriteClosingParens</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">stack = </span><span class="p">[]</span>
|
||||
<span class="nv">debt = </span><span class="p">{}</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="nx">all</span> <span class="nx">key</span> <span class="k">of</span> <span class="nx">INVERSES</span>
|
||||
<span class="nx">debt</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">for</span> <span class="nx">key</span> <span class="k">of</span> <span class="nx">INVERSES</span>
|
||||
<span class="nx">@scanTokens</span> <span class="p">(</span><span class="nx">token</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">tokens</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">in</span> <span class="nx">EXPRESSION_START</span>
|
||||
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span>
|
||||
|
||||
@@ -11,58 +11,44 @@ where it should declare its variables, and a reference to the function that
|
||||
it wraps.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">constructor</span><span class="o">:</span><span class="p">(</span><span class="nx">@parent</span><span class="p">,</span> <span class="nx">@expressions</span><span class="p">,</span> <span class="nx">@method</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="vi">@variables = </span><span class="p">[{</span><span class="nx">name</span><span class="o">:</span> <span class="s1">'arguments'</span><span class="p">,</span> <span class="nx">type</span><span class="o">:</span> <span class="s1">'arguments'</span><span class="p">}]</span>
|
||||
<span class="vi">@positions = </span><span class="p">{}</span>
|
||||
<span class="k">if</span> <span class="nx">@parent</span>
|
||||
<span class="vi">@garbage = </span><span class="nx">@parent</span><span class="p">.</span><span class="nx">garbage</span>
|
||||
<span class="k">else</span>
|
||||
<span class="vi">@garbage = </span><span class="p">[]</span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Adds a new variable or overrides an existing one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">add</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">Scope.root = </span><span class="k">this</span> <span class="nx">unless</span> <span class="nx">@parent</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Adds a new variable or overrides an existing one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">add</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="k">typeof</span> <span class="p">(</span><span class="nv">pos = </span><span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">])</span> <span class="o">is</span> <span class="s1">'number'</span>
|
||||
<span class="nx">@variables</span><span class="p">[</span><span class="nx">pos</span><span class="p">].</span><span class="nv">type = </span><span class="nx">type</span>
|
||||
<span class="k">else</span>
|
||||
<span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@variables</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">})</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Create a new garbage level</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">startLevel</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@garbage</span><span class="p">.</span><span class="nx">push</span> <span class="p">[]</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Return to the previous garbage level and erase referenced temporary
|
||||
variables in current level from scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">endLevel</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'reuse'</span> <span class="k">for</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">@garbage</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">when</span> <span class="nx">@type</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'var'</span>
|
||||
<span class="k">this</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
|
||||
<span class="nx">@positions</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@variables</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="nx">name</span><span class="p">,</span> <span class="nx">type</span><span class="p">})</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Look up a variable name in lexical scope, and declare it if it does not
|
||||
already exist.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">find</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">true</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="nx">@check</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">options</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'var'</span>
|
||||
<span class="kc">false</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Test variables and return <code>true</code> the first time <code>fn(v)</code> returns <code>true</code></p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">any</span><span class="o">:</span> <span class="p">(</span><span class="nx">fn</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="kc">yes</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">fn</span> <span class="nx">v</span>
|
||||
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Reserve a variable name as originating from a function parameter for this
|
||||
<span class="vi">@hasDeclarations = </span><span class="kc">yes</span>
|
||||
<span class="kc">no</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Reserve a variable name as originating from a function parameter for this
|
||||
scope. No <code>var</code> required for internal references.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">parameter</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'param'</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Just check to see if a variable has already been declared, without reserving,
|
||||
<span class="k">return</span> <span class="k">if</span> <span class="nx">@shared</span> <span class="o">and</span> <span class="nx">@check</span> <span class="nx">name</span><span class="p">,</span> <span class="kc">yes</span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="s1">'param'</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <p>Just check to see if a variable has already been declared, without reserving,
|
||||
walks up to the root scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">check</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">immediate</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">found = </span><span class="o">!!</span><span class="nx">@type</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="nx">found</span> <span class="k">if</span> <span class="nx">found</span> <span class="o">or</span> <span class="nx">immediate</span>
|
||||
<span class="o">!!</span><span class="nx">@parent</span><span class="o">?</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Generate a temporary variable name at the given index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">temporary</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="o">!!</span><span class="nx">@parent</span><span class="o">?</span><span class="p">.</span><span class="nx">check</span> <span class="nx">name</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Generate a temporary variable name at the given index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">temporary</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">if</span> <span class="nx">name</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">1</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="k">if</span> <span class="nx">index</span> <span class="o">></span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">index</span> <span class="k">else</span> <span class="s1">''</span>
|
||||
<span class="k">else</span>
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">name</span><span class="p">,</span> <span class="mi">36</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span> <span class="sr">/\d/g</span><span class="p">,</span> <span class="s1">'a'</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Gets the type of a variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">type</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="nx">name</span> <span class="k">then</span> <span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
<span class="s1">'_'</span> <span class="o">+</span> <span class="p">(</span><span class="nx">index</span> <span class="o">+</span> <span class="nb">parseInt</span> <span class="nx">name</span><span class="p">,</span> <span class="mi">36</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="mi">36</span><span class="p">).</span><span class="nx">replace</span> <span class="sr">/\d/g</span><span class="p">,</span> <span class="s1">'a'</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>Gets the type of a variable.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">type</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="k">return</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span> <span class="o">is</span> <span class="nx">name</span>
|
||||
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>If we need to store an intermediate result, find an available name for a
|
||||
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">freeVariable</span><span class="o">:</span> <span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nv">index = </span><span class="mi">0</span>
|
||||
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">),</span> <span class="kc">true</span><span class="p">)</span> <span class="o">and</span> <span class="nx">@type</span><span class="p">(</span><span class="nx">temp</span><span class="p">)</span> <span class="o">isnt</span> <span class="s1">'reuse'</span>
|
||||
<span class="nx">index</span><span class="o">++</span> <span class="k">while</span> <span class="nx">@check</span><span class="p">((</span><span class="nv">temp = </span><span class="nx">@temporary</span> <span class="nx">type</span><span class="p">,</span> <span class="nx">index</span><span class="p">),</span> <span class="kc">true</span><span class="p">)</span>
|
||||
<span class="nx">@add</span> <span class="nx">temp</span><span class="p">,</span> <span class="s1">'var'</span>
|
||||
<span class="nx">last</span><span class="p">(</span><span class="nx">@garbage</span><span class="p">)</span><span class="o">?</span><span class="p">.</span><span class="nx">push</span> <span class="nx">temp</span>
|
||||
<span class="nx">temp</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>Ensure that an assignment is made at the top of this scope
|
||||
<span class="vi">@hasDeclarations = </span><span class="kc">yes</span>
|
||||
<span class="nx">temp</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Ensure that an assignment is made at the top of this scope
|
||||
(or at the top-level scope, if requested).</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">assign</span><span class="o">:</span> <span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">assigned</span><span class="o">:</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Does this scope reference any variables that need to be declared in the
|
||||
given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasDeclarations</span><span class="o">:</span> <span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">body</span> <span class="o">is</span> <span class="nx">@expressions</span> <span class="o">and</span> <span class="nx">@any</span> <span class="p">(</span><span class="nx">v</span><span class="p">)</span> <span class="o">-></span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'var'</span><span class="p">,</span> <span class="s1">'reuse'</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Does this scope reference any assignments that need to be declared at the
|
||||
top of the given function body?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasAssignments</span><span class="o">:</span> <span class="p">(</span><span class="nx">body</span><span class="p">)</span> <span class="o">-></span>
|
||||
<span class="nx">body</span> <span class="o">is</span> <span class="nx">@expressions</span> <span class="o">and</span> <span class="nx">@any</span> <span class="p">(</span><span class="nx">v</span><span class="p">)</span> <span class="o">-></span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">declaredVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">usr = </span><span class="p">[]</span>
|
||||
<span class="nv">tmp = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="k">in</span> <span class="p">[</span><span class="s1">'var'</span><span class="p">,</span> <span class="s1">'reuse'</span><span class="p">]</span>
|
||||
<span class="p">(</span><span class="k">if</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'_'</span> <span class="k">then</span> <span class="nx">tmp</span> <span class="k">else</span> <span class="nx">usr</span><span class="p">).</span><span class="nx">push</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span>
|
||||
<span class="nx">usr</span><span class="p">.</span><span class="nx">sort</span><span class="p">().</span><span class="nx">concat</span> <span class="nx">tmp</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Return the list of assignments that are supposed to be made at the top
|
||||
<span class="nx">@add</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">value</span><span class="o">:</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">assigned</span><span class="o">:</span> <span class="kc">true</span>
|
||||
<span class="vi">@hasAssignments = </span><span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Return the list of variables first declared in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">declaredVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nv">realVars = </span><span class="p">[]</span>
|
||||
<span class="nv">tempVars = </span><span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s1">'var'</span>
|
||||
<span class="p">(</span><span class="k">if</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="s1">'_'</span> <span class="k">then</span> <span class="nx">tempVars</span> <span class="k">else</span> <span class="nx">realVars</span><span class="p">).</span><span class="nx">push</span> <span class="nx">v</span><span class="p">.</span><span class="nx">name</span>
|
||||
<span class="nx">realVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">().</span><span class="nx">concat</span> <span class="nx">tempVars</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>Return the list of assignments that are supposed to be made at the top
|
||||
of this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">assignedVariables</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="p">(</span><span class="s2">"#{v.name} = #{v.type.value}"</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Compile the JavaScript for all of the variable declarations in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compiledDeclarations</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@declaredVariables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">', '</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Compile the JavaScript for all of the variable assignments in this scope.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">compiledAssignments</span><span class="o">:</span> <span class="o">-></span>
|
||||
<span class="nx">@assignedVariables</span><span class="p">().</span><span class="nx">join</span> <span class="s1">', '</span>
|
||||
<span class="s2">"#{v.name} = #{v.type.value}"</span> <span class="k">for</span> <span class="nx">v</span> <span class="k">in</span> <span class="nx">@variables</span> <span class="k">when</span> <span class="nx">v</span><span class="p">.</span><span class="nx">type</span><span class="p">.</span><span class="nx">assigned</span>
|
||||
|
||||
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|
||||
@@ -46,6 +46,7 @@
|
||||
<a href="#splats">Splats...</a>
|
||||
<a href="#while">While, Until, and Loop</a>
|
||||
<a href="#comprehensions">Comprehensions (Arrays, Objects, and Ranges)</a>
|
||||
<a href="#slices">Array Slicing and Splicing</a>
|
||||
<a href="#expressions">Everything is an Expression</a>
|
||||
<a href="#existence">The Existential Operator</a>
|
||||
<a href="#classes">Classes, Inheritance, and Super</a>
|
||||
@@ -122,7 +123,7 @@
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.5">0.9.5</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.6">0.9.6</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -516,6 +517,15 @@ coffee --bare --print --stdio</pre>
|
||||
end of your comprehension.
|
||||
</p>
|
||||
<%= code_for('range_comprehensions', 'countdown') %>
|
||||
<p>
|
||||
Note how because we are assigning the value of the comprehensions to a
|
||||
variable in the example above, CoffeeScript is collecting the result of
|
||||
each iteration into an array. Sometimes functions end with loops that are
|
||||
intended to run only for their side-effects. Be careful that you're not
|
||||
accidentally returning the results of the comprehension in these cases,
|
||||
by adding a meaningful return value, like <tt>true</tt>, or <tt>null</tt>,
|
||||
to the bottom of your function.
|
||||
</p>
|
||||
<p>
|
||||
Comprehensions can also be used to iterate over the keys and values in
|
||||
an object. Use <tt>of</tt> to signal comprehension over the properties of
|
||||
@@ -529,6 +539,22 @@ coffee --bare --print --stdio</pre>
|
||||
loop, for speed or for another reason, you can use <br />
|
||||
<tt>for all key, value of object</tt> in CoffeeScript.
|
||||
</p>
|
||||
<p>
|
||||
<span id="slices" class="bookmark"></span>
|
||||
<b class="header">Array Slicing and Splicing with Ranges</b>
|
||||
Ranges can also be used to extract slices of arrays.
|
||||
With two dots (<tt>3..6</tt>), the range is inclusive (<tt>3, 4, 5, 6</tt>);
|
||||
with three docs (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
|
||||
</p>
|
||||
<%= code_for('slices', 'middle') %>
|
||||
<p>
|
||||
The same syntax can be used with assignment to replace a segment of an array
|
||||
with new values, splicing it.
|
||||
</p>
|
||||
<%= code_for('splices', 'numbers') %>
|
||||
<p>
|
||||
Note that JavaScript strings are immutable, and can't be spliced.
|
||||
</p>
|
||||
<p>
|
||||
<span id="expressions" class="bookmark"></span>
|
||||
<b class="header">Everything is an Expression (at least, as much as possible)</b>
|
||||
@@ -1008,21 +1034,41 @@ coffee --bare --print --stdio</pre>
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.6
|
||||
<span class="timestamp"> – <small>Dec 6, 2010</small></span>
|
||||
</b>
|
||||
The REPL now properly formats stacktraces, and stays alive through
|
||||
asynchronous exceptions. Using <tt>--watch</tt> now prints timestamps as
|
||||
files are compiled. Fixed some accidentally-leaking variables within
|
||||
plucked closure-loops. Constructors now maintain their declaration
|
||||
location within a class body.
|
||||
Nested classes are now supported. Fixes execution context for naked
|
||||
splatted functions. Bugfix for inversion of chained comparisons.
|
||||
Chained class instantiation now works properly with splats.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.5
|
||||
<span class="timestamp"> – <small>Nov 21, 2010</small></span>
|
||||
</b>
|
||||
0.9.5 should be considered the first release candidate for CoffeeScript 1.0.
|
||||
There have been a large number of internal changes since the previous release,
|
||||
many contributed from <b>satyr</b>'s <a href="http://github.com/satyr/coco">Coco</a>
|
||||
dialect of CoffeeScript. Heregexes (extended regexes) were added. Functions
|
||||
can now have default arguments. Class bodies are now executable code.
|
||||
Improved syntax errors for invalid CoffeeScript. Object literals
|
||||
can now take dynamic keys, like this: <tt>{(key): value}</tt>. <tt>undefined</tt> now
|
||||
Improved syntax errors for invalid CoffeeScript. <tt>undefined</tt> now
|
||||
works like <tt>null</tt>, and cannot be assigned a new value.
|
||||
There was a precedence change with respect to single-line comprehensions:
|
||||
<tt>result = i for i in list</tt><br /> used to parse as <tt>result = (i for i in list)</tt>
|
||||
by default ... it now parses as <br /><tt>(result = i) for i in list</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.4
|
||||
<span class="timestamp"> – <small>Sep 21, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript now uses appropriately-named temporary variables, and recycles
|
||||
their references after use. Added <tt>require.extensions</tt> support for
|
||||
<b>Node.js 0.3</b>. Loading CoffeeScript in the browser now adds just a
|
||||
@@ -1031,7 +1077,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.3</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.3
|
||||
<span class="timestamp"> – <small>Sep 16, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript <tt>switch</tt> statements now compile into JS <tt>switch</tt>
|
||||
statements — they previously compiled into <tt>if/else</tt> chains
|
||||
for JavaScript 1.3 compatibility.
|
||||
@@ -1040,7 +1088,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.2
|
||||
<span class="timestamp"> – <small>Aug 23, 2010</small></span>
|
||||
</b>
|
||||
Specifying the start and end of a range literal is now optional, eg. <tt>array[3..]</tt>.
|
||||
You can now say <tt>a not instanceof b</tt>.
|
||||
Fixed important bugs with nested significant and non-significant indentation (Issue #637).
|
||||
@@ -1054,7 +1104,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.1
|
||||
<span class="timestamp"> – <small>Aug 11, 2010</small></span>
|
||||
</b>
|
||||
Bugfix release for <b>0.9.1</b>. Greatly improves the handling of mixed
|
||||
implicit objects, implicit function calls, and implicit indentation.
|
||||
String and regex interpolation is now strictly <tt>#{ ... }</tt> (Ruby style).
|
||||
@@ -1063,7 +1115,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.0
|
||||
<span class="timestamp"> – <small>Aug 4, 2010</small></span>
|
||||
</b>
|
||||
The CoffeeScript <b>0.9</b> series is considered to be a release candidate
|
||||
for <b>1.0</b>; let's give her a shakedown cruise. <b>0.9.0</b> introduces a massive
|
||||
backwards-incompatible change: Assignment now uses <tt>=</tt>, and object
|
||||
@@ -1087,13 +1141,17 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.7.2
|
||||
<span class="timestamp"> – <small>Jul 12, 2010</small></span>
|
||||
</b>
|
||||
Quick bugfix (right after 0.7.1) for a problem that prevented <tt>coffee</tt>
|
||||
command-line options from being parsed in some circumstances.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.7.1
|
||||
<span class="timestamp"> – <small>Jul 11, 2010</small></span>
|
||||
</b>
|
||||
Block-style comments are now passed through and printed as JavaScript block
|
||||
comments -- making them useful for licenses and copyright headers. Better
|
||||
support for running coffee scripts standalone via hashbangs.
|
||||
@@ -1101,7 +1159,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.7.0
|
||||
<span class="timestamp"> – <small>Jun 28, 2010</small></span>
|
||||
</b>
|
||||
Official CoffeeScript variable style is now camelCase, as in JavaScript.
|
||||
Reserved words are now allowed as object keys, and will be quoted for you.
|
||||
Range comprehensions now generate cleaner code, but you have to specify <tt>by -1</tt>
|
||||
@@ -1118,7 +1178,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.6.2
|
||||
<span class="timestamp"> – <small>May 15, 2010</small></span>
|
||||
</b>
|
||||
The <tt>coffee</tt> command will now preserve directory structure when
|
||||
compiling a directory full of scripts. Fixed two omissions that were preventing
|
||||
the CoffeeScript compiler from running live within Internet Explorer.
|
||||
@@ -1133,20 +1195,26 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.6.1
|
||||
<span class="timestamp"> – <small>Apr 12, 2010</small></span>
|
||||
</b>
|
||||
Upgraded CoffeeScript for compatibility with the new Node.js <b>v0.1.90</b>
|
||||
series.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.6.0
|
||||
<span class="timestamp"> – <small>Apr 3, 2010</small></span>
|
||||
</b>
|
||||
Trailing commas are now allowed, a-la Python. Static
|
||||
properties may be assigned directly within class definitions,
|
||||
using <tt>@property</tt> notation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.6</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.6
|
||||
<span class="timestamp"> – <small>Mar 23, 2010</small></span>
|
||||
</b>
|
||||
Interpolation can now be used within regular expressions and heredocs, as well as
|
||||
strings. Added the <tt><-</tt> bind operator.
|
||||
Allowing assignment to half-expressions instead of special <tt>||=</tt>-style
|
||||
@@ -1157,7 +1225,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.5
|
||||
<span class="timestamp"> – <small>Mar 8, 2010</small></span>
|
||||
</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
|
||||
@@ -1166,14 +1236,18 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.4
|
||||
<span class="timestamp"> – <small>Mar 3, 2010</small></span>
|
||||
</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>
|
||||
<b class="header" style="margin-top: 20px;">0.5.3
|
||||
<span class="timestamp"> – <small>Feb 27, 2010</small></span>
|
||||
</b>
|
||||
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.
|
||||
@@ -1183,7 +1257,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.2
|
||||
<span class="timestamp"> – <small>Feb 25, 2010</small></span>
|
||||
</b>
|
||||
Added a compressed version of the compiler for inclusion in web pages as
|
||||
<br /><tt>extras/coffee-script.js</tt>. It'll automatically run any script tags
|
||||
with type <tt>text/coffeescript</tt> for you. Added a <tt>--stdio</tt> option
|
||||
@@ -1192,7 +1268,9 @@ coffee --bare --print --stdio</pre>
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.1
|
||||
<span class="timestamp"> – <small>Feb 24, 2010</small></span>
|
||||
</b>
|
||||
Improvements to null soaking with the existential operator, including
|
||||
soaks on indexed properties. Added conditions to <tt>while</tt> loops,
|
||||
so you can use them as filters with <tt>when</tt>, in the same manner as
|
||||
@@ -1200,21 +1278,27 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.0
|
||||
<span class="timestamp"> – <small>Feb 21, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript 0.5.0 is a major release, While there are no language changes,
|
||||
the Ruby compiler has been removed in favor of a self-hosting
|
||||
compiler written in pure CoffeeScript.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.3.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.3.2
|
||||
<span class="timestamp"> – <small>Feb 8, 2010</small></span>
|
||||
</b>
|
||||
<tt>@property</tt> is now a shorthand for <tt>this.property</tt>.<br />
|
||||
Switched the default JavaScript engine from Narwhal to Node.js. Pass
|
||||
the <tt>--narwhal</tt> flag if you'd like to continue using it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.3.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.3.0
|
||||
<span class="timestamp"> – <small>Jan 26, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript 0.3 includes major syntax changes:
|
||||
<br />
|
||||
The function symbol was changed to
|
||||
@@ -1230,7 +1314,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.6</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.6
|
||||
<span class="timestamp"> – <small>Jan 17, 2010</small></span>
|
||||
</b>
|
||||
Added Python-style chained comparisons, the conditional existence
|
||||
operator <tt>?=</tt>, and some examples from <i>Beautiful Code</i>.
|
||||
Bugfixes relating to statement-to-expression conversion, arguments-to-array
|
||||
@@ -1238,7 +1324,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.5
|
||||
<span class="timestamp"> – <small>Jan 13, 2010</small></span>
|
||||
</b>
|
||||
The conditions in switch statements can now take multiple values at once —
|
||||
If any of them are true, the case will run. Added the long arrow <tt>==></tt>,
|
||||
which defines and immediately binds a function to <tt>this</tt>. While loops can
|
||||
@@ -1247,20 +1335,26 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.4
|
||||
<span class="timestamp"> – <small>Jan 12, 2010</small></span>
|
||||
</b>
|
||||
Added ECMAScript Harmony style destructuring assignment, for dealing with
|
||||
extracting values from nested arrays and objects. Added indentation-sensitive
|
||||
heredocs for nicely formatted strings or chunks of code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.3</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.3
|
||||
<span class="timestamp"> – <small>Jan 11, 2010</small></span>
|
||||
</b>
|
||||
Axed the unsatisfactory <tt>ino</tt> keyword, replacing it with <tt>of</tt> for
|
||||
object comprehensions. They now look like: <tt>for prop, value of object</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.2
|
||||
<span class="timestamp"> – <small>Jan 10, 2010</small></span>
|
||||
</b>
|
||||
When performing a comprehension over an object, use <tt>ino</tt>, instead
|
||||
of <tt>in</tt>, which helps us generate smaller, more efficient code at
|
||||
compile time.
|
||||
@@ -1281,12 +1375,16 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.1
|
||||
<span class="timestamp"> – <small>Jan 5, 2010</small></span>
|
||||
</b>
|
||||
Arguments objects are now converted into real arrays when referenced.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.0
|
||||
<span class="timestamp"> – <small>Jan 5, 2010</small></span>
|
||||
</b>
|
||||
Major release. Significant whitespace. Better statement-to-expression
|
||||
conversion. Splats. Splice literals. Object comprehensions. Blocks.
|
||||
The existential operator. Many thanks to all the folks who posted issues,
|
||||
@@ -1296,14 +1394,18 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.6</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.6
|
||||
<span class="timestamp"> – <small>Dec 27, 2009</small></span>
|
||||
</b>
|
||||
Bugfix for running <tt>coffee --interactive</tt> and <tt>--run</tt>
|
||||
from outside of the CoffeeScript directory. Bugfix for nested
|
||||
function/if-statements.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.5
|
||||
<span class="timestamp"> – <small>Dec 26, 2009</small></span>
|
||||
</b>
|
||||
Array slice literals and array comprehensions can now both take Ruby-style
|
||||
ranges to specify the start and end. JavaScript variable declaration is
|
||||
now pushed up to the top of the scope, making all assignment statements into
|
||||
@@ -1312,7 +1414,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.4
|
||||
<span class="timestamp"> – <small>Dec 25, 2009</small></span>
|
||||
</b>
|
||||
The official CoffeeScript extension is now <tt>.coffee</tt> instead of
|
||||
<tt>.cs</tt>, which properly belongs to
|
||||
<a href="http://en.wikipedia.org/wiki/C_Sharp_(programming_language)">C#</a>.
|
||||
@@ -1324,7 +1428,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.3</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.3
|
||||
<span class="timestamp"> – <small>Dec 25, 2009</small></span>
|
||||
</b>
|
||||
The <tt>coffee</tt> command now includes <tt>--interactive</tt>,
|
||||
which launches an interactive CoffeeScript session, and <tt>--run</tt>,
|
||||
which directly compiles and executes a script. Both options depend on a
|
||||
@@ -1338,7 +1444,9 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.2
|
||||
<span class="timestamp"> – <small>Dec 24, 2009</small></span>
|
||||
</b>
|
||||
Fixed a bug with calling <tt>super()</tt> through more than one level of
|
||||
inheritance, with the re-addition of the <tt>extends</tt> keyword.
|
||||
Added experimental <a href="http://narwhaljs.org/">Narwhal</a>
|
||||
@@ -1350,12 +1458,16 @@ coffee --bare --print --stdio</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.1
|
||||
<span class="timestamp"> – <small>Dec 24, 2009</small></span>
|
||||
</b>
|
||||
Added <tt>instanceof</tt> and <tt>typeof</tt> as operators.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.0
|
||||
<span class="timestamp"> – <small>Dec 24, 2009</small></span>
|
||||
</b>
|
||||
Initial CoffeeScript release.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
var food, lunch, pos, roid, roid2, _i, _j, _len, _len2, _len3, _ref;
|
||||
var food, _i, _len, _ref;
|
||||
_ref = ['toast', 'cheese', 'wine'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
food = _ref[_i];
|
||||
lunch = eat(food);
|
||||
}
|
||||
for (pos = 0, _len2 = asteroids.length; pos < _len2; pos++) {
|
||||
roid = asteroids[pos];
|
||||
for (_j = 0, _len3 = asteroids.length; _j < _len3; _j++) {
|
||||
roid2 = asteroids[_j];
|
||||
if (roid !== roid2) {
|
||||
if (roid.overlaps(roid2)) {
|
||||
roid.explode();
|
||||
}
|
||||
}
|
||||
}
|
||||
eat(food);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
CoffeeScript Compiler v0.9.5
|
||||
CoffeeScript Compiler v0.9.6
|
||||
Released under the MIT License
|
||||
*/
|
||||
@@ -1,3 +1,3 @@
|
||||
var cholesterol, healthy;
|
||||
cholesterol = 127;
|
||||
healthy = 200 > cholesterol && cholesterol > 60;
|
||||
healthy = (200 > cholesterol && cholesterol > 60);
|
||||
@@ -1,9 +1,7 @@
|
||||
var globals, name, _results;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
globals = (function() {
|
||||
_results = [];
|
||||
for (name in window) {
|
||||
if (!__hasProp.call(window, name)) continue;
|
||||
_results.push(name);
|
||||
}
|
||||
return _results;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
var age, ages, child, yearsOld, _results;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
yearsOld = {
|
||||
max: 10,
|
||||
ida: 9,
|
||||
@@ -8,7 +7,6 @@ yearsOld = {
|
||||
ages = function() {
|
||||
_results = [];
|
||||
for (child in yearsOld) {
|
||||
if (!__hasProp.call(yearsOld, child)) continue;
|
||||
age = yearsOld[child];
|
||||
_results.push(child + " is " + age);
|
||||
}
|
||||
|
||||
4
documentation/js/slices.js
Normal file
4
documentation/js/slices.js
Normal file
@@ -0,0 +1,4 @@
|
||||
var copy, middle, numbers;
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
copy = numbers.slice(0, numbers.length);
|
||||
middle = copy.slice(3, 6 + 1);
|
||||
@@ -9,7 +9,7 @@ awardMedals = function() {
|
||||
return rest = others;
|
||||
};
|
||||
contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
|
||||
awardMedals.apply(awardMedals, contenders);
|
||||
awardMedals.apply(null, contenders);
|
||||
alert("Gold: " + gold);
|
||||
alert("Silver: " + silver);
|
||||
alert("The Field: " + rest);
|
||||
3
documentation/js/splices.js
Normal file
3
documentation/js/splices.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var numbers;
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
[].splice.apply(numbers, [3, 4].concat([-3, -4, -5, -6]));
|
||||
@@ -3,7 +3,7 @@ if (this.studyingEconomics) {
|
||||
while (supply > demand) {
|
||||
buy();
|
||||
}
|
||||
while (supply <= demand) {
|
||||
while (!(supply > demand)) {
|
||||
sell();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ _.each = (obj, iterator, context) ->
|
||||
else if _.isNumber obj.length
|
||||
iterator.call context, obj[i], i, obj for i in [0...obj.length]
|
||||
else
|
||||
iterator.call context, val, key, obj for key, val of obj
|
||||
iterator.call context, val, key, obj for own key, val of obj
|
||||
catch e
|
||||
throw e if e isnt breaker
|
||||
obj
|
||||
@@ -176,8 +176,7 @@ _.some = (obj, iterator, context) ->
|
||||
# based on `===`.
|
||||
_.include = (obj, target) ->
|
||||
return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
|
||||
for key, val of obj
|
||||
return true if val is target
|
||||
return true for own key, val of obj when val is target
|
||||
false
|
||||
|
||||
|
||||
@@ -486,14 +485,14 @@ _.isEqual = (a, b) ->
|
||||
# Different object sizes?
|
||||
return false if aKeys.length isnt bKeys.length
|
||||
# Recursive comparison of contents.
|
||||
return false for all key, val of a when !(key of b) or !_.isEqual(val, b[key])
|
||||
return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
|
||||
true
|
||||
|
||||
|
||||
# Is a given array or object empty?
|
||||
_.isEmpty = (obj) ->
|
||||
return obj.length is 0 if _.isArray(obj) or _.isString(obj)
|
||||
return false for key of obj when hasOwnProperty.call(obj, key)
|
||||
return false for own key of obj
|
||||
true
|
||||
|
||||
|
||||
@@ -654,7 +653,7 @@ addToWrapper = (name, func) ->
|
||||
result func.apply(_, args), this._chain
|
||||
|
||||
|
||||
# Add all of the Underscore functions to the wrapper object.
|
||||
# Add all ofthe Underscore functions to the wrapper object.
|
||||
_.mixin _
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
257
index.html
257
index.html
@@ -33,6 +33,7 @@
|
||||
<a href="#splats">Splats...</a>
|
||||
<a href="#while">While, Until, and Loop</a>
|
||||
<a href="#comprehensions">Comprehensions (Arrays, Objects, and Ranges)</a>
|
||||
<a href="#slices">Array Slicing and Splicing</a>
|
||||
<a href="#expressions">Everything is an Expression</a>
|
||||
<a href="#existence">The Existential Operator</a>
|
||||
<a href="#classes">Classes, Inheritance, and Super</a>
|
||||
@@ -109,7 +110,7 @@
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.5">0.9.5</a>
|
||||
<a href="http://github.com/jashkenas/coffee-script/tarball/0.9.6">0.9.6</a>
|
||||
</p>
|
||||
|
||||
<h2>
|
||||
@@ -761,7 +762,7 @@ gold <span class="Keyword">=</span> silver <span class="Keyword">=</span> rest <
|
||||
<span class="Keyword">return</span> rest <span class="Keyword">=</span> others;
|
||||
};
|
||||
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>, <span class="String"><span class="String">"</span>Allyson Felix<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Shawn Johnson<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Roman Sebrle<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Guo Jingjing<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Tyson Gay<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Asafa Powell<span class="String">"</span></span>, <span class="String"><span class="String">"</span>Usain Bolt<span class="String">"</span></span>];
|
||||
awardMedals.<span class="LibraryFunction">apply</span>(awardMedals, contenders);
|
||||
awardMedals.<span class="LibraryFunction">apply</span>(<span class="BuiltInConstant">null</span>, contenders);
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>Gold: <span class="String">"</span></span> <span class="Keyword">+</span> gold);
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>Silver: <span class="String">"</span></span> <span class="Keyword">+</span> silver);
|
||||
<span class="LibraryFunction">alert</span>(<span class="String"><span class="String">"</span>The Field: <span class="String">"</span></span> <span class="Keyword">+</span> rest);
|
||||
@@ -776,7 +777,7 @@ awardMedals = function() {
|
||||
return rest = others;
|
||||
};
|
||||
contenders = ["Michael Phelps", "Liu Xiang", "Yao Ming", "Allyson Felix", "Shawn Johnson", "Roman Sebrle", "Guo Jingjing", "Tyson Gay", "Asafa Powell", "Usain Bolt"];
|
||||
awardMedals.apply(awardMedals, contenders);
|
||||
awardMedals.apply(null, contenders);
|
||||
alert("Gold: " + gold);
|
||||
alert("Silver: " + silver);
|
||||
alert("The Field: " + rest);;'>run</button><br class='clear' /></div>
|
||||
@@ -804,7 +805,7 @@ lyrics <span class="Keyword">=</span> <span class="Keyword">while</span> num <sp
|
||||
<span class="Keyword">while</span> (supply <span class="Keyword">></span> demand) {
|
||||
buy();
|
||||
}
|
||||
<span class="Keyword">while</span> (supply <span class="Keyword"><=</span> demand) {
|
||||
<span class="Keyword">while</span> (<span class="Keyword">!</span>(supply <span class="Keyword">></span> demand)) {
|
||||
sell();
|
||||
}
|
||||
}
|
||||
@@ -821,7 +822,7 @@ if (this.studyingEconomics) {
|
||||
while (supply > demand) {
|
||||
buy();
|
||||
}
|
||||
while (supply <= demand) {
|
||||
while (!(supply > demand)) {
|
||||
sell();
|
||||
}
|
||||
}
|
||||
@@ -853,28 +854,12 @@ lyrics = function() {
|
||||
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>
|
||||
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, pos <span class="Keyword">in</span> asteroids
|
||||
<span class="Keyword">for</span> roid2 <span class="Keyword">in</span> asteroids <span class="Keyword">when</span> roid <span class="Keyword">isnt</span> roid2
|
||||
roid.explode() <span class="Keyword">if</span> roid.overlaps roid2
|
||||
</pre><pre class="idle"><span class="Storage">var</span> food, lunch, pos, roid, roid2, _i, _j, _len, _len2, _len3, _ref;
|
||||
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>]
|
||||
</pre><pre class="idle"><span class="Storage">var</span> food, _i, _len, _ref;
|
||||
_ref <span class="Keyword">=</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="Keyword">for</span> (_i <span class="Keyword">=</span> <span class="Number">0</span>, _len <span class="Keyword">=</span> _ref.<span class="LibraryConstant">length</span>; _i <span class="Keyword"><</span> _len; _i<span class="Keyword">++</span>) {
|
||||
food <span class="Keyword">=</span> _ref[_i];
|
||||
lunch <span class="Keyword">=</span> eat(food);
|
||||
}
|
||||
<span class="Keyword">for</span> (pos <span class="Keyword">=</span> <span class="Number">0</span>, _len2 <span class="Keyword">=</span> asteroids.<span class="LibraryConstant">length</span>; pos <span class="Keyword"><</span> _len2; pos<span class="Keyword">++</span>) {
|
||||
roid <span class="Keyword">=</span> asteroids[pos];
|
||||
<span class="Keyword">for</span> (_j <span class="Keyword">=</span> <span class="Number">0</span>, _len3 <span class="Keyword">=</span> asteroids.<span class="LibraryConstant">length</span>; _j <span class="Keyword"><</span> _len3; _j<span class="Keyword">++</span>) {
|
||||
roid2 <span class="Keyword">=</span> asteroids[_j];
|
||||
<span class="Keyword">if</span> (roid <span class="Keyword">!</span><span class="Keyword">==</span> roid2) {
|
||||
<span class="Keyword">if</span> (roid.overlaps(roid2)) {
|
||||
roid.explode();
|
||||
}
|
||||
}
|
||||
}
|
||||
eat(food);
|
||||
}
|
||||
</pre><br class='clear' /></div>
|
||||
<p>
|
||||
@@ -900,6 +885,15 @@ countdown = (function() {
|
||||
}
|
||||
return _results;
|
||||
}());;alert(countdown);'>run: countdown</button><br class='clear' /></div>
|
||||
<p>
|
||||
Note how because we are assigning the value of the comprehensions to a
|
||||
variable in the example above, CoffeeScript is collecting the result of
|
||||
each iteration into an array. Sometimes functions end with loops that are
|
||||
intended to run only for their side-effects. Be careful that you're not
|
||||
accidentally returning the results of the comprehension in these cases,
|
||||
by adding a meaningful return value, like <tt>true</tt>, or <tt>null</tt>,
|
||||
to the bottom of your function.
|
||||
</p>
|
||||
<p>
|
||||
Comprehensions can also be used to iterate over the keys and values in
|
||||
an object. Use <tt>of</tt> to signal comprehension over the properties of
|
||||
@@ -910,7 +904,6 @@ countdown = (function() {
|
||||
ages <span class="Keyword">=</span> <span class="Keyword">for</span> child, age <span class="Keyword">of</span> yearsOld
|
||||
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> age, ages, child, yearsOld, _results;
|
||||
<span class="Storage">var</span> __hasProp <span class="Keyword">=</span> <span class="LibraryClassType">Object</span>.<span class="LibraryConstant">prototype</span>.hasOwnProperty;
|
||||
yearsOld <span class="Keyword">=</span> {
|
||||
max: <span class="Number">10</span>,
|
||||
ida: <span class="Number">9</span>,
|
||||
@@ -919,14 +912,12 @@ yearsOld <span class="Keyword">=</span> {
|
||||
<span class="FunctionName">ages</span> = <span class="Storage">function</span>() {
|
||||
_results <span class="Keyword">=</span> [];
|
||||
<span class="Keyword">for</span> (child <span class="Keyword">in</span> yearsOld) {
|
||||
<span class="Keyword">if</span> (<span class="Keyword">!</span>__hasProp.<span class="LibraryFunction">call</span>(yearsOld, child)) <span class="Keyword">continue</span>;
|
||||
age <span class="Keyword">=</span> yearsOld[child];
|
||||
_results.<span class="LibraryFunction">push</span>(child <span class="Keyword">+</span> <span class="String"><span class="String">"</span> is <span class="String">"</span></span> <span class="Keyword">+</span> age);
|
||||
}
|
||||
<span class="Keyword">return</span> _results;
|
||||
}();
|
||||
</pre><button onclick='javascript: var age, ages, child, yearsOld, _results;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
yearsOld = {
|
||||
max: 10,
|
||||
ida: 9,
|
||||
@@ -935,7 +926,6 @@ yearsOld = {
|
||||
ages = function() {
|
||||
_results = [];
|
||||
for (child in yearsOld) {
|
||||
if (!__hasProp.call(yearsOld, child)) continue;
|
||||
age = yearsOld[child];
|
||||
_results.push(child + " is " + age);
|
||||
}
|
||||
@@ -948,6 +938,45 @@ ages = function() {
|
||||
loop, for speed or for another reason, you can use <br />
|
||||
<tt>for all key, value of object</tt> in CoffeeScript.
|
||||
</p>
|
||||
<p>
|
||||
<span id="slices" class="bookmark"></span>
|
||||
<b class="header">Array Slicing and Splicing with Ranges</b>
|
||||
Ranges can also be used to extract slices of arrays.
|
||||
With two dots (<tt>3..6</tt>), the range is inclusive (<tt>3, 4, 5, 6</tt>);
|
||||
with three docs (<tt>3...6</tt>), the range excludes the end (<tt>3, 4, 5</tt>).
|
||||
</p>
|
||||
<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>]
|
||||
|
||||
copy <span class="Keyword">=</span> numbers[<span class="Number">0</span>...numbers.length]
|
||||
|
||||
middle <span class="Keyword">=</span> copy[<span class="Number">3</span>..<span class="Number">6</span>]
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> copy, middle, numbers;
|
||||
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>];
|
||||
copy <span class="Keyword">=</span> numbers.<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, numbers.<span class="LibraryConstant">length</span>);
|
||||
middle <span class="Keyword">=</span> copy.<span class="LibraryFunction">slice</span>(<span class="Number">3</span>, <span class="Number">6</span> <span class="Keyword">+</span> <span class="Number">1</span>);
|
||||
</pre><button onclick='javascript: var copy, middle, numbers;
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
copy = numbers.slice(0, numbers.length);
|
||||
middle = copy.slice(3, 6 + 1);;alert(middle);'>run: middle</button><br class='clear' /></div>
|
||||
<p>
|
||||
The same syntax can be used with assignment to replace a segment of an array
|
||||
with new values, splicing it.
|
||||
</p>
|
||||
<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>]
|
||||
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> numbers;
|
||||
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>];
|
||||
[].splice.<span class="LibraryFunction">apply</span>(numbers, [<span class="Number">3</span>, <span class="Number">4</span>].<span class="LibraryFunction">concat</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><button onclick='javascript: var numbers;
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
[].splice.apply(numbers, [3, 4].concat([-3, -4, -5, -6]));;alert(numbers);'>run: numbers</button><br class='clear' /></div>
|
||||
<p>
|
||||
Note that JavaScript strings are immutable, and can't be spliced.
|
||||
</p>
|
||||
<p>
|
||||
<span id="expressions" class="bookmark"></span>
|
||||
<b class="header">Everything is an Expression (at least, as much as possible)</b>
|
||||
@@ -1021,21 +1050,17 @@ six = (one = 1) + (two = 2) + (three = 3);;alert(six);'>run: six</button><br cla
|
||||
|
||||
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> globals, name, _results;
|
||||
<span class="Storage">var</span> __hasProp <span class="Keyword">=</span> <span class="LibraryClassType">Object</span>.<span class="LibraryConstant">prototype</span>.hasOwnProperty;
|
||||
globals <span class="Keyword">=</span> (<span class="Storage">function</span>() {
|
||||
_results <span class="Keyword">=</span> [];
|
||||
<span class="Keyword">for</span> (name <span class="Keyword">in</span> <span class="LibraryClassType">window</span>) {
|
||||
<span class="Keyword">if</span> (<span class="Keyword">!</span>__hasProp.<span class="LibraryFunction">call</span>(<span class="LibraryClassType">window</span>, name)) <span class="Keyword">continue</span>;
|
||||
_results.<span class="LibraryFunction">push</span>(name);
|
||||
}
|
||||
<span class="Keyword">return</span> _results;
|
||||
}()).<span class="LibraryFunction">slice</span>(<span class="Number">0</span>, <span class="Number">10</span>);
|
||||
</pre><button onclick='javascript: var globals, name, _results;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
globals = (function() {
|
||||
_results = [];
|
||||
for (name in window) {
|
||||
if (!__hasProp.call(window, name)) continue;
|
||||
_results.push(name);
|
||||
}
|
||||
return _results;
|
||||
@@ -1531,10 +1556,10 @@ healthy <span class="Keyword">=</span> <span class="Number">200</span> <span cla
|
||||
|
||||
</pre><pre class="idle"><span class="Storage">var</span> cholesterol, healthy;
|
||||
cholesterol <span class="Keyword">=</span> <span class="Number">127</span>;
|
||||
healthy <span class="Keyword">=</span> <span class="Number">200</span> <span class="Keyword">></span> cholesterol <span class="Keyword">&</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="Keyword">&</span> cholesterol <span class="Keyword">></span> <span class="Number">60</span>);
|
||||
</pre><button onclick='javascript: var cholesterol, healthy;
|
||||
cholesterol = 127;
|
||||
healthy = 200 > cholesterol && cholesterol > 60;;alert(healthy);'>run: healthy</button><br class='clear' /></div>
|
||||
healthy = (200 > cholesterol && cholesterol > 60);;alert(healthy);'>run: healthy</button><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="strings" class="bookmark"></span>
|
||||
@@ -1596,11 +1621,11 @@ html <span class="Keyword">=</span> <span class="String"><span class="String">'<
|
||||
are preserved in the generated code.
|
||||
</p>
|
||||
<div class='code'><pre class="idle"><span class="Comment"><span class="Comment">###</span></span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.5</span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.6</span>
|
||||
<span class="Comment">Released under the MIT License</span>
|
||||
<span class="Comment">###</span>
|
||||
</pre><pre class="idle"><span class="Comment"><span class="Comment">/*</span></span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.5</span>
|
||||
<span class="Comment">CoffeeScript Compiler v0.9.6</span>
|
||||
<span class="Comment">Released under the MIT License</span>
|
||||
<span class="Comment"><span class="Comment">*/</span></span>
|
||||
</pre><br class='clear' /></div>
|
||||
@@ -1876,21 +1901,41 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
<span id="change_log" class="bookmark"></span>
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.6
|
||||
<span class="timestamp"> – <small>Dec 6, 2010</small></span>
|
||||
</b>
|
||||
The REPL now properly formats stacktraces, and stays alive through
|
||||
asynchronous exceptions. Using <tt>--watch</tt> now prints timestamps as
|
||||
files are compiled. Fixed some accidentally-leaking variables within
|
||||
plucked closure-loops. Constructors now maintain their declaration
|
||||
location within a class body.
|
||||
Nested classes are now supported. Fixes execution context for naked
|
||||
splatted functions. Bugfix for inversion of chained comparisons.
|
||||
Chained class instantiation now works properly with splats.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.5
|
||||
<span class="timestamp"> – <small>Nov 21, 2010</small></span>
|
||||
</b>
|
||||
0.9.5 should be considered the first release candidate for CoffeeScript 1.0.
|
||||
There have been a large number of internal changes since the previous release,
|
||||
many contributed from <b>satyr</b>'s <a href="http://github.com/satyr/coco">Coco</a>
|
||||
dialect of CoffeeScript. Heregexes (extended regexes) were added. Functions
|
||||
can now have default arguments. Class bodies are now executable code.
|
||||
Improved syntax errors for invalid CoffeeScript. Object literals
|
||||
can now take dynamic keys, like this: <tt>{(key): value}</tt>. <tt>undefined</tt> now
|
||||
Improved syntax errors for invalid CoffeeScript. <tt>undefined</tt> now
|
||||
works like <tt>null</tt>, and cannot be assigned a new value.
|
||||
There was a precedence change with respect to single-line comprehensions:
|
||||
<tt>result = i for i in list</tt><br /> used to parse as <tt>result = (i for i in list)</tt>
|
||||
by default ... it now parses as <br /><tt>(result = i) for i in list</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.4
|
||||
<span class="timestamp"> – <small>Sep 21, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript now uses appropriately-named temporary variables, and recycles
|
||||
their references after use. Added <tt>require.extensions</tt> support for
|
||||
<b>Node.js 0.3</b>. Loading CoffeeScript in the browser now adds just a
|
||||
@@ -1899,7 +1944,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.3</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.3
|
||||
<span class="timestamp"> – <small>Sep 16, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript <tt>switch</tt> statements now compile into JS <tt>switch</tt>
|
||||
statements — they previously compiled into <tt>if/else</tt> chains
|
||||
for JavaScript 1.3 compatibility.
|
||||
@@ -1908,7 +1955,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.2
|
||||
<span class="timestamp"> – <small>Aug 23, 2010</small></span>
|
||||
</b>
|
||||
Specifying the start and end of a range literal is now optional, eg. <tt>array[3..]</tt>.
|
||||
You can now say <tt>a not instanceof b</tt>.
|
||||
Fixed important bugs with nested significant and non-significant indentation (Issue #637).
|
||||
@@ -1922,7 +1971,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.1
|
||||
<span class="timestamp"> – <small>Aug 11, 2010</small></span>
|
||||
</b>
|
||||
Bugfix release for <b>0.9.1</b>. Greatly improves the handling of mixed
|
||||
implicit objects, implicit function calls, and implicit indentation.
|
||||
String and regex interpolation is now strictly <tt>#{ ... }</tt> (Ruby style).
|
||||
@@ -1931,7 +1982,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.9.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.9.0
|
||||
<span class="timestamp"> – <small>Aug 4, 2010</small></span>
|
||||
</b>
|
||||
The CoffeeScript <b>0.9</b> series is considered to be a release candidate
|
||||
for <b>1.0</b>; let's give her a shakedown cruise. <b>0.9.0</b> introduces a massive
|
||||
backwards-incompatible change: Assignment now uses <tt>=</tt>, and object
|
||||
@@ -1955,13 +2008,17 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.7.2
|
||||
<span class="timestamp"> – <small>Jul 12, 2010</small></span>
|
||||
</b>
|
||||
Quick bugfix (right after 0.7.1) for a problem that prevented <tt>coffee</tt>
|
||||
command-line options from being parsed in some circumstances.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.7.1
|
||||
<span class="timestamp"> – <small>Jul 11, 2010</small></span>
|
||||
</b>
|
||||
Block-style comments are now passed through and printed as JavaScript block
|
||||
comments -- making them useful for licenses and copyright headers. Better
|
||||
support for running coffee scripts standalone via hashbangs.
|
||||
@@ -1969,7 +2026,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.7.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.7.0
|
||||
<span class="timestamp"> – <small>Jun 28, 2010</small></span>
|
||||
</b>
|
||||
Official CoffeeScript variable style is now camelCase, as in JavaScript.
|
||||
Reserved words are now allowed as object keys, and will be quoted for you.
|
||||
Range comprehensions now generate cleaner code, but you have to specify <tt>by -1</tt>
|
||||
@@ -1986,7 +2045,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.6.2
|
||||
<span class="timestamp"> – <small>May 15, 2010</small></span>
|
||||
</b>
|
||||
The <tt>coffee</tt> command will now preserve directory structure when
|
||||
compiling a directory full of scripts. Fixed two omissions that were preventing
|
||||
the CoffeeScript compiler from running live within Internet Explorer.
|
||||
@@ -2001,20 +2062,26 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.6.1
|
||||
<span class="timestamp"> – <small>Apr 12, 2010</small></span>
|
||||
</b>
|
||||
Upgraded CoffeeScript for compatibility with the new Node.js <b>v0.1.90</b>
|
||||
series.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.6.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.6.0
|
||||
<span class="timestamp"> – <small>Apr 3, 2010</small></span>
|
||||
</b>
|
||||
Trailing commas are now allowed, a-la Python. Static
|
||||
properties may be assigned directly within class definitions,
|
||||
using <tt>@property</tt> notation.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.6</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.6
|
||||
<span class="timestamp"> – <small>Mar 23, 2010</small></span>
|
||||
</b>
|
||||
Interpolation can now be used within regular expressions and heredocs, as well as
|
||||
strings. Added the <tt><-</tt> bind operator.
|
||||
Allowing assignment to half-expressions instead of special <tt>||=</tt>-style
|
||||
@@ -2025,7 +2092,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.5
|
||||
<span class="timestamp"> – <small>Mar 8, 2010</small></span>
|
||||
</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
|
||||
@@ -2034,14 +2103,18 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.4
|
||||
<span class="timestamp"> – <small>Mar 3, 2010</small></span>
|
||||
</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>
|
||||
<b class="header" style="margin-top: 20px;">0.5.3
|
||||
<span class="timestamp"> – <small>Feb 27, 2010</small></span>
|
||||
</b>
|
||||
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.
|
||||
@@ -2051,7 +2124,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.2
|
||||
<span class="timestamp"> – <small>Feb 25, 2010</small></span>
|
||||
</b>
|
||||
Added a compressed version of the compiler for inclusion in web pages as
|
||||
<br /><tt>extras/coffee-script.js</tt>. It'll automatically run any script tags
|
||||
with type <tt>text/coffeescript</tt> for you. Added a <tt>--stdio</tt> option
|
||||
@@ -2060,7 +2135,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.1
|
||||
<span class="timestamp"> – <small>Feb 24, 2010</small></span>
|
||||
</b>
|
||||
Improvements to null soaking with the existential operator, including
|
||||
soaks on indexed properties. Added conditions to <tt>while</tt> loops,
|
||||
so you can use them as filters with <tt>when</tt>, in the same manner as
|
||||
@@ -2068,21 +2145,27 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.5.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.5.0
|
||||
<span class="timestamp"> – <small>Feb 21, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript 0.5.0 is a major release, While there are no language changes,
|
||||
the Ruby compiler has been removed in favor of a self-hosting
|
||||
compiler written in pure CoffeeScript.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.3.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.3.2
|
||||
<span class="timestamp"> – <small>Feb 8, 2010</small></span>
|
||||
</b>
|
||||
<tt>@property</tt> is now a shorthand for <tt>this.property</tt>.<br />
|
||||
Switched the default JavaScript engine from Narwhal to Node.js. Pass
|
||||
the <tt>--narwhal</tt> flag if you'd like to continue using it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.3.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.3.0
|
||||
<span class="timestamp"> – <small>Jan 26, 2010</small></span>
|
||||
</b>
|
||||
CoffeeScript 0.3 includes major syntax changes:
|
||||
<br />
|
||||
The function symbol was changed to
|
||||
@@ -2098,7 +2181,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.6</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.6
|
||||
<span class="timestamp"> – <small>Jan 17, 2010</small></span>
|
||||
</b>
|
||||
Added Python-style chained comparisons, the conditional existence
|
||||
operator <tt>?=</tt>, and some examples from <i>Beautiful Code</i>.
|
||||
Bugfixes relating to statement-to-expression conversion, arguments-to-array
|
||||
@@ -2106,7 +2191,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.5
|
||||
<span class="timestamp"> – <small>Jan 13, 2010</small></span>
|
||||
</b>
|
||||
The conditions in switch statements can now take multiple values at once —
|
||||
If any of them are true, the case will run. Added the long arrow <tt>==></tt>,
|
||||
which defines and immediately binds a function to <tt>this</tt>. While loops can
|
||||
@@ -2115,20 +2202,26 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.4
|
||||
<span class="timestamp"> – <small>Jan 12, 2010</small></span>
|
||||
</b>
|
||||
Added ECMAScript Harmony style destructuring assignment, for dealing with
|
||||
extracting values from nested arrays and objects. Added indentation-sensitive
|
||||
heredocs for nicely formatted strings or chunks of code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.3</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.3
|
||||
<span class="timestamp"> – <small>Jan 11, 2010</small></span>
|
||||
</b>
|
||||
Axed the unsatisfactory <tt>ino</tt> keyword, replacing it with <tt>of</tt> for
|
||||
object comprehensions. They now look like: <tt>for prop, value of object</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.2
|
||||
<span class="timestamp"> – <small>Jan 10, 2010</small></span>
|
||||
</b>
|
||||
When performing a comprehension over an object, use <tt>ino</tt>, instead
|
||||
of <tt>in</tt>, which helps us generate smaller, more efficient code at
|
||||
compile time.
|
||||
@@ -2149,12 +2242,16 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.1
|
||||
<span class="timestamp"> – <small>Jan 5, 2010</small></span>
|
||||
</b>
|
||||
Arguments objects are now converted into real arrays when referenced.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.2.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.2.0
|
||||
<span class="timestamp"> – <small>Jan 5, 2010</small></span>
|
||||
</b>
|
||||
Major release. Significant whitespace. Better statement-to-expression
|
||||
conversion. Splats. Splice literals. Object comprehensions. Blocks.
|
||||
The existential operator. Many thanks to all the folks who posted issues,
|
||||
@@ -2164,14 +2261,18 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.6</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.6
|
||||
<span class="timestamp"> – <small>Dec 27, 2009</small></span>
|
||||
</b>
|
||||
Bugfix for running <tt>coffee --interactive</tt> and <tt>--run</tt>
|
||||
from outside of the CoffeeScript directory. Bugfix for nested
|
||||
function/if-statements.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.5</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.5
|
||||
<span class="timestamp"> – <small>Dec 26, 2009</small></span>
|
||||
</b>
|
||||
Array slice literals and array comprehensions can now both take Ruby-style
|
||||
ranges to specify the start and end. JavaScript variable declaration is
|
||||
now pushed up to the top of the scope, making all assignment statements into
|
||||
@@ -2180,7 +2281,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.4</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.4
|
||||
<span class="timestamp"> – <small>Dec 25, 2009</small></span>
|
||||
</b>
|
||||
The official CoffeeScript extension is now <tt>.coffee</tt> instead of
|
||||
<tt>.cs</tt>, which properly belongs to
|
||||
<a href="http://en.wikipedia.org/wiki/C_Sharp_(programming_language)">C#</a>.
|
||||
@@ -2192,7 +2295,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.3</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.3
|
||||
<span class="timestamp"> – <small>Dec 25, 2009</small></span>
|
||||
</b>
|
||||
The <tt>coffee</tt> command now includes <tt>--interactive</tt>,
|
||||
which launches an interactive CoffeeScript session, and <tt>--run</tt>,
|
||||
which directly compiles and executes a script. Both options depend on a
|
||||
@@ -2206,7 +2311,9 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.2</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.2
|
||||
<span class="timestamp"> – <small>Dec 24, 2009</small></span>
|
||||
</b>
|
||||
Fixed a bug with calling <tt>super()</tt> through more than one level of
|
||||
inheritance, with the re-addition of the <tt>extends</tt> keyword.
|
||||
Added experimental <a href="http://narwhaljs.org/">Narwhal</a>
|
||||
@@ -2218,12 +2325,16 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.1</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.1
|
||||
<span class="timestamp"> – <small>Dec 24, 2009</small></span>
|
||||
</b>
|
||||
Added <tt>instanceof</tt> and <tt>typeof</tt> as operators.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b class="header" style="margin-top: 20px;">0.1.0</b>
|
||||
<b class="header" style="margin-top: 20px;">0.1.0
|
||||
<span class="timestamp"> – <small>Dec 24, 2009</small></span>
|
||||
</b>
|
||||
Initial CoffeeScript release.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
return compile(content);
|
||||
});
|
||||
}
|
||||
exports.VERSION = '0.9.5';
|
||||
exports.VERSION = '0.9.6';
|
||||
exports.helpers = require('./helpers');
|
||||
exports.compile = compile = function(code, options) {
|
||||
if (options == null) {
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
(function() {
|
||||
var ALL_SWITCHES, BANNER, CoffeeScript, DEPRECATED_SWITCHES, EventEmitter, SWITCHES, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, helpers, lint, optionParser, optparse, opts, parseOptions, path, printTokens, sources, spawn, usage, version, watch, writeJs, _ref;
|
||||
var ALL_SWITCHES, BANNER, CoffeeScript, DEPRECATED_SWITCHES, EventEmitter, SWITCHES, compileOptions, compileScript, compileScripts, compileStdio, exec, fs, helpers, lint, optionParser, optparse, opts, parseOptions, path, printLine, printTokens, printWarn, sources, spawn, usage, util, version, watch, writeJs, _ref;
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
util = require('util');
|
||||
helpers = require('./helpers');
|
||||
optparse = require('./optparse');
|
||||
CoffeeScript = require('./coffee-script');
|
||||
_ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
helpers.extend(CoffeeScript, new EventEmitter);
|
||||
printLine = function(line) {
|
||||
return process.stdout.write(line + '\n');
|
||||
};
|
||||
printWarn = function(line) {
|
||||
return process.binding('stdio').writeError(line + '\n');
|
||||
};
|
||||
BANNER = 'Usage: coffee [options] path/to/script.coffee';
|
||||
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JSLint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
|
||||
DEPRECATED_SWITCHES = [['--no-wrap', 'compile without the top-level function wrapper']];
|
||||
@@ -49,9 +56,8 @@
|
||||
return compileScripts();
|
||||
};
|
||||
compileScripts = function() {
|
||||
var _fn, _i, _len, _results;
|
||||
var base, compile, source, _fn, _i, _len, _results;
|
||||
_fn = function(source) {
|
||||
var base, compile;
|
||||
base = path.join(source);
|
||||
compile = function(source, topLevel) {
|
||||
return path.exists(source, function(exists) {
|
||||
@@ -110,14 +116,14 @@
|
||||
if (o.tokens) {
|
||||
return printTokens(CoffeeScript.tokens(t.input));
|
||||
} else if (o.nodes) {
|
||||
return console.log(CoffeeScript.nodes(t.input).toString().trim());
|
||||
return printLine(CoffeeScript.nodes(t.input).toString().trim());
|
||||
} else if (o.run) {
|
||||
return CoffeeScript.run(t.input, t.options);
|
||||
} else {
|
||||
t.output = CoffeeScript.compile(t.input, t.options);
|
||||
CoffeeScript.emit('success', task);
|
||||
if (o.print) {
|
||||
return console.log(t.output.trim());
|
||||
return printLine(t.output.trim());
|
||||
} else if (o.compile) {
|
||||
return writeJs(t.file, t.output, base);
|
||||
} else if (o.lint) {
|
||||
@@ -130,9 +136,9 @@
|
||||
return;
|
||||
}
|
||||
if (o.watch) {
|
||||
return console.log(err.message);
|
||||
return printLine(err.message);
|
||||
}
|
||||
console.error(err.stack);
|
||||
printWarn(err.stack);
|
||||
return process.exit(1);
|
||||
}
|
||||
};
|
||||
@@ -178,9 +184,9 @@
|
||||
}
|
||||
return fs.writeFile(jsPath, js, function(err) {
|
||||
if (err) {
|
||||
return console.log(err.message);
|
||||
return printLine(err.message);
|
||||
} else if (opts.compile && opts.watch) {
|
||||
return console.log("Compiled " + source);
|
||||
return util.log("compiled " + source);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -195,7 +201,7 @@
|
||||
lint = function(file, js) {
|
||||
var conf, jsl, printIt;
|
||||
printIt = function(buffer) {
|
||||
return console.log(file + ':\t' + buffer.toString().trim());
|
||||
return printLine(file + ':\t' + buffer.toString().trim());
|
||||
};
|
||||
conf = __dirname + '/../extras/jsl.conf';
|
||||
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
|
||||
@@ -215,7 +221,7 @@
|
||||
}
|
||||
return _results;
|
||||
}();
|
||||
return console.log(strings.join(' '));
|
||||
return printLine(strings.join(' '));
|
||||
};
|
||||
parseOptions = function() {
|
||||
var o;
|
||||
@@ -226,7 +232,7 @@
|
||||
o.print = !!(o.print || (o.eval || o.stdio && o.compile));
|
||||
sources = o.arguments;
|
||||
if (opts['no-wrap']) {
|
||||
return console.warn('--no-wrap is deprecated; please use --bare instead.');
|
||||
return printWarn('--no-wrap is deprecated; please use --bare instead.');
|
||||
}
|
||||
};
|
||||
compileOptions = function(fileName) {
|
||||
@@ -236,11 +242,11 @@
|
||||
};
|
||||
};
|
||||
usage = function() {
|
||||
console.log((new optparse.OptionParser(SWITCHES, BANNER)).help());
|
||||
printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
|
||||
return process.exit(0);
|
||||
};
|
||||
version = function() {
|
||||
console.log("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
printLine("CoffeeScript version " + CoffeeScript.VERSION);
|
||||
return process.exit(0);
|
||||
};
|
||||
}).call(this);
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
return new Assign(new Value($1), $4, 'object');
|
||||
}), o('Comment')
|
||||
],
|
||||
ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('Parenthetical'), o('ThisProperty')],
|
||||
ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')],
|
||||
Return: [
|
||||
o('RETURN Expression', function() {
|
||||
return new Return($2);
|
||||
@@ -382,7 +382,7 @@
|
||||
vars: []
|
||||
};
|
||||
}), o('ForStart ForSource', function() {
|
||||
$2.raw = $1.raw;
|
||||
$2.own = $1.own;
|
||||
$2.vars = $1;
|
||||
return $2;
|
||||
})
|
||||
@@ -390,8 +390,8 @@
|
||||
ForStart: [
|
||||
o('FOR ForVariables', function() {
|
||||
return $2;
|
||||
}), o('FOR ALL ForVariables', function() {
|
||||
$3.raw = true;
|
||||
}), o('FOR OWN ForVariables', function() {
|
||||
$3.own = true;
|
||||
return $3;
|
||||
})
|
||||
],
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
(function() {
|
||||
var key, val, _ref;
|
||||
var __hasProp = Object.prototype.hasOwnProperty;
|
||||
_ref = require('./coffee-script');
|
||||
for (key in _ref) {
|
||||
if (!__hasProp.call(_ref, key)) continue;
|
||||
val = _ref[key];
|
||||
exports[key] = val;
|
||||
}
|
||||
|
||||
14
lib/lexer.js
14
lib/lexer.js
@@ -39,8 +39,8 @@
|
||||
return 0;
|
||||
}
|
||||
input = match[0], id = match[1], colon = match[2];
|
||||
if (id === 'all' && this.tag() === 'FOR') {
|
||||
this.token('ALL', id);
|
||||
if (id === 'own' && this.tag() === 'FOR') {
|
||||
this.token('OWN', id);
|
||||
return id.length;
|
||||
}
|
||||
forcedIdentifier = colon || (prev = last(this.tokens)) && !prev.spaced && ((_ref = prev[0]) === '.' || _ref === '?.' || _ref === '@' || _ref === '::');
|
||||
@@ -208,7 +208,7 @@
|
||||
return regex.length;
|
||||
};
|
||||
Lexer.prototype.heregexToken = function(match) {
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref, _ref2, _ref3, _this;
|
||||
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref, _ref2, _ref3, _ref4;
|
||||
heregex = match[0], body = match[1], flags = match[2];
|
||||
if (0 > body.indexOf('#{')) {
|
||||
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
|
||||
@@ -238,7 +238,7 @@
|
||||
if (((_ref3 = tokens[0]) != null ? _ref3[0] : void 0) !== 'STRING') {
|
||||
this.tokens.push(['STRING', '""'], ['+', '+']);
|
||||
}
|
||||
(_this = this.tokens).push.apply(_this, tokens);
|
||||
(_ref4 = this.tokens).push.apply(_ref4, tokens);
|
||||
if (flags) {
|
||||
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
|
||||
}
|
||||
@@ -478,7 +478,7 @@
|
||||
throw new Error("unterminated " + (stack.pop()[0]) + " on line " + (this.line + 1));
|
||||
};
|
||||
Lexer.prototype.interpolateString = function(str, options) {
|
||||
var expr, heredoc, i, inner, interpolated, letter, nested, pi, regex, tag, tokens, value, _len, _ref, _ref2, _this;
|
||||
var expr, heredoc, i, inner, interpolated, letter, nested, pi, regex, tag, tokens, value, _len, _ref, _ref2, _ref3;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
@@ -516,7 +516,7 @@
|
||||
i += expr.length;
|
||||
pi = i + 1;
|
||||
}
|
||||
if (i > pi && pi < str.length) {
|
||||
if ((i > pi && pi < str.length)) {
|
||||
tokens.push(['NEOSTRING', str.slice(pi)]);
|
||||
}
|
||||
if (regex) {
|
||||
@@ -537,7 +537,7 @@
|
||||
this.token('+', '+');
|
||||
}
|
||||
if (tag === 'TOKENS') {
|
||||
(_this = this.tokens).push.apply(_this, value);
|
||||
(_ref3 = this.tokens).push.apply(_ref3, value);
|
||||
} else {
|
||||
this.token('STRING', this.makeString(value, '"', heredoc));
|
||||
}
|
||||
|
||||
284
lib/nodes.js
284
lib/nodes.js
@@ -162,10 +162,10 @@
|
||||
return Base;
|
||||
}();
|
||||
exports.Expressions = Expressions = function() {
|
||||
__extends(Expressions, Base);
|
||||
function Expressions(nodes) {
|
||||
this.expressions = compact(flatten(nodes || []));
|
||||
}
|
||||
__extends(Expressions, Base);
|
||||
Expressions.prototype.children = ['expressions'];
|
||||
Expressions.prototype.push = function(node) {
|
||||
this.expressions.push(node);
|
||||
@@ -281,11 +281,13 @@
|
||||
}
|
||||
post = this.compileNode(o);
|
||||
scope = o.scope;
|
||||
if (!o.globals && o.scope.hasDeclarations(this)) {
|
||||
code += "" + this.tab + "var " + (scope.compiledDeclarations()) + ";\n";
|
||||
}
|
||||
if (scope.hasAssignments(this)) {
|
||||
code += "" + this.tab + "var " + (multident(scope.compiledAssignments(), this.tab)) + ";\n";
|
||||
if (scope.expressions === this) {
|
||||
if (!o.globals && o.scope.hasDeclarations) {
|
||||
code += "" + this.tab + "var " + (scope.declaredVariables().join(', ')) + ";\n";
|
||||
}
|
||||
if (scope.hasAssignments) {
|
||||
code += "" + this.tab + "var " + (multident(scope.assignedVariables().join(', '), this.tab)) + ";\n";
|
||||
}
|
||||
}
|
||||
return code + post;
|
||||
};
|
||||
@@ -298,10 +300,10 @@
|
||||
return Expressions;
|
||||
}();
|
||||
exports.Literal = Literal = function() {
|
||||
__extends(Literal, Base);
|
||||
function Literal(value) {
|
||||
this.value = value;
|
||||
}
|
||||
__extends(Literal, Base);
|
||||
Literal.prototype.makeReturn = function() {
|
||||
if (this.isPureStatement()) {
|
||||
return this;
|
||||
@@ -333,10 +335,10 @@
|
||||
return Literal;
|
||||
}();
|
||||
exports.Return = Return = function() {
|
||||
__extends(Return, Base);
|
||||
function Return(expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
__extends(Return, Base);
|
||||
Return.prototype.children = ['expression'];
|
||||
Return.prototype.isStatement = YES;
|
||||
Return.prototype.isPureStatement = YES;
|
||||
@@ -357,6 +359,7 @@
|
||||
return Return;
|
||||
}();
|
||||
exports.Value = Value = function() {
|
||||
__extends(Value, Base);
|
||||
function Value(base, props, tag) {
|
||||
if (!props && base instanceof Value) {
|
||||
return base;
|
||||
@@ -368,7 +371,6 @@
|
||||
}
|
||||
return this;
|
||||
}
|
||||
__extends(Value, Base);
|
||||
Value.prototype.children = ['base', 'properties'];
|
||||
Value.prototype.push = function(prop) {
|
||||
this.properties.push(prop);
|
||||
@@ -492,10 +494,10 @@
|
||||
return Value;
|
||||
}();
|
||||
exports.Comment = Comment = function() {
|
||||
__extends(Comment, Base);
|
||||
function Comment(comment) {
|
||||
this.comment = comment;
|
||||
}
|
||||
__extends(Comment, Base);
|
||||
Comment.prototype.isPureStatement = YES;
|
||||
Comment.prototype.isStatement = YES;
|
||||
Comment.prototype.makeReturn = THIS;
|
||||
@@ -510,6 +512,7 @@
|
||||
return Comment;
|
||||
}();
|
||||
exports.Call = Call = function() {
|
||||
__extends(Call, Base);
|
||||
function Call(variable, args, soak) {
|
||||
this.args = args != null ? args : [];
|
||||
this.soak = soak;
|
||||
@@ -517,10 +520,15 @@
|
||||
this.isSuper = variable === 'super';
|
||||
this.variable = this.isSuper ? null : variable;
|
||||
}
|
||||
__extends(Call, Base);
|
||||
Call.prototype.children = ['variable', 'args'];
|
||||
Call.prototype.newInstance = function() {
|
||||
this.isNew = true;
|
||||
var base;
|
||||
base = this.variable.base || this.variable;
|
||||
if (base instanceof Call) {
|
||||
base.newInstance();
|
||||
} else {
|
||||
this.isNew = true;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Call.prototype.superReference = function(o) {
|
||||
@@ -606,7 +614,7 @@
|
||||
return _results;
|
||||
}.call(this)).join(', ');
|
||||
if (this.isSuper) {
|
||||
return this.compileSuper(args, o);
|
||||
return this.superReference(o) + (".call(this" + (args && ', ' + args) + ")");
|
||||
} else {
|
||||
return (this.isNew ? 'new ' : '') + this.variable.compile(o, LEVEL_ACCESS) + ("(" + args + ")");
|
||||
}
|
||||
@@ -619,30 +627,33 @@
|
||||
if (this.isSuper) {
|
||||
return "" + (this.superReference(o)) + ".apply(this, " + splatArgs + ")";
|
||||
}
|
||||
if (!this.isNew) {
|
||||
base = new Value(this.variable);
|
||||
if ((name = base.properties.pop()) && base.isComplex()) {
|
||||
ref = o.scope.freeVariable('this');
|
||||
fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o));
|
||||
} else {
|
||||
fun = ref = base.compile(o, LEVEL_ACCESS);
|
||||
if (name) {
|
||||
fun += name.compile(o);
|
||||
}
|
||||
}
|
||||
return "" + fun + ".apply(" + ref + ", " + splatArgs + ")";
|
||||
if (this.isNew) {
|
||||
idt = this.tab + TAB;
|
||||
return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return typeof result === \"object\" ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function() {})";
|
||||
}
|
||||
idt = this.tab + TAB;
|
||||
return "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args);\n" + idt + "return typeof result === \"object\" ? result : child;\n" + this.tab + "})(" + (this.variable.compile(o, LEVEL_LIST)) + ", " + splatArgs + ", function() {})";
|
||||
base = new Value(this.variable);
|
||||
if ((name = base.properties.pop()) && base.isComplex()) {
|
||||
ref = o.scope.freeVariable('ref');
|
||||
fun = "(" + ref + " = " + (base.compile(o, LEVEL_LIST)) + ")" + (name.compile(o));
|
||||
} else {
|
||||
fun = base.compile(o, LEVEL_ACCESS);
|
||||
if (name) {
|
||||
ref = fun;
|
||||
fun += name.compile(o);
|
||||
} else {
|
||||
ref = 'null';
|
||||
}
|
||||
}
|
||||
return "" + fun + ".apply(" + ref + ", " + splatArgs + ")";
|
||||
};
|
||||
return Call;
|
||||
}();
|
||||
exports.Extends = Extends = function() {
|
||||
__extends(Extends, Base);
|
||||
function Extends(child, parent) {
|
||||
this.child = child;
|
||||
this.parent = parent;
|
||||
}
|
||||
__extends(Extends, Base);
|
||||
Extends.prototype.children = ['child', 'parent'];
|
||||
Extends.prototype.compile = function(o) {
|
||||
utility('hasProp');
|
||||
@@ -651,12 +662,12 @@
|
||||
return Extends;
|
||||
}();
|
||||
exports.Access = Access = function() {
|
||||
__extends(Access, Base);
|
||||
function Access(name, tag) {
|
||||
this.name = name;
|
||||
this.proto = tag === 'proto' ? '.prototype' : '';
|
||||
this.soak = tag === 'soak';
|
||||
}
|
||||
__extends(Access, Base);
|
||||
Access.prototype.children = ['name'];
|
||||
Access.prototype.compile = function(o) {
|
||||
var name;
|
||||
@@ -667,10 +678,10 @@
|
||||
return Access;
|
||||
}();
|
||||
exports.Index = Index = function() {
|
||||
__extends(Index, Base);
|
||||
function Index(index) {
|
||||
this.index = index;
|
||||
}
|
||||
__extends(Index, Base);
|
||||
Index.prototype.children = ['index'];
|
||||
Index.prototype.compile = function(o) {
|
||||
return (this.proto ? '.prototype' : '') + ("[" + (this.index.compile(o, LEVEL_PAREN)) + "]");
|
||||
@@ -681,14 +692,14 @@
|
||||
return Index;
|
||||
}();
|
||||
exports.Range = Range = function() {
|
||||
__extends(Range, Base);
|
||||
Range.prototype.children = ['from', 'to'];
|
||||
function Range(from, to, tag) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.exclusive = tag === 'exclusive';
|
||||
this.equals = this.exclusive ? '' : '=';
|
||||
}
|
||||
__extends(Range, Base);
|
||||
Range.prototype.children = ['from', 'to'];
|
||||
Range.prototype.compileVariables = function(o) {
|
||||
var parts, _ref, _ref2, _ref3;
|
||||
o = merge(o, {
|
||||
@@ -766,12 +777,12 @@
|
||||
return Range;
|
||||
}();
|
||||
exports.Slice = Slice = function() {
|
||||
__extends(Slice, Base);
|
||||
Slice.prototype.children = ['range'];
|
||||
function Slice(range) {
|
||||
this.range = range;
|
||||
Slice.__super__.constructor.call(this);
|
||||
}
|
||||
__extends(Slice, Base);
|
||||
Slice.prototype.children = ['range'];
|
||||
Slice.prototype.compileNode = function(o) {
|
||||
var from, to;
|
||||
from = this.range.from ? this.range.from.compile(o) : '0';
|
||||
@@ -785,14 +796,14 @@
|
||||
return Slice;
|
||||
}();
|
||||
exports.Obj = Obj = function() {
|
||||
__extends(Obj, Base);
|
||||
function Obj(props, generated) {
|
||||
this.generated = generated != null ? generated : false;
|
||||
this.objects = this.properties = props || [];
|
||||
}
|
||||
__extends(Obj, Base);
|
||||
Obj.prototype.children = ['properties'];
|
||||
Obj.prototype.compileNode = function(o) {
|
||||
var i, idt, indent, join, lastNoncom, nonComments, obj, prop, props, rest, _i, _len, _len2, _len3, _ref, _results, _results2;
|
||||
var i, idt, indent, join, lastNoncom, nonComments, obj, prop, props, _i, _len, _len2, _ref, _results, _results2;
|
||||
props = this.properties;
|
||||
if (!props.length) {
|
||||
if (this.front) {
|
||||
@@ -801,18 +812,11 @@
|
||||
return '{}';
|
||||
}
|
||||
}
|
||||
for (i = 0, _len = props.length; i < _len; i++) {
|
||||
prop = props[i];
|
||||
if (prop instanceof Splat || (prop.variable || prop).base instanceof Parens) {
|
||||
rest = props.splice(i, 1 / 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
idt = o.indent += TAB;
|
||||
nonComments = (function() {
|
||||
_ref = this.properties;
|
||||
_results = [];
|
||||
for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) {
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
prop = _ref[_i];
|
||||
if (!(prop instanceof Comment)) {
|
||||
_results.push(prop);
|
||||
@@ -823,7 +827,7 @@
|
||||
lastNoncom = last(nonComments);
|
||||
props = function() {
|
||||
_results2 = [];
|
||||
for (i = 0, _len3 = props.length; i < _len3; i++) {
|
||||
for (i = 0, _len2 = props.length; i < _len2; i++) {
|
||||
prop = props[i];
|
||||
join = i === props.length - 1 ? '' : prop === lastNoncom || prop instanceof Comment ? '\n' : ',\n';
|
||||
indent = prop instanceof Comment ? '' : idt;
|
||||
@@ -838,45 +842,12 @@
|
||||
}();
|
||||
props = props.join('');
|
||||
obj = "{" + (props && '\n' + props + '\n' + this.tab) + "}";
|
||||
if (rest) {
|
||||
return this.compileDynamic(o, obj, rest);
|
||||
}
|
||||
if (this.front) {
|
||||
return "(" + obj + ")";
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
};
|
||||
Obj.prototype.compileDynamic = function(o, code, props) {
|
||||
var acc, i, key, oref, prop, ref, val, _len, _ref;
|
||||
code = "" + (oref = o.scope.freeVariable('obj')) + " = " + code + ", ";
|
||||
for (i = 0, _len = props.length; i < _len; i++) {
|
||||
prop = props[i];
|
||||
if (prop instanceof Comment) {
|
||||
code += prop.compile(o, LEVEL_LIST) + ' ';
|
||||
continue;
|
||||
}
|
||||
if (prop instanceof Assign) {
|
||||
acc = prop.variable.base;
|
||||
key = acc.compile(o, LEVEL_PAREN);
|
||||
val = prop.value.compile(o, LEVEL_LIST);
|
||||
} else {
|
||||
acc = prop.base;
|
||||
_ref = acc.cache(o, LEVEL_LIST, ref), key = _ref[0], val = _ref[1];
|
||||
if (key !== val) {
|
||||
ref = val;
|
||||
}
|
||||
}
|
||||
key = acc instanceof Literal && IDENTIFIER.test(key) ? '.' + key : '[' + key + ']';
|
||||
code += "" + oref + key + " = " + val + ", ";
|
||||
}
|
||||
code += oref;
|
||||
if (o.level <= LEVEL_PAREN) {
|
||||
return code;
|
||||
} else {
|
||||
return "(" + code + ")";
|
||||
}
|
||||
};
|
||||
Obj.prototype.assigns = function(name) {
|
||||
var prop, _i, _len, _ref;
|
||||
_ref = this.properties;
|
||||
@@ -891,10 +862,10 @@
|
||||
return Obj;
|
||||
}();
|
||||
exports.Arr = Arr = function() {
|
||||
__extends(Arr, Base);
|
||||
function Arr(objs) {
|
||||
this.objects = objs || [];
|
||||
}
|
||||
__extends(Arr, Base);
|
||||
Arr.prototype.children = ['objects'];
|
||||
Arr.prototype.compileNode = function(o) {
|
||||
var code, obj, _i, _len, _ref, _results;
|
||||
@@ -934,13 +905,13 @@
|
||||
return Arr;
|
||||
}();
|
||||
exports.Class = Class = function() {
|
||||
__extends(Class, Base);
|
||||
function Class(variable, parent, body) {
|
||||
this.variable = variable;
|
||||
this.parent = parent;
|
||||
this.body = body != null ? body : new Expressions;
|
||||
this.boundFuncs = [];
|
||||
}
|
||||
__extends(Class, Base);
|
||||
Class.prototype.children = ['variable', 'parent', 'body'];
|
||||
Class.prototype.determineName = function() {
|
||||
var decl, tail;
|
||||
@@ -992,11 +963,10 @@
|
||||
throw new Error('cannot define a constructor as a bound function');
|
||||
}
|
||||
if (func instanceof Code) {
|
||||
this.ctor = func;
|
||||
assign = this.ctor = func;
|
||||
} else {
|
||||
this.ctor = new Assign(new Value(new Literal(name)), func);
|
||||
assign = this.ctor = new Assign(new Value(new Literal(name)), func);
|
||||
}
|
||||
assign = null;
|
||||
} else {
|
||||
if (!assign.variable["this"]) {
|
||||
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')]);
|
||||
@@ -1014,15 +984,18 @@
|
||||
Class.prototype.walkBody = function(name) {
|
||||
return this.traverseChildren(false, __bind(function(child) {
|
||||
var exps, i, node, _len, _ref;
|
||||
if (child instanceof Class) {
|
||||
return false;
|
||||
}
|
||||
if (child instanceof Expressions) {
|
||||
_ref = exps = child.expressions;
|
||||
for (i = 0, _len = _ref.length; i < _len; i++) {
|
||||
node = _ref[i];
|
||||
if (node instanceof Value && node.isObject(true)) {
|
||||
exps[i] = compact(this.addProperties(node, name));
|
||||
exps[i] = this.addProperties(node, name);
|
||||
}
|
||||
}
|
||||
return child.expressions = exps = compact(flatten(exps));
|
||||
return child.expressions = exps = flatten(exps);
|
||||
}
|
||||
}, this));
|
||||
};
|
||||
@@ -1032,29 +1005,26 @@
|
||||
if (this.parent) {
|
||||
this.ctor.body.push(new Call('super', [new Splat(new Literal('arguments'))]));
|
||||
}
|
||||
this.body.expressions.unshift(this.ctor);
|
||||
}
|
||||
this.ctor.ctor = this.ctor.name = name;
|
||||
this.ctor.klass = null;
|
||||
return this.ctor.noReturn = true;
|
||||
};
|
||||
Class.prototype.compileNode = function(o) {
|
||||
var decl, klass, lname, name, _ref;
|
||||
var decl, klass, lname, name;
|
||||
decl = this.determineName();
|
||||
name = decl || this.name || '_Class';
|
||||
lname = new Literal(name);
|
||||
this.setContext(name);
|
||||
this.walkBody(name);
|
||||
this.ensureConstructor(name);
|
||||
if (this.parent) {
|
||||
this.body.expressions.unshift(new Extends(lname, this.parent));
|
||||
}
|
||||
this.body.expressions.unshift(this.ctor);
|
||||
this.ensureConstructor(name);
|
||||
this.body.expressions.push(lname);
|
||||
this.addBoundFunctions(o);
|
||||
klass = new Parens(new Call(new Code([], this.body)), true);
|
||||
if (decl && ((_ref = this.variable) != null ? _ref.isComplex() : void 0)) {
|
||||
klass = new Assign(new Value(lname), klass);
|
||||
}
|
||||
if (this.variable) {
|
||||
klass = new Assign(this.variable, klass);
|
||||
}
|
||||
@@ -1063,12 +1033,12 @@
|
||||
return Class;
|
||||
}();
|
||||
exports.Assign = Assign = function() {
|
||||
__extends(Assign, Base);
|
||||
function Assign(variable, value, context) {
|
||||
this.variable = variable;
|
||||
this.value = value;
|
||||
this.context = context;
|
||||
}
|
||||
__extends(Assign, Base);
|
||||
Assign.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.|\S+?)?\b([$A-Za-z_][$\w]*)$/;
|
||||
Assign.prototype.children = ['variable', 'value'];
|
||||
Assign.prototype.assigns = function(name) {
|
||||
@@ -1200,19 +1170,28 @@
|
||||
return new Op(this.context.slice(0, -1), left, new Assign(rite, this.value, '=')).compile(o);
|
||||
};
|
||||
Assign.prototype.compileSplice = function(o) {
|
||||
var from, name, plus, range, ref, to, val;
|
||||
var from, name, plus, range, to, val;
|
||||
range = this.variable.properties.pop().range;
|
||||
name = this.variable.compile(o);
|
||||
plus = range.exclusive ? '' : ' + 1';
|
||||
from = range.from ? range.from.compile(o) : '0';
|
||||
to = range.to ? range.to.compile(o) + ' - ' + from + plus : "" + name + ".length";
|
||||
ref = o.scope.freeVariable('ref');
|
||||
if (!range.to) {
|
||||
to = "" + name + ".length";
|
||||
}
|
||||
if (!to) {
|
||||
if (range.from && range.from.isSimpleNumber() && range.to.isSimpleNumber()) {
|
||||
to = (+range.to.compile(o)) - +from + +plus;
|
||||
} else {
|
||||
to = range.to.compile(o) + ' - ' + from + plus;
|
||||
}
|
||||
}
|
||||
val = this.value.compile(o);
|
||||
return "([].splice.apply(" + name + ", [" + from + ", " + to + "].concat(" + ref + " = " + val + ")), " + ref + ")";
|
||||
return "[].splice.apply(" + name + ", [" + from + ", " + to + "].concat(" + val + "))";
|
||||
};
|
||||
return Assign;
|
||||
}();
|
||||
exports.Code = Code = function() {
|
||||
__extends(Code, Base);
|
||||
function Code(params, body, tag) {
|
||||
this.params = params || [];
|
||||
this.body = body || new Expressions;
|
||||
@@ -1221,15 +1200,17 @@
|
||||
this.context = 'this';
|
||||
}
|
||||
}
|
||||
__extends(Code, Base);
|
||||
Code.prototype.children = ['params', 'body'];
|
||||
Code.prototype.isStatement = function() {
|
||||
return !!this.ctor;
|
||||
};
|
||||
Code.prototype.compileNode = function(o) {
|
||||
var code, exprs, i, idt, lit, p, param, ref, scope, sharedScope, splats, v, val, vars, wasEmpty, _i, _j, _k, _len, _len2, _len3, _len4, _ref, _ref2, _ref3, _results, _this;
|
||||
var code, exprs, i, idt, lit, p, param, ref, sharedScope, splats, v, val, vars, wasEmpty, _i, _j, _k, _len, _len2, _len3, _len4, _ref, _ref2, _ref3, _ref4, _results;
|
||||
sharedScope = del(o, 'sharedScope');
|
||||
o.scope = scope = sharedScope || new Scope(o.scope, this.body, this);
|
||||
o.scope = sharedScope || new Scope(o.scope, this.body, this);
|
||||
if (sharedScope) {
|
||||
o.scope.shared = true;
|
||||
}
|
||||
o.indent += TAB;
|
||||
delete o.bare;
|
||||
delete o.globals;
|
||||
@@ -1272,18 +1253,17 @@
|
||||
vars.push(ref);
|
||||
}
|
||||
}
|
||||
scope.startLevel();
|
||||
wasEmpty = this.body.isEmpty();
|
||||
if (splats) {
|
||||
exprs.unshift(splats);
|
||||
}
|
||||
if (exprs.length) {
|
||||
(_this = this.body.expressions).unshift.apply(_this, exprs);
|
||||
(_ref4 = this.body.expressions).unshift.apply(_ref4, exprs);
|
||||
}
|
||||
if (!splats) {
|
||||
for (i = 0, _len4 = vars.length; i < _len4; i++) {
|
||||
v = vars[i];
|
||||
scope.parameter(vars[i] = v.compile(o));
|
||||
o.scope.parameter(vars[i] = v.compile(o));
|
||||
}
|
||||
}
|
||||
if (!(wasEmpty || this.noReturn)) {
|
||||
@@ -1319,12 +1299,12 @@
|
||||
return Code;
|
||||
}();
|
||||
exports.Param = Param = function() {
|
||||
__extends(Param, Base);
|
||||
function Param(name, value, splat) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.splat = splat;
|
||||
}
|
||||
__extends(Param, Base);
|
||||
Param.prototype.children = ['name', 'value'];
|
||||
Param.prototype.compile = function(o) {
|
||||
return this.name.compile(o, LEVEL_LIST);
|
||||
@@ -1355,12 +1335,12 @@
|
||||
return Param;
|
||||
}();
|
||||
exports.Splat = Splat = function() {
|
||||
function Splat(name) {
|
||||
this.name = name.compile ? name : new Literal(name);
|
||||
}
|
||||
__extends(Splat, Base);
|
||||
Splat.prototype.children = ['name'];
|
||||
Splat.prototype.isAssignable = YES;
|
||||
function Splat(name) {
|
||||
this.name = name.compile ? name : new Literal(name);
|
||||
}
|
||||
Splat.prototype.assigns = function(name) {
|
||||
return this.name.assigns(name);
|
||||
};
|
||||
@@ -1410,11 +1390,11 @@
|
||||
return Splat;
|
||||
}();
|
||||
exports.While = While = function() {
|
||||
__extends(While, Base);
|
||||
function While(condition, options) {
|
||||
this.condition = (options != null ? options.invert : void 0) ? condition.invert() : condition;
|
||||
this.guard = options != null ? options.guard : void 0;
|
||||
}
|
||||
__extends(While, Base);
|
||||
While.prototype.children = ['condition', 'guard', 'body'];
|
||||
While.prototype.isStatement = YES;
|
||||
While.prototype.makeReturn = function() {
|
||||
@@ -1473,6 +1453,7 @@
|
||||
}();
|
||||
exports.Op = Op = function() {
|
||||
var CONVERSIONS, INVERSIONS;
|
||||
__extends(Op, Base);
|
||||
function Op(op, first, second, flip) {
|
||||
if (op === 'in') {
|
||||
return new In(first, second);
|
||||
@@ -1491,7 +1472,6 @@
|
||||
this.flip = !!flip;
|
||||
return this;
|
||||
}
|
||||
__extends(Op, Base);
|
||||
CONVERSIONS = {
|
||||
'==': '===',
|
||||
'!=': '!==',
|
||||
@@ -1499,11 +1479,7 @@
|
||||
};
|
||||
INVERSIONS = {
|
||||
'!==': '===',
|
||||
'===': '!==',
|
||||
'>': '<=',
|
||||
'<=': '>',
|
||||
'<': '>=',
|
||||
'>=': '<'
|
||||
'===': '!=='
|
||||
};
|
||||
Op.prototype.children = ['first', 'second'];
|
||||
Op.prototype.isUnary = function() {
|
||||
@@ -1514,9 +1490,29 @@
|
||||
return (_ref = this.operator) === '<' || _ref === '>' || _ref === '>=' || _ref === '<=' || _ref === '===' || _ref === '!==';
|
||||
};
|
||||
Op.prototype.invert = function() {
|
||||
var fst, op, _ref;
|
||||
if (op = INVERSIONS[this.operator]) {
|
||||
var allInvertable, curr, fst, op, _ref;
|
||||
if (this.isChainable() && this.first.isChainable()) {
|
||||
allInvertable = true;
|
||||
curr = this;
|
||||
while (curr && curr.operator) {
|
||||
allInvertable && (allInvertable = curr.operator in INVERSIONS);
|
||||
curr = curr.first;
|
||||
}
|
||||
if (!allInvertable) {
|
||||
return new Parens(this).invert();
|
||||
}
|
||||
curr = this;
|
||||
while (curr && curr.operator) {
|
||||
curr.invert = !curr.invert;
|
||||
curr.operator = INVERSIONS[curr.operator];
|
||||
curr = curr.first;
|
||||
}
|
||||
return this;
|
||||
} else if (op = INVERSIONS[this.operator]) {
|
||||
this.operator = op;
|
||||
if (this.first.unwrap() instanceof Op) {
|
||||
this.first.invert();
|
||||
}
|
||||
return this;
|
||||
} else if (this.second) {
|
||||
return new Parens(this).invert();
|
||||
@@ -1553,15 +1549,11 @@
|
||||
var code, fst, shared, _ref;
|
||||
_ref = this.first.second.cache(o), this.first.second = _ref[0], shared = _ref[1];
|
||||
fst = this.first.compile(o, LEVEL_OP);
|
||||
if (fst.charAt(0) === '(') {
|
||||
if (this.first.unwrap() instanceof Op && this.first.isChainable() && fst.charAt(0) === '(') {
|
||||
fst = fst.slice(1, -1);
|
||||
}
|
||||
code = "" + fst + " && " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP));
|
||||
if (o.level < LEVEL_OP) {
|
||||
return code;
|
||||
} else {
|
||||
return "(" + code + ")";
|
||||
}
|
||||
code = "" + fst + " " + (this.invert ? '&&' : '||') + " " + (shared.compile(o)) + " " + this.operator + " " + (this.second.compile(o, LEVEL_OP));
|
||||
return "(" + code + ")";
|
||||
};
|
||||
Op.prototype.compileExistence = function(o) {
|
||||
var fst, ref;
|
||||
@@ -1592,11 +1584,11 @@
|
||||
return Op;
|
||||
}();
|
||||
exports.In = In = function() {
|
||||
__extends(In, Base);
|
||||
function In(object, array) {
|
||||
this.object = object;
|
||||
this.array = array;
|
||||
}
|
||||
__extends(In, Base);
|
||||
In.prototype.children = ['object', 'array'];
|
||||
In.prototype.invert = NEGATE;
|
||||
In.prototype.compileNode = function(o) {
|
||||
@@ -1646,13 +1638,13 @@
|
||||
return In;
|
||||
}();
|
||||
exports.Try = Try = function() {
|
||||
__extends(Try, Base);
|
||||
function Try(attempt, error, recovery, ensure) {
|
||||
this.attempt = attempt;
|
||||
this.error = error;
|
||||
this.recovery = recovery;
|
||||
this.ensure = ensure;
|
||||
}
|
||||
__extends(Try, Base);
|
||||
Try.prototype.children = ['attempt', 'recovery', 'ensure'];
|
||||
Try.prototype.isStatement = YES;
|
||||
Try.prototype.makeReturn = function() {
|
||||
@@ -1674,10 +1666,10 @@
|
||||
return Try;
|
||||
}();
|
||||
exports.Throw = Throw = function() {
|
||||
__extends(Throw, Base);
|
||||
function Throw(expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
__extends(Throw, Base);
|
||||
Throw.prototype.children = ['expression'];
|
||||
Throw.prototype.isStatement = YES;
|
||||
Throw.prototype.makeReturn = THIS;
|
||||
@@ -1687,10 +1679,10 @@
|
||||
return Throw;
|
||||
}();
|
||||
exports.Existence = Existence = function() {
|
||||
__extends(Existence, Base);
|
||||
function Existence(expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
__extends(Existence, Base);
|
||||
Existence.prototype.children = ['expression'];
|
||||
Existence.prototype.invert = NEGATE;
|
||||
Existence.prototype.compileNode = function(o) {
|
||||
@@ -1706,10 +1698,10 @@
|
||||
return Existence;
|
||||
}();
|
||||
exports.Parens = Parens = function() {
|
||||
__extends(Parens, Base);
|
||||
function Parens(body) {
|
||||
this.body = body;
|
||||
}
|
||||
__extends(Parens, Base);
|
||||
Parens.prototype.children = ['body'];
|
||||
Parens.prototype.unwrap = function() {
|
||||
return this.body;
|
||||
@@ -1738,13 +1730,14 @@
|
||||
return Parens;
|
||||
}();
|
||||
exports.For = For = function() {
|
||||
__extends(For, Base);
|
||||
function For(body, source, name, index) {
|
||||
var _ref;
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.source = source.source, this.guard = source.guard, this.step = source.step;
|
||||
this.body = Expressions.wrap([body]);
|
||||
this.raw = !!source.raw;
|
||||
this.own = !!source.own;
|
||||
this.object = !!source.object;
|
||||
if (this.object) {
|
||||
_ref = [this.index, this.name], this.name = _ref[0], this.index = _ref[1];
|
||||
@@ -1754,12 +1747,14 @@
|
||||
}
|
||||
this.range = this.source instanceof Value && this.source.base instanceof Range && !this.source.properties.length;
|
||||
this.pattern = this.name instanceof Value;
|
||||
if (this.range && this.index) {
|
||||
throw SyntaxError('indexes do not apply to range loops');
|
||||
}
|
||||
if (this.range && this.pattern) {
|
||||
throw SyntaxError('cannot pattern match a range loop');
|
||||
throw SyntaxError('cannot pattern match over range loops');
|
||||
}
|
||||
this.returns = false;
|
||||
}
|
||||
__extends(For, Base);
|
||||
For.prototype.children = ['body', 'source', 'guard', 'step'];
|
||||
For.prototype.isStatement = YES;
|
||||
For.prototype.makeReturn = function() {
|
||||
@@ -1778,17 +1773,15 @@
|
||||
scope = o.scope;
|
||||
name = this.name && this.name.compile(o, LEVEL_LIST);
|
||||
index = this.index && this.index.compile(o, LEVEL_LIST);
|
||||
if (!hasCode) {
|
||||
if (name && !this.pattern) {
|
||||
scope.find(name, {
|
||||
immediate: true
|
||||
});
|
||||
}
|
||||
if (index) {
|
||||
scope.find(index, {
|
||||
immediate: true
|
||||
});
|
||||
}
|
||||
if (name && !this.pattern) {
|
||||
scope.find(name, {
|
||||
immediate: true
|
||||
});
|
||||
}
|
||||
if (index) {
|
||||
scope.find(index, {
|
||||
immediate: true
|
||||
});
|
||||
}
|
||||
if (this.returns && !hasPure) {
|
||||
rvar = scope.freeVariable('results');
|
||||
@@ -1805,7 +1798,7 @@
|
||||
}));
|
||||
} else {
|
||||
svar = this.source.compile(o, LEVEL_TOP);
|
||||
if ((name || !this.raw) && !IDENTIFIER.test(svar)) {
|
||||
if ((name || this.own) && !IDENTIFIER.test(svar)) {
|
||||
defPart = "" + this.tab + (ref = scope.freeVariable('ref')) + " = " + svar + ";\n";
|
||||
svar = ref;
|
||||
}
|
||||
@@ -1832,7 +1825,7 @@
|
||||
}
|
||||
if (this.object) {
|
||||
forPart = "" + ivar + " in " + svar;
|
||||
if (!this.raw) {
|
||||
if (this.own) {
|
||||
guardPart = "\n" + idt1 + "if (!" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")) continue;";
|
||||
}
|
||||
}
|
||||
@@ -1877,6 +1870,7 @@
|
||||
args.unshift(new Literal('this'));
|
||||
}
|
||||
body.expressions[idx] = new Call(base, args);
|
||||
o.sharedScope = o.scope;
|
||||
defs += this.tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n';
|
||||
}
|
||||
return defs;
|
||||
@@ -1884,12 +1878,12 @@
|
||||
return For;
|
||||
}();
|
||||
exports.Switch = Switch = function() {
|
||||
__extends(Switch, Base);
|
||||
function Switch(subject, cases, otherwise) {
|
||||
this.subject = subject;
|
||||
this.cases = cases;
|
||||
this.otherwise = otherwise;
|
||||
}
|
||||
__extends(Switch, Base);
|
||||
Switch.prototype.children = ['subject', 'cases', 'otherwise'];
|
||||
Switch.prototype.isStatement = YES;
|
||||
Switch.prototype.makeReturn = function() {
|
||||
@@ -1945,6 +1939,7 @@
|
||||
return Switch;
|
||||
}();
|
||||
exports.If = If = function() {
|
||||
__extends(If, Base);
|
||||
function If(condition, body, options) {
|
||||
this.body = body;
|
||||
if (options == null) {
|
||||
@@ -1955,7 +1950,6 @@
|
||||
this.isChain = false;
|
||||
this.soak = options.soak;
|
||||
}
|
||||
__extends(If, Base);
|
||||
If.prototype.children = ['condition', 'body', 'elseBody'];
|
||||
If.prototype.bodyNode = function() {
|
||||
var _ref;
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
if (tuple.length < 3) {
|
||||
tuple.unshift(null);
|
||||
}
|
||||
_results.push(buildRule.apply(buildRule, tuple));
|
||||
_results.push(buildRule.apply(null, tuple));
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
|
||||
298
lib/parser.js
298
lib/parser.js
File diff suppressed because one or more lines are too long
@@ -1,9 +1,12 @@
|
||||
(function() {
|
||||
var CoffeeScript, helpers, readline, repl, run, stdio;
|
||||
var CoffeeScript, error, helpers, readline, repl, run, stdio;
|
||||
CoffeeScript = require('./coffee-script');
|
||||
helpers = require('./helpers');
|
||||
readline = require('readline');
|
||||
stdio = process.openStdin();
|
||||
error = function(err) {
|
||||
return stdio.write((err.stack || err.toString()) + '\n\n');
|
||||
};
|
||||
helpers.extend(global, {
|
||||
quit: function() {
|
||||
return process.exit(0);
|
||||
@@ -21,10 +24,11 @@
|
||||
console.log(val);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err.stack || err.toString());
|
||||
error(err);
|
||||
}
|
||||
return repl.prompt();
|
||||
};
|
||||
process.on('uncaughtException', error);
|
||||
repl = readline.createInterface(stdio);
|
||||
repl.setPrompt('coffee> ');
|
||||
stdio.on('data', function(buffer) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
(function() {
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
|
||||
var __indexOf = Array.prototype.indexOf || function(item) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (this[i] === item) return i;
|
||||
}
|
||||
return -1;
|
||||
}, __slice = Array.prototype.slice;
|
||||
exports.Rewriter = Rewriter = function() {
|
||||
exports.Rewriter = function() {
|
||||
function Rewriter() {}
|
||||
Rewriter.prototype.rewrite = function(tokens) {
|
||||
this.tokens = tokens;
|
||||
@@ -113,18 +113,18 @@
|
||||
startIndent = 0;
|
||||
condition = function(token, i) {
|
||||
var one, tag, three, two, _ref, _ref2;
|
||||
_ref = this.tokens, one = _ref[i + 1], two = _ref[i + 2], three = _ref[i + 3];
|
||||
_ref = this.tokens.slice(i + 1, i + 3 + 1), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
|
||||
return false;
|
||||
}
|
||||
tag = token[0];
|
||||
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT' && _ref2 !== '('));
|
||||
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice(i, 0, ['}', '}', token[2]]);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var ago1, ago2, idx, tag, tok, value, _ref, _ref2;
|
||||
var ago, idx, tag, tok, value, _ref, _ref2;
|
||||
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
|
||||
return 1;
|
||||
@@ -133,12 +133,12 @@
|
||||
start = stack.pop();
|
||||
return 1;
|
||||
}
|
||||
if (!(tag === ':' && ((ago2 = this.tag(i - 2)) === ':' || (ago1 = this.tag(i - 1)) === ')' && this.tag(start[1] - 1) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
|
||||
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
|
||||
return 1;
|
||||
}
|
||||
stack.push(['{']);
|
||||
idx = ago1 === ')' ? start[1] : ago2 === '@' ? i - 2 : i - 1;
|
||||
if (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx = ago === '@' ? i - 2 : i - 1;
|
||||
while (this.tag(idx - 2) === 'HERECOMMENT') {
|
||||
idx -= 2;
|
||||
}
|
||||
value = new String('{');
|
||||
@@ -159,13 +159,13 @@
|
||||
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var callObject, next, prev, seenSingle, tag, _ref, _ref2;
|
||||
var callObject, current, next, prev, seenSingle, tag, _ref, _ref2, _ref3;
|
||||
tag = token[0];
|
||||
if (tag === 'CLASS' || tag === 'IF' || tag === 'UNLESS') {
|
||||
noCall = true;
|
||||
}
|
||||
prev = tokens[i - 1], next = tokens[i + 1];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref) >= 0);
|
||||
_ref = tokens.slice(i - 1, i + 1 + 1), prev = _ref[0], current = _ref[1], next = _ref[2];
|
||||
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
|
||||
seenSingle = false;
|
||||
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
noCall = false;
|
||||
@@ -173,7 +173,7 @@
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
|
||||
77
lib/scope.js
77
lib/scope.js
@@ -2,6 +2,7 @@
|
||||
var Scope, extend, last, _ref;
|
||||
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
|
||||
exports.Scope = Scope = function() {
|
||||
Scope.root = null;
|
||||
function Scope(parent, expressions, method) {
|
||||
this.parent = parent;
|
||||
this.expressions = expressions;
|
||||
@@ -13,14 +14,10 @@
|
||||
}
|
||||
];
|
||||
this.positions = {};
|
||||
if (this.parent) {
|
||||
this.garbage = this.parent.garbage;
|
||||
} else {
|
||||
this.garbage = [];
|
||||
if (!this.parent) {
|
||||
Scope.root = this;
|
||||
}
|
||||
}
|
||||
Scope.root = null;
|
||||
Scope.prototype.add = function(name, type) {
|
||||
var pos;
|
||||
if (typeof (pos = this.positions[name]) === 'number') {
|
||||
@@ -32,40 +29,18 @@
|
||||
}) - 1;
|
||||
}
|
||||
};
|
||||
Scope.prototype.startLevel = function() {
|
||||
this.garbage.push([]);
|
||||
return this;
|
||||
};
|
||||
Scope.prototype.endLevel = function() {
|
||||
var name, _i, _len, _ref;
|
||||
_ref = this.garbage.pop();
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
name = _ref[_i];
|
||||
if (this.type(name) === 'var') {
|
||||
this.add(name, 'reuse');
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
Scope.prototype.find = function(name, options) {
|
||||
if (this.check(name, options)) {
|
||||
return true;
|
||||
}
|
||||
this.add(name, 'var');
|
||||
return false;
|
||||
};
|
||||
Scope.prototype.any = function(fn) {
|
||||
var v, _i, _len, _ref;
|
||||
_ref = this.variables;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
v = _ref[_i];
|
||||
if (fn(v)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this.hasDeclarations = true;
|
||||
return false;
|
||||
};
|
||||
Scope.prototype.parameter = function(name) {
|
||||
if (this.shared && this.check(name, true)) {
|
||||
return;
|
||||
}
|
||||
return this.add(name, 'param');
|
||||
};
|
||||
Scope.prototype.check = function(name, immediate) {
|
||||
@@ -95,46 +70,34 @@
|
||||
return null;
|
||||
};
|
||||
Scope.prototype.freeVariable = function(type) {
|
||||
var index, temp, _ref;
|
||||
var index, temp;
|
||||
index = 0;
|
||||
while (this.check((temp = this.temporary(type, index)), true) && this.type(temp) !== 'reuse') {
|
||||
while (this.check((temp = this.temporary(type, index)), true)) {
|
||||
index++;
|
||||
}
|
||||
this.add(temp, 'var');
|
||||
if ((_ref = last(this.garbage)) != null) {
|
||||
_ref.push(temp);
|
||||
}
|
||||
this.hasDeclarations = true;
|
||||
return temp;
|
||||
};
|
||||
Scope.prototype.assign = function(name, value) {
|
||||
return this.add(name, {
|
||||
this.add(name, {
|
||||
value: value,
|
||||
assigned: true
|
||||
});
|
||||
};
|
||||
Scope.prototype.hasDeclarations = function(body) {
|
||||
return body === this.expressions && this.any(function(v) {
|
||||
var _ref;
|
||||
return (_ref = v.type) === 'var' || _ref === 'reuse';
|
||||
});
|
||||
};
|
||||
Scope.prototype.hasAssignments = function(body) {
|
||||
return body === this.expressions && this.any(function(v) {
|
||||
return v.type.assigned;
|
||||
});
|
||||
return this.hasAssignments = true;
|
||||
};
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var tmp, usr, v, _i, _len, _ref, _ref2;
|
||||
usr = [];
|
||||
tmp = [];
|
||||
var realVars, tempVars, v, _i, _len, _ref;
|
||||
realVars = [];
|
||||
tempVars = [];
|
||||
_ref = this.variables;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
v = _ref[_i];
|
||||
if ((_ref2 = v.type) === 'var' || _ref2 === 'reuse') {
|
||||
(v.name.charAt(0) === '_' ? tmp : usr).push(v.name);
|
||||
if (v.type === 'var') {
|
||||
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
|
||||
}
|
||||
}
|
||||
return usr.sort().concat(tmp.sort());
|
||||
return realVars.sort().concat(tempVars.sort());
|
||||
};
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var v, _i, _len, _ref, _results;
|
||||
@@ -148,12 +111,6 @@
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
Scope.prototype.compiledDeclarations = function() {
|
||||
return this.declaredVariables().join(', ');
|
||||
};
|
||||
Scope.prototype.compiledAssignments = function() {
|
||||
return this.assignedVariables().join(', ');
|
||||
};
|
||||
return Scope;
|
||||
}();
|
||||
}).call(this);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": ["javascript", "language", "coffeescript", "compiler"],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "0.9.5",
|
||||
"version": "0.9.6",
|
||||
"licenses": [{
|
||||
"type": "MIT",
|
||||
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
|
||||
|
||||
@@ -56,7 +56,7 @@ exports.run = ->
|
||||
# Display the list of Cake tasks in a format similar to `rake -T`
|
||||
printTasks = ->
|
||||
console.log ''
|
||||
for all name, task of tasks
|
||||
for name, task of tasks
|
||||
spaces = 20 - name.length
|
||||
spaces = if spaces > 0 then Array(spaces + 1).join(' ') else ''
|
||||
desc = if task.description then "# #{task.description}" else ''
|
||||
|
||||
@@ -20,7 +20,7 @@ else if require.registerExtension
|
||||
require.registerExtension '.coffee', (content) -> compile content
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION = '0.9.5'
|
||||
exports.VERSION = '0.9.6'
|
||||
|
||||
# Expose helpers for testing.
|
||||
exports.helpers = require './helpers'
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
# External dependencies.
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
util = require 'util'
|
||||
helpers = require './helpers'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
@@ -16,6 +17,9 @@ CoffeeScript = require './coffee-script'
|
||||
# Allow CoffeeScript to emit Node.js events.
|
||||
helpers.extend CoffeeScript, new EventEmitter
|
||||
|
||||
printLine = (line) -> process.stdout.write line + '\n'
|
||||
printWarn = (line) -> process.binding('stdio').writeError line + '\n'
|
||||
|
||||
# The help banner that is printed when `coffee` is called without arguments.
|
||||
BANNER = '''
|
||||
Usage: coffee [options] path/to/script.coffee
|
||||
@@ -103,19 +107,19 @@ compileScript = (file, input, base) ->
|
||||
t = task = {file, input, options}
|
||||
CoffeeScript.emit 'compile', task
|
||||
if o.tokens then printTokens CoffeeScript.tokens t.input
|
||||
else if o.nodes then console.log CoffeeScript.nodes(t.input).toString().trim()
|
||||
else if o.nodes then printLine CoffeeScript.nodes(t.input).toString().trim()
|
||||
else if o.run then CoffeeScript.run t.input, t.options
|
||||
else
|
||||
t.output = CoffeeScript.compile t.input, t.options
|
||||
CoffeeScript.emit 'success', task
|
||||
if o.print then console.log t.output.trim()
|
||||
if o.print then printLine t.output.trim()
|
||||
else if o.compile then writeJs t.file, t.output, base
|
||||
else if o.lint then lint t.file, t.output
|
||||
catch err
|
||||
CoffeeScript.emit 'failure', err, task
|
||||
return if CoffeeScript.listeners('failure').length
|
||||
return console.log err.message if o.watch
|
||||
console.error err.stack
|
||||
return printLine err.message if o.watch
|
||||
printWarn err.stack
|
||||
process.exit 1
|
||||
|
||||
# Attach the appropriate listeners to compile scripts incoming over **stdin**,
|
||||
@@ -150,15 +154,15 @@ writeJs = (source, js, base) ->
|
||||
compile = ->
|
||||
js = ' ' if js.length <= 0
|
||||
fs.writeFile jsPath, js, (err) ->
|
||||
if err then console.log err.message
|
||||
else if opts.compile and opts.watch then console.log "Compiled #{source}"
|
||||
if err then printLine err.message
|
||||
else if opts.compile and opts.watch then util.log "compiled #{source}"
|
||||
path.exists dir, (exists) ->
|
||||
if exists then compile() else exec "mkdir -p #{dir}", compile
|
||||
|
||||
# Pipe compiled JS through JSLint (requires a working `jsl` command), printing
|
||||
# any errors or warnings that arise.
|
||||
lint = (file, js) ->
|
||||
printIt = (buffer) -> console.log file + ':\t' + buffer.toString().trim()
|
||||
printIt = (buffer) -> printLine file + ':\t' + buffer.toString().trim()
|
||||
conf = __dirname + '/../extras/jsl.conf'
|
||||
jsl = spawn 'jsl', ['-nologo', '-stdin', '-conf', conf]
|
||||
jsl.stdout.on 'data', printIt
|
||||
@@ -171,7 +175,7 @@ printTokens = (tokens) ->
|
||||
strings = for token in tokens
|
||||
[tag, value] = [token[0], token[1].toString().replace(/\n/, '\\n')]
|
||||
"[#{tag} #{value}]"
|
||||
console.log strings.join(' ')
|
||||
printLine strings.join(' ')
|
||||
|
||||
# Use the [OptionParser module](optparse.html) to extract all options from
|
||||
# `process.argv` that are specified in `SWITCHES`.
|
||||
@@ -183,7 +187,7 @@ parseOptions = ->
|
||||
o.print = !! (o.print or (o.eval or o.stdio and o.compile))
|
||||
sources = o.arguments
|
||||
if opts['no-wrap']
|
||||
console.warn '--no-wrap is deprecated; please use --bare instead.'
|
||||
printWarn '--no-wrap is deprecated; please use --bare instead.'
|
||||
|
||||
# The compile-time options to pass to the CoffeeScript compiler.
|
||||
compileOptions = (fileName) -> {fileName, bare: opts.bare or opts['no-wrap']}
|
||||
@@ -191,10 +195,10 @@ compileOptions = (fileName) -> {fileName, bare: opts.bare or opts['no-wrap']}
|
||||
# Print the `--help` usage message and exit. Deprecated switches are not
|
||||
# shown.
|
||||
usage = ->
|
||||
console.log (new optparse.OptionParser SWITCHES, BANNER).help()
|
||||
printLine (new optparse.OptionParser SWITCHES, BANNER).help()
|
||||
process.exit 0
|
||||
|
||||
# Print the `--version` message and exit.
|
||||
version = ->
|
||||
console.log "CoffeeScript version #{CoffeeScript.VERSION}"
|
||||
printLine "CoffeeScript version #{CoffeeScript.VERSION}"
|
||||
process.exit 0
|
||||
|
||||
@@ -149,7 +149,6 @@ grammar =
|
||||
ObjAssignable: [
|
||||
o 'Identifier'
|
||||
o 'AlphaNumeric'
|
||||
o 'Parenthetical'
|
||||
o 'ThisProperty'
|
||||
]
|
||||
|
||||
@@ -425,12 +424,12 @@ grammar =
|
||||
|
||||
ForBody: [
|
||||
o 'FOR Range', -> source: new Value($2), vars: []
|
||||
o 'ForStart ForSource', -> $2.raw = $1.raw; $2.vars = $1; $2
|
||||
o 'ForStart ForSource', -> $2.own = $1.own; $2.vars = $1; $2
|
||||
]
|
||||
|
||||
ForStart: [
|
||||
o 'FOR ForVariables', -> $2
|
||||
o 'FOR ALL ForVariables', -> $3.raw = yes; $3
|
||||
o 'FOR OWN ForVariables', -> $3.own = yes; $3
|
||||
]
|
||||
|
||||
# An array of all accepted values for a variable inside the loop.
|
||||
@@ -578,7 +577,7 @@ operators = [
|
||||
# terminals (every symbol which does not appear as the name of a rule above)
|
||||
# as "tokens".
|
||||
tokens = []
|
||||
for all name, alternatives of grammar
|
||||
for name, alternatives of grammar
|
||||
grammar[name] = for alt in alternatives
|
||||
for token in alt[0].split ' '
|
||||
tokens.push token unless grammar[token]
|
||||
|
||||
@@ -29,7 +29,7 @@ exports.merge = (options, overrides) ->
|
||||
|
||||
# Extend a source object with the properties of another object (shallow copy).
|
||||
extend = exports.extend = (object, properties) ->
|
||||
for all key, val of properties
|
||||
for key, val of properties
|
||||
object[key] = val
|
||||
object
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ exports.Lexer = class Lexer
|
||||
return 0 unless match = IDENTIFIER.exec @chunk
|
||||
[input, id, colon] = match
|
||||
|
||||
if id is 'all' and @tag() is 'FOR'
|
||||
@token 'ALL', id
|
||||
if id is 'own' and @tag() is 'FOR'
|
||||
@token 'OWN', id
|
||||
return id.length
|
||||
forcedIdentifier = colon or
|
||||
(prev = last @tokens) and not prev.spaced and prev[0] in ['.', '?.', '@', '::']
|
||||
@@ -499,7 +499,7 @@ JS_KEYWORDS = [
|
||||
|
||||
# CoffeeScript-only keywords.
|
||||
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when']
|
||||
COFFEE_KEYWORDS.push op for all op of COFFEE_ALIASES =
|
||||
COFFEE_KEYWORDS.push op for op of COFFEE_ALIASES =
|
||||
and : '&&'
|
||||
or : '||'
|
||||
is : '=='
|
||||
|
||||
167
src/nodes.coffee
167
src/nodes.coffee
@@ -244,10 +244,11 @@ exports.Expressions = class Expressions extends Base
|
||||
@expressions = rest
|
||||
post = @compileNode o
|
||||
{scope} = o
|
||||
if not o.globals and o.scope.hasDeclarations this
|
||||
code += "#{@tab}var #{ scope.compiledDeclarations() };\n"
|
||||
if scope.hasAssignments this
|
||||
code += "#{@tab}var #{ multident scope.compiledAssignments(), @tab };\n"
|
||||
if scope.expressions is this
|
||||
if not o.globals and o.scope.hasDeclarations
|
||||
code += "#{@tab}var #{ scope.declaredVariables().join(', ') };\n"
|
||||
if scope.hasAssignments
|
||||
code += "#{@tab}var #{ multident scope.assignedVariables().join(', '), @tab };\n"
|
||||
code + post
|
||||
|
||||
# Wrap up the given nodes as an **Expressions**, unless it already happens
|
||||
@@ -433,7 +434,11 @@ exports.Call = class Call extends Base
|
||||
|
||||
# Tag this invocation as creating a new instance.
|
||||
newInstance: ->
|
||||
@isNew = true
|
||||
base = @variable.base or @variable
|
||||
if base instanceof Call
|
||||
base.newInstance()
|
||||
else
|
||||
@isNew = true
|
||||
this
|
||||
|
||||
# Grab the reference to the superclass's implementation of the current
|
||||
@@ -487,7 +492,7 @@ exports.Call = class Call extends Base
|
||||
return @compileSplat o, code
|
||||
args = (arg.compile o, LEVEL_LIST for arg in @args).join ', '
|
||||
if @isSuper
|
||||
@compileSuper args, o
|
||||
@superReference(o) + ".call(this#{ args and ', ' + args })"
|
||||
else
|
||||
(if @isNew then 'new ' else '') + @variable.compile(o, LEVEL_ACCESS) + "(#{args})"
|
||||
|
||||
@@ -502,23 +507,27 @@ exports.Call = class Call extends Base
|
||||
# inner constructor in order to be able to pass the varargs.
|
||||
compileSplat: (o, splatArgs) ->
|
||||
return "#{ @superReference o }.apply(this, #{splatArgs})" if @isSuper
|
||||
unless @isNew
|
||||
base = new Value @variable
|
||||
if (name = base.properties.pop()) and base.isComplex()
|
||||
ref = o.scope.freeVariable 'this'
|
||||
fun = "(#{ref} = #{ base.compile o, LEVEL_LIST })#{ name.compile o }"
|
||||
if @isNew
|
||||
idt = @tab + TAB
|
||||
return """
|
||||
(function(func, args, ctor) {
|
||||
#{idt}ctor.prototype = func.prototype;
|
||||
#{idt}var child = new ctor, result = func.apply(child, args);
|
||||
#{idt}return typeof result === "object" ? result : child;
|
||||
#{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})
|
||||
"""
|
||||
base = new Value @variable
|
||||
if (name = base.properties.pop()) and base.isComplex()
|
||||
ref = o.scope.freeVariable 'ref'
|
||||
fun = "(#{ref} = #{ base.compile o, LEVEL_LIST })#{ name.compile o }"
|
||||
else
|
||||
fun = base.compile o, LEVEL_ACCESS
|
||||
if name
|
||||
ref = fun
|
||||
fun += name.compile o
|
||||
else
|
||||
fun = ref = base.compile o, LEVEL_ACCESS
|
||||
fun += name.compile o if name
|
||||
return "#{fun}.apply(#{ref}, #{splatArgs})"
|
||||
idt = @tab + TAB
|
||||
"""
|
||||
(function(func, args, ctor) {
|
||||
#{idt}ctor.prototype = func.prototype;
|
||||
#{idt}var child = new ctor, result = func.apply(child, args);
|
||||
#{idt}return typeof result === "object" ? result : child;
|
||||
#{@tab}})(#{ @variable.compile o, LEVEL_LIST }, #{splatArgs}, function() {})
|
||||
"""
|
||||
ref = 'null'
|
||||
"#{fun}.apply(#{ref}, #{splatArgs})"
|
||||
|
||||
#### Extends
|
||||
|
||||
@@ -667,10 +676,6 @@ exports.Obj = class Obj extends Base
|
||||
compileNode: (o) ->
|
||||
props = @properties
|
||||
return (if @front then '({})' else '{}') unless props.length
|
||||
for prop, i in props
|
||||
if prop instanceof Splat or (prop.variable or prop).base instanceof Parens
|
||||
rest = props.splice i, 1/0
|
||||
break
|
||||
idt = o.indent += TAB
|
||||
nonComments = (prop for prop in @properties when prop not instanceof Comment)
|
||||
lastNoncom = last nonComments
|
||||
@@ -689,31 +694,8 @@ exports.Obj = class Obj extends Base
|
||||
indent + prop.compile(o, LEVEL_TOP) + join
|
||||
props = props.join ''
|
||||
obj = "{#{ props and '\n' + props + '\n' + @tab }}"
|
||||
return @compileDynamic o, obj, rest if rest
|
||||
if @front then "(#{obj})" else obj
|
||||
|
||||
compileDynamic: (o, code, props) ->
|
||||
code = "#{ oref = o.scope.freeVariable 'obj' } = #{code}, "
|
||||
for prop, i in props
|
||||
if prop instanceof Comment
|
||||
code += prop.compile(o, LEVEL_LIST) + ' '
|
||||
continue
|
||||
if prop instanceof Assign
|
||||
acc = prop.variable.base
|
||||
key = acc.compile o, LEVEL_PAREN
|
||||
val = prop.value.compile o, LEVEL_LIST
|
||||
else
|
||||
acc = prop.base
|
||||
[key, val] = acc.cache o, LEVEL_LIST, ref
|
||||
ref = val if key isnt val
|
||||
key = if acc instanceof Literal and IDENTIFIER.test key
|
||||
'.' + key
|
||||
else
|
||||
'[' + key + ']'
|
||||
code += "#{oref}#{key} = #{val}, "
|
||||
code += oref
|
||||
if o.level <= LEVEL_PAREN then code else "(#{code})"
|
||||
|
||||
assigns: (name) ->
|
||||
for prop in @properties when prop.assigns name then return yes
|
||||
no
|
||||
@@ -794,10 +776,9 @@ exports.Class = class Class extends Base
|
||||
if func.bound
|
||||
throw new Error 'cannot define a constructor as a bound function'
|
||||
if func instanceof Code
|
||||
@ctor = func
|
||||
assign = @ctor = func
|
||||
else
|
||||
@ctor = new Assign(new Value(new Literal name), func)
|
||||
assign = null
|
||||
assign = @ctor = new Assign(new Value(new Literal name), func)
|
||||
else
|
||||
unless assign.variable.this
|
||||
assign.variable = new Value(new Literal(name), [new Access(base, 'proto')])
|
||||
@@ -809,11 +790,12 @@ exports.Class = class Class extends Base
|
||||
# Walk the body of the class, looking for prototype properties to be converted.
|
||||
walkBody: (name) ->
|
||||
@traverseChildren false, (child) =>
|
||||
return false if child instanceof Class
|
||||
if child instanceof Expressions
|
||||
for node, i in exps = child.expressions
|
||||
if node instanceof Value and node.isObject(true)
|
||||
exps[i] = compact @addProperties node, name
|
||||
child.expressions = exps = compact flatten exps
|
||||
exps[i] = @addProperties node, name
|
||||
child.expressions = exps = flatten exps
|
||||
|
||||
# Make sure that a constructor is defined for the class, and properly
|
||||
# configured.
|
||||
@@ -821,6 +803,7 @@ exports.Class = class Class extends Base
|
||||
if not @ctor
|
||||
@ctor = new Code
|
||||
@ctor.body.push new Call 'super', [new Splat new Literal 'arguments'] if @parent
|
||||
@body.expressions.unshift @ctor
|
||||
@ctor.ctor = @ctor.name = name
|
||||
@ctor.klass = null
|
||||
@ctor.noReturn = yes
|
||||
@@ -835,14 +818,12 @@ exports.Class = class Class extends Base
|
||||
|
||||
@setContext name
|
||||
@walkBody name
|
||||
@ensureConstructor name
|
||||
@body.expressions.unshift new Extends lname, @parent if @parent
|
||||
@body.expressions.unshift @ctor
|
||||
@ensureConstructor name
|
||||
@body.expressions.push lname
|
||||
@addBoundFunctions o
|
||||
|
||||
klass = new Parens new Call(new Code [], @body), true
|
||||
klass = new Assign new Value(lname), klass if decl and @variable?.isComplex()
|
||||
klass = new Assign @variable, klass if @variable
|
||||
klass.compile o
|
||||
|
||||
@@ -967,13 +948,17 @@ exports.Assign = class Assign extends Base
|
||||
# `Array#splice` method.
|
||||
compileSplice: (o) ->
|
||||
{range} = @variable.properties.pop()
|
||||
name = @variable.compile o
|
||||
plus = if range.exclusive then '' else ' + 1'
|
||||
from = if range.from then range.from.compile(o) else '0'
|
||||
to = if range.to then range.to.compile(o) + ' - ' + from + plus else "#{name}.length"
|
||||
ref = o.scope.freeVariable 'ref'
|
||||
val = @value.compile(o)
|
||||
"([].splice.apply(#{name}, [#{from}, #{to}].concat(#{ref} = #{val})), #{ref})"
|
||||
name = @variable.compile o
|
||||
plus = if range.exclusive then '' else ' + 1'
|
||||
from = if range.from then range.from.compile(o) else '0'
|
||||
to = "#{name}.length" unless range.to
|
||||
unless to
|
||||
if range.from and range.from.isSimpleNumber() and range.to.isSimpleNumber()
|
||||
to = (+range.to.compile(o)) - +from + +plus
|
||||
else
|
||||
to = range.to.compile(o) + ' - ' + from + plus
|
||||
val = @value.compile(o)
|
||||
"[].splice.apply(#{name}, [#{from}, #{to}].concat(#{val}))"
|
||||
|
||||
#### Code
|
||||
|
||||
@@ -997,9 +982,10 @@ exports.Code = class Code extends Base
|
||||
# arrow, generates a wrapper that saves the current value of `this` through
|
||||
# a closure.
|
||||
compileNode: (o) ->
|
||||
sharedScope = del o, 'sharedScope'
|
||||
o.scope = scope = sharedScope or new Scope o.scope, @body, this
|
||||
o.indent += TAB
|
||||
sharedScope = del o, 'sharedScope'
|
||||
o.scope = sharedScope or new Scope o.scope, @body, this
|
||||
o.scope.shared = yes if sharedScope
|
||||
o.indent += TAB
|
||||
delete o.bare
|
||||
delete o.globals
|
||||
vars = []
|
||||
@@ -1020,11 +1006,10 @@ exports.Code = class Code extends Base
|
||||
val = new Assign new Value(param.name), param.value, '='
|
||||
exprs.push new If lit, val
|
||||
vars.push ref unless splats
|
||||
scope.startLevel()
|
||||
wasEmpty = @body.isEmpty()
|
||||
exprs.unshift splats if splats
|
||||
@body.expressions.unshift exprs... if exprs.length
|
||||
scope.parameter vars[i] = v.compile o for v, i in vars unless splats
|
||||
o.scope.parameter vars[i] = v.compile o for v, i in vars unless splats
|
||||
@body.makeReturn() unless wasEmpty or @noReturn
|
||||
idt = o.indent
|
||||
code = 'function'
|
||||
@@ -1185,10 +1170,6 @@ exports.Op = class Op extends Base
|
||||
INVERSIONS =
|
||||
'!==': '==='
|
||||
'===': '!=='
|
||||
'>': '<='
|
||||
'<=': '>'
|
||||
'<': '>='
|
||||
'>=': '<'
|
||||
|
||||
children: ['first', 'second']
|
||||
|
||||
@@ -1201,8 +1182,23 @@ exports.Op = class Op extends Base
|
||||
@operator in ['<', '>', '>=', '<=', '===', '!==']
|
||||
|
||||
invert: ->
|
||||
if op = INVERSIONS[@operator]
|
||||
if @isChainable() and @first.isChainable()
|
||||
allInvertable = yes
|
||||
curr = this
|
||||
while curr and curr.operator
|
||||
allInvertable and= (curr.operator of INVERSIONS)
|
||||
curr = curr.first
|
||||
return new Parens(this).invert() unless allInvertable
|
||||
curr = this
|
||||
while curr and curr.operator
|
||||
curr.invert = !curr.invert
|
||||
curr.operator = INVERSIONS[curr.operator]
|
||||
curr = curr.first
|
||||
this
|
||||
else if op = INVERSIONS[@operator]
|
||||
@operator = op
|
||||
if @first.unwrap() instanceof Op
|
||||
@first.invert()
|
||||
this
|
||||
else if @second
|
||||
new Parens(this).invert()
|
||||
@@ -1231,10 +1227,10 @@ exports.Op = class Op extends Base
|
||||
# true
|
||||
compileChain: (o) ->
|
||||
[@first.second, shared] = @first.second.cache o
|
||||
fst = @first .compile o, LEVEL_OP
|
||||
fst = fst.slice 1, -1 if fst.charAt(0) is '('
|
||||
code = "#{fst} && #{ shared.compile o } #{@operator} #{ @second.compile o, LEVEL_OP }"
|
||||
if o.level < LEVEL_OP then code else "(#{code})"
|
||||
fst = @first.compile o, LEVEL_OP
|
||||
fst = fst.slice 1, -1 if @first.unwrap() instanceof Op and @first.isChainable() and fst.charAt(0) is '('
|
||||
code = "#{fst} #{if @invert then '&&' else '||'} #{ shared.compile o } #{@operator} #{ @second.compile o, LEVEL_OP }"
|
||||
"(#{code})"
|
||||
|
||||
compileExistence: (o) ->
|
||||
if @first.isComplex()
|
||||
@@ -1398,13 +1394,14 @@ exports.For = class For extends Base
|
||||
constructor: (body, source, @name, @index) ->
|
||||
{@source, @guard, @step} = source
|
||||
@body = Expressions.wrap [body]
|
||||
@raw = !!source.raw
|
||||
@own = !!source.own
|
||||
@object = !!source.object
|
||||
[@name, @index] = [@index, @name] if @object
|
||||
throw SyntaxError 'index cannot be a pattern matching expression' if @index instanceof Value
|
||||
@range = @source instanceof Value and @source.base instanceof Range and not @source.properties.length
|
||||
@pattern = @name instanceof Value
|
||||
throw SyntaxError 'cannot pattern match a range loop' if @range and @pattern
|
||||
throw SyntaxError 'indexes do not apply to range loops' if @range and @index
|
||||
throw SyntaxError 'cannot pattern match over range loops' if @range and @pattern
|
||||
@returns = false
|
||||
|
||||
children: ['body', 'source', 'guard', 'step']
|
||||
@@ -1429,9 +1426,8 @@ exports.For = class For extends Base
|
||||
scope = o.scope
|
||||
name = @name and @name.compile o, LEVEL_LIST
|
||||
index = @index and @index.compile o, LEVEL_LIST
|
||||
unless hasCode
|
||||
scope.find(name, immediate: yes) if name and not @pattern
|
||||
scope.find(index, immediate: yes) if index
|
||||
scope.find(name, immediate: yes) if name and not @pattern
|
||||
scope.find(index, immediate: yes) if index
|
||||
rvar = scope.freeVariable 'results' if @returns and not hasPure
|
||||
ivar = (if @range then name else index) or scope.freeVariable 'i'
|
||||
varPart = ''
|
||||
@@ -1442,7 +1438,7 @@ exports.For = class For extends Base
|
||||
forPart = source.compile merge(o, {index: ivar, @step})
|
||||
else
|
||||
svar = @source.compile o, LEVEL_TOP
|
||||
if (name or not @raw) and not IDENTIFIER.test svar
|
||||
if (name or @own) and not IDENTIFIER.test svar
|
||||
defPart = "#{@tab}#{ref = scope.freeVariable 'ref'} = #{svar};\n"
|
||||
svar = ref
|
||||
namePart = if @pattern
|
||||
@@ -1464,7 +1460,7 @@ exports.For = class For extends Base
|
||||
varPart = "\n#{idt1}#{namePart};" if namePart
|
||||
if @object
|
||||
forPart = "#{ivar} in #{svar}"
|
||||
guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" unless @raw
|
||||
guardPart = "\n#{idt1}if (!#{utility('hasProp')}.call(#{svar}, #{ivar})) continue;" if @own
|
||||
defPart += @pluckDirectCall o, body, name, index unless @pattern
|
||||
body = body.compile merge(o, indent: idt1), LEVEL_TOP
|
||||
body = '\n' + body + '\n' if body
|
||||
@@ -1494,6 +1490,7 @@ exports.For = class For extends Base
|
||||
[val.base, base] = [base, val]
|
||||
args.unshift new Literal 'this'
|
||||
body.expressions[idx] = new Call base, args
|
||||
o.sharedScope = o.scope
|
||||
defs += @tab + new Assign(ref, fn).compile(o, LEVEL_TOP) + ';\n'
|
||||
defs
|
||||
|
||||
|
||||
@@ -12,6 +12,10 @@ readline = require 'readline'
|
||||
# Start by opening up **stdio**.
|
||||
stdio = process.openStdin()
|
||||
|
||||
# Log an error.
|
||||
error = (err) ->
|
||||
stdio.write (err.stack or err.toString()) + '\n\n'
|
||||
|
||||
# Quick alias for quitting the REPL.
|
||||
helpers.extend global, quit: -> process.exit(0)
|
||||
|
||||
@@ -23,9 +27,12 @@ run = (buffer) ->
|
||||
val = CoffeeScript.eval buffer.toString(), bare: on, globals: on, fileName: 'repl'
|
||||
console.log val if val isnt undefined
|
||||
catch err
|
||||
console.error err.stack or err.toString()
|
||||
error err
|
||||
repl.prompt()
|
||||
|
||||
# Make sure that uncaught exceptions don't kill the REPL.
|
||||
process.on 'uncaughtException', error
|
||||
|
||||
# Create the REPL by listening to **stdin**.
|
||||
repl = readline.createInterface stdio
|
||||
repl.setPrompt 'coffee> '
|
||||
|
||||
@@ -97,13 +97,13 @@ class exports.Rewriter
|
||||
start = null
|
||||
startIndent = 0
|
||||
condition = (token, i) ->
|
||||
{(i+1): one, (i+2): two, (i+3): three} = @tokens
|
||||
[one, two, three] = @tokens[i + 1 .. i + 3]
|
||||
return false if 'HERECOMMENT' is one?[0]
|
||||
[tag] = token
|
||||
(tag in ['TERMINATOR', 'OUTDENT'] and
|
||||
not (two?[0] is ':' or one?[0] is '@' and three?[0] is ':')) or
|
||||
(tag is ',' and one and
|
||||
one[0] not in ['IDENTIFIER', 'NUMBER', 'STRING', '@', 'TERMINATOR', 'OUTDENT', '('])
|
||||
one[0] not in ['IDENTIFIER', 'NUMBER', 'STRING', '@', 'TERMINATOR', 'OUTDENT'])
|
||||
action = (token, i) -> @tokens.splice i, 0, ['}', '}', token[2]]
|
||||
@scanTokens (token, i, tokens) ->
|
||||
if (tag = token[0]) in EXPRESSION_START
|
||||
@@ -113,17 +113,10 @@ class exports.Rewriter
|
||||
start = stack.pop()
|
||||
return 1
|
||||
return 1 unless tag is ':' and
|
||||
((ago2 = @tag i - 2) is ':' or
|
||||
(ago1 = @tag i - 1) is ')' and @tag(start[1] - 1) is ':' or
|
||||
stack[stack.length - 1]?[0] isnt '{')
|
||||
((ago = @tag i - 2) is ':' or stack[stack.length - 1]?[0] isnt '{')
|
||||
stack.push ['{']
|
||||
idx = if ago1 is ')'
|
||||
start[1]
|
||||
else if ago2 is '@'
|
||||
i - 2
|
||||
else
|
||||
i - 1
|
||||
idx -= 2 if @tag(idx - 2) is 'HERECOMMENT'
|
||||
idx = if ago is '@' then i - 2 else i - 1
|
||||
idx -= 2 while @tag(idx - 2) is 'HERECOMMENT'
|
||||
value = new String('{')
|
||||
value.generated = yes
|
||||
tok = ['{', value, token[2]]
|
||||
@@ -143,7 +136,7 @@ class exports.Rewriter
|
||||
@scanTokens (token, i, tokens) ->
|
||||
tag = token[0]
|
||||
noCall = yes if tag in ['CLASS', 'IF', 'UNLESS']
|
||||
{(i-1): prev, (i+1): next} = tokens
|
||||
[prev, current, next] = tokens[i - 1 .. i + 1]
|
||||
callObject = not noCall and tag is 'INDENT' and
|
||||
next and next.generated and next[0] is '{' and
|
||||
prev and prev[0] in IMPLICIT_FUNC
|
||||
@@ -224,7 +217,7 @@ class exports.Rewriter
|
||||
openLine[open] = token[2] if levels[open]++ is 0
|
||||
else if tag is close and --levels[open] < 0
|
||||
throw Error "too many #{token[1]} on line #{token[2] + 1}"
|
||||
for all open, level of levels when level > 0
|
||||
for open, level of levels when level > 0
|
||||
throw Error "unclosed #{ open } on line #{openLine[open] + 1}"
|
||||
this
|
||||
|
||||
@@ -247,7 +240,7 @@ class exports.Rewriter
|
||||
rewriteClosingParens: ->
|
||||
stack = []
|
||||
debt = {}
|
||||
debt[key] = 0 for all key of INVERSES
|
||||
debt[key] = 0 for key of INVERSES
|
||||
@scanTokens (token, i, tokens) ->
|
||||
if (tag = token[0]) in EXPRESSION_START
|
||||
stack.push token
|
||||
|
||||
@@ -20,11 +20,7 @@ exports.Scope = class Scope
|
||||
constructor:(@parent, @expressions, @method) ->
|
||||
@variables = [{name: 'arguments', type: 'arguments'}]
|
||||
@positions = {}
|
||||
if @parent
|
||||
@garbage = @parent.garbage
|
||||
else
|
||||
@garbage = []
|
||||
Scope.root = this
|
||||
Scope.root = this unless @parent
|
||||
|
||||
# Adds a new variable or overrides an existing one.
|
||||
add: (name, type) ->
|
||||
@@ -33,32 +29,18 @@ exports.Scope = class Scope
|
||||
else
|
||||
@positions[name] = @variables.push({name, type}) - 1
|
||||
|
||||
# Create a new garbage level
|
||||
startLevel: ->
|
||||
@garbage.push []
|
||||
this
|
||||
|
||||
# Return to the previous garbage level and erase referenced temporary
|
||||
# variables in current level from scope.
|
||||
endLevel: ->
|
||||
@add name, 'reuse' for name in @garbage.pop() when @type(name) is 'var'
|
||||
this
|
||||
|
||||
# Look up a variable name in lexical scope, and declare it if it does not
|
||||
# already exist.
|
||||
find: (name, options) ->
|
||||
return true if @check name, options
|
||||
return yes if @check name, options
|
||||
@add name, 'var'
|
||||
false
|
||||
|
||||
# Test variables and return `true` the first time `fn(v)` returns `true`
|
||||
any: (fn) ->
|
||||
return yes for v in @variables when fn v
|
||||
@hasDeclarations = yes
|
||||
no
|
||||
|
||||
# Reserve a variable name as originating from a function parameter for this
|
||||
# scope. No `var` required for internal references.
|
||||
parameter: (name) ->
|
||||
return if @shared and @check name, yes
|
||||
@add name, 'param'
|
||||
|
||||
# Just check to see if a variable has already been declared, without reserving,
|
||||
@@ -77,50 +59,33 @@ exports.Scope = class Scope
|
||||
|
||||
# Gets the type of a variable.
|
||||
type: (name) ->
|
||||
for v in @variables when v.name is name then return v.type
|
||||
return v.type for v in @variables when v.name is name
|
||||
null
|
||||
|
||||
# If we need to store an intermediate result, find an available name for a
|
||||
# compiler-generated variable. `_var`, `_var2`, and so on...
|
||||
freeVariable: (type) ->
|
||||
index = 0
|
||||
index++ while @check((temp = @temporary type, index), true) and @type(temp) isnt 'reuse'
|
||||
index++ while @check((temp = @temporary type, index), true)
|
||||
@add temp, 'var'
|
||||
last(@garbage)?.push temp
|
||||
@hasDeclarations = yes
|
||||
temp
|
||||
|
||||
# Ensure that an assignment is made at the top of this scope
|
||||
# (or at the top-level scope, if requested).
|
||||
assign: (name, value) ->
|
||||
@add name, value: value, assigned: true
|
||||
|
||||
# Does this scope reference any variables that need to be declared in the
|
||||
# given function body?
|
||||
hasDeclarations: (body) ->
|
||||
body is @expressions and @any (v) -> v.type in ['var', 'reuse']
|
||||
|
||||
# Does this scope reference any assignments that need to be declared at the
|
||||
# top of the given function body?
|
||||
hasAssignments: (body) ->
|
||||
body is @expressions and @any (v) -> v.type.assigned
|
||||
@hasAssignments = yes
|
||||
|
||||
# Return the list of variables first declared in this scope.
|
||||
declaredVariables: ->
|
||||
usr = []
|
||||
tmp = []
|
||||
for v in @variables when v.type in ['var', 'reuse']
|
||||
(if v.name.charAt(0) is '_' then tmp else usr).push v.name
|
||||
usr.sort().concat tmp.sort()
|
||||
realVars = []
|
||||
tempVars = []
|
||||
for v in @variables when v.type is 'var'
|
||||
(if v.name.charAt(0) is '_' then tempVars else realVars).push v.name
|
||||
realVars.sort().concat tempVars.sort()
|
||||
|
||||
# Return the list of assignments that are supposed to be made at the top
|
||||
# of this scope.
|
||||
assignedVariables: ->
|
||||
("#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned)
|
||||
|
||||
# Compile the JavaScript for all of the variable declarations in this scope.
|
||||
compiledDeclarations: ->
|
||||
@declaredVariables().join ', '
|
||||
|
||||
# Compile the JavaScript for all of the variable assignments in this scope.
|
||||
compiledAssignments: ->
|
||||
@assignedVariables().join ', '
|
||||
"#{v.name} = #{v.type.value}" for v in @variables when v.type.assigned
|
||||
|
||||
@@ -305,3 +305,44 @@ eq robby.power(), 11
|
||||
eq robby.speed(), Infinity
|
||||
|
||||
|
||||
# Namespaced classes do not reserve their function name in outside scope.
|
||||
one = {}
|
||||
two = {}
|
||||
|
||||
class one.Klass
|
||||
@label = "one"
|
||||
|
||||
class two.Klass
|
||||
@label = "two"
|
||||
|
||||
eq typeof Klass, 'undefined'
|
||||
eq one.Klass.label, 'one'
|
||||
eq two.Klass.label, 'two'
|
||||
|
||||
|
||||
# Nested classes.
|
||||
class Outer
|
||||
constructor: ->
|
||||
@label = 'outer'
|
||||
|
||||
class @Inner
|
||||
constructor: ->
|
||||
@label = 'inner'
|
||||
|
||||
eq (new Outer).label, 'outer'
|
||||
eq (new Outer.Inner).label, 'inner'
|
||||
|
||||
|
||||
# Variables in constructor bodies are correctly scoped.
|
||||
class A
|
||||
x = 1
|
||||
constructor: ->
|
||||
x = 10
|
||||
y = 20
|
||||
y = 2
|
||||
captured: ->
|
||||
{x, y}
|
||||
|
||||
a = new A
|
||||
eq a.captured().x, 10
|
||||
eq a.captured().y, 2
|
||||
|
||||
@@ -10,5 +10,6 @@ ok 'passed' is CoffeeScript.eval '"passed"', bare: on, fileName: 'test'
|
||||
try ok not CoffeeScript.nodes 'f(->'
|
||||
catch e then eq e.message, 'unclosed CALL_START on line 1'
|
||||
|
||||
eq CoffeeScript.compile('for all k of o then', bare: on, globals: on),
|
||||
eq CoffeeScript.compile('for k of o then', bare: on, globals: on),
|
||||
'for (k in o) {}'
|
||||
|
||||
|
||||
@@ -171,8 +171,8 @@ class Cat
|
||||
hair: 'cream'
|
||||
|
||||
whiskers = new Cat
|
||||
own = (value for key, value of whiskers)
|
||||
all = (value for all key, value of whiskers)
|
||||
own = (value for own key, value of whiskers)
|
||||
all = (value for key, value of whiskers)
|
||||
|
||||
ok own.join(' ') is 'Whiskers'
|
||||
ok all.sort().join(' ') is 'Whiskers cream tabby'
|
||||
@@ -219,3 +219,25 @@ odds = while i--
|
||||
i
|
||||
|
||||
ok odds.join(', ') is '5, 3, 1'
|
||||
|
||||
|
||||
# Nested shared scopes.
|
||||
foo = ->
|
||||
for i in [0..7]
|
||||
for j in [0..7]
|
||||
-> i + j
|
||||
|
||||
eq foo()[3][4](), 7
|
||||
|
||||
|
||||
# Issue #897: Ensure that plucked function variables aren't leaked.
|
||||
facets = {}
|
||||
list = ['one', 'two']
|
||||
|
||||
(->
|
||||
for entity in list
|
||||
facets[entity] = -> entity
|
||||
)()
|
||||
|
||||
eq typeof entity, 'undefined'
|
||||
eq facets['two'](), 'two'
|
||||
|
||||
@@ -345,3 +345,25 @@ eq ok, new ->
|
||||
ok
|
||||
### Should `return` implicitly ###
|
||||
### even with trailing comments. ###
|
||||
|
||||
|
||||
#855: execution context for `func arr...` should be `null`
|
||||
(->
|
||||
global = @
|
||||
contextTest = -> ok global is @
|
||||
array = []
|
||||
contextTest array
|
||||
contextTest.apply null, array
|
||||
contextTest array...
|
||||
)()
|
||||
|
||||
|
||||
# #894: Splatting against constructor-chained functions.
|
||||
x = null
|
||||
|
||||
class Foo
|
||||
bar: (y) -> x = y
|
||||
|
||||
new Foo().bar([101]...)
|
||||
|
||||
eq x, 101
|
||||
@@ -216,6 +216,8 @@ eq '\\`', `
|
||||
|
||||
# Shorthand objects with property references.
|
||||
obj =
|
||||
### comment one ###
|
||||
### comment two ###
|
||||
one: 1
|
||||
two: 2
|
||||
object: -> {@one, @two}
|
||||
@@ -228,35 +230,6 @@ eq result.two, 2
|
||||
eq result.two, obj.list()[1]
|
||||
|
||||
|
||||
# Dynamic object keys.
|
||||
i = 0
|
||||
obj = {
|
||||
### leading comment ###
|
||||
(4 * 2): 8
|
||||
### cached shorthand ###
|
||||
(++i)
|
||||
### normal keys ###
|
||||
key: ok
|
||||
's': ok
|
||||
0.0: ok
|
||||
|
||||
"#{'interpolated'}":
|
||||
"""#{"nested"}""": 123: 456
|
||||
### traling comment ###
|
||||
}
|
||||
eq obj.interpolated.nested[123], 456
|
||||
eq obj[8], 8
|
||||
eq obj[1], 1
|
||||
ok obj.key is obj.s is obj[0]
|
||||
|
||||
eq 'braceless dynamic key',
|
||||
(key for key of """braceless #{ 0 of ((0):(0)) and 'dynamic' } key""": 0)[0]
|
||||
|
||||
obj.key = 'val'
|
||||
obj.val = ok
|
||||
{(obj.key)} = obj
|
||||
eq ok, obj.key
|
||||
|
||||
#542: Objects leading expression statement should be parenthesized.
|
||||
{f: -> ok yes }.f() + 1
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# CoffeeScript's operations should be chainable, like Python's.
|
||||
ok 500 > 50 > 5 > -5
|
||||
|
||||
# Some chainable operators can be negated by `unless`
|
||||
ok (true unless 0==10!=100)
|
||||
|
||||
ok true is not false is true is not false
|
||||
|
||||
ok 0 is 0 isnt 50 is 50
|
||||
@@ -173,3 +176,9 @@ ok a is '123456'
|
||||
|
||||
# Multiple operators should space themselves.
|
||||
ok + +1 is - -1
|
||||
|
||||
#891: incorrect inversion of chained comparisons
|
||||
(->
|
||||
ok (true unless 0 > 1 > 2)
|
||||
ok (true unless (NaN = 0/0) < 0/0 < NaN)
|
||||
)()
|
||||
|
||||
@@ -123,3 +123,13 @@ try
|
||||
failed = false
|
||||
catch err
|
||||
ok failed
|
||||
|
||||
|
||||
# multiple generated references
|
||||
(->
|
||||
a = {b: []}
|
||||
a.b[true] = -> this == a.b
|
||||
c = 0
|
||||
d = []
|
||||
ok a.b[0<++c<2] d...
|
||||
)()
|
||||
|
||||
Reference in New Issue
Block a user