Compare commits

..

77 Commits
1.5.0 ... 1.6.1

Author SHA1 Message Date
Jeremy Ashkenas
eef83a9fcb CoffeeScript 1.6.1 2013-03-05 11:07:16 +13:00
Jeremy Ashkenas
b62a90d54c Fixes #2765 -- incorrect line number in mappings 2013-03-05 10:49:47 +13:00
Jeremy Ashkenas
b2ef77d92e refactoring to a baseFileName that can work in the browser, for later 2013-03-05 10:40:39 +13:00
Jeremy Ashkenas
b2b801a78b Fixes #2766 -- incompatible line number API 2013-03-05 10:19:21 +13:00
Jeremy Ashkenas
b4c12f6746 Fixing lingering brain fart. Inexcusable. 2013-03-05 09:23:50 +13:00
Jeremy Ashkenas
a4cc15c95c Merge pull request #2763 from matthewwithanm/source-map-fix
Fix Source Map Generation for 1.6.0
2013-03-04 12:09:26 -08:00
Matthew Tretter
3c42a8e01c Update compiled version 2013-03-04 15:07:20 -05:00
Matthew Tretter
4a94a9fbd1 Fix source map generation
Small typo fix (:
2013-03-04 14:57:56 -05:00
Jeremy Ashkenas
9f614fedec CoffeeScript 1.6.0 2013-03-05 08:19:08 +13:00
Jeremy Ashkenas
e417a0ca6f Reverts 56fe211b79 2013-03-05 07:38:41 +13:00
Jeremy Ashkenas
75769503ff Renaming --maps option to --map for consistency. 2013-03-05 07:29:46 +13:00
Jason Walton
979e110a84 Minor API changes. 2013-03-04 09:45:25 -05:00
Jason Walton
96785872cd Merge remote-tracking branch 'upstream/master' into sourcemaps
Conflicts:
	lib/coffee-script/coffee-script.js
	lib/coffee-script/command.js
	lib/coffee-script/nodes.js
	src/coffee-script.coffee
	src/command.coffee
	src/nodes.coffee
2013-03-04 09:25:55 -05:00
Jason Walton
ee71b9143f Remove PARANOID flag. 2013-03-04 09:11:34 -05:00
Troels Nielsen
37a6ea63b1 #2757, Allow non-significant commas at end of nested implicit objects 2013-03-04 12:55:15 +01:00
Jeremy Ashkenas
56fe211b79 Fixes #2455 -- condition should know what variables the body has declared. 2013-03-04 23:33:50 +13:00
Jeremy Ashkenas
cf11a570e9 Fixes #2489, fixes #1819, fixes #1821 -- remove the __bind helper. 2013-03-04 23:11:38 +13:00
Jeremy Ashkenas
9fe0e711d6 Fixes #2502 -- improper compilation with parenthesized inner value of instance properties in a class body. 2013-03-04 22:26:55 +13:00
Jeremy Ashkenas
b3452c1276 Fixes #2508 -- existential access of the prototype. 2013-03-04 22:07:47 +13:00
Jeremy Ashkenas
47f0ea69b8 Fixes #2749. Restricting to instance methods in class bodies, where it actually has a chance in hell of calling the correct thing. 2013-03-04 21:26:01 +13:00
Jeremy Ashkenas
667b96b495 Fixes #2750 -- clarify error message 2013-03-04 21:17:26 +13:00
Jeremy Ashkenas
3b25aea168 When printing out --tokens, hide the location data. 2013-03-04 20:54:45 +13:00
Michael Ficarra
8435df29c6 Merge pull request #2752 from marchaefner/master
Fix line number mismatch when first line is indented.
2013-03-03 16:21:49 -08:00
Marc Häfner
3c38a34ab2 Fix line numbers when first line is indented.
* Offset @chunkLine for inserted line break.
* Avoid line break insertion for blank lines.
2013-03-01 21:30:07 +01:00
Jason Walton
ad7dcbc797 Change some more "!"s to "not"s. Make spacing consistent after periods in commnets. 2013-03-01 11:36:48 -05:00
Jason Walton
ad0306b00c Change compileWithSourceMap() so it returns an object instead of an Array, and return the SourceMap object. 2013-03-01 11:34:39 -05:00
Jason Walton
d626e70287 Fix from code inspect: Use "not" instead of "!". 2013-03-01 11:19:22 -05:00
Jason Walton
ea86e3e7b1 Optionally allow replacement of existing mappings in SourceMap#addMapping(). 2013-03-01 10:18:37 -05:00
Jason Walton
844549954a Minor API clean up, and make it so sourcemaps are pretty-printed to the .map file. 2013-03-01 10:12:10 -05:00
Jason Walton
51fe417d58 Fix generated file name in v3 source map 2013-03-01 08:56:17 -05:00
Jason Walton
0e718f0968 Merge branch 'sourcemaps' of https://github.com/surjikal/coffee-script into sourcemaps 2013-03-01 08:47:42 -05:00
Jason Walton
0d6d479d77 Merge branch 'master' into sourcemaps
Conflicts:
	lib/coffee-script/coffee-script.js
	lib/coffee-script/nodes.js
	src/nodes.coffee
2013-03-01 08:47:16 -05:00
Nicolas Porter
88e02322e5 Fixed key name in source map, added coffee file to map sources
These are the modifications I had to do in order to get source maps working
in 27.0.1425.2 (Official Build 185250) canary. I haven't tested other
browsers.

I first looked at the V3 spec and a few examples, and I saw that the
`source` key of the source map should be called `sources`.

After doing the `source` to `sources` change, the coffee source and for
some odd reason the javascript file would not show up in the browser
dev tools (it was being fetched but not evaluated).

To fix this, I had to add the coffee source to the `sources` list in the
source map file.
2013-03-01 05:58:26 -05:00
Jeremy Ashkenas
5dea70b82e Fixes #2721 -- show error message for naked super 2013-03-01 13:25:49 +13:00
Jeremy Ashkenas
6b79af2b7c Fixes #2721, super outside of classes with extends for instance methods. 2013-03-01 13:17:07 +13:00
Jeremy Ashkenas
68718b6938 Moving path dependency back into 'command' 2013-03-01 12:50:42 +13:00
Jeremy Ashkenas
d70d71f574 Merging in .coffee.md support alongside .litcoffee ... I think we'll keep .litcoffee as the canonical, however. 2013-03-01 12:46:40 +13:00
Jeremy Ashkenas
f33517368e Removing duplicate 'CATCH' 2013-03-01 12:38:41 +13:00
Jeremy Ashkenas
a48ca260bd Merge pull request #2746 from troels/implicit-calls-with-overhang-on-first-argument-only-on-implicit-object
Disallow implicit calls in cases like:
2013-02-28 14:55:45 -08:00
Troels Nielsen
71e04d9839 Disallow implicit calls in cases like:
f
  a

and only allow cases like:

f
  a: 1
2013-02-28 23:20:42 +01:00
Jeremy Ashkenas
2970d59395 Merge pull request #2743 from epidemian/revert-2599
Revert #2599
2013-02-28 13:53:34 -08:00
Jason Walton
7073d18f23 Add source map support 2013-02-28 15:51:29 -05:00
Jeremy Ashkenas
23d8cd6c2a Merge branch 'master' of https://github.com/jashkenas/coffee-script 2013-03-01 07:46:04 +13:00
Jeremy Ashkenas
e70dd156b0 Fixing heredocs in literate coffeescript 2013-03-01 07:42:12 +13:00
Demian Ferreiro
4469d062e1 Add a couple of tests to document the behaviour of other typed constructors 2013-02-28 10:37:47 -03:00
Demian Ferreiro
bf70b4660e Revert #2599 2013-02-28 10:37:30 -03:00
Jeremy Ashkenas
c0e07013e8 Merge pull request #2741 from troels/implicit-call-try-catch-finally
Fix implicit calls with try/catch/finally as arguments
2013-02-28 03:00:49 -08:00
Jeremy Ashkenas
c6f30935a8 (Aside: For historical reasons we do make the filename extension optional, which is a deeply regrettable accident of history that I would not repeat, given the chance.) 2013-02-28 23:54:19 +13:00
Troels Nielsen
cb187fd900 Fix implicit calls with try/catch/finally as arguments 2013-02-28 11:53:04 +01:00
Jeremy Ashkenas
3f23be2854 Merge pull request #2718 from sbp/sbp-literate
Add support for text/literate-coffeescript in the browser
2013-02-28 02:47:43 -08:00
Sean B. Palmer
881ae5528d Add support for text/literate-coffeescript in the browser 2013-02-28 10:15:20 +00:00
Michael Smith
1a8354482a Modify extension handling to allow for .coffee.md
Move filename processing to a `parseFileName` function in
helpers.coffee.

Map `.coffee.md` as a Literate CoffeeScript extension.

Also, make .litcoffee and .coffee.md files executable without their file
extension - eg. `coffee test` would work for a file called
`test.litcoffee`.
2013-02-27 22:49:24 -08:00
Jeremy Ashkenas
32eb1bf58f Merge pull request #2740 from mintplant/hoist-build
Hoist build function to top level of Cakefile
2013-02-27 22:27:01 -08:00
Michael Smith
b2e17c3045 Hoist build function to top level of Cakefile 2013-02-27 22:21:10 -08:00
Jeremy Ashkenas
ac2c5f0201 Merge pull request #2712 from troels/implicit-object-implicit-call-stuff
Implicit object/implicit call interaction handling
2013-02-27 17:32:31 -08:00
Troels Nielsen
1666716c31 Improve the handling of implicit object and implicit call combinations
by handling them together.
2013-02-27 08:15:38 +01:00
Jason Walton
541ab8334d Compile to an array of CodeFragments instead of to a giant string. 2013-02-26 13:34:27 -05:00
Michael Ficarra
965237e0da Merge pull request #2725 from mintplant/repl-fix
Fix REPL crashing on execution error
2013-02-26 08:20:36 -08:00
Michael Smith
5698e425fd Use blank line regex from Redux 2013-02-26 08:08:47 -08:00
Michael Smith
ff1ddd0284 Fix repl handling of blank line
Since the move to the nodeREPL package, input lines to be evaluated are
now wrapped in parentheses; that is:

    'foo'

would become:

    ('foo'
    )

The old way of detecting empty lines was to see if the input string was
either totally empty, or whitespace-only. The addition of these
parentheses breaks that.

In order to fix this, we simply tweak the regex a little to ignore these
added parentheses if they're present. As an added bonus, the regex
should match empty inputs even if they aren't.

This also makes the "empty command evaluates to undefined" test pass,
for the right reasons (i.e. not because of the broken error behavior
from before).
2013-02-25 22:09:50 -08:00
Michael Smith
deaa31dca5 Prevent repl from crashing on error [Fixes #2716]
Move execution of the compiled code inside the try/catch block:

    try
      js = CoffeeScript.compile "_=(#{input}\n)", {filename, bare: yes}
    catch err
      cb err
>   cb null, vm.runInContext(js, context, filename)

    try
      js = CoffeeScript.compile "_=(#{input}\n)", {filename, bare: yes}
>     cb null, vm.runInContext(js, context, filename)
    catch err
      cb err
2013-02-25 22:08:01 -08:00
Michael Ficarra
8b0dd9d224 Merge pull request #2719 from epidemian/minor-embellishments
Minor embellishments
2013-02-25 10:35:25 -08:00
Demian Ferreiro
dcdfe9bc34 Fix indentation on test 2013-02-25 14:15:24 -03:00
Demian Ferreiro
f609036bee Remove unnecessary returns and use default parameters 2013-02-25 10:44:56 -03:00
Jeremy Ashkenas
c39723c053 expanding literate explanation 2013-02-25 22:29:42 +13:00
Jeremy Ashkenas
d2f400944d Adding a negative array loop example to the docs 2013-02-25 22:27:06 +13:00
Jeremy Ashkenas
673125e64a Merge branch 'master' into gh-pages 2013-02-25 21:23:24 +13:00
Jeremy Ashkenas
e1592890cb Retina-ifying the CoffeeScript logo 2013-02-25 21:23:08 +13:00
Jeremy Ashkenas
f1b5f81eaf merged 2013-02-25 21:13:39 +13:00
Jeremy Ashkenas
39a05b7e4f Merge branch 'master' into gh-pages 2013-01-28 20:06:25 +10:00
Jeremy Ashkenas
e7f72c9555 Adding new coffeescript book per request 2013-01-28 20:06:07 +10:00
Jeremy Ashkenas
be65807370 Merge branch 'master' into gh-pages 2012-10-23 16:45:50 -04:00
Jeremy Ashkenas
caed958455 Fixes #2577 -- better instructions for installing master 2012-10-08 10:08:33 -04:00
Jeremy Ashkenas
1cba2e2339 Merge branch 'master' into gh-pages 2012-05-15 12:36:12 -04:00
Jeremy Ashkenas
b4af24b7e2 Merge branch 'master' into gh-pages 2012-05-14 14:45:35 -04:00
Jeremy Ashkenas
3fc0e6be90 adding a rel=canonical 2012-05-10 17:42:40 -04:00
Jeremy Ashkenas
9d4dc094a1 adding a link to the high-rez logo 2012-04-24 12:12:32 -04:00
94 changed files with 4091 additions and 2110 deletions

View File

@@ -1,8 +1,8 @@
fs = require 'fs'
path = require 'path'
{extend} = require './lib/coffee-script/helpers'
CoffeeScript = require './lib/coffee-script'
{spawn, exec} = require 'child_process'
helpers = require './lib/coffee-script/helpers'
# ANSI Terminal Colors.
bold = red = green = reset = ''
@@ -23,6 +23,12 @@ header = """
*/
"""
# Build the CoffeeScript language from source.
build = (cb) ->
files = fs.readdirSync 'src'
files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/))
run ['-c', '-o', 'lib/coffee-script'].concat(files), cb
# Run a CoffeeScript through our node/coffee interpreter.
run = (args, cb) ->
proc = spawn 'node', ['bin/coffee'].concat(args)
@@ -57,11 +63,7 @@ task 'install', 'install CoffeeScript into /usr/local (or --prefix)', (options)
)
task 'build', 'build the CoffeeScript language from source', build = (cb) ->
files = fs.readdirSync 'src'
files = ('src/' + file for file in files when file.match(/\.(lit)?coffee$/))
run ['-c', '-o', 'lib/coffee-script'].concat(files), cb
task 'build', 'build the CoffeeScript language from source', build
task 'build:full', 'rebuild the source twice, and run the tests', ->
build ->
@@ -77,7 +79,7 @@ task 'build:full', 'rebuild the source twice, and run the tests', ->
task 'build:parser', 'rebuild the Jison parser (run build first)', ->
extend global, require('util')
helpers.extend global, require('util')
require 'jison'
parser = require('./lib/coffee-script/grammar').parser
fs.writeFile 'lib/coffee-script/parser.js', parser.generate()
@@ -91,7 +93,7 @@ task 'build:ultraviolet', 'build and install the Ultraviolet syntax highlighter'
task 'build:browser', 'rebuild the merged script for inclusion in the browser', ->
code = ''
for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'nodes', 'coffee-script', 'browser']
for name in ['helpers', 'rewriter', 'lexer', 'parser', 'scope', 'nodes', 'sourcemap', 'coffee-script', 'browser']
code += """
require['./#{name}'] = new function() {
var exports = this;
@@ -223,7 +225,7 @@ runTests = (CoffeeScript) ->
# Run every test in the `test` folder, recording failures.
files = fs.readdirSync 'test'
for file in files when file.match /\.(lit)?coffee$/i
literate = path.extname(file) is '.litcoffee'
literate = helpers.isLiterate file
currentFile = filename = path.join 'test', file
code = fs.readFileSync filename
try

View File

@@ -1,5 +1,5 @@
###
CoffeeScript Compiler v1.5.0
CoffeeScript Compiler v1.6.1
Released under the MIT License
###

View File

@@ -147,11 +147,13 @@ div.code {
}
#logo {
display: block;
width: 225px; height: 50px;
background: url('../images/logo.png');
outline: none;
position: absolute;
top: 0px; left: 10px;
}
#logo img {
margin: 5px 0 0 3px;
}
#error {
position: absolute;
-webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px;
@@ -380,4 +382,4 @@ div.code {
box-shadow: none; -webkit-box-shadow: none; -moz-box-shadow: none;
background-image: url(../images/button_bg_dark.gif);
text-shadow: none;
}
}

View File

@@ -1,9 +1,9 @@
<!DOCTYPE html> <html> <head> <title>browser.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> browser.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>Override exported methods for non-Node.js engines.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<!DOCTYPE html> <html> <head> <title>browser.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> browser.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>Override exported methods for non-Node.js engines.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<span class="nv">CoffeeScript.require = </span><span class="nx">require</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>Use standard JavaScript <code>eval</code> to eval code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.eval = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="nx">options</span><span class="p">.</span><span class="nx">bare</span> <span class="o">?=</span> <span class="kc">on</span>
<span class="nb">eval</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Running code does not provide access to this scope.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.run = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="nv">options.bare = </span><span class="kc">on</span>
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</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">&#182;</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="k">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="nf">(url, callback) -&gt;</span>
<span class="nb">Function</span><span class="p">(</span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">options</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">&#182;</a> </div> <p>If we're not in a browser environment, we're finished with the public API.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">return</span> <span class="k">unless</span> <span class="nb">window</span><span class="o">?</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Load a remote script from the current domain via XHR.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">CoffeeScript.load = </span><span class="nf">(url, callback, options = {}) -&gt;</span>
<span class="nv">xhr = </span><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span>
<span class="k">new</span> <span class="nb">window</span><span class="p">.</span><span class="nx">ActiveXObject</span><span class="p">(</span><span class="s">&#39;Microsoft.XMLHTTP&#39;</span><span class="p">)</span>
<span class="k">else</span>
@@ -13,7 +13,7 @@
<span class="nv">xhr.onreadystatechange = </span><span class="nf">-&gt;</span>
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">readyState</span> <span class="o">is</span> <span class="mi">4</span>
<span class="k">if</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">status</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">200</span><span class="p">]</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">responseText</span><span class="p">,</span> <span class="nx">options</span>
<span class="k">else</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Could not load </span><span class="si">#{</span><span class="nx">url</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">callback</span><span class="p">()</span> <span class="k">if</span> <span class="nx">callback</span>
@@ -21,16 +21,19 @@
all script tags with a content-type of <code>text/coffeescript</code>.
This happens on page load.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">runScripts = </span><span class="nf">-&gt;</span>
<span class="nv">scripts = </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span> <span class="s">&#39;script&#39;</span>
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">&#39;text/coffeescript&#39;</span><span class="p">)</span>
<span class="nv">coffeetypes = </span><span class="p">[</span><span class="s">&#39;text/coffeescript&#39;</span><span class="p">,</span> <span class="s">&#39;text/literate-coffeescript&#39;</span><span class="p">]</span>
<span class="nv">coffees = </span><span class="p">(</span><span class="nx">s</span> <span class="k">for</span> <span class="nx">s</span> <span class="k">in</span> <span class="nx">scripts</span> <span class="k">when</span> <span class="nx">s</span><span class="p">.</span><span class="nx">type</span> <span class="k">in</span> <span class="nx">coffeetypes</span><span class="p">)</span>
<span class="nv">index = </span><span class="mi">0</span>
<span class="nv">length = </span><span class="nx">coffees</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">do</span> <span class="nv">execute = </span><span class="nf">-&gt;</span>
<span class="nv">script = </span><span class="nx">coffees</span><span class="p">[</span><span class="nx">index</span><span class="o">++</span><span class="p">]</span>
<span class="k">if</span> <span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span> <span class="o">is</span> <span class="s">&#39;text/coffeescript&#39;</span>
<span class="nv">mediatype = </span><span class="nx">script</span><span class="o">?</span><span class="p">.</span><span class="nx">type</span>
<span class="k">if</span> <span class="nx">mediatype</span> <span class="k">in</span> <span class="nx">coffeetypes</span>
<span class="nv">options = </span><span class="p">{</span><span class="nv">literate: </span><span class="nx">mediatype</span> <span class="o">is</span> <span class="s">&#39;text/literate-coffeescript&#39;</span><span class="p">}</span>
<span class="k">if</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span><span class="p">,</span> <span class="nx">execute</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">load</span> <span class="nx">script</span><span class="p">.</span><span class="nx">src</span><span class="p">,</span> <span class="nx">execute</span><span class="p">,</span> <span class="nx">options</span>
<span class="k">else</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">run</span> <span class="nx">script</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">,</span> <span class="nx">options</span>
<span class="nx">execute</span><span class="p">()</span>
<span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Listen for window load, both in browsers and in IE.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">if</span> <span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span>
<span class="nx">addEventListener</span> <span class="s">&#39;DOMContentLoaded&#39;</span><span class="p">,</span> <span class="nx">runScripts</span><span class="p">,</span> <span class="kc">no</span>

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html> <html> <head> <title>cake.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> cake.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
<!DOCTYPE html> <html> <head> <title>cake.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> cake.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p><code>cake</code> is a simplified version of <a href="http://www.gnu.org/software/make/">Make</a>
(<a href="http://rake.rubyforge.org/">Rake</a>, <a href="http://github.com/280north/jake">Jake</a>)
for CoffeeScript. You define tasks with names and descriptions in a Cakefile,
and can call them from the command line, or invoke them from other tasks.</p>

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html> <html> <head> <title>coffee-script.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> coffee-script.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>CoffeeScript can be used both on the server, as a command-line compiler based
<!DOCTYPE html> <html> <head> <title>coffee-script.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> coffee-script.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>CoffeeScript can be used both on the server, as a command-line compiler based
on Node.js/V8, or to run CoffeeScripts directly in the browser. This module
contains the main entry functions for tokenizing, parsing, and compiling
source CoffeeScript into JavaScript.</p>
@@ -8,37 +8,77 @@ execute all scripts present in <code>text/coffeescript</code> tags.</p>
<span class="nv">path = </span><span class="nx">require</span> <span class="s">&#39;path&#39;</span>
<span class="p">{</span><span class="nx">Lexer</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;./lexer&#39;</span>
<span class="p">{</span><span class="nx">parser</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;./parser&#39;</span>
<span class="nv">vm = </span><span class="nx">require</span> <span class="s">&#39;vm&#39;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>The file extensions that are considered to be CoffeeScript.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">extensions = </span><span class="p">[</span><span class="s">&#39;.coffee&#39;</span><span class="p">,</span> <span class="s">&#39;.litcoffee&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadFile = </span><span class="nf">(module, filename) -&gt;</span>
<span class="nv">helpers = </span><span class="nx">require</span> <span class="s">&#39;./helpers&#39;</span>
<span class="nv">vm = </span><span class="nx">require</span> <span class="s">&#39;vm&#39;</span>
<span class="nv">sourcemap = </span><span class="nx">require</span> <span class="s">&#39;./sourcemap&#39;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>Load and run a CoffeeScript file for Node, stripping any <code>BOM</code>s.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">loadFile = </span><span class="nf">(module, filename) -&gt;</span>
<span class="nv">raw = </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="s">&#39;utf8&#39;</span>
<span class="nv">stripped = </span><span class="k">if</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="mh">0xFEFF</span> <span class="k">then</span> <span class="nx">raw</span><span class="p">.</span><span class="nx">substring</span> <span class="mi">1</span> <span class="k">else</span> <span class="nx">raw</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">stripped</span><span class="p">,</span> <span class="p">{</span><span class="nx">filename</span><span class="p">}),</span> <span class="nx">filename</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">stripped</span><span class="p">,</span> <span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nv">literate: </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">isLiterate</span> <span class="nx">filename</span><span class="p">}),</span> <span class="nx">filename</span>
<span class="k">if</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="k">for</span> <span class="nx">ext</span> <span class="k">in</span> <span class="nx">extensions</span>
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="nx">ext</span><span class="p">]</span> <span class="o">=</span> <span class="nx">loadFile</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</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="s">&#39;1.5.0&#39;</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</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="s">&#39;./helpers&#39;</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</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="nf">(code, options = {}) -&gt;</span>
<span class="k">for</span> <span class="nx">ext</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;.coffee&#39;</span><span class="p">,</span> <span class="s">&#39;.litcoffee&#39;</span><span class="p">,</span> <span class="s">&#39;.md&#39;</span><span class="p">,</span> <span class="s">&#39;.coffee.md&#39;</span><span class="p">]</span>
<span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span><span class="p">[</span><span class="nx">ext</span><span class="p">]</span> <span class="o">=</span> <span class="nx">loadFile</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</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="s">&#39;1.6.1&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</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">helpers</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.</p>
<p>If <code>options.sourceMap</code> is specified, then <code>options.filename</code> must also be specified.</p>
<p>This returns a javascript string, unless <code>options.sourceMap</code> is passed,
in which case this returns a `{js, v3SourceMap, sourceMap}
object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
lookups.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.compile = compile = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="p">{</span><span class="nx">merge</span><span class="p">}</span> <span class="o">=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">helpers</span>
<span class="k">try</span>
<span class="nv">js = </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="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)).</span><span class="nx">compile</span> <span class="nx">options</span>
<span class="k">return</span> <span class="nx">js</span> <span class="k">unless</span> <span class="nx">options</span><span class="p">.</span><span class="nx">header</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sourceMap</span>
<span class="nv">coffeeFile = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
<span class="nv">jsFile = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">,</span> <span class="kc">yes</span><span class="p">)</span> <span class="o">+</span> <span class="s">&quot;.js&quot;</span>
<span class="nv">sourceMap = </span><span class="k">new</span> <span class="nx">sourcemap</span><span class="p">.</span><span class="nx">SourceMap</span><span class="p">()</span>
<span class="nv">fragments = </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="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">)).</span><span class="nx">compileToFragments</span> <span class="nx">options</span>
<span class="nv">currentLine = </span><span class="mi">0</span>
<span class="nx">currentLine</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">header</span>
<span class="nx">currentLine</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sourceMap</span>
<span class="nv">currentColumn = </span><span class="mi">0</span>
<span class="nv">js = </span><span class="s">&quot;&quot;</span>
<span class="k">for</span> <span class="nx">fragment</span> <span class="k">in</span> <span class="nx">fragments</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Update the sourcemap with data from each fragment</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">sourceMap</span>
<span class="k">if</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">locationData</span>
<span class="nx">sourceMap</span><span class="p">.</span><span class="nx">addMapping</span><span class="p">(</span>
<span class="p">[</span><span class="nx">fragment</span><span class="p">.</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_line</span><span class="p">,</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_column</span><span class="p">],</span>
<span class="p">[</span><span class="nx">currentLine</span><span class="p">,</span> <span class="nx">currentColumn</span><span class="p">],</span>
<span class="p">{</span><span class="nv">noReplace: </span><span class="kc">true</span><span class="p">})</span>
<span class="nv">newLines = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">count</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span><span class="p">,</span> <span class="s">&quot;\n&quot;</span>
<span class="nx">currentLine</span> <span class="o">+=</span> <span class="nx">newLines</span>
<span class="nv">currentColumn = </span><span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="p">(</span><span class="k">if</span> <span class="nx">newLines</span> <span class="k">then</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span><span class="p">.</span><span class="nx">lastIndexOf</span> <span class="s">&quot;\n&quot;</span> <span class="k">else</span> <span class="mi">0</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">&#182;</a> </div> <p>Copy the code from each fragment into the final JavaScript.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">js</span> <span class="o">+=</span> <span class="nx">fragment</span><span class="p">.</span><span class="nx">code</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nv">err.message = </span><span class="s">&quot;In </span><span class="si">#{</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="si">}</span><span class="s">, </span><span class="si">#{</span><span class="nx">err</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="s">&quot;</span> <span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span>
<span class="k">throw</span> <span class="nx">err</span>
<span class="nv">header = </span><span class="s">&quot;Generated by CoffeeScript </span><span class="si">#{</span><span class="nx">@VERSION</span><span class="si">}</span><span class="s">&quot;</span>
<span class="s">&quot;// </span><span class="si">#{</span><span class="nx">header</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">js</span><span class="si">}</span><span class="s">&quot;</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.tokens = </span><span class="nf">(code, options) -&gt;</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">options</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Parse a string of CoffeeScript code or an array of lexed tokens, and
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">header</span>
<span class="nv">header = </span><span class="s">&quot;Generated by CoffeeScript </span><span class="si">#{</span><span class="nx">@VERSION</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nv">js = </span><span class="s">&quot;// </span><span class="si">#{</span><span class="nx">header</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">js</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">sourceMap</span>
<span class="nv">answer = </span><span class="p">{</span><span class="nx">js</span><span class="p">}</span>
<span class="k">if</span> <span class="nx">sourceMap</span>
<span class="nv">answer.sourceMap = </span><span class="nx">sourceMap</span>
<span class="nv">answer.v3SourceMap = </span><span class="nx">sourcemap</span><span class="p">.</span><span class="nx">generateV3SourceMap</span> <span class="nx">sourceMap</span><span class="p">,</span> <span class="nx">coffeeFile</span><span class="p">,</span> <span class="nx">jsFile</span>
<span class="nx">answer</span>
<span class="k">else</span>
<span class="nx">js</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.tokens = </span><span class="nf">(code, options) -&gt;</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">options</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Parse a string of CoffeeScript code or an array of lexed tokens, and
return the AST. You can then compile it by calling <code>.compile()</code> on the root,
or traverse it by using <code>.traverseChildren()</code> with a callback.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.nodes = </span><span class="nf">(source, options) -&gt;</span>
<span class="k">if</span> <span class="k">typeof</span> <span class="nx">source</span> <span class="o">is</span> <span class="s">&#39;string&#39;</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">source</span><span class="p">,</span> <span class="nx">options</span>
<span class="k">else</span>
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
<span class="nx">parser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Compile and execute a string of CoffeeScript (on the server), correctly
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="nv">mainModule = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s">&#39;.&#39;</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s">&#39;module&#39;</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">extensions</span><span class="p">)</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="nv">mainModule = </span><span class="nx">require</span><span class="p">.</span><span class="nx">main</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Set the filename.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.filename = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span>
<span class="k">if</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="k">then</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="k">else</span> <span class="s">&#39;.&#39;</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Clear the module cache.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">moduleCache</span> <span class="o">and=</span> <span class="p">{}</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Assign paths for node_modules loading</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">mainModule.paths = </span><span class="nx">require</span><span class="p">(</span><span class="s">&#39;module&#39;</span><span class="p">).</span><span class="nx">_nodeModulePaths</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">realpathSync</span> <span class="nx">options</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Compile.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="o">not</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">isCoffee</span><span class="p">(</span><span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span><span class="p">)</span> <span class="o">or</span> <span class="nx">require</span><span class="p">.</span><span class="nx">extensions</span>
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">compile</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">options</span><span class="p">),</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span>
<span class="k">else</span>
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
<span class="nx">mainModule</span><span class="p">.</span><span class="nx">_compile</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">mainModule</span><span class="p">.</span><span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Compile and evaluate a string of CoffeeScript (in a Node.js-like environment).
The CoffeeScript REPL uses this to run the input.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.eval = </span><span class="nf">(code, options = {}) -&gt;</span>
<span class="k">return</span> <span class="k">unless</span> <span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">trim</span><span class="p">()</span>
<span class="nv">Script = </span><span class="nx">vm</span><span class="p">.</span><span class="nx">Script</span>
@@ -53,12 +93,12 @@ The CoffeeScript REPL uses this to run the input.</p> </td>
<span class="k">else</span>
<span class="nv">sandbox = </span><span class="nx">global</span>
<span class="nv">sandbox.__filename = </span><span class="nx">options</span><span class="p">.</span><span class="nx">filename</span> <span class="o">||</span> <span class="s">&#39;eval&#39;</span>
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>define module/require only if they chose not to specify their own</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
<span class="nv">sandbox.__dirname = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>define module/require only if they chose not to specify their own</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">unless</span> <span class="nx">sandbox</span> <span class="o">isnt</span> <span class="nx">global</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">module</span> <span class="o">or</span> <span class="nx">sandbox</span><span class="p">.</span><span class="nx">require</span>
<span class="nv">Module = </span><span class="nx">require</span> <span class="s">&#39;module&#39;</span>
<span class="nv">sandbox.module = _module = </span><span class="k">new</span> <span class="nx">Module</span><span class="p">(</span><span class="nx">options</span><span class="p">.</span><span class="nx">modulename</span> <span class="o">||</span> <span class="s">&#39;eval&#39;</span><span class="p">)</span>
<span class="nv">sandbox.require = _require = </span><span class="nf">(path) -&gt;</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_load</span> <span class="nx">path</span><span class="p">,</span> <span class="nx">_module</span><span class="p">,</span> <span class="kc">true</span>
<span class="nv">_module.filename = </span><span class="nx">sandbox</span><span class="p">.</span><span class="nx">__filename</span>
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s">&#39;paths&#39;</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>use the same hack node currently uses for their own REPL</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
<span class="nx">_require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="o">=</span> <span class="nx">require</span><span class="p">[</span><span class="nx">r</span><span class="p">]</span> <span class="k">for</span> <span class="nx">r</span> <span class="k">in</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">getOwnPropertyNames</span> <span class="nx">require</span> <span class="k">when</span> <span class="nx">r</span> <span class="o">isnt</span> <span class="s">&#39;paths&#39;</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>use the same hack node currently uses for their own REPL</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">_require.paths = _module.paths = </span><span class="nx">Module</span><span class="p">.</span><span class="nx">_nodeModulePaths</span> <span class="nx">process</span><span class="p">.</span><span class="nx">cwd</span><span class="p">()</span>
<span class="nv">_require.resolve = </span><span class="nf">(request) -&gt;</span> <span class="nx">Module</span><span class="p">.</span><span class="nx">_resolveFilename</span> <span class="nx">request</span><span class="p">,</span> <span class="nx">_module</span>
<span class="nv">o = </span><span class="p">{}</span>
<span class="nx">o</span><span class="p">[</span><span class="nx">k</span><span class="p">]</span> <span class="o">=</span> <span class="nx">v</span> <span class="k">for</span> <span class="k">own</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="k">of</span> <span class="nx">options</span>
@@ -67,7 +107,7 @@ The CoffeeScript REPL uses this to run the input.</p> </td>
<span class="k">if</span> <span class="nx">sandbox</span> <span class="o">is</span> <span class="nx">global</span>
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInThisContext</span> <span class="nx">js</span>
<span class="k">else</span>
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
<span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span> <span class="nx">js</span><span class="p">,</span> <span class="nx">sandbox</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>Instantiate a Lexer for our use here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">lexer = </span><span class="k">new</span> <span class="nx">Lexer</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>The real Lexer produces a generic stream of tokens. This object provides a
thin wrapper around it, compatible with the Jison API. We can then pass it
directly as a "Jison lexer".</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parser.lexer =</span>
<span class="nv">lex: </span><span class="nf">-&gt;</span>

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
<!DOCTYPE html> <html> <head> <title>command.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> command.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The <code>coffee</code> utility. Handles command-line compilation of CoffeeScript
into various forms: saved into <code>.js</code> files or printed to stdout, piped to
<a href="http://javascriptlint.com/">JavaScript Lint</a> or recompiled every time the source is
saved, printed as a token stream or as the syntax tree, or launch an
@@ -27,6 +27,7 @@ interactive REPL.</p> </td> <td class="code">
<span class="p">[</span><span class="s">&#39;-i&#39;</span><span class="p">,</span> <span class="s">&#39;--interactive&#39;</span><span class="p">,</span> <span class="s">&#39;run an interactive CoffeeScript REPL&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-j&#39;</span><span class="p">,</span> <span class="s">&#39;--join [FILE]&#39;</span><span class="p">,</span> <span class="s">&#39;concatenate the source CoffeeScript before compiling&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-l&#39;</span><span class="p">,</span> <span class="s">&#39;--lint&#39;</span><span class="p">,</span> <span class="s">&#39;pipe the compiled JavaScript through JavaScript Lint&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-m&#39;</span><span class="p">,</span> <span class="s">&#39;--map&#39;</span><span class="p">,</span> <span class="s">&#39;generate source map and save as .map files&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-n&#39;</span><span class="p">,</span> <span class="s">&#39;--nodes&#39;</span><span class="p">,</span> <span class="s">&#39;print out the parse tree that the parser produces&#39;</span><span class="p">]</span>
<span class="p">[</span> <span class="s">&#39;--nodejs [ARGS]&#39;</span><span class="p">,</span> <span class="s">&#39;pass options directly to the &quot;node&quot; binary&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;-o&#39;</span><span class="p">,</span> <span class="s">&#39;--output [DIR]&#39;</span><span class="p">,</span> <span class="s">&#39;set the output directory for compiled JavaScript&#39;</span><span class="p">]</span>
@@ -40,8 +41,7 @@ interactive REPL.</p> </td> <td class="code">
<span class="nv">sourceCode = </span><span class="p">[]</span>
<span class="nv">notSources = </span><span class="p">{}</span>
<span class="nv">watchers = </span><span class="p">{}</span>
<span class="nv">optionParser = </span><span class="kc">null</span>
<span class="nv">coffee_exts = </span><span class="p">[</span><span class="s">&#39;.coffee&#39;</span><span class="p">,</span> <span class="s">&#39;.litcoffee&#39;</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">&#182;</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
<span class="nv">optionParser = </span><span class="kc">null</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Run <code>coffee</code> by parsing passed options and determining what action to take.
Many flags cause us to divert before compiling anything. Flags passed after
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.run = </span><span class="nf">-&gt;</span>
<span class="nx">parseOptions</span><span class="p">()</span>
@@ -59,18 +59,13 @@ Many flags cause us to divert before compiling anything. Flags passed after
<span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;coffee&#39;</span>
<span class="k">for</span> <span class="nx">source</span> <span class="k">in</span> <span class="nx">sources</span>
<span class="nx">compilePath</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">yes</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">normalize</span> <span class="nx">source</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Compile a path, which could be a script or a directory. If a directory
is passed, recursively compile all '.coffee' and '.litcoffee' extension source
files in it and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compilePath = </span><span class="nf">(source, topLevel, base) -&gt;</span>
is passed, recursively compile all '.coffee', '.litcoffee', and '.coffee.md'
extension source files in it and all subdirectories.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">compilePath = </span><span class="nf">(source, topLevel, base) -&gt;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, stats) -&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="k">if</span> <span class="nx">err</span><span class="o">?</span><span class="p">.</span><span class="nx">code</span> <span class="o">is</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="k">if</span> <span class="nx">topLevel</span> <span class="o">and</span> <span class="nx">source</span> <span class="o">and</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">coffee_exts</span>
<span class="nv">source = </span><span class="nx">sources</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">source</span><span class="p">)]</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">.coffee&quot;</span>
<span class="k">return</span> <span class="nx">compilePath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">topLevel</span><span class="p">,</span> <span class="nx">base</span>
<span class="k">if</span> <span class="nx">topLevel</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="s">&quot;File not found: </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
<span class="k">return</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="s">&quot;File not found: </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">process</span><span class="p">.</span><span class="nx">exit</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">stats</span><span class="p">.</span><span class="nx">isDirectory</span><span class="p">()</span> <span class="o">and</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">&#39;node_modules&#39;</span>
<span class="nx">watchDir</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readdir</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, files) -&gt;</span>
@@ -82,7 +77,7 @@ files in it and all subdirectories.</p> </td> <td class=
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">index</span><span class="p">..</span><span class="nx">index</span><span class="p">]</span> <span class="o">=</span> <span class="nx">files</span><span class="p">.</span><span class="nx">map</span> <span class="nf">-&gt;</span> <span class="kc">null</span>
<span class="nx">files</span><span class="p">.</span><span class="nx">forEach</span> <span class="nf">(file) -&gt;</span>
<span class="nx">compilePath</span> <span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">file</span><span class="p">),</span> <span class="kc">no</span><span class="p">,</span> <span class="nx">base</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)</span> <span class="k">in</span> <span class="nx">coffee_exts</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">topLevel</span> <span class="o">or</span> <span class="nx">helpers</span><span class="p">.</span><span class="nx">isCoffee</span> <span class="nx">source</span>
<span class="nx">watch</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span> <span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">watch</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="nf">(err, code) -&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">&#39;ENOENT&#39;</span>
@@ -105,11 +100,19 @@ requested options. If evaluating the script directly sets <code>__filename</code
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">sources</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">file</span><span class="p">)]</span> <span class="o">=</span> <span class="nx">t</span><span class="p">.</span><span class="nx">input</span>
<span class="nx">compileJoin</span><span class="p">()</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="nv">compiled = </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="nv">t.output = </span><span class="nx">compiled</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">map</span>
<span class="nv">t.output = </span><span class="nx">compiled</span><span class="p">.</span><span class="nx">js</span>
<span class="nv">t.sourceMap = </span><span class="nx">compiled</span><span class="p">.</span><span class="nx">v3SourceMap</span>
<span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">emit</span> <span class="s">&#39;success&#39;</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="k">then</span> <span class="nx">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">if</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</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="o">||</span> <span class="nx">o</span><span class="p">.</span><span class="nx">map</span>
<span class="nx">writeJs</span> <span class="nx">base</span><span class="p">,</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">t</span><span class="p">.</span><span class="nx">sourceMap</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="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="s">&#39;failure&#39;</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">task</span>
<span class="k">return</span> <span class="k">if</span> <span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">listeners</span><span class="p">(</span><span class="s">&#39;failure&#39;</span><span class="p">).</span><span class="nx">length</span>
@@ -203,23 +206,33 @@ the compiled JS version as well.</p> </td> <td class="co
<span class="k">if</span> <span class="nx">itExists</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">unlink</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nf">(err) -&gt;</span>
<span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">isnt</span> <span class="s">&#39;ENOENT&#39;</span>
<span class="nx">timeLog</span> <span class="s">&quot;removed </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">&quot;</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Get the corresponding output JavaScript path for a source file.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">outputPath = </span><span class="nf">(source, base) -&gt;</span>
<span class="nv">filename = </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">source</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">))</span> <span class="o">+</span> <span class="s">&#39;.js&#39;</span>
<span class="nx">timeLog</span> <span class="s">&quot;removed </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">&quot;</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Get the corresponding output JavaScript path for a source file.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">outputPath = </span><span class="nf">(source, base, extension=&quot;.js&quot;) -&gt;</span>
<span class="nv">basename = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span> <span class="nx">source</span><span class="p">,</span> <span class="kc">yes</span>
<span class="nv">srcDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">source</span>
<span class="nv">baseDir = </span><span class="k">if</span> <span class="nx">base</span> <span class="o">is</span> <span class="s">&#39;.&#39;</span> <span class="k">then</span> <span class="nx">srcDir</span> <span class="k">else</span> <span class="nx">srcDir</span><span class="p">.</span><span class="nx">substring</span> <span class="nx">base</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">dir = </span><span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">output</span><span class="p">,</span> <span class="nx">baseDir</span> <span class="k">else</span> <span class="nx">srcDir</span>
<span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">filename</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Write out a JavaScript source file with the compiled code. By default, files
<span class="nx">path</span><span class="p">.</span><span class="nx">join</span> <span class="nx">dir</span><span class="p">,</span> <span class="nx">basename</span> <span class="o">+</span> <span class="nx">extension</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Write out a JavaScript source file with the compiled code. By default, files
are written out in <code>cwd</code> as <code>.js</code> files with the same name, but the output
directory can be customized with <code>--output</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">writeJs = </span><span class="nf">(source, js, base) -&gt;</span>
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">base</span>
directory can be customized with <code>--output</code>.</p>
<p>If <code>generatedSourceMap</code> is provided, this will write a <code>.map</code> file into the
same directory as the <code>.js</code> file.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">writeJs = </span><span class="nf">(base, sourcePath, js, generatedSourceMap = null) -&gt;</span>
<span class="nv">jsPath = </span><span class="nx">outputPath</span> <span class="nx">sourcePath</span><span class="p">,</span> <span class="nx">base</span>
<span class="nv">sourceMapPath = </span><span class="nx">outputPath</span> <span class="nx">sourcePath</span><span class="p">,</span> <span class="nx">base</span><span class="p">,</span> <span class="s">&quot;.map&quot;</span>
<span class="nv">jsDir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span> <span class="nx">jsPath</span>
<span class="nv">compile = </span><span class="nf">-&gt;</span>
<span class="nv">js = </span><span class="s">&#39; &#39;</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;=</span> <span class="mi">0</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">jsPath</span><span class="p">,</span> <span class="nx">js</span><span class="p">,</span> <span class="nf">(err) -&gt;</span>
<span class="k">if</span> <span class="nx">err</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="nx">timeLog</span> <span class="s">&quot;compiled </span><span class="si">#{</span><span class="nx">source</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">if</span> <span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span>
<span class="nv">js = </span><span class="s">&#39; &#39;</span> <span class="k">if</span> <span class="nx">js</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;=</span> <span class="mi">0</span>
<span class="k">if</span> <span class="nx">generatedSourceMap</span> <span class="k">then</span> <span class="nv">js = </span><span class="s">&quot;//@ sourceMappingURL=</span><span class="si">#{</span><span class="nx">helpers</span><span class="p">.</span><span class="nx">baseFileName</span> <span class="nx">sourceMapPath</span><span class="si">}</span><span class="s">\n</span><span class="si">#{</span><span class="nx">js</span><span class="si">}</span><span class="s">&quot;</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="nf">(err) -&gt;</span>
<span class="k">if</span> <span class="nx">err</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="nx">timeLog</span> <span class="s">&quot;compiled </span><span class="si">#{</span><span class="nx">sourcePath</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">if</span> <span class="nx">generatedSourceMap</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">sourceMapPath</span><span class="p">,</span> <span class="nx">generatedSourceMap</span><span class="p">,</span> <span class="nf">(err) -&gt;</span>
<span class="k">if</span> <span class="nx">err</span>
<span class="nx">printLine</span> <span class="s">&quot;Could not write source map: </span><span class="si">#{</span><span class="nx">err</span><span class="p">.</span><span class="nx">message</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">exists</span> <span class="nx">jsDir</span><span class="p">,</span> <span class="nf">(itExists) -&gt;</span>
<span class="k">if</span> <span class="nx">itExists</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="s">&quot;mkdir -p </span><span class="si">#{</span><span class="nx">jsDir</span><span class="si">}</span><span class="s">&quot;</span><span class="p">,</span> <span class="nx">compile</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Convenience for cleaner setTimeouts.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">wait = </span><span class="nf">(milliseconds, func) -&gt;</span> <span class="nx">setTimeout</span> <span class="nx">func</span><span class="p">,</span> <span class="nx">milliseconds</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>When watching scripts, it's useful to log changes with the timestamp.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">timeLog = </span><span class="nf">(message) -&gt;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s">&quot;</span><span class="si">#{</span><span class="p">(</span><span class="k">new</span> <span class="nb">Date</span><span class="p">).</span><span class="nx">toLocaleTimeString</span><span class="p">()</span><span class="si">}</span><span class="s"> - </span><span class="si">#{</span><span class="nx">message</span><span class="si">}</span><span class="s">&quot;</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
@@ -230,24 +243,28 @@ any errors or warnings that arise.</p> </td> <td class="
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">on</span> <span class="s">&#39;data&#39;</span><span class="p">,</span> <span class="nx">printIt</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">write</span> <span class="nx">js</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</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">&#182;</a> </div> <p>Pretty-print a stream of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTokens = </span><span class="nf">(tokens) -&gt;</span>
<span class="nx">jsl</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</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">&#182;</a> </div> <p>Pretty-print a stream of tokens, sans location data.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">printTokens = </span><span class="nf">(tokens) -&gt;</span>
<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="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">value = </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="s">&#39;\\n&#39;</span><span class="p">)</span>
<span class="nv">locationData = </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">locationDataToString</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="s">&quot;[</span><span class="si">#{</span><span class="nx">tag</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">locationData</span><span class="si">}</span><span class="s">]&quot;</span>
<span class="s">&quot;[</span><span class="si">#{</span><span class="nx">tag</span><span class="si">}</span><span class="s"> </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s">]&quot;</span>
<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="s">&#39; &#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</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="nf">-&gt;</span>
<span class="nv">optionParser = </span><span class="k">new</span> <span class="nx">optparse</span><span class="p">.</span><span class="nx">OptionParser</span> <span class="nx">SWITCHES</span><span class="p">,</span> <span class="nx">BANNER</span>
<span class="nv">o = opts = </span><span class="nx">optionParser</span><span class="p">.</span><span class="nx">parse</span> <span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">..]</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or=</span> <span class="o">!!</span><span class="nx">o</span><span class="p">.</span><span class="nx">output</span>
<span class="nv">o.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span><span class="p">)</span>
<span class="nv">o.run = </span><span class="o">not</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">compile</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">lint</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">map</span><span class="p">)</span>
<span class="nv">o.print = </span><span class="o">!!</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">print</span> <span class="o">or</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nb">eval</span> <span class="o">or</span> <span class="nx">o</span><span class="p">.</span><span class="nx">stdio</span> <span class="o">and</span> <span class="nx">o</span><span class="p">.</span><span class="nx">compile</span><span class="p">))</span>
<span class="nv">sources = </span><span class="nx">o</span><span class="p">.</span><span class="nx">arguments</span>
<span class="nx">sourceCode</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="kc">null</span> <span class="k">for</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">sources</span>
<span class="k">return</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</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="nf">(filename) -&gt;</span>
<span class="nv">literate = </span><span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">filename</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;.litcoffee&#39;</span>
<span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nx">literate</span><span class="p">,</span> <span class="nv">bare: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span><span class="p">,</span> <span class="nv">header: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span><span class="p">}</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
<span class="p">{</span>
<span class="nx">filename</span>
<span class="nv">literate: </span><span class="nx">helpers</span><span class="p">.</span><span class="nx">isLiterate</span><span class="p">(</span><span class="nx">filename</span><span class="p">)</span>
<span class="nv">bare: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">bare</span>
<span class="nv">header: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">compile</span>
<span class="nv">sourceMap: </span><span class="nx">opts</span><span class="p">.</span><span class="nx">map</span>
<span class="p">}</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Start up a new Node.js instance with the arguments in <code>--nodejs</code> passed to
the <code>node</code> binary, preserving the other options.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">forkNode = </span><span class="nf">-&gt;</span>
<span class="nv">nodeArgs = </span><span class="nx">opts</span><span class="p">.</span><span class="nx">nodejs</span><span class="p">.</span><span class="nx">split</span> <span class="sr">/\s+/</span>
<span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">..]</span>

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html> <html> <head> <title>grammar.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> grammar.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The CoffeeScript parser is generated by <a href="http://github.com/zaach/jison">Jison</a>
<!DOCTYPE html> <html> <head> <title>grammar.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> grammar.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The CoffeeScript parser is generated by <a href="http://github.com/zaach/jison">Jison</a>
from this grammar file. Jison is a bottom-up parser generator, similar in
style to <a href="http://www.gnu.org/software/bison">Bison</a>, implemented in JavaScript.
It can recognize <a href="http://en.wikipedia.org/wiki/LR_grammar">LALR(1), LR(0), SLR(1), and LR(1)</a>
@@ -23,8 +23,7 @@ previous nonterminal.</p> </td> <td class="code">
<span class="nv">patternCount = </span><span class="nx">patternString</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s">&#39; &#39;</span><span class="p">).</span><span class="nx">length</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">patternString</span><span class="p">,</span> <span class="s">&#39;$$ = $1;&#39;</span><span class="p">,</span> <span class="nx">options</span><span class="p">]</span> <span class="k">unless</span> <span class="nx">action</span>
<span class="nv">action = </span><span class="k">if</span> <span class="nv">match = </span><span class="nx">unwrap</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">action</span> <span class="k">then</span> <span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="s">&quot;(</span><span class="si">#{</span><span class="nx">action</span><span class="si">}</span><span class="s">())&quot;</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>All runtime functions we need are defined on "yy"</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\bnew /g</span><span class="p">,</span> <span class="s">&#39;$&amp;yy.&#39;</span>
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(?:Block\.wrap|extend)\b/g</span><span class="p">,</span> <span class="s">&#39;yy.$&amp;&#39;</span>
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(Op|Value\.(create|wrap))\b/g</span><span class="p">,</span> <span class="s">&#39;yy.$&amp;&#39;</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Returns a function which adds location data to the first parameter passed
<span class="nv">action = </span><span class="nx">action</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\b(?:Block\.wrap|extend)\b/g</span><span class="p">,</span> <span class="s">&#39;yy.$&amp;&#39;</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Returns a function which adds location data to the first parameter passed
in, and returns the parameter. If the parameter is not a node, it will
just be passed through unaffected.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addLocationDataFn = </span><span class="nf">(first, last) -&gt;</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">last</span>
@@ -103,10 +102,10 @@ through and printed to JavaScript.</p> </td> <td class="
<span class="nx">o</span> <span class="s">&#39;Assignable = INDENT Expression OUTDENT&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$4</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>Assignment when it happens within an object literal. The difference from
the ordinary <strong>Assign</strong> is that these allow numbers and strings as keys.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">AssignObj: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;ObjAssignable&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;ObjAssignable : Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">$1</span><span class="p">)),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s">&#39;object&#39;</span>
<span class="nx">o</span> <span class="s">&#39;ObjAssignable&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;ObjAssignable : Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$1</span><span class="p">)),</span> <span class="nx">$3</span><span class="p">,</span> <span class="s">&#39;object&#39;</span>
<span class="nx">o</span> <span class="s">&#39;ObjAssignable :</span>
<span class="s"> INDENT Expression OUTDENT&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">$1</span><span class="p">)),</span> <span class="nx">$4</span><span class="p">,</span> <span class="s">&#39;object&#39;</span>
<span class="s"> INDENT Expression OUTDENT&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Value</span><span class="p">(</span><span class="nx">$1</span><span class="p">)),</span> <span class="nx">$4</span><span class="p">,</span> <span class="s">&#39;object&#39;</span>
<span class="nx">o</span> <span class="s">&#39;Comment&#39;</span>
<span class="p">]</span>
@@ -150,26 +149,27 @@ that hoovers up the remaining arguments.</p> </td> <td c
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>A splat that occurs outside of a parameter list.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Splat: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;Expression ...&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Splat</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>Variables and properties that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">SimpleAssignable: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Value Accessor&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">$1</span><span class="p">.</span><span class="nx">add</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;Invocation Accessor&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;Invocation Accessor&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span><span class="p">,</span> <span class="p">[].</span><span class="nx">concat</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;ThisProperty&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>Everything that can be assigned to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Assignable: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;SimpleAssignable&#39;</span>
<span class="nx">o</span> <span class="s">&#39;Array&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Object&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Array&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Object&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">&#182;</a> </div> <p>The types of things that can be treated as values -- assigned to, invoked
as functions, indexed into, named as a class, etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Value: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;Assignable&#39;</span>
<span class="nx">o</span> <span class="s">&#39;Literal&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Parenthetical&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Range&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Literal&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Parenthetical&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Range&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;This&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>The general group of accessors into an object, by property, by prototype
or by array index or slice.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Accessor: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;. Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;?. Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">,</span> <span class="s">&#39;soak&#39;</span>
<span class="nx">o</span> <span class="s">&#39;:: Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">&#39;prototype&#39;</span><span class="p">),</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">)]</span>
<span class="nx">o</span> <span class="s">&#39;:: Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s">&#39;prototype&#39;</span><span class="p">)),</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">)]</span>
<span class="nx">o</span> <span class="s">&#39;?:: Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s">&#39;prototype&#39;</span><span class="p">),</span> <span class="s">&#39;soak&#39;</span><span class="p">),</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span> <span class="nx">$2</span><span class="p">)]</span>
<span class="nx">o</span> <span class="s">&#39;::&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Access</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">&#39;prototype&#39;</span>
<span class="nx">o</span> <span class="s">&#39;Index&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>Indexing into an object or array using bracket notation.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Index: </span><span class="p">[</span>
@@ -211,10 +211,10 @@ and optional references to the superclass.</p> </td> <td
<span class="nx">o</span> <span class="s">&#39;CALL_START CALL_END&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s">&#39;CALL_START ArgList OptComma CALL_END&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>A reference to the <em>this</em> current object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">This: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;THIS&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">&#39;this&#39;</span>
<span class="nx">o</span> <span class="s">&#39;@&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">&#39;this&#39;</span>
<span class="nx">o</span> <span class="s">&#39;THIS&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">&#39;this&#39;</span>
<span class="nx">o</span> <span class="s">&#39;@&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="k">new</span> <span class="nx">Literal</span> <span class="s">&#39;this&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>A reference to a property on <em>this</em>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ThisProperty: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;@ Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s">&#39;this&#39;</span><span class="p">)),</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="nx">$2</span><span class="p">))],</span> <span class="s">&#39;this&#39;</span>
<span class="nx">o</span> <span class="s">&#39;@ Identifier&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">LOC</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Literal</span><span class="p">(</span><span class="s">&#39;this&#39;</span><span class="p">)),</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="k">new</span> <span class="nx">Access</span><span class="p">(</span><span class="nx">$2</span><span class="p">))],</span> <span class="s">&#39;this&#39;</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <p>The array literal.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nb">Array</span><span class="o">:</span> <span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;[ ]&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Arr</span> <span class="p">[]</span>
<span class="nx">o</span> <span class="s">&#39;[ ArgList OptComma ]&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Arr</span> <span class="nx">$2</span>
@@ -251,7 +251,7 @@ having the newlines wouldn't make sense.</p> </td> <td c
<span class="nx">o</span> <span class="s">&#39;TRY Block Catch FINALLY Block&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Try</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">$3</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nx">$5</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>A catch clause names its error and runs a block of code.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Catch: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;CATCH Identifier Block&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="p">[</span><span class="nx">$2</span><span class="p">,</span> <span class="nx">$3</span><span class="p">]</span>
<span class="nx">o</span> <span class="s">&#39;CATCH Object Block&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</span><span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">$2</span><span class="p">)),</span> <span class="nx">$3</span><span class="p">]</span>
<span class="nx">o</span> <span class="s">&#39;CATCH Object Block&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="p">[</span><span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)(</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">$3</span><span class="p">]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p>Throw an exception object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Throw: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;THROW Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Throw</span> <span class="nx">$2</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">&#182;</a> </div> <p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
@@ -285,7 +285,7 @@ or postfix, with a single expression.</p> </td> <td clas
<span class="p">]</span>
<span class="nv">ForBody: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;FOR Range&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nv">source: </span><span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span><span class="p">(</span><span class="nx">$2</span><span class="p">)</span>
<span class="nx">o</span> <span class="s">&#39;FOR Range&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nv">source: </span><span class="nx">LOC</span><span class="p">(</span><span class="mi">2</span><span class="p">)</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">o</span> <span class="s">&#39;ForStart ForSource&#39;</span><span class="p">,</span> <span class="nf">-&gt;</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.name = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="nv">$2.index = </span><span class="nx">$1</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span> <span class="nx">$2</span>
<span class="p">]</span>
@@ -296,8 +296,8 @@ or postfix, with a single expression.</p> </td> <td clas
This enables support for pattern matching.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForValue: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;Identifier&#39;</span>
<span class="nx">o</span> <span class="s">&#39;ThisProperty&#39;</span>
<span class="nx">o</span> <span class="s">&#39;Array&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Object&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Value</span><span class="p">.</span><span class="nx">wrap</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Array&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Object&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Value</span> <span class="nx">$1</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-58"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-58">&#182;</a> </div> <p>An array or range comprehension has variables for the current element
and (optional) reference to the current index. Or, <em>key, value</em>, in the case
of object comprehensions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">ForVariables: </span><span class="p">[</span>
@@ -345,27 +345,27 @@ are defined at the bottom of the page. It would be shorter if we could
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
-type rule, but in order to make the precedence binding possible, separate
rules are necessary.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">Operation: </span><span class="p">[</span>
<span class="nx">o</span> <span class="s">&#39;UNARY Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$1</span> <span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;- Expression&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;-&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">&#39;UNARY&#39;</span>
<span class="nx">o</span> <span class="s">&#39;+ Expression&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">&#39;UNARY&#39;</span>
<span class="nx">o</span> <span class="s">&#39;UNARY Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$1</span> <span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;- Expression&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;-&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">&#39;UNARY&#39;</span>
<span class="nx">o</span> <span class="s">&#39;+ Expression&#39;</span><span class="p">,</span> <span class="p">(</span><span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="nx">$2</span><span class="p">),</span> <span class="nv">prec: </span><span class="s">&#39;UNARY&#39;</span>
<span class="nx">o</span> <span class="s">&#39;-- SimpleAssignable&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;++ SimpleAssignable&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;SimpleAssignable --&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s">&#39;SimpleAssignable ++&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <p><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">o</span> <span class="s">&#39;Expression ?&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;-- SimpleAssignable&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;++ SimpleAssignable&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$2</span>
<span class="nx">o</span> <span class="s">&#39;SimpleAssignable --&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;--&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span>
<span class="nx">o</span> <span class="s">&#39;SimpleAssignable ++&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;++&#39;</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="kc">true</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <p><a href="http://jashkenas.github.com/coffee-script/#existence">The existential operator</a>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">o</span> <span class="s">&#39;Expression ?&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Existence</span> <span class="nx">$1</span>
<span class="nx">o</span> <span class="s">&#39;Expression + Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;+&#39;</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression - Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="s">&#39;-&#39;</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression + Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;+&#39;</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression - Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="s">&#39;-&#39;</span> <span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression MATH Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression SHIFT Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression COMPARE Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression LOGIC Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression MATH Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression SHIFT Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression COMPARE Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression LOGIC Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;Expression RELATION Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span>
<span class="k">if</span> <span class="nx">$2</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="s">&#39;!&#39;</span>
<span class="nx">Op</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">$2</span><span class="p">[</span><span class="mi">1</span><span class="p">..],</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span>
<span class="k">new</span> <span class="nx">Op</span><span class="p">(</span><span class="nx">$2</span><span class="p">[</span><span class="mi">1</span><span class="p">..],</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">).</span><span class="nx">invert</span><span class="p">()</span>
<span class="k">else</span>
<span class="nx">Op</span><span class="p">.</span><span class="nx">create</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="k">new</span> <span class="nx">Op</span> <span class="nx">$2</span><span class="p">,</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span>
<span class="nx">o</span> <span class="s">&#39;SimpleAssignable COMPOUND_ASSIGN</span>
<span class="s"> Expression&#39;</span><span class="p">,</span> <span class="nf">-&gt;</span> <span class="k">new</span> <span class="nx">Assign</span> <span class="nx">$1</span><span class="p">,</span> <span class="nx">$3</span><span class="p">,</span> <span class="nx">$2</span>
@@ -384,7 +384,7 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<pre><code>(2 + 3) * 4
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">operators = </span><span class="p">[</span>
<span class="p">[</span><span class="s">&#39;left&#39;</span><span class="p">,</span> <span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;::&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;left&#39;</span><span class="p">,</span> <span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;::&#39;</span><span class="p">,</span> <span class="s">&#39;?::&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;left&#39;</span><span class="p">,</span> <span class="s">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s">&#39;CALL_END&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;nonassoc&#39;</span><span class="p">,</span> <span class="s">&#39;++&#39;</span><span class="p">,</span> <span class="s">&#39;--&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;left&#39;</span><span class="p">,</span> <span class="s">&#39;?&#39;</span><span class="p">]</span>

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> helpers.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>This file contains the common helper functions that we'd like to share among
<!DOCTYPE html> <html> <head> <title>helpers.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> helpers.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>This file contains the common helper functions that we'd like to share among
the <strong>Lexer</strong>, <strong>Rewriter</strong>, and the <strong>Nodes</strong>. Merge objects, flatten
arrays, count characters, that sort of thing.</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">&#182;</a> </div> <p>Peek at the beginning of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.starts = </span><span class="nf">(string, literal, start) -&gt;</span>
<span class="nx">literal</span> <span class="o">is</span> <span class="nx">string</span><span class="p">.</span><span class="nx">substr</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">literal</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Peek at the end of a given string to see if it matches a sequence.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.ends = </span><span class="nf">(string, literal, back) -&gt;</span>
@@ -51,6 +51,13 @@ updates that object's locationData. The object is returned either way.</p>
<span class="s">&quot;</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_line</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">:</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_column</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">-&quot;</span> <span class="o">+</span>
<span class="s">&quot;</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">last_line</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">:</span><span class="si">#{</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">last_column</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">else</span>
<span class="s">&quot;No location data&quot;</span>
<span class="s">&quot;No location data&quot;</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.baseFileName = </span><span class="nf">(file, stripExt = no) -&gt;</span>
<span class="nv">parts = </span><span class="nx">file</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
<span class="nv">file = </span><span class="nx">parts</span><span class="p">[</span><span class="nx">parts</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">file</span> <span class="k">unless</span> <span class="nx">stripExt</span>
<span class="nv">parts = </span><span class="nx">file</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">)</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">parts</span><span class="p">[</span><span class="nx">parts</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">is</span> <span class="s">&#39;coffee&#39;</span>
<span class="nx">parts</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s">&#39;.&#39;</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">&#182;</a> </div> <p>Determine if a filename represents a CoffeeScript file.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.isCoffee = </span><span class="nf">(file) -&gt;</span> <span class="o">/</span><span class="err">\</span><span class="p">.((</span><span class="nx">lit</span><span class="p">)</span><span class="o">?</span><span class="nx">coffee</span><span class="o">|</span><span class="nx">coffee</span><span class="err">\</span><span class="p">.</span><span class="nx">md</span><span class="p">)</span><span class="nx">$</span><span class="o">/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">file</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Determine if a filename represents a Literate CoffeeScript file.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.isLiterate = </span><span class="nf">(file) -&gt;</span> <span class="o">/</span><span class="err">\</span><span class="p">.(</span><span class="nx">litcoffee</span><span class="o">|</span><span class="nx">coffee</span><span class="err">\</span><span class="p">.</span><span class="nx">md</span><span class="p">)</span><span class="nx">$</span><span class="o">/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">file</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -1,3 +1,3 @@
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>Loader for CoffeeScript as a Node.js library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</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="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">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<!DOCTYPE html> <html> <head> <title>index.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> index.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>Loader for CoffeeScript as a Node.js library.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nx">exports</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="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">require</span> <span class="s">&#39;./coffee-script&#39;</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html> <html> <head> <title>lexer.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> lexer.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
<!DOCTYPE html> <html> <head> <title>lexer.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> lexer.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The CoffeeScript Lexer. Uses a series of token-matching regexes to attempt
matches against the beginning of the source code. When a match is found,
a token is produced, we consume the match, and start again. Tokens are in the
form:</p>
@@ -22,7 +22,6 @@ it has consumed.</p>
<p>Before returning the token stream, run it through the <a href="rewriter.html">Rewriter</a>
unless explicitly asked not to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tokenize: </span><span class="nf">(code, opts = {}) -&gt;</span>
<span class="vi">@literate = </span><span class="nx">opts</span><span class="p">.</span><span class="nx">literate</span> <span class="c1"># Are we lexing literate CoffeeScript?</span>
<span class="nv">code = </span><span class="nx">@clean</span> <span class="nx">code</span> <span class="c1"># The stripped, cleaned original source code.</span>
<span class="vi">@indent = </span><span class="mi">0</span> <span class="c1"># The current indentation level.</span>
<span class="vi">@indebt = </span><span class="mi">0</span> <span class="c1"># The over-indentation at the current level.</span>
<span class="vi">@outdebt = </span><span class="mi">0</span> <span class="c1"># The under-outdentation at the current level.</span>
@@ -33,7 +32,8 @@ unless explicitly asked not to.</p> </td> <td class="cod
<span class="vi">@chunkLine =</span>
<span class="nx">opts</span><span class="p">.</span><span class="nx">line</span> <span class="o">or</span> <span class="mi">0</span> <span class="c1"># The start line for the current @chunk.</span>
<span class="vi">@chunkColumn =</span>
<span class="nx">opts</span><span class="p">.</span><span class="nx">column</span> <span class="o">or</span> <span class="mi">0</span> <span class="c1"># The start column of the current @chunk.</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>At every position, run through this list of attempted matches,
<span class="nx">opts</span><span class="p">.</span><span class="nx">column</span> <span class="o">or</span> <span class="mi">0</span> <span class="c1"># The start column of the current @chunk.</span>
<span class="nv">code = </span><span class="nx">@clean</span> <span class="nx">code</span> <span class="c1"># The stripped, cleaned original source code.</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>At every position, run through this list of attempted matches,
short-circuiting if any of them succeed. Their order determines precedence:
<code>@literalToken</code> is the fallback catch-all.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">i = </span><span class="mi">0</span>
<span class="k">while</span> <span class="vi">@chunk = </span><span class="nx">code</span><span class="p">[</span><span class="nx">i</span><span class="p">..]</span>
@@ -58,8 +58,10 @@ short-circuiting if any of them succeed. Their order determines precedence:
returns, etc. If we're lexing literate CoffeeScript, strip external Markdown
by removing all lines that aren't indented by at least four spaces or a tab.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">clean: </span><span class="nf">(code) -&gt;</span>
<span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="nx">code</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">is</span> <span class="nx">BOM</span>
<span class="nv">code = </span><span class="s">&quot;\n</span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s">&quot;</span> <span class="k">if</span> <span class="nx">WHITESPACE</span><span class="p">.</span><span class="nx">test</span> <span class="nx">code</span>
<span class="nv">code = </span><span class="nx">code</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\r/g</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">).</span><span class="nx">replace</span> <span class="nx">TRAILING_SPACES</span><span class="p">,</span> <span class="s">&#39;&#39;</span>
<span class="k">if</span> <span class="nx">WHITESPACE</span><span class="p">.</span><span class="nx">test</span> <span class="nx">code</span>
<span class="nv">code = </span><span class="s">&quot;\n</span><span class="si">#{</span><span class="nx">code</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">@chunkLine</span><span class="o">--</span>
<span class="k">if</span> <span class="nx">@literate</span>
<span class="nv">lines = </span><span class="k">for</span> <span class="nx">line</span> <span class="k">in</span> <span class="nx">code</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s">&#39;\n&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="nv">match = </span><span class="nx">LITERATE</span><span class="p">.</span><span class="nx">exec</span> <span class="nx">line</span>
@@ -81,7 +83,7 @@ though <code>is</code> means <code>===</code> otherwise.</p> </td>
<span class="nx">@token</span> <span class="s">&#39;OWN&#39;</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="p">(</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="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;::&#39;</span><span class="p">]</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="p">(</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="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;::&#39;</span><span class="p">,</span> <span class="s">&#39;?::&#39;</span><span class="p">]</span> <span class="o">or</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="o">is</span> <span class="s">&#39;@&#39;</span><span class="p">)</span>
<span class="nv">tag = </span><span class="s">&#39;IDENTIFIER&#39;</span>
@@ -359,6 +361,7 @@ erasing all external indentation on the left-hand side.</p> </td>
<span class="nv">attempt = </span><span class="nx">match</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nv">indent = </span><span class="nx">attempt</span> <span class="k">if</span> <span class="nx">indent</span> <span class="o">is</span> <span class="kc">null</span> <span class="o">or</span> <span class="mi">0</span> <span class="o">&lt;</span> <span class="nx">attempt</span><span class="p">.</span><span class="nx">length</span> <span class="o">&lt;</span> <span class="nx">indent</span><span class="p">.</span><span class="nx">length</span>
<span class="nv">doc = </span><span class="nx">doc</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/// \n </span><span class="si">#{</span><span class="nx">indent</span><span class="si">}</span><span class="sr"> ///g</span><span class="p">,</span> <span class="s">&#39;\n&#39;</span> <span class="k">if</span> <span class="nx">indent</span>
<span class="nv">doc = </span><span class="nx">doc</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\n# \n/g</span><span class="p">,</span> <span class="s">&#39;\n\n&#39;</span> <span class="k">if</span> <span class="nx">@literate</span>
<span class="nv">doc = </span><span class="nx">doc</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/^\n/</span><span class="p">,</span> <span class="s">&#39;&#39;</span> <span class="k">unless</span> <span class="nx">herecomment</span>
<span class="nx">doc</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>A source of ambiguity in our grammar used to be parameter lists in function
definitions versus argument lists in function calls. Walk backwards, tagging
@@ -505,21 +508,18 @@ correctly balanced throughout the course of the token stream.</p> </
<span class="k">else</span>
<span class="nx">column</span> <span class="o">+=</span> <span class="nx">string</span><span class="p">.</span><span class="nx">length</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">@chunkLine</span> <span class="o">+</span> <span class="nx">lineCount</span><span class="p">,</span> <span class="nx">column</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">&#182;</a> </div> <p>Same as "token", exception this just returns the token without adding it
to the results.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">makeToken: </span><span class="nf">(tag, value, offsetInChunk, length) -&gt;</span>
<span class="nv">offsetInChunk = </span><span class="nx">offsetInChunk</span> <span class="o">||</span> <span class="mi">0</span>
<span class="k">if</span> <span class="nx">length</span> <span class="o">is</span> <span class="kc">undefined</span> <span class="k">then</span> <span class="nv">length = </span><span class="nx">value</span><span class="p">.</span><span class="nx">length</span>
<span class="p">[</span><span class="nx">@chunkLine</span> <span class="o">+</span> <span class="nx">lineCount</span><span class="p">,</span> <span class="nx">column</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">&#182;</a> </div> <p>Same as "token", exception this just returns the token without adding it
to the results.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">makeToken: </span><span class="nf">(tag, value, offsetInChunk = 0, length = value.length) -&gt;</span>
<span class="nv">locationData = </span><span class="p">{}</span>
<span class="p">[</span><span class="nx">locationData</span><span class="p">.</span><span class="nx">first_line</span><span class="p">,</span> <span class="nx">locationData</span><span class="p">.</span><span class="nx">first_column</span><span class="p">]</span> <span class="o">=</span>
<span class="nx">@getLineAndColumnFromChunk</span> <span class="nx">offsetInChunk</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">&#182;</a> </div> <p>Use length - 1 for the final offset - we're supplying the last<em>line and the last</em>column,
so if last<em>column == first</em>column, then we're looking at a character of length 1.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">lastCharacter = </span><span class="k">if</span> <span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="p">(</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="k">else</span> <span class="mi">0</span>
so if last<em>column == first</em>column, then we're looking at a character of length 1.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">lastCharacter = </span><span class="nb">Math</span><span class="p">.</span><span class="nx">max</span> <span class="mi">0</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="nx">locationData</span><span class="p">.</span><span class="nx">last_line</span><span class="p">,</span> <span class="nx">locationData</span><span class="p">.</span><span class="nx">last_column</span><span class="p">]</span> <span class="o">=</span>
<span class="nx">@getLineAndColumnFromChunk</span> <span class="nx">offsetInChunk</span> <span class="o">+</span> <span class="p">(</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="nv">token = </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="nx">locationData</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">token</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>Add a token to the results.
<span class="nx">token</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>Add a token to the results.
<code>offset</code> is the offset into the current @chunk where the token starts.
<code>length</code> is the length of the token in the @chunk, after the offset. If
not specified, the length of <code>value</code> will be used.</p>
@@ -527,11 +527,11 @@ not specified, the length of <code>value</code> will be used.</p>
<p>Returns the new token.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">token: </span><span class="nf">(tag, value, offsetInChunk, length) -&gt;</span>
<span class="nv">token = </span><span class="nx">@makeToken</span> <span class="nx">tag</span><span class="p">,</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">offsetInChunk</span><span class="p">,</span> <span class="nx">length</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">push</span> <span class="nx">token</span>
<span class="k">return</span> <span class="nx">token</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p>Peek at a tag in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="nf">(index, tag) -&gt;</span>
<span class="nx">token</span></pre></div> </td> </tr> <tr id="section-52"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-52">&#182;</a> </div> <p>Peek at a tag in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="nf">(index, tag) -&gt;</span>
<span class="p">(</span><span class="nv">tok = </span><span class="nx">last</span> <span class="nx">@tokens</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">and</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="nx">tag</span> <span class="k">else</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-53"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-53">&#182;</a> </div> <p>Peek at a value in the current token stream.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">value: </span><span class="nf">(index, val) -&gt;</span>
<span class="p">(</span><span class="nv">tok = </span><span class="nx">last</span> <span class="nx">@tokens</span><span class="p">,</span> <span class="nx">index</span><span class="p">)</span> <span class="o">and</span> <span class="k">if</span> <span class="nx">val</span> <span class="k">then</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span> <span class="k">else</span> <span class="nx">tok</span><span class="p">[</span><span class="mi">1</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">&#182;</a> </div> <p>Are we in the midst of an unfinished expression?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">unfinished: </span><span class="nf">-&gt;</span>
<span class="nx">LINE_CONTINUER</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">@chunk</span><span class="p">)</span> <span class="o">or</span>
<span class="nx">@tag</span><span class="p">()</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;\\&#39;</span><span class="p">,</span> <span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;UNARY&#39;</span><span class="p">,</span> <span class="s">&#39;MATH&#39;</span><span class="p">,</span> <span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">,</span> <span class="s">&#39;SHIFT&#39;</span><span class="p">,</span> <span class="s">&#39;RELATION&#39;</span>
<span class="nx">@tag</span><span class="p">()</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;\\&#39;</span><span class="p">,</span> <span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;?::&#39;</span><span class="p">,</span> <span class="s">&#39;UNARY&#39;</span><span class="p">,</span> <span class="s">&#39;MATH&#39;</span><span class="p">,</span> <span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">,</span> <span class="s">&#39;SHIFT&#39;</span><span class="p">,</span> <span class="s">&#39;RELATION&#39;</span>
<span class="s">&#39;COMPARE&#39;</span><span class="p">,</span> <span class="s">&#39;LOGIC&#39;</span><span class="p">,</span> <span class="s">&#39;THROW&#39;</span><span class="p">,</span> <span class="s">&#39;EXTENDS&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">&#182;</a> </div> <p>Converts newlines for string literals.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">escapeLines: </span><span class="nf">(str, heredoc) -&gt;</span>
<span class="nx">str</span><span class="p">.</span><span class="nx">replace</span> <span class="nx">MULTILINER</span><span class="p">,</span> <span class="k">if</span> <span class="nx">heredoc</span> <span class="k">then</span> <span class="s">&#39;\\n&#39;</span> <span class="k">else</span> <span class="s">&#39;&#39;</span></pre></div> </td> </tr> <tr id="section-56"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-56">&#182;</a> </div> <p>Constructs a string token by escaping quotes and newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">makeString: </span><span class="nf">(body, quote, heredoc) -&gt;</span>
<span class="k">return</span> <span class="nx">quote</span> <span class="o">+</span> <span class="nx">quote</span> <span class="k">unless</span> <span class="nx">body</span>
@@ -592,7 +592,7 @@ be used as identifiers or properties.</p> </td> <td clas
<span class="sr"> | &gt;&gt;&gt;=? # zero-fill right shift</span>
<span class="sr"> | ([-+:])\1 # doubles</span>
<span class="sr"> | ([&amp;|&lt;&gt;])\2=? # logic / shift</span>
<span class="sr"> | \?\. # soak access</span>
<span class="sr"> | \?(\.|::) # soak access</span>
<span class="sr"> | \.{2,3} # range or splat</span>
<span class="sr">) ///</span>

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> optparse.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
<!DOCTYPE html> <html> <head> <title>optparse.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> optparse.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>A simple <strong>OptionParser</strong> class to parse option flags from the command-line.
Use it like so:</p>
<pre><code>parser = new OptionParser switches, helpBanner

View File

@@ -1,15 +1,15 @@
<!DOCTYPE html> <html> <head> <title>repl.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> repl.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="nv">vm = </span><span class="nx">require</span> <span class="s">&#39;vm&#39;</span>
<!DOCTYPE html> <html> <head> <title>repl.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> repl.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> </td> <td class="code"> <div class="highlight"><pre><span class="nv">vm = </span><span class="nx">require</span> <span class="s">&#39;vm&#39;</span>
<span class="nv">nodeREPL = </span><span class="nx">require</span> <span class="s">&#39;repl&#39;</span>
<span class="nv">CoffeeScript = </span><span class="nx">require</span> <span class="s">&#39;./coffee-script&#39;</span>
<span class="p">{</span><span class="nx">merge</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s">&#39;./helpers&#39;</span>
<span class="nv">replDefaults =</span>
<span class="nv">prompt: </span><span class="s">&#39;coffee&gt; &#39;</span><span class="p">,</span>
<span class="nb">eval</span><span class="o">:</span> <span class="nf">(input, context, filename, cb) -&gt;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>XXX: multiline hack</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\uFF00/g</span><span class="p">,</span> <span class="s">&#39;\n&#39;</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>strip single-line comments</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/</span><span class="p">,</span> <span class="s">&#39;$1$2$3&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>empty command</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="nx">cb</span> <span class="kc">null</span> <span class="k">if</span> <span class="sr">/^\s*$/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">input</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span>
<span class="nb">eval</span><span class="o">:</span> <span class="nf">(input, context, filename, cb) -&gt;</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <p>XXX: multiline hack</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/\uFF00/g</span><span class="p">,</span> <span class="s">&#39;\n&#39;</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>strip single-line comments</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">input = </span><span class="nx">input</span><span class="p">.</span><span class="nx">replace</span> <span class="sr">/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/</span><span class="p">,</span> <span class="s">&#39;$1$2$3&#39;</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>empty command</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="nx">cb</span> <span class="kc">null</span> <span class="k">if</span> <span class="sr">/^(\s*|\(\s*\))$/</span><span class="p">.</span><span class="nx">test</span> <span class="nx">input</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">try</span>
<span class="nv">js = </span><span class="nx">CoffeeScript</span><span class="p">.</span><span class="nx">compile</span> <span class="s">&quot;_=(</span><span class="si">#{</span><span class="nx">input</span><span class="si">}</span><span class="s">\n)&quot;</span><span class="p">,</span> <span class="p">{</span><span class="nx">filename</span><span class="p">,</span> <span class="nv">bare: </span><span class="kc">yes</span><span class="p">}</span>
<span class="nx">cb</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span><span class="p">(</span><span class="nx">js</span><span class="p">,</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span>
<span class="k">catch</span> <span class="nx">err</span>
<span class="nx">cb</span> <span class="nx">err</span>
<span class="nx">cb</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">vm</span><span class="p">.</span><span class="nx">runInContext</span><span class="p">(</span><span class="nx">js</span><span class="p">,</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">filename</span><span class="p">)</span>
<span class="nv">addMultilineHandler = </span><span class="nf">(repl) -&gt;</span>
<span class="p">{</span><span class="nx">rli</span><span class="p">,</span> <span class="nx">inputStream</span><span class="p">,</span> <span class="nx">outputStream</span><span class="p">}</span> <span class="o">=</span> <span class="nx">repl</span>

View File

@@ -1,11 +1,14 @@
<!DOCTYPE html> <html> <head> <title>rewriter.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> rewriter.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The CoffeeScript language has a good deal of optional syntax, implicit syntax,
<!DOCTYPE html> <html> <head> <title>rewriter.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> rewriter.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <p>The CoffeeScript language has a good deal of optional syntax, implicit syntax,
and shorthand syntax. This can greatly complicate a grammar and bloat
the resulting parse table. Instead of making the parser handle it all, we take
a series of passes over the token stream, using this <strong>Rewriter</strong> to convert
shorthand into the unambiguous long form, add implicit indentation and
parentheses, and generally clean things up.</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">&#182;</a> </div> <p>The <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>Helpful snippet for debugging:
console.log (t[0] + '/' + t[1] for t in @tokens).join ' '</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Rewrite the token stream in multiple passes, one logical filter at
parentheses, and generally clean things up.</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">&#182;</a> </div> <p>Create a generated token: one that exists due to a use of implicit syntax.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">generate = </span><span class="nf">(tag, value) -&gt;</span>
<span class="nv">tok = </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="nv">tok.generated = </span><span class="kc">yes</span>
<span class="nx">tok</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>The <strong>Rewriter</strong> class is used by the <a href="lexer.html">Lexer</a>, directly against
its internal array of tokens.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">Rewriter</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Helpful snippet for debugging:
console.log (t[0] + '/' + t[1] for t in @tokens).join ' '</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Rewrite the token stream in multiple passes, one logical filter at
a time. This could certainly be changed into a single pass through the
stream, with a big ol' efficient switch, but it's much nicer to work with
like this. The order of these passes matters -- indentation must be
@@ -16,10 +19,9 @@ corrected before implicit parentheses can be wrapped around blocks of code.</p>
<span class="nx">@closeOpenIndexes</span><span class="p">()</span>
<span class="nx">@addImplicitIndentation</span><span class="p">()</span>
<span class="nx">@tagPostfixConditionals</span><span class="p">()</span>
<span class="nx">@addImplicitBraces</span><span class="p">()</span>
<span class="nx">@addImplicitParentheses</span><span class="p">()</span>
<span class="nx">@addImplicitBracesAndParens</span><span class="p">()</span>
<span class="nx">@addLocationDataToGeneratedTokens</span><span class="p">()</span>
<span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
<span class="nx">@tokens</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Rewrite the token stream, looking one token ahead and behind.
Allow the return value of the block to tell us how many tokens to move
forwards (or backwards) in the stream, to make sure we don't miss anything
as tokens are inserted and removed, and the stream changes length under
@@ -40,18 +42,17 @@ our feet.</p> </td> <td class="code"> <div
<span class="k">else</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="nx">EXPRESSION_END</span>
<span class="nx">levels</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we
<span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Leading newlines would introduce an ambiguity in the grammar, so we
dispatch them here.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeLeadingNewlines: </span><span class="nf">-&gt;</span>
<span class="k">break</span> <span class="k">for</span> <span class="p">[</span><span class="nx">tag</span><span class="p">],</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">@tokens</span> <span class="k">when</span> <span class="nx">tag</span> <span class="o">isnt</span> <span class="s">&#39;TERMINATOR&#39;</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">i</span> <span class="k">if</span> <span class="nx">i</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">i</span> <span class="k">if</span> <span class="nx">i</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Some blocks occur in the middle of expressions -- when we're expecting
this, remove their trailing newlines.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">removeMidExpressionNewlines: </span><span class="nf">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -&gt;</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;TERMINATOR&#39;</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="nx">EXPRESSION_CLOSE</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span>
<span class="mi">0</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>The lexer has tagged the opening parenthesis of a method call. Match it with
<span class="mi">0</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>The lexer has tagged the opening parenthesis of a method call. Match it with
its paired close. We have the mis-nested outdent case included here for
calls that close on the same line, just before their outdent.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenCalls: </span><span class="nf">-&gt;</span>
<span class="nv">condition = </span><span class="nf">(token, i) -&gt;</span>
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;)&#39;</span><span class="p">,</span> <span class="s">&#39;CALL_END&#39;</span><span class="p">]</span> <span class="o">or</span>
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;OUTDENT&#39;</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;)&#39;</span>
@@ -61,9 +62,8 @@ calls that close on the same line, just before their outdent.</p> </
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -&gt;</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;CALL_START&#39;</span>
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>The lexer has tagged the opening parenthesis of an indexing operation call.
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>The lexer has tagged the opening parenthesis of an indexing operation call.
Match it with its paired close.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">closeOpenIndexes: </span><span class="nf">-&gt;</span>
<span class="nv">condition = </span><span class="nf">(token, i) -&gt;</span>
<span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;]&#39;</span><span class="p">,</span> <span class="s">&#39;INDEX_END&#39;</span><span class="p">]</span>
@@ -72,114 +72,176 @@ Match it with its paired close.</p> </td> <td class="cod
<span class="nx">@scanTokens</span> <span class="nf">(token, i) -&gt;</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;INDEX_START&#39;</span>
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Object literals may be written with implicit braces, for simple cases.
Insert the missing braces here, so that the parser doesn't have to.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitBraces: </span><span class="nf">-&gt;</span>
<span class="nv">stack = </span><span class="p">[]</span>
<span class="nv">start = </span><span class="kc">null</span>
<span class="nv">startsLine = </span><span class="kc">null</span>
<span class="nv">sameLine = </span><span class="kc">yes</span>
<span class="nv">startIndent = </span><span class="mi">0</span>
<span class="nv">startIndex = </span><span class="mi">0</span>
<span class="nv">condition = </span><span class="nf">(token, i) -&gt;</span>
<span class="p">[</span><span class="nx">one</span><span class="p">,</span> <span class="nx">two</span><span class="p">,</span> <span class="nx">three</span><span class="p">]</span> <span class="o">=</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">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">no</span> <span class="k">if</span> <span class="s">&#39;HERECOMMENT&#39;</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="nv">sameLine = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
<span class="k">return</span> <span class="p">(</span>
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s">&#39;OUTDENT&#39;</span><span class="p">]</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">and</span> <span class="nx">sameLine</span> <span class="o">and</span> <span class="o">not</span> <span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="nx">startIndex</span> <span class="o">is</span> <span class="mi">1</span><span class="p">)))</span> <span class="o">and</span>
<span class="p">((</span><span class="o">!</span><span class="nx">startsLine</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">&#39;,&#39;</span><span class="p">)</span> <span class="o">or</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="s">&#39;:&#39;</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="s">&#39;@&#39;</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="s">&#39;:&#39;</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="s">&#39;,&#39;</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="s">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="s">&#39;STRING&#39;</span><span class="p">,</span> <span class="s">&#39;@&#39;</span><span class="p">,</span> <span class="s">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s">&#39;OUTDENT&#39;</span><span class="p">]</span>
<span class="p">)</span>
<span class="nv">action = </span><span class="nf">(token, i) -&gt;</span>
<span class="nv">tok = </span><span class="nx">@generate</span> <span class="s">&#39;}&#39;</span><span class="p">,</span> <span class="s">&#39;}&#39;</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</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">&#182;</a> </div> <p>Match tags in token stream starting at i with pattern, skipping HERECOMMENTs
Pattern may consist of strings (equality), an array of strings (one of)
or null (wildcard)</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">matchTags: </span><span class="nf">(i, pattern...) -&gt;</span>
<span class="nv">fuzz = </span><span class="mi">0</span>
<span class="k">for</span> <span class="nx">j</span> <span class="k">in</span> <span class="p">[</span><span class="mi">0</span> <span class="p">...</span> <span class="nx">pattern</span><span class="p">.</span><span class="nx">length</span><span class="p">]</span>
<span class="nx">fuzz</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">i</span> <span class="o">+</span> <span class="nx">j</span> <span class="o">+</span> <span class="nx">fuzz</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;HERECOMMENT&#39;</span>
<span class="k">continue</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">pattern</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="o">?</span>
<span class="nx">pattern</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="nx">pattern</span><span class="p">[</span><span class="nx">j</span><span class="p">]]</span> <span class="k">if</span> <span class="k">typeof</span> <span class="nx">pattern</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;string&#39;</span>
<span class="k">return</span> <span class="kc">no</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="nx">j</span> <span class="o">+</span> <span class="nx">fuzz</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">pattern</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span>
<span class="kc">yes</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>yes iff standing in front of something looking like
@<x>: or <x>:, skipping over 'HERECOMMENT's</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">looksObjectish: </span><span class="nf">(j) -&gt;</span>
<span class="nx">@matchTags</span><span class="p">(</span><span class="nx">j</span><span class="p">,</span> <span class="s">&#39;@&#39;</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#39;:&#39;</span><span class="p">)</span> <span class="o">or</span> <span class="nx">@matchTags</span><span class="p">(</span><span class="nx">j</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#39;:&#39;</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>yes iff current line of tokens contain an element of tags on same
expression level. Stop searching at LINEBREAKS or explicit start of
containing balanced expression.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">findTagsBackwards: </span><span class="nf">(i, tags) -&gt;</span>
<span class="nv">backStack = </span><span class="p">[]</span>
<span class="k">while</span> <span class="nx">i</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">and</span> <span class="p">(</span><span class="nx">backStack</span><span class="p">.</span><span class="nx">length</span> <span class="o">or</span>
<span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">tags</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">EXPRESSION_START</span> <span class="o">or</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">generated</span><span class="p">)</span> <span class="o">and</span>
<span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span><span class="p">)</span>
<span class="nx">backStack</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="k">in</span> <span class="nx">EXPRESSION_END</span>
<span class="nx">backStack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="k">in</span> <span class="nx">EXPRESSION_START</span> <span class="o">and</span> <span class="nx">backStack</span><span class="p">.</span><span class="nx">length</span>
<span class="nx">i</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span> <span class="k">in</span> <span class="nx">tags</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Look for signs of implicit calls and objects in the token stream and
add them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitBracesAndParens: </span><span class="nf">-&gt;</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Track current balancing depth (both implicit and explicit) on stack.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">stack = </span><span class="p">[]</span>
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -&gt;</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="p">[(</span><span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;{&#39;</span> <span class="k">then</span> <span class="s">&#39;{&#39;</span> <span class="k">else</span> <span class="nx">tag</span><span class="p">),</span> <span class="nx">i</span><span class="p">]</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">EXPRESSION_END</span>
<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="k">unless</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;:&#39;</span> <span class="o">and</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="s">&#39;:&#39;</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="s">&#39;{&#39;</span><span class="p">)</span>
<span class="nv">sameLine = </span><span class="kc">yes</span>
<span class="nv">startIndex = </span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s">&#39;{&#39;</span><span class="p">]</span>
<span class="nv">idx = </span> <span class="k">if</span> <span class="nx">ago</span> <span class="o">is</span> <span class="s">&#39;@&#39;</span> <span class="k">then</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nx">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="s">&#39;HERECOMMENT&#39;</span>
<span class="nv">prevTag = </span><span class="nx">@tag</span><span class="p">(</span><span class="nx">idx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="nv">startsLine = </span><span class="o">not</span> <span class="nx">prevTag</span> <span class="o">or</span> <span class="p">(</span><span class="nx">prevTag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span><span class="p">)</span>
<span class="nv">value = </span><span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="s">&#39;{&#39;</span><span class="p">)</span>
<span class="nv">value.generated = </span><span class="kc">yes</span>
<span class="nv">tok = </span><span class="nx">@generate</span> <span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="nx">value</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">tok</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="mi">2</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Methods may be optionally called without parentheses, for simple cases.
Insert the implicit parentheses here, so that the parser doesn't have to
deal with them.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitParentheses: </span><span class="nf">-&gt;</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">prevTag</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="p">[]</span>
<span class="p">[</span><span class="nx">nextTag</span><span class="p">]</span> <span class="o">=</span> <span class="k">if</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">tokens</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">then</span> <span class="nx">tokens</span><span class="p">[</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span> <span class="p">[]</span>
<span class="nv">stackTop = </span><span class="nf">-&gt;</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="nv">startIdx = </span><span class="nx">i</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Helper function, used for keeping track of the number of tokens consumed
and spliced, when returning for getting a new token.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">forward = </span><span class="nf">(n) -&gt;</span> <span class="nx">i</span> <span class="o">-</span> <span class="nx">startIdx</span> <span class="o">+</span> <span class="nx">n</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Helper functions</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">inImplicit = </span><span class="nf">-&gt;</span> <span class="nx">stackTop</span><span class="p">()</span><span class="o">?</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">?</span><span class="p">.</span><span class="nx">ours</span>
<span class="nv">inImplicitCall = </span><span class="nf">-&gt;</span> <span class="nx">inImplicit</span><span class="p">()</span> <span class="o">and</span> <span class="nx">stackTop</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">is</span> <span class="s">&#39;(&#39;</span>
<span class="nv">inImplicitObject = </span><span class="nf">-&gt;</span> <span class="nx">inImplicit</span><span class="p">()</span> <span class="o">and</span> <span class="nx">stackTop</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">is</span> <span class="s">&#39;{&#39;</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>Unclosed control statement inside implicit parens (like
class declaration or if-conditionals)</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">inImplicitControl = </span><span class="nf">-&gt;</span> <span class="nx">inImplicit</span> <span class="o">and</span> <span class="nx">stackTop</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">is</span> <span class="s">&#39;CONTROL&#39;</span>
<span class="nv">noCall = seenSingle = seenControl = </span><span class="kc">no</span>
<span class="nv">callIndex = </span><span class="kc">null</span>
<span class="nv">startImplicitCall = </span><span class="nf">(j) -&gt;</span>
<span class="nv">idx = </span><span class="nx">j</span> <span class="o">?</span> <span class="nx">i</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s">&#39;(&#39;</span><span class="p">,</span> <span class="nx">idx</span><span class="p">,</span> <span class="nv">ours: </span><span class="kc">yes</span><span class="p">]</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">generate</span> <span class="s">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s">&#39;(&#39;</span>
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">j</span><span class="o">?</span>
<span class="nv">condition = </span><span class="nf">(token, i) -&gt;</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="k">return</span> <span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">seenSingle</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
<span class="nv">seenSingle = </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="s">&#39;IF&#39;</span><span class="p">,</span> <span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;CLASS&#39;</span><span class="p">]</span>
<span class="nv">seenControl = </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="s">&#39;IF&#39;</span><span class="p">,</span> <span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;SWITCH&#39;</span><span class="p">,</span> <span class="s">&#39;TRY&#39;</span><span class="p">,</span> <span class="s">&#39;=&#39;</span><span class="p">]</span>
<span class="k">return</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="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;::&#39;</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;OUTDENT&#39;</span>
<span class="o">not</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">isnt</span> <span class="s">&#39;,&#39;</span> <span class="o">and</span> <span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">seenControl</span><span class="p">))</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">tag</span> <span class="o">isnt</span> <span class="s">&#39;INDENT&#39;</span> <span class="o">or</span>
<span class="p">(</span><span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;CLASS&#39;</span><span class="p">,</span> <span class="s">&#39;EXTENDS&#39;</span><span class="p">]</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">not</span> <span class="k">in</span> <span class="nx">IMPLICIT_BLOCK</span> <span class="o">and</span>
<span class="o">not</span> <span class="p">(</span><span class="nx">callIndex</span> <span class="o">is</span> <span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">and</span> <span class="p">(</span><span class="nv">post = </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="o">and</span> <span class="nx">post</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">post</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;{&#39;</span><span class="p">)))</span>
<span class="nv">endImplicitCall = </span><span class="nf">-&gt;</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">generate</span> <span class="s">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s">&#39;)&#39;</span>
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nv">action = </span><span class="nf">(token, i) -&gt;</span>
<span class="nx">@tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@generate</span> <span class="s">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s">&#39;)&#39;</span>
<span class="nv">startImplicitObject = </span><span class="nf">(j, startsLine = yes) -&gt;</span>
<span class="nv">idx = </span><span class="nx">j</span> <span class="o">?</span> <span class="nx">i</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="nx">idx</span><span class="p">,</span> <span class="nv">sameLine: </span><span class="kc">yes</span><span class="p">,</span> <span class="nv">startsLine: </span><span class="nx">startsLine</span><span class="p">,</span> <span class="nv">ours: </span><span class="kc">yes</span><span class="p">]</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">idx</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">generate</span> <span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="nx">generate</span><span class="p">(</span><span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="s">&#39;{&#39;</span><span class="p">))</span>
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">j</span><span class="o">?</span>
<span class="nv">endImplicitObject = </span><span class="nf">(j) -&gt;</span>
<span class="nv">j = </span><span class="nx">j</span> <span class="o">?</span> <span class="nx">i</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">j</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">generate</span> <span class="s">&#39;}&#39;</span><span class="p">,</span> <span class="s">&#39;}&#39;</span>
<span class="nx">i</span> <span class="o">+=</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>Don't end an implicit call on next indent if any of these are in an argument</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">inImplicitCall</span><span class="p">()</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;IF&#39;</span><span class="p">,</span> <span class="s">&#39;TRY&#39;</span><span class="p">,</span> <span class="s">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s">&#39;CATCH&#39;</span><span class="p">,</span>
<span class="s">&#39;CLASS&#39;</span><span class="p">,</span> <span class="s">&#39;SWITCH&#39;</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="s">&#39;CONTROL&#39;</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nv">ours: </span><span class="kc">true</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="nx">inImplicit</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">&#182;</a> </div> <p>An INDENT closes an implicit call unless
1. We have seen a CONTROL argument on the line.
2. The last token before the indent is part of the list below</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">prevTag</span> <span class="o">not</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;[&#39;</span><span class="p">,</span> <span class="s">&#39;(&#39;</span><span class="p">,</span> <span class="s">&#39;,&#39;</span><span class="p">,</span> <span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="s">&#39;TRY&#39;</span><span class="p">,</span> <span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;=&#39;</span><span class="p">]</span>
<span class="nx">endImplicitCall</span><span class="p">()</span> <span class="k">while</span> <span class="nx">inImplicitCall</span><span class="p">()</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span> <span class="k">if</span> <span class="nx">inImplicitControl</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="nx">tag</span><span class="p">,</span> <span class="nx">i</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>Straightforward start of explicit expression</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">tag</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="p">[</span><span class="nx">tag</span><span class="p">,</span> <span class="nx">i</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>Close all implicit expressions inside of explicitly closed expressions.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">EXPRESSION_END</span>
<span class="k">while</span> <span class="nx">inImplicit</span><span class="p">()</span>
<span class="k">if</span> <span class="nx">inImplicitCall</span><span class="p">()</span>
<span class="nx">endImplicitCall</span><span class="p">()</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">inImplicitObject</span><span class="p">()</span>
<span class="nx">endImplicitObject</span><span class="p">()</span>
<span class="k">else</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">pop</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Recognize standard implicit calls like
f a, f() b, f? c, h[0] d etc.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_FUNC</span> <span class="o">and</span> <span class="nx">token</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">or</span>
<span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;?&#39;</span> <span class="o">and</span> <span class="nx">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="o">and</span> <span class="o">not</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">spaced</span><span class="p">)</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">nextTag</span> <span class="k">in</span> <span class="nx">IMPLICIT_CALL</span> <span class="o">or</span>
<span class="nx">nextTag</span> <span class="k">in</span> <span class="nx">IMPLICIT_UNSPACED_CALL</span> <span class="o">and</span>
<span class="o">not</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="o">?</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="o">not</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="o">?</span><span class="p">.</span><span class="nx">newLine</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="o">=</span> <span class="s">&#39;FUNC_EXIST&#39;</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;?&#39;</span>
<span class="nx">startImplicitCall</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>Implicit call taking an implicit indented object as first argument.
f
a: b
c: d
and
f
1
a: b
b: c
Don't accept implicit calls of this type, when on the same line
as the control strucutures below as that may misinterpret constructs like:
if f
a: 1
as
if f(a: 1)
which is probably always unintended.
Furthermore don't allow this in literal arrays, as
that creates grammatical ambiguities.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">@matchTags</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">IMPLICIT_FUNC</span><span class="p">,</span> <span class="s">&#39;INDENT&#39;</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="s">&#39;:&#39;</span><span class="p">)</span> <span class="o">and</span>
<span class="o">not</span> <span class="nx">@findTagsBackwards</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="p">[</span><span class="s">&#39;CLASS&#39;</span><span class="p">,</span> <span class="s">&#39;EXTENDS&#39;</span><span class="p">,</span> <span class="s">&#39;IF&#39;</span><span class="p">,</span> <span class="s">&#39;CATCH&#39;</span><span class="p">,</span>
<span class="s">&#39;SWITCH&#39;</span><span class="p">,</span> <span class="s">&#39;LEADING_WHEN&#39;</span><span class="p">,</span> <span class="s">&#39;FOR&#39;</span><span class="p">,</span> <span class="s">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s">&#39;UNTIL&#39;</span><span class="p">])</span>
<span class="nx">startImplicitCall</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span>
<span class="nx">stack</span><span class="p">.</span><span class="nx">push</span> <span class="p">[</span><span class="s">&#39;INDENT&#39;</span><span class="p">,</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>Implicit objects start here</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;:&#39;</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>Go back to the (implicit) start of the object</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;@&#39;</span> <span class="k">then</span> <span class="nv">s = </span><span class="nx">i</span> <span class="o">-</span> <span class="mi">2</span> <span class="k">else</span> <span class="nv">s = </span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nx">s</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">s</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;HERECOMMENT&#39;</span>
<span class="nv">startsLine = </span><span class="nx">s</span> <span class="o">is</span> <span class="mi">0</span> <span class="o">or</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">s</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span> <span class="o">or</span> <span class="nx">tokens</span><span class="p">[</span><span class="nx">s</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="nx">newLine</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>Are we just continuing an already declared object?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">stackTop</span><span class="p">()</span>
<span class="p">[</span><span class="nx">stackTag</span><span class="p">,</span> <span class="nx">stackIdx</span><span class="p">]</span> <span class="o">=</span> <span class="nx">stackTop</span><span class="p">()</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">stackTag</span> <span class="o">is</span> <span class="s">&#39;{&#39;</span> <span class="o">or</span> <span class="nx">stackTag</span> <span class="o">is</span> <span class="s">&#39;INDENT&#39;</span> <span class="o">and</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">stackIdx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;{&#39;</span><span class="p">)</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">startsLine</span> <span class="o">or</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">s</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;,&#39;</span> <span class="o">or</span> <span class="nx">@tag</span><span class="p">(</span><span class="nx">s</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">is</span> <span class="s">&#39;{&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="nx">startImplicitObject</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span> <span class="o">!!</span><span class="nx">startsLine</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>End implicit calls when chaining method calls
like e.g.:
f ->
a
.g b, ->
c
.h a</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">prevTag</span> <span class="o">is</span> <span class="s">&#39;OUTDENT&#39;</span> <span class="o">and</span> <span class="nx">inImplicitCall</span><span class="p">()</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="p">[</span><span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="s">&#39;?.&#39;</span><span class="p">,</span> <span class="s">&#39;::&#39;</span><span class="p">,</span> <span class="s">&#39;?::&#39;</span><span class="p">]</span>
<span class="nx">endImplicitCall</span><span class="p">()</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="nx">stackTop</span><span class="p">()[</span><span class="mi">2</span><span class="p">].</span><span class="nv">sameLine = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">inImplicitObject</span><span class="p">()</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
<span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_END</span>
<span class="k">while</span> <span class="nx">inImplicit</span><span class="p">()</span>
<span class="p">[</span><span class="nx">stackTag</span><span class="p">,</span> <span class="nx">stackIdx</span><span class="p">,</span> <span class="p">{</span><span class="nx">sameLine</span><span class="p">,</span> <span class="nx">startsLine</span><span class="p">}]</span> <span class="o">=</span> <span class="nx">stackTop</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Close implicit calls when reached end of argument list</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">inImplicitCall</span><span class="p">()</span> <span class="o">and</span> <span class="nx">prevTag</span> <span class="o">isnt</span> <span class="s">&#39;,&#39;</span>
<span class="nx">endImplicitCall</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>Close implicit objects such as:
return a: 1, b: 2 unless true</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">else</span> <span class="k">if</span> <span class="nx">inImplicitObject</span><span class="p">()</span> <span class="o">and</span> <span class="nx">sameLine</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">startsLine</span>
<span class="nx">endImplicitObject</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>Close implicit objects when at end of line, line didn't end with a comma
and the implicit object didn't start the line or the next line doesn't look like
the continuation of an object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">else</span> <span class="k">if</span> <span class="nx">inImplicitObject</span><span class="p">()</span> <span class="o">and</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;TERMINATOR&#39;</span> <span class="o">and</span> <span class="nx">prevTag</span> <span class="o">isnt</span> <span class="s">&#39;,&#39;</span> <span class="o">and</span>
<span class="o">not</span> <span class="p">(</span><span class="nx">startsLine</span> <span class="o">and</span> <span class="nx">@looksObjectish</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">endImplicitObject</span><span class="p">()</span>
<span class="k">else</span>
<span class="k">break</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">&#182;</a> </div> <p>Close implicit object if comma is the last character
and what comes after doesn't look like it belongs.
This is used for trailing commas and calls, like:
x =
a: b,
c: d,
e = 2</p>
<p>and</p>
<p>f a, b: c, d: e, f, g: h: i, j</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;,&#39;</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">@looksObjectish</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">and</span> <span class="nx">inImplicitObject</span><span class="p">()</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">nextTag</span> <span class="o">isnt</span> <span class="s">&#39;TERMINATOR&#39;</span> <span class="o">or</span> <span class="o">not</span> <span class="nx">@looksObjectish</span><span class="p">(</span><span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">))</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>When nextTag is OUTDENT the comma is insignificant and
should just be ignored so embed it in the implicit object.</p>
<p>When it isn't the comma go on to play a role in a call or
array further up the stack, so give it a chance.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">offset = </span><span class="k">if</span> <span class="nx">nextTag</span> <span class="o">is</span> <span class="s">&#39;OUTDENT&#39;</span> <span class="k">then</span> <span class="mi">1</span> <span class="k">else</span> <span class="mi">0</span>
<span class="k">while</span> <span class="nx">inImplicitObject</span><span class="p">()</span>
<span class="nx">endImplicitObject</span> <span class="nx">i</span> <span class="o">+</span> <span class="nx">offset</span>
<span class="k">return</span> <span class="nx">forward</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>Add location data to all tokens generated by the rewriter.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addLocationDataToGeneratedTokens: </span><span class="nf">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -&gt;</span>
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="nv">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="s">&#39;CLASS&#39;</span><span class="p">,</span> <span class="s">&#39;IF&#39;</span><span class="p">,</span> <span class="s">&#39;FOR&#39;</span><span class="p">,</span> <span class="s">&#39;WHILE&#39;</span><span class="p">]</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="s">&#39;INDENT&#39;</span> <span class="o">and</span>
<span class="nx">next</span> <span class="o">and</span> <span class="nx">next</span><span class="p">.</span><span class="nx">generated</span> <span class="o">and</span> <span class="nx">next</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;{&#39;</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>
<span class="nv">seenSingle = </span><span class="kc">no</span>
<span class="nv">seenControl = </span><span class="kc">no</span>
<span class="nv">noCall = </span><span class="kc">no</span> <span class="k">if</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">LINEBREAKS</span>
<span class="nv">token.call = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">prev</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">tag</span> <span class="o">is</span> <span class="s">&#39;?&#39;</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">token</span><span class="p">.</span><span class="nx">fromThen</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">callObject</span> <span class="o">or</span>
<span class="nx">prev</span><span class="o">?</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">and</span> <span class="p">(</span><span class="nx">prev</span><span class="p">.</span><span class="nx">call</span> <span class="o">or</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><span class="p">)</span> <span class="o">and</span>
<span class="p">(</span><span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_CALL</span> <span class="o">or</span> <span class="o">not</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">spaced</span> <span class="o">or</span> <span class="nx">token</span><span class="p">.</span><span class="nx">newLine</span><span class="p">)</span> <span class="o">and</span> <span class="nx">tag</span> <span class="k">in</span> <span class="nx">IMPLICIT_UNSPACED_CALL</span><span class="p">)</span>
<span class="nv">callIndex = </span><span class="nx">i</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">@generate</span> <span class="s">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s">&#39;(&#39;</span><span class="p">,</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;FUNC_EXIST&#39;</span> <span class="k">if</span> <span class="nx">prev</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;?&#39;</span>
<span class="mi">2</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Add location data to all tokens generated by the rewriter.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addLocationDataToGeneratedTokens: </span><span class="nf">-&gt;</span>
<span class="nx">@scanTokens</span> <span class="nf">(token, i, tokens) -&gt;</span>
<span class="nv">tag = </span><span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">or</span> <span class="nx">token</span><span class="p">.</span><span class="nx">explicit</span><span class="p">)</span> <span class="o">and</span> <span class="p">(</span><span class="o">not</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">i</span> <span class="o">&gt;</span> <span class="mi">0</span>
<span class="nv">prevToken = </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">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span>
<span class="nv">first_line: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_line</span>
<span class="nv">first_column: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_column</span>
<span class="nv">last_line: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_line</span>
<span class="nv">last_column: </span><span class="nx">prevToken</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="nx">last_column</span>
<span class="k">else</span>
<span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span>
<span class="nv">first_line: </span><span class="mi">0</span>
<span class="nv">first_column: </span><span class="mi">0</span>
<span class="nv">last_line: </span><span class="mi">0</span>
<span class="nv">last_column: </span><span class="mi">0</span>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
<span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">token</span><span class="p">.</span><span class="nx">generated</span> <span class="o">or</span> <span class="nx">token</span><span class="p">.</span><span class="nx">explicit</span>
<span class="p">{</span><span class="nx">last_line</span><span class="p">,</span> <span class="nx">last_column</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="o">?</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">?</span> <span class="nv">last_line: </span><span class="mi">0</span><span class="p">,</span> <span class="nv">last_column: </span><span class="mi">0</span>
<span class="nx">token</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span>
<span class="nv">first_line: </span> <span class="nx">last_line</span>
<span class="nv">first_column: </span><span class="nx">last_column</span>
<span class="nv">last_line: </span> <span class="nx">last_line</span>
<span class="nv">last_column: </span> <span class="nx">last_column</span>
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>Because our grammar is LALR(1), it can't handle some single-line
expressions that lack ending delimiters. The <strong>Rewriter</strong> adds the implicit
blocks, so it doesn't need to. ')' can close a single-line block,
but we need to make sure it's balanced.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addImplicitIndentation: </span><span class="nf">-&gt;</span>
@@ -212,7 +274,7 @@ but we need to make sure it's balanced.</p> </td> <td cl
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="nx">tokens</span><span class="p">.</span><span class="nx">splice</span> <span class="nx">i</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="nx">tag</span> <span class="o">is</span> <span class="s">&#39;THEN&#39;</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Tag postfix conditionals as such, so that we can parse them with a
<span class="k">return</span> <span class="mi">1</span></pre></div> </td> </tr> <tr id="section-36"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-36">&#182;</a> </div> <p>Tag postfix conditionals as such, so that we can parse them with a
different precedence.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tagPostfixConditionals: </span><span class="nf">-&gt;</span>
<span class="nv">original = </span><span class="kc">null</span>
@@ -228,15 +290,14 @@ different precedence.</p> </td> <td class="code">
<span class="k">return</span> <span class="mi">1</span> <span class="k">unless</span> <span class="nx">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">is</span> <span class="s">&#39;IF&#39;</span>
<span class="nv">original = </span><span class="nx">token</span>
<span class="nx">@detectEnd</span> <span class="nx">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">condition</span><span class="p">,</span> <span class="nx">action</span>
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">indentation: </span><span class="nf">(token, implicit = no) -&gt;</span>
<span class="mi">1</span></pre></div> </td> </tr> <tr id="section-37"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-37">&#182;</a> </div> <p>Generate the indentation tokens, based on another token on the same line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">indentation: </span><span class="nf">(token, implicit = no) -&gt;</span>
<span class="nv">indent = </span><span class="p">[</span><span class="s">&#39;INDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="nv">outdent = </span><span class="p">[</span><span class="s">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="nv">indent.generated = outdent.generated = </span><span class="kc">yes</span> <span class="k">if</span> <span class="nx">implicit</span>
<span class="nv">indent.explicit = outdent.explicit = </span><span class="kc">yes</span> <span class="k">if</span> <span class="o">not</span> <span class="nx">implicit</span>
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</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">&#182;</a> </div> <p>Create a generated token: one that exists due to a use of implicit syntax.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">generate: </span><span class="nf">(tag, value) -&gt;</span>
<span class="nv">tok = </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="nv">tok.generated = </span><span class="kc">yes</span>
<span class="nx">tok</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="nf">(i) -&gt;</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</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">&#182;</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
<span class="p">[</span><span class="nx">indent</span><span class="p">,</span> <span class="nx">outdent</span><span class="p">]</span>
<span class="nv">generate: </span><span class="nx">generate</span></pre></div> </td> </tr> <tr id="section-38"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-38">&#182;</a> </div> <p>Look up a tag by token index.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">tag: </span><span class="nf">(i) -&gt;</span> <span class="nx">@tokens</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="o">?</span><span class="p">[</span><span class="mi">0</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">&#182;</a> </div> <h2>Constants</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-40"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-40">&#182;</a> </div> <p>List of the token pairs that must be balanced.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BALANCED_PAIRS = </span><span class="p">[</span>
<span class="p">[</span><span class="s">&#39;(&#39;</span><span class="p">,</span> <span class="s">&#39;)&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;[&#39;</span><span class="p">,</span> <span class="s">&#39;]&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="s">&#39;}&#39;</span><span class="p">]</span>
@@ -244,20 +305,21 @@ different precedence.</p> </td> <td class="code">
<span class="p">[</span><span class="s">&#39;CALL_START&#39;</span><span class="p">,</span> <span class="s">&#39;CALL_END&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;PARAM_START&#39;</span><span class="p">,</span> <span class="s">&#39;PARAM_END&#39;</span><span class="p">]</span>
<span class="p">[</span><span class="s">&#39;INDEX_START&#39;</span><span class="p">,</span> <span class="s">&#39;INDEX_END&#39;</span><span class="p">]</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">&#182;</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.INVERSES = INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
<span class="p">]</span></pre></div> </td> </tr> <tr id="section-41"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-41">&#182;</a> </div> <p>The inverse mappings of <code>BALANCED_PAIRS</code> we're trying to fix up, so we can
look things up from either end.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.INVERSES = INVERSES = </span><span class="p">{}</span></pre></div> </td> </tr> <tr id="section-42"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-42">&#182;</a> </div> <p>The tokens that signal the start/end of a balanced pair.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_START = </span><span class="p">[]</span>
<span class="nv">EXPRESSION_END = </span><span class="p">[]</span>
<span class="k">for</span> <span class="p">[</span><span class="nx">left</span><span class="p">,</span> <span class="nx">rite</span><span class="p">]</span> <span class="k">in</span> <span class="nx">BALANCED_PAIRS</span>
<span class="nx">EXPRESSION_START</span><span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">rite</span><span class="p">]</span> <span class="o">=</span> <span class="nx">left</span>
<span class="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;FINALLY&#39;</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s">&#39;)&#39;</span><span class="p">,</span> <span class="s">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s">&#39;]&#39;</span><span class="p">,</span> <span class="s">&#39;INDEX_END&#39;</span><span class="p">,</span> <span class="s">&#39;@&#39;</span><span class="p">,</span> <span class="s">&#39;THIS&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
<span class="nx">EXPRESSION_END</span> <span class="p">.</span><span class="nx">push</span> <span class="nx">INVERSES</span><span class="p">[</span><span class="nx">left</span><span class="p">]</span> <span class="o">=</span> <span class="nx">rite</span></pre></div> </td> </tr> <tr id="section-43"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-43">&#182;</a> </div> <p>Tokens that indicate the close of a clause of an expression.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">EXPRESSION_CLOSE = </span><span class="p">[</span><span class="s">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;FINALLY&#39;</span><span class="p">].</span><span class="nx">concat</span> <span class="nx">EXPRESSION_END</span></pre></div> </td> </tr> <tr id="section-44"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-44">&#182;</a> </div> <p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_FUNC = </span><span class="p">[</span><span class="s">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s">&#39;SUPER&#39;</span><span class="p">,</span> <span class="s">&#39;)&#39;</span><span class="p">,</span> <span class="s">&#39;CALL_END&#39;</span><span class="p">,</span> <span class="s">&#39;]&#39;</span><span class="p">,</span> <span class="s">&#39;INDEX_END&#39;</span><span class="p">,</span> <span class="s">&#39;@&#39;</span><span class="p">,</span> <span class="s">&#39;THIS&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-45"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-45">&#182;</a> </div> <p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_CALL = </span><span class="p">[</span>
<span class="s">&#39;IDENTIFIER&#39;</span><span class="p">,</span> <span class="s">&#39;NUMBER&#39;</span><span class="p">,</span> <span class="s">&#39;STRING&#39;</span><span class="p">,</span> <span class="s">&#39;JS&#39;</span><span class="p">,</span> <span class="s">&#39;REGEX&#39;</span><span class="p">,</span> <span class="s">&#39;NEW&#39;</span><span class="p">,</span> <span class="s">&#39;PARAM_START&#39;</span><span class="p">,</span> <span class="s">&#39;CLASS&#39;</span>
<span class="s">&#39;IF&#39;</span><span class="p">,</span> <span class="s">&#39;TRY&#39;</span><span class="p">,</span> <span class="s">&#39;SWITCH&#39;</span><span class="p">,</span> <span class="s">&#39;THIS&#39;</span><span class="p">,</span> <span class="s">&#39;BOOL&#39;</span><span class="p">,</span> <span class="s">&#39;NULL&#39;</span><span class="p">,</span> <span class="s">&#39;UNDEFINED&#39;</span><span class="p">,</span> <span class="s">&#39;UNARY&#39;</span><span class="p">,</span> <span class="s">&#39;SUPER&#39;</span>
<span class="s">&#39;@&#39;</span><span class="p">,</span> <span class="s">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;[&#39;</span><span class="p">,</span> <span class="s">&#39;(&#39;</span><span class="p">,</span> <span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="s">&#39;--&#39;</span><span class="p">,</span> <span class="s">&#39;++&#39;</span>
<span class="p">]</span>
<span class="nv">IMPLICIT_UNSPACED_CALL = </span><span class="p">[</span><span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="s">&#39;[&#39;</span><span class="p">,</span> <span class="s">&#39;,&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s">&#39;POST_IF&#39;</span><span class="p">,</span> <span class="s">&#39;FOR&#39;</span><span class="p">,</span> <span class="s">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s">&#39;UNTIL&#39;</span><span class="p">,</span> <span class="s">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s">&#39;BY&#39;</span><span class="p">,</span> <span class="s">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s">&#39;TERMINATOR&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
<span class="nv">IMPLICIT_UNSPACED_CALL = </span><span class="p">[</span><span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-46"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-46">&#182;</a> </div> <p>Tokens indicating that the implicit call must enclose a block of expressions.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_BLOCK = </span><span class="p">[</span><span class="s">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;{&#39;</span><span class="p">,</span> <span class="s">&#39;[&#39;</span><span class="p">,</span> <span class="s">&#39;,&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-47"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-47">&#182;</a> </div> <p>Tokens that always mark the end of an implicit call for single-liners.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">IMPLICIT_END = </span><span class="p">[</span><span class="s">&#39;POST_IF&#39;</span><span class="p">,</span> <span class="s">&#39;FOR&#39;</span><span class="p">,</span> <span class="s">&#39;WHILE&#39;</span><span class="p">,</span> <span class="s">&#39;UNTIL&#39;</span><span class="p">,</span> <span class="s">&#39;WHEN&#39;</span><span class="p">,</span> <span class="s">&#39;BY&#39;</span><span class="p">,</span>
<span class="s">&#39;LOOP&#39;</span><span class="p">,</span> <span class="s">&#39;TERMINATOR&#39;</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">&#182;</a> </div> <p>Single-line flavors of block expressions that have unclosed endings.
The grammar can't disambiguate them, so we insert the implicit indentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">SINGLE_LINERS = </span><span class="p">[</span><span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;=&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;TRY&#39;</span><span class="p">,</span> <span class="s">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s">&#39;THEN&#39;</span><span class="p">]</span>
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s">&#39;LEADING_WHEN&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s">&#39;OUTDENT&#39;</span><span class="p">]</span>
<span class="nv">SINGLE_CLOSERS = </span><span class="p">[</span><span class="s">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s">&#39;CATCH&#39;</span><span class="p">,</span> <span class="s">&#39;FINALLY&#39;</span><span class="p">,</span> <span class="s">&#39;ELSE&#39;</span><span class="p">,</span> <span class="s">&#39;OUTDENT&#39;</span><span class="p">,</span> <span class="s">&#39;LEADING_WHEN&#39;</span><span class="p">]</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">&#182;</a> </div> <p>Tokens that end a line.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">LINEBREAKS = </span><span class="p">[</span><span class="s">&#39;TERMINATOR&#39;</span><span class="p">,</span> <span class="s">&#39;INDENT&#39;</span><span class="p">,</span> <span class="s">&#39;OUTDENT&#39;</span><span class="p">]</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

View File

@@ -0,0 +1,155 @@
<!DOCTYPE html> <html> <head> <title>sourcemap.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <div id="jump_to"> Jump To &hellip; <div id="jump_wrapper"> <div id="jump_page"> <a class="source" href="browser.html"> browser.coffee </a> <a class="source" href="cake.html"> cake.coffee </a> <a class="source" href="coffee-script.html"> coffee-script.coffee </a> <a class="source" href="command.html"> command.coffee </a> <a class="source" href="grammar.html"> grammar.coffee </a> <a class="source" href="helpers.html"> helpers.coffee </a> <a class="source" href="index.html"> index.coffee </a> <a class="source" href="lexer.html"> lexer.coffee </a> <a class="source" href="nodes.html"> nodes.coffee </a> <a class="source" href="optparse.html"> optparse.coffee </a> <a class="source" href="repl.html"> repl.coffee </a> <a class="source" href="rewriter.html"> rewriter.coffee </a> <a class="source" href="sourcemap.html"> sourcemap.coffee </a> </div> </div> </div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> sourcemap.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">&#182;</a> </div> <h3>LineMapping</h3> </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">&#182;</a> </div> <p>Hold data about mappings for one line of generated source code.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">class</span> <span class="nx">LineMapping</span>
<span class="nv">constructor: </span><span class="nf">(@generatedLine) -&gt;</span></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>columnMap keeps track of which columns we've already mapped.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@columnMap = </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">&#182;</a> </div> <p>columnMappings is an array of all column mappings, sorted by generated-column.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@columnMappings = </span><span class="p">[]</span>
<span class="nv">addMapping: </span><span class="nf">(generatedColumn, [sourceLine, sourceColumn], options={}) -&gt;</span>
<span class="k">if</span> <span class="nx">@columnMap</span><span class="p">[</span><span class="nx">generatedColumn</span><span class="p">]</span> <span class="o">and</span> <span class="nx">options</span><span class="p">.</span><span class="nx">noReplace</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>We already have a mapping for this column.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span>
<span class="nx">@columnMap</span><span class="p">[</span><span class="nx">generatedColumn</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="nv">generatedLine: </span><span class="nx">@generatedLine</span>
<span class="nx">generatedColumn</span>
<span class="nx">sourceLine</span>
<span class="nx">sourceColumn</span>
<span class="p">}</span>
<span class="nx">@columnMappings</span><span class="p">.</span><span class="nx">push</span> <span class="nx">@columnMap</span><span class="p">[</span><span class="nx">generatedColumn</span><span class="p">]</span>
<span class="nx">@columnMappings</span><span class="p">.</span><span class="nx">sort</span> <span class="nf">(a,b) -&gt;</span> <span class="nx">a</span><span class="p">.</span><span class="nx">generatedColumn</span> <span class="o">-</span> <span class="nx">b</span><span class="p">.</span><span class="nx">generatedColumn</span>
<span class="nv">getSourcePosition: </span><span class="nf">(generatedColumn) -&gt;</span>
<span class="nv">answer = </span><span class="kc">null</span>
<span class="nv">lastColumnMapping = </span><span class="kc">null</span>
<span class="k">for</span> <span class="nx">columnMapping</span> <span class="k">in</span> <span class="nx">@columnMappings</span>
<span class="k">if</span> <span class="nx">columnMapping</span><span class="p">.</span><span class="nx">generatedColumn</span> <span class="o">&gt;</span> <span class="nx">generatedColumn</span>
<span class="k">break</span>
<span class="k">else</span>
<span class="nv">lastColumnMapping = </span><span class="nx">columnMapping</span>
<span class="k">if</span> <span class="nx">lastColumnMapping</span>
<span class="nv">answer = </span><span class="p">[</span><span class="nx">lastColumnMapping</span><span class="p">.</span><span class="nx">sourceLine</span><span class="p">,</span> <span class="nx">lastColumnMapping</span><span class="p">.</span><span class="nx">sourceColumn</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">&#182;</a> </div> <h3>SourceMap</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Maps locations in a generated source file back to locations in the original source file.</p>
<p>This is intentionally agnostic towards how a source map might be represented on disk. A
SourceMap can be converted to a "v3" style sourcemap with <code>#generateV3SourceMap()</code>, for example
but the SourceMap class itself knows nothing about v3 source maps.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">class</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">SourceMap</span>
<span class="nv">constructor: </span><span class="p">()</span> <span class="nf">-&gt;</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p><code>generatedLines</code> is an array of LineMappings, one per generated line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="vi">@generatedLines = </span><span class="p">[]</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>Adds a mapping to this SourceMap.</p>
<p><code>sourceLocation</code> and <code>generatedLocation</code> are both [line, column] arrays.</p>
<p>If <code>options.noReplace</code> is true, then if there is already a mapping for
the specified <code>generatedLine</code> and <code>generatedColumn</code>, this will have no effect.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">addMapping: </span><span class="nf">(sourceLocation, generatedLocation, options={}) -&gt;</span>
<span class="p">[</span><span class="nx">generatedLine</span><span class="p">,</span> <span class="nx">generatedColumn</span><span class="p">]</span> <span class="o">=</span> <span class="nx">generatedLocation</span>
<span class="nv">lineMapping = </span><span class="nx">@generatedLines</span><span class="p">[</span><span class="nx">generatedLine</span><span class="p">]</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">lineMapping</span>
<span class="nv">lineMapping = </span><span class="nx">@generatedLines</span><span class="p">[</span><span class="nx">generatedLine</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">LineMapping</span><span class="p">(</span><span class="nx">generatedLine</span><span class="p">)</span>
<span class="nx">lineMapping</span><span class="p">.</span><span class="nx">addMapping</span> <span class="nx">generatedColumn</span><span class="p">,</span> <span class="nx">sourceLocation</span><span class="p">,</span> <span class="nx">options</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Returns [sourceLine, sourceColumn], or null if no mapping could be found.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">getSourcePosition: </span><span class="nf">([generatedLine, generatedColumn]) -&gt;</span>
<span class="nv">answer = </span><span class="kc">null</span>
<span class="nv">lineMapping = </span><span class="nx">@generatedLines</span><span class="p">[</span><span class="nx">generatedLine</span><span class="p">]</span>
<span class="k">if</span> <span class="o">not</span> <span class="nx">lineMapping</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>TODO: Search backwards for the line?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">else</span>
<span class="nv">answer = </span><span class="nx">lineMapping</span><span class="p">.</span><span class="nx">getSourcePosition</span> <span class="nx">generatedColumn</span>
<span class="nx">answer</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p><code>fn</code> will be called once for every recorded mapping, in the order in
which they occur in the generated source. <code>fn</code> will be passed an object
with four properties: sourceLine, sourceColumn, generatedLine, and
generatedColumn.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">forEachMapping: </span><span class="nf">(fn) -&gt;</span>
<span class="k">for</span> <span class="nx">lineMapping</span><span class="p">,</span> <span class="nx">generatedLineNumber</span> <span class="k">in</span> <span class="nx">@generatedLines</span>
<span class="k">if</span> <span class="nx">lineMapping</span>
<span class="k">for</span> <span class="nx">columnMapping</span> <span class="k">in</span> <span class="nx">lineMapping</span><span class="p">.</span><span class="nx">columnMappings</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">columnMapping</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <h3>generateV3SourceMap</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Builds a V3 source map from a SourceMap object.
Returns the generated JSON as a string.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.generateV3SourceMap = </span><span class="nf">(sourceMap, sourceFile=null, generatedFile=null) -&gt;</span>
<span class="nv">writingGeneratedLine = </span><span class="mi">0</span>
<span class="nv">lastGeneratedColumnWritten = </span><span class="mi">0</span>
<span class="nv">lastSourceLineWritten = </span><span class="mi">0</span>
<span class="nv">lastSourceColumnWritten = </span><span class="mi">0</span>
<span class="nv">needComma = </span><span class="kc">no</span>
<span class="nv">mappings = </span><span class="s">&quot;&quot;</span>
<span class="nx">sourceMap</span><span class="p">.</span><span class="nx">forEachMapping</span> <span class="nf">(mapping) -&gt;</span>
<span class="k">while</span> <span class="nx">writingGeneratedLine</span> <span class="o">&lt;</span> <span class="nx">mapping</span><span class="p">.</span><span class="nx">generatedLine</span>
<span class="nv">lastGeneratedColumnWritten = </span><span class="mi">0</span>
<span class="nv">needComma = </span><span class="kc">no</span>
<span class="nx">mappings</span> <span class="o">+=</span> <span class="s">&quot;;&quot;</span>
<span class="nx">writingGeneratedLine</span><span class="o">++</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Write a comma if we've already written a segment on this line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="nx">needComma</span>
<span class="nx">mappings</span> <span class="o">+=</span> <span class="s">&quot;,&quot;</span>
<span class="nv">needComma = </span><span class="kc">no</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Write the next segment.
Segments can be 1, 4, or 5 values. If just one, then it is a generated column which
doesn't match anything in the source code.</p>
<p>Fields are all zero-based, and relative to the previous occurence unless otherwise noted:
* starting-column in generated source, relative to previous occurence for the current line.
* index into the "sources" list
* starting line in the original source
* starting column in the original source
* index into the "names" list associated with this segment.</p> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>Add the generated start-column</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">generatedColumn</span> <span class="o">-</span> <span class="nx">lastGeneratedColumnWritten</span><span class="p">)</span>
<span class="nv">lastGeneratedColumnWritten = </span><span class="nx">mapping</span><span class="p">.</span><span class="nx">generatedColumn</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>Add the index into the sources list</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="mi">0</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">&#182;</a> </div> <p>Add the source start-line</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceLine</span> <span class="o">-</span> <span class="nx">lastSourceLineWritten</span><span class="p">)</span>
<span class="nv">lastSourceLineWritten = </span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceLine</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>Add the source start-column</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">mappings</span> <span class="o">+=</span> <span class="nx">exports</span><span class="p">.</span><span class="nx">vlqEncodeValue</span><span class="p">(</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceColumn</span> <span class="o">-</span> <span class="nx">lastSourceColumnWritten</span><span class="p">)</span>
<span class="nv">lastSourceColumnWritten = </span><span class="nx">mapping</span><span class="p">.</span><span class="nx">sourceColumn</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>TODO: Do we care about symbol names for CoffeeScript? Probably not.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">needComma = </span><span class="kc">yes</span>
<span class="nv">answer = </span><span class="p">{</span>
<span class="nv">version: </span><span class="mi">3</span>
<span class="nv">file: </span><span class="nx">generatedFile</span>
<span class="nv">sourceRoot: </span><span class="s">&quot;&quot;</span>
<span class="nv">sources: </span><span class="k">if</span> <span class="nx">sourceFile</span> <span class="k">then</span> <span class="p">[</span><span class="nx">sourceFile</span><span class="p">]</span> <span class="k">else</span> <span class="p">[]</span>
<span class="nv">names: </span><span class="p">[]</span>
<span class="nx">mappings</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span> <span class="nx">answer</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="mi">2</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>Load a SourceMap from a JSON string. Returns the SourceMap object.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.loadV3SourceMap = </span><span class="nf">(sourceMap) -&gt;</span>
<span class="nx">todo</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <h3>Base64 encoding helpers</h3> </td> <td class="code"> <div class="highlight"><pre><span class="nv">BASE64_CHARS = </span><span class="s">&#39;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#39;</span>
<span class="nv">MAX_BASE64_VALUE = </span><span class="nx">BASE64_CHARS</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="nv">encodeBase64Char = </span><span class="nf">(value) -&gt;</span>
<span class="k">if</span> <span class="nx">value</span> <span class="o">&gt;</span> <span class="nx">MAX_BASE64_VALUE</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Cannot encode value </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s"> &gt; </span><span class="si">#{</span><span class="nx">MAX_BASE64_VALUE</span><span class="si">}</span><span class="s">&quot;</span>
<span class="k">else</span> <span class="k">if</span> <span class="nx">value</span> <span class="o">&lt;</span> <span class="mi">0</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Cannot encode value </span><span class="si">#{</span><span class="nx">value</span><span class="si">}</span><span class="s"> &lt; 0&quot;</span>
<span class="nx">BASE64_CHARS</span><span class="p">[</span><span class="nx">value</span><span class="p">]</span>
<span class="nv">decodeBase64Char = </span><span class="nf">(char) -&gt;</span>
<span class="nv">value = </span><span class="nx">BASE64_CHARS</span><span class="p">.</span><span class="nx">indexOf</span> <span class="nx">char</span>
<span class="k">if</span> <span class="nx">value</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span> <span class="s">&quot;Invalid Base 64 character: </span><span class="si">#{</span><span class="nx">char</span><span class="si">}</span><span class="s">&quot;</span>
<span class="nx">value</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</a> </div> <h3>Base 64 VLQ encoding/decoding helpers</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>Note that SourceMap VLQ encoding is "backwards". MIDI style VLQ encoding puts the
most-significant-bit (MSB) from the original value into the MSB of the VLQ encoded value
(see http://en.wikipedia.org/wiki/File:Uintvar_coding.svg). SourceMap VLQ does things
the other way around, with the least significat four bits of the original value encoded
into the first byte of the VLQ encoded value.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">VLQ_SHIFT = </span><span class="mi">5</span>
<span class="nv">VLQ_CONTINUATION_BIT = </span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="nx">VLQ_SHIFT</span> <span class="c1"># 0010 0000</span>
<span class="nv">VLQ_VALUE_MASK = </span><span class="nx">VLQ_CONTINUATION_BIT</span> <span class="o">-</span> <span class="mi">1</span> <span class="c1"># 0001 1111</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">&#182;</a> </div> <p>Encode a value as Base 64 VLQ.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.vlqEncodeValue = </span><span class="nf">(value) -&gt;</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>Least significant bit represents the sign.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">signBit = </span><span class="k">if</span> <span class="nx">value</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="k">then</span> <span class="mi">1</span> <span class="k">else</span> <span class="mi">0</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Next bits are the actual value</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">valueToEncode = </span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="nx">signBit</span>
<span class="nv">answer = </span><span class="s">&quot;&quot;</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Make sure we encode at least one character, even if valueToEncode is 0.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">while</span> <span class="nx">valueToEncode</span> <span class="o">||</span> <span class="o">!</span><span class="nx">answer</span>
<span class="nv">nextVlqChunk = </span><span class="nx">valueToEncode</span> <span class="o">&amp;</span> <span class="nx">VLQ_VALUE_MASK</span>
<span class="nv">valueToEncode = </span><span class="nx">valueToEncode</span> <span class="o">&gt;&gt;</span> <span class="nx">VLQ_SHIFT</span>
<span class="k">if</span> <span class="nx">valueToEncode</span>
<span class="nx">nextVlqChunk</span> <span class="o">|=</span> <span class="nx">VLQ_CONTINUATION_BIT</span>
<span class="nx">answer</span> <span class="o">+=</span> <span class="nx">encodeBase64Char</span><span class="p">(</span><span class="nx">nextVlqChunk</span><span class="p">)</span>
<span class="k">return</span> <span class="nx">answer</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">&#182;</a> </div> <p>Decode a Base 64 VLQ value.</p>
<p>Returns <code>[value, consumed]</code> where <code>value</code> is the decoded value, and <code>consumed</code> is the number
of characters consumed from <code>str</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">exports.vlqDecodeValue = </span><span class="nf">(str, offset=0) -&gt;</span>
<span class="nv">position = </span><span class="nx">offset</span>
<span class="nv">done = </span><span class="kc">false</span>
<span class="nv">value = </span><span class="mi">0</span>
<span class="nv">continuationShift = </span><span class="mi">0</span>
<span class="k">while</span> <span class="o">!</span><span class="nx">done</span>
<span class="nv">nextVlqChunk = </span><span class="nx">decodeBase64Char</span><span class="p">(</span><span class="nx">str</span><span class="p">[</span><span class="nx">position</span><span class="p">])</span>
<span class="nx">position</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nv">nextChunkValue = </span><span class="nx">nextVlqChunk</span> <span class="o">&amp;</span> <span class="nx">VLQ_VALUE_MASK</span>
<span class="nx">value</span> <span class="o">+=</span> <span class="p">(</span><span class="nx">nextChunkValue</span> <span class="o">&lt;&lt;</span> <span class="nx">continuationShift</span><span class="p">)</span>
<span class="k">if</span> <span class="o">!</span><span class="p">(</span><span class="nx">nextVlqChunk</span> <span class="o">&amp;</span> <span class="nx">VLQ_CONTINUATION_BIT</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>We'll be done after this character.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">done = </span><span class="kc">true</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">&#182;</a> </div> <p>Bits are encoded least-significant first (opposite of MIDI VLQ). Increase the
continuationShift, so the next byte will end up where it should in the value.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">continuationShift</span> <span class="o">+=</span> <span class="nx">VLQ_SHIFT</span>
<span class="nv">consumed = </span><span class="nx">position</span> <span class="o">-</span> <span class="nx">offset</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>Least significant bit represents the sign.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">signBit = </span><span class="nx">value</span> <span class="o">&amp;</span> <span class="mi">1</span>
<span class="nv">value = </span><span class="nx">value</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nx">signBit</span> <span class="k">then</span> <span class="nv">value = </span><span class="o">-</span><span class="nx">value</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">value</span><span class="p">,</span> <span class="nx">consumed</span><span class="p">]</span>
</pre></div> </td> </tr> </tbody> </table> </div> </body> </html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -39,7 +39,7 @@
<div id="fadeout"></div>
<div id="flybar">
<a id="logo" href="#top"> </a>
<a id="logo" href="#top"><img src="documentation/images/logo.png" width="225" height="39" alt="CoffeeScript" /></a>
<div class="navigation toc">
<div class="button">
Table of Contents
@@ -51,7 +51,7 @@
<a href="#literate">Literate CoffeeScript</a>
<a href="#language">Language Reference</a>
<a href="#literals">Literals: Functions, Objects and Arrays</a>
<a href="#lexical_scope">Lexical Scoping and Variable Safety</a>
<a href="#lexical-scope">Lexical Scoping and Variable Safety</a>
<a href="#conditionals">If, Else, Unless, and Conditional Assignment</a>
<a href="#splats">Splats...</a>
<a href="#loops">Loops and Comprehensions</a>
@@ -60,13 +60,14 @@
<a href="#operators">Operators and Aliases</a>
<a href="#classes">Classes, Inheritance, and Super</a>
<a href="#destructuring">Destructuring Assignment</a>
<a href="#fat_arrow">Function Binding</a>
<a href="#fat-arrow">Function Binding</a>
<a href="#embedded">Embedded JavaScript</a>
<a href="#switch">Switch and Try/Catch</a>
<a href="#comparisons">Chained Comparisons</a>
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
<a href="#regexes">Block Regular Expressions</a>
<a href="#cake">Cake, and Cakefiles</a>
<a href="#source-maps">Source Maps</a>
<a href="#scripts">"text/coffeescript" Script Tags</a>
<a href="#resources">Books, Screencasts, Examples and Resources</a>
<a href="#changelog">Change Log</a>
@@ -109,6 +110,7 @@
<a href="documentation/docs/command.html">"coffee" Command-Line Utility &mdash; src/command</a>
<a href="documentation/docs/optparse.html">Option Parsing &mdash; src/optparse</a>
<a href="documentation/docs/repl.html">Interactive REPL &mdash; src/repl</a>
<a href="documentation/docs/sourcemap.html">Source Maps &mdash; src/sourcemap</a>
</div>
</div>
<div id="error" style="display:none;"></div>
@@ -137,9 +139,12 @@
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.5.0">1.5.0</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.6.1">1.6.1</a>
</p>
<pre>
sudo npm install -g coffee-script</pre>
<h2>
<span id="overview" class="bookmark"></span>
Overview
@@ -218,6 +223,13 @@ sudo bin/cake install</pre>
of the same name.
</td>
</tr>
<tr>
<td><code>-m, --map</code></td>
<td>
Generate source maps alongside the compiled JavaScript files. Adds
<tt>sourceMappingURL</tt> directives to the JavaScript as well.
</td>
</tr>
<tr>
<td width="25%"><code>-i, --interactive</code></td>
<td>
@@ -290,7 +302,7 @@ sudo bin/cake install</pre>
<td><code>-b, --bare</code></td>
<td>
Compile the JavaScript without the
<a href="#lexical_scope">top-level function safety wrapper</a>.
<a href="#lexical-scope">top-level function safety wrapper</a>.
</td>
</tr>
<tr>
@@ -367,7 +379,9 @@ Expressions
Besides being used as an ordinary programming language, CoffeeScript may
also be written in "literate" mode. If you name your file with a
<tt>.litcoffee</tt> extension, you can write it as a Markdown document &mdash;
a document that also happens to be executable CoffeeScript code.
a document that also happens to be executable CoffeeScript code. The compiler
will treat any indented blocks (Markdown's way of indicating source code)
as code, and ignore the rest as comments.
</p>
<p>
@@ -381,8 +395,9 @@ Expressions
<p>
I'm fairly excited about this direction for the language, and am looking
forward to writing (and more importantly, reading) more programs in this style.
As <b>1.5.0</b> is the first version of CoffeeScript that supports it, let us know
if you have any ideas for improving the feature.
More information about Literate CoffeeScript, including an
<a href="https://github.com/jashkenas/journo">example program</a>,
are <a href="http://ashkenas.com/literate-coffeescript">available in this blog post</a>.
</p>
<h2>
@@ -456,7 +471,7 @@ Expressions
<%= code_for('objects_reserved') %>
<p>
<span id="lexical_scope" class="bookmark"></span>
<span id="lexical-scope" class="bookmark"></span>
<b class="header">Lexical Scoping and Variable Safety</b>
The CoffeeScript compiler takes care to make sure that all of your variables
are properly declared within lexical scope &mdash; you never need to write
@@ -799,7 +814,7 @@ Expressions
<%= code_for('patterns_and_splats', 'contents.join("")') %>
<p>
<span id="fat_arrow" class="bookmark"></span>
<span id="fat-arrow" class="bookmark"></span>
<b class="header">Function binding</b>
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
object that the current function is attached to. If you pass a function as
@@ -948,6 +963,26 @@ Expressions
code itself &mdash; not the cake task.
</p>
<h2>
<span id="source-maps" class="bookmark"></span>
Source Maps
</h2>
<p>
CoffeeScript 1.6.1 and above include support for generating source maps,
a way to tell your JavaScript engine what part of your CoffeeScript
program matches up with the code being evaluated. Browsers that support it
can automatically use source maps to show your original source code
in the debugger. To generate source maps alongside your JavaScript files,
pass the <tt>--map</tt> or <tt>-m</tt> flag to the compiler.
</p>
<p>
For a full introduction to source maps, how they work, and how to hook
them up in your browser, read the
<a href="http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/">HTML5 Tutorial</a>.
</p>
<h2>
<span id="scripts" class="bookmark"></span>
"text/coffeescript" Script Tags
@@ -1008,6 +1043,12 @@ Expressions
a fast-paced multiplayer word game, writing both the client-side and Node.js
portions in CoffeeScript.
</li>
<li>
<a href="http://www.packtpub.com/coffeescript-programming-with-jquery-rails-nodejs/book">CoffeeScript Programming with jQuery, Rails, and Node.js</a>
is a new book by Michael Erasmus that covers CoffeeScript with an eye
towards real-world usage both in the browser (jQuery) and on the server
size (Rails, Node).
</li>
<li>
<a href="http://ristrettolo.gy">CoffeeScript Ristretto</a>
is a deep dive into CoffeeScript's semantics from simple functions up through
@@ -1151,6 +1192,35 @@ Expressions
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.5.0...1.6.1">1.6.1</a>
<span class="timestamp"> &ndash; <small>March 5, 2013</small></span>
</b>
<ul>
<li>
First release of <a href="#source-maps">source maps</a>. Pass the
<tt>--map</tt> flag to the compiler, and off you go. Direct all your
thanks over to <a href="http://github.com/jwalton">Jason Walton</a>.
</li>
<li>
Fixed a 1.5.0 regression with multiple implicit calls against an
indented implicit object. Combinations of implicit function calls
and implicit objects should generally be parsed better now &mdash;
but it still isn't good <i>style</i> to nest them too heavily.
</li>
<li>
<tt>.coffee.md</tt> is now also supported as a Literate CoffeeScript
file extension, for existing tooling.
<tt>.litcoffee</tt> remains the canonical one.
</li>
<li>
Several minor fixes surrounding member properties, bound methods and
<tt>super</tt> in class declarations.
</li>
</ul>
</p>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.4.0...1.5.0">1.5.0</a>
@@ -1170,7 +1240,7 @@ Expressions
</li>
<li>
You can now loop over an array backwards, without having to manually
deal with the indexes.
deal with the indexes: <tt>for item in list by -1</tt>
</li>
<li>
Source locations are now preserved in the CoffeeScript AST, although

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var volume, winner;
if (ignition === true) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;
_ref = ['toast', 'cheese', 'wine'];

View File

@@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
/*
CoffeeScript Compiler v1.5.0
CoffeeScript Compiler v1.6.1
Released under the MIT License
*/

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var fs;
fs = require('fs');

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var Animal, Horse, Snake, sam, tom,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
@@ -22,7 +22,7 @@ Snake = (function(_super) {
__extends(Snake, _super);
function Snake() {
Snake.__super__.constructor.apply(this, arguments);
return Snake.__super__.constructor.apply(this, arguments);
}
Snake.prototype.move = function() {
@@ -39,7 +39,7 @@ Horse = (function(_super) {
__extends(Horse, _super);
function Horse() {
Horse.__super__.constructor.apply(this, arguments);
return Horse.__super__.constructor.apply(this, arguments);
}
Horse.prototype.move = function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var cholesterol, healthy;
cholesterol = 127;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var date, mood;
if (singing) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var fill;
fill = function(container, liquid) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var filename, _fn, _i, _len;
_fn = function(filename) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var hi;
hi = function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var footprints, solipsism, speed;
if ((typeof mind !== "undefined" && mind !== null) && (typeof world === "undefined" || world === null)) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var eldest, grade;
grade = function(student) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var one, six, three, two;
six = (one = 1) + (two = 2) + (three = 3);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var globals, name;
globals = ((function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
alert((function() {
try {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var Account;
Account = function(customer, cart) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var cube, square;
square = function(x) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var html;
html = "<strong>\n cup of coffeescript\n</strong>";

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var OPERATOR;
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var author, quote, sentence;
author = "Wittgenstein";

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var city, forecast, temp, weatherReport, _ref;
weatherReport = function(location) {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var age, ages, child, yearsOld;
yearsOld = {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var city, futurists, name, street, _ref, _ref1;
futurists = {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var bitlist, kids, singers, song;
song = ["do", "re", "mi", "fa", "so"];

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
$('.account').attr({
"class": 'active'

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var cubes, list, math, num, number, opposite, race, square,
__slice = [].slice;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var theBait, theSwitch, _ref;
theBait = 1000;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var close, contents, open, tag, _i, _ref,
__slice = [].slice;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
String.prototype.dasherize = function() {
return this.replace(/_/g, "-");

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var countdown, num;
countdown = (function() {

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var changeNumbers, inner, outer;
outer = 1;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var copy, end, middle, numbers, start;
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var zip, _ref;
zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var awardMedals, contenders, gold, rest, silver,
__slice = [].slice;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var numbers, _ref;
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

View File

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

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
switch (day) {
case "Mon":

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
try {
allHellBreaksLoose();

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
var lyrics, num;
if (this.studyingEconomics) {

File diff suppressed because one or more lines are too long

View File

@@ -16,7 +16,7 @@
<div id="fadeout"></div>
<div id="flybar">
<a id="logo" href="#top"> </a>
<a id="logo" href="#top"><img src="documentation/images/logo.png" width="225" height="39" alt="CoffeeScript" /></a>
<div class="navigation toc">
<div class="button">
Table of Contents
@@ -28,7 +28,7 @@
<a href="#literate">Literate CoffeeScript</a>
<a href="#language">Language Reference</a>
<a href="#literals">Literals: Functions, Objects and Arrays</a>
<a href="#lexical_scope">Lexical Scoping and Variable Safety</a>
<a href="#lexical-scope">Lexical Scoping and Variable Safety</a>
<a href="#conditionals">If, Else, Unless, and Conditional Assignment</a>
<a href="#splats">Splats...</a>
<a href="#loops">Loops and Comprehensions</a>
@@ -37,13 +37,14 @@
<a href="#operators">Operators and Aliases</a>
<a href="#classes">Classes, Inheritance, and Super</a>
<a href="#destructuring">Destructuring Assignment</a>
<a href="#fat_arrow">Function Binding</a>
<a href="#fat-arrow">Function Binding</a>
<a href="#embedded">Embedded JavaScript</a>
<a href="#switch">Switch and Try/Catch</a>
<a href="#comparisons">Chained Comparisons</a>
<a href="#strings">String Interpolation, Block Strings, and Block Comments</a>
<a href="#regexes">Block Regular Expressions</a>
<a href="#cake">Cake, and Cakefiles</a>
<a href="#source-maps">Source Maps</a>
<a href="#scripts">"text/coffeescript" Script Tags</a>
<a href="#resources">Books, Screencasts, Examples and Resources</a>
<a href="#changelog">Change Log</a>
@@ -86,6 +87,7 @@
<a href="documentation/docs/command.html">"coffee" Command-Line Utility &mdash; src/command</a>
<a href="documentation/docs/optparse.html">Option Parsing &mdash; src/optparse</a>
<a href="documentation/docs/repl.html">Interactive REPL &mdash; src/repl</a>
<a href="documentation/docs/sourcemap.html">Source Maps &mdash; src/sourcemap</a>
</div>
</div>
<div id="error" style="display:none;"></div>
@@ -114,9 +116,12 @@
<p>
<b>Latest Version:</b>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.5.0">1.5.0</a>
<a href="http://github.com/jashkenas/coffee-script/tarball/1.6.1">1.6.1</a>
</p>
<pre>
sudo npm install -g coffee-script</pre>
<h2>
<span id="overview" class="bookmark"></span>
Overview
@@ -311,6 +316,13 @@ sudo bin/cake install</pre>
of the same name.
</td>
</tr>
<tr>
<td><code>-m, --map</code></td>
<td>
Generate source maps alongside the compiled JavaScript files. Adds
<tt>sourceMappingURL</tt> directives to the JavaScript as well.
</td>
</tr>
<tr>
<td width="25%"><code>-i, --interactive</code></td>
<td>
@@ -383,7 +395,7 @@ sudo bin/cake install</pre>
<td><code>-b, --bare</code></td>
<td>
Compile the JavaScript without the
<a href="#lexical_scope">top-level function safety wrapper</a>.
<a href="#lexical-scope">top-level function safety wrapper</a>.
</td>
</tr>
<tr>
@@ -460,7 +472,9 @@ Expressions
Besides being used as an ordinary programming language, CoffeeScript may
also be written in "literate" mode. If you name your file with a
<tt>.litcoffee</tt> extension, you can write it as a Markdown document &mdash;
a document that also happens to be executable CoffeeScript code.
a document that also happens to be executable CoffeeScript code. The compiler
will treat any indented blocks (Markdown's way of indicating source code)
as code, and ignore the rest as comments.
</p>
<p>
@@ -474,8 +488,9 @@ Expressions
<p>
I'm fairly excited about this direction for the language, and am looking
forward to writing (and more importantly, reading) more programs in this style.
As <b>1.5.0</b> is the first version of CoffeeScript that supports it, let us know
if you have any ideas for improving the feature.
More information about Literate CoffeeScript, including an
<a href="https://github.com/jashkenas/journo">example program</a>,
are <a href="http://ashkenas.com/literate-coffeescript">available in this blog post</a>.
</p>
<h2>
@@ -665,7 +680,7 @@ log object.<span class="Storage">class</span>
</pre><script>window.example5 = "$('.account').attr class: 'active'\n\nlog object.class\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example5);'>load</div><br class='clear' /></div>
<p>
<span id="lexical_scope" class="bookmark"></span>
<span id="lexical-scope" class="bookmark"></span>
<b class="header">Lexical Scoping and Variable Safety</b>
The CoffeeScript compiler takes care to make sure that all of your variables
are properly declared within lexical scope &mdash; you never need to write
@@ -1517,7 +1532,7 @@ Snake <span class="Keyword">=</span> (<span class="Storage">function</span>(_sup
__extends(Snake, _super);
<span class="Storage">function</span> <span class="FunctionName">Snake</span>() {
Snake.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
<span class="Keyword">return</span> Snake.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
}
<span class="LibraryClassType">Snake</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
@@ -1534,7 +1549,7 @@ Horse <span class="Keyword">=</span> (<span class="Storage">function</span>(_sup
__extends(Horse, _super);
<span class="Storage">function</span> <span class="FunctionName">Horse</span>() {
Horse.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
<span class="Keyword">return</span> Horse.__super__.<span class="LibraryConstant">constructor</span>.<span class="LibraryFunction">apply</span>(<span class="Variable">this</span>, arguments);
}
<span class="LibraryClassType">Horse</span>.<span class="LibraryConstant">prototype</span>.<span class="FunctionName">move</span> = <span class="Storage">function</span>() {
@@ -1576,7 +1591,7 @@ Snake = (function(_super) {
__extends(Snake, _super);
function Snake() {
Snake.__super__.constructor.apply(this, arguments);
return Snake.__super__.constructor.apply(this, arguments);
}
Snake.prototype.move = function() {
@@ -1593,7 +1608,7 @@ Horse = (function(_super) {
__extends(Horse, _super);
function Horse() {
Horse.__super__.constructor.apply(this, arguments);
return Horse.__super__.constructor.apply(this, arguments);
}
Horse.prototype.move = function() {
@@ -1774,7 +1789,7 @@ _ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call
;alert(contents.join(""));'>run: contents.join("")</div><br class='clear' /></div>
<p>
<span id="fat_arrow" class="bookmark"></span>
<span id="fat-arrow" class="bookmark"></span>
<b class="header">Function binding</b>
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
object that the current function is attached to. If you pass a function as
@@ -2023,18 +2038,18 @@ html = "<strong>\n cup of coffeescript\n</strong>";
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 v1.5.0</span>
<span class="Comment">CoffeeScript Compiler v1.6.1</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">###</span></span>
</pre><pre class="idle"><span class="Comment"><span class="Comment">/*</span></span>
<span class="Comment">CoffeeScript Compiler v1.5.0</span>
<span class="Comment">CoffeeScript Compiler v1.6.1</span>
<span class="Comment">Released under the MIT License</span>
<span class="Comment"><span class="Comment">*/</span></span>
</pre><script>window.example37 = "###\nCoffeeScript Compiler v1.5.0\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><br class='clear' /></div>
</pre><script>window.example37 = "###\nCoffeeScript Compiler v1.6.1\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><br class='clear' /></div>
<p>
<span id="regexes" class="bookmark"></span>
@@ -2118,6 +2133,26 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
code itself &mdash; not the cake task.
</p>
<h2>
<span id="source-maps" class="bookmark"></span>
Source Maps
</h2>
<p>
CoffeeScript 1.6.1 and above include support for generating source maps,
a way to tell your JavaScript engine what part of your CoffeeScript
program matches up with the code being evaluated. Browsers that support it
can automatically use source maps to show your original source code
in the debugger. To generate source maps alongside your JavaScript files,
pass the <tt>--map</tt> or <tt>-m</tt> flag to the compiler.
</p>
<p>
For a full introduction to source maps, how they work, and how to hook
them up in your browser, read the
<a href="http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/">HTML5 Tutorial</a>.
</p>
<h2>
<span id="scripts" class="bookmark"></span>
"text/coffeescript" Script Tags
@@ -2178,6 +2213,12 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
a fast-paced multiplayer word game, writing both the client-side and Node.js
portions in CoffeeScript.
</li>
<li>
<a href="http://www.packtpub.com/coffeescript-programming-with-jquery-rails-nodejs/book">CoffeeScript Programming with jQuery, Rails, and Node.js</a>
is a new book by Michael Erasmus that covers CoffeeScript with an eye
towards real-world usage both in the browser (jQuery) and on the server
size (Rails, Node).
</li>
<li>
<a href="http://ristrettolo.gy">CoffeeScript Ristretto</a>
is a deep dive into CoffeeScript's semantics from simple functions up through
@@ -2321,6 +2362,35 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
Change Log
</h2>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.5.0...1.6.1">1.6.1</a>
<span class="timestamp"> &ndash; <small>March 5, 2013</small></span>
</b>
<ul>
<li>
First release of <a href="#source-maps">source maps</a>. Pass the
<tt>--map</tt> flag to the compiler, and off you go. Direct all your
thanks over to <a href="http://github.com/jwalton">Jason Walton</a>.
</li>
<li>
Fixed a 1.5.0 regression with multiple implicit calls against an
indented implicit object. Combinations of implicit function calls
and implicit objects should generally be parsed better now &mdash;
but it still isn't good <i>style</i> to nest them too heavily.
</li>
<li>
<tt>.coffee.md</tt> is now also supported as a Literate CoffeeScript
file extension, for existing tooling.
<tt>.litcoffee</tt> remains the canonical one.
</li>
<li>
Several minor fixes surrounding member properties, bound methods and
<tt>super</tt> in class declarations.
</li>
</ul>
</p>
<p>
<b class="header" style="margin-top: 20px;">
<a href="https://github.com/jashkenas/coffee-script/compare/1.4.0...1.5.0">1.5.0</a>
@@ -2340,7 +2410,7 @@ task(<span class="String"><span class="String">'</span>build:parser<span class="
</li>
<li>
You can now loop over an array backwards, without having to manually
deal with the indexes.
deal with the indexes: <tt>for item in list by -1</tt>
</li>
<li>
Source locations are now preserved in the CoffeeScript AST, although

View File

@@ -1,6 +1,7 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var CoffeeScript, runScripts;
var CoffeeScript, runScripts,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
CoffeeScript = require('./coffee-script');
@@ -29,8 +30,11 @@
return;
}
CoffeeScript.load = function(url, callback) {
CoffeeScript.load = function(url, callback, options) {
var xhr;
if (options == null) {
options = {};
}
xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) {
@@ -40,7 +44,7 @@
var _ref;
if (xhr.readyState === 4) {
if ((_ref = xhr.status) === 0 || _ref === 200) {
CoffeeScript.run(xhr.responseText);
CoffeeScript.run(xhr.responseText, options);
} else {
throw new Error("Could not load " + url);
}
@@ -53,14 +57,15 @@
};
runScripts = function() {
var coffees, execute, index, length, s, scripts;
var coffees, coffeetypes, execute, index, length, s, scripts;
scripts = document.getElementsByTagName('script');
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
coffees = (function() {
var _i, _len, _results;
var _i, _len, _ref, _results;
_results = [];
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
s = scripts[_i];
if (s.type === 'text/coffeescript') {
if (_ref = s.type, __indexOf.call(coffeetypes, _ref) >= 0) {
_results.push(s);
}
}
@@ -69,13 +74,17 @@
index = 0;
length = coffees.length;
(execute = function() {
var script;
var mediatype, options, script;
script = coffees[index++];
if ((script != null ? script.type : void 0) === 'text/coffeescript') {
mediatype = script != null ? script.type : void 0;
if (__indexOf.call(coffeetypes, mediatype) >= 0) {
options = {
literate: mediatype === 'text/literate-coffeescript'
};
if (script.src) {
return CoffeeScript.load(script.src, execute);
return CoffeeScript.load(script.src, execute, options);
} else {
CoffeeScript.run(script.innerHTML);
CoffeeScript.run(script.innerHTML, options);
return execute();
}
}

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var CoffeeScript, cakefileDirectory, existsSync, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;

View File

@@ -1,7 +1,6 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var Lexer, compile, ext, extensions, fs, lexer, loadFile, parser, path, vm, _i, _len,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
var Lexer, compile, ext, fs, helpers, lexer, loadFile, parser, path, sourcemap, vm, _i, _len, _ref,
__hasProp = {}.hasOwnProperty;
fs = require('fs');
@@ -12,40 +11,69 @@
parser = require('./parser').parser;
helpers = require('./helpers');
vm = require('vm');
extensions = ['.coffee', '.litcoffee'];
sourcemap = require('./sourcemap');
loadFile = function(module, filename) {
var raw, stripped;
raw = fs.readFileSync(filename, 'utf8');
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
return module._compile(compile(stripped, {
filename: filename
filename: filename,
literate: helpers.isLiterate(filename)
}), filename);
};
if (require.extensions) {
for (_i = 0, _len = extensions.length; _i < _len; _i++) {
ext = extensions[_i];
_ref = ['.coffee', '.litcoffee', '.md', '.coffee.md'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ext = _ref[_i];
require.extensions[ext] = loadFile;
}
}
exports.VERSION = '1.5.0';
exports.VERSION = '1.6.1';
exports.helpers = require('./helpers');
exports.helpers = helpers;
exports.compile = compile = function(code, options) {
var header, js, merge;
var answer, coffeeFile, currentColumn, currentLine, fragment, fragments, header, js, jsFile, merge, newLines, sourceMap, _j, _len1;
if (options == null) {
options = {};
}
merge = exports.helpers.merge;
try {
js = (parser.parse(lexer.tokenize(code, options))).compile(options);
if (!options.header) {
return js;
if (options.sourceMap) {
coffeeFile = helpers.baseFileName(options.filename);
jsFile = helpers.baseFileName(options.filename, true) + ".js";
sourceMap = new sourcemap.SourceMap();
}
fragments = (parser.parse(lexer.tokenize(code, options))).compileToFragments(options);
currentLine = 0;
if (options.header) {
currentLine += 1;
}
if (options.sourceMap) {
currentLine += 1;
}
currentColumn = 0;
js = "";
for (_j = 0, _len1 = fragments.length; _j < _len1; _j++) {
fragment = fragments[_j];
if (sourceMap) {
if (fragment.locationData) {
sourceMap.addMapping([fragment.locationData.first_line, fragment.locationData.first_column], [currentLine, currentColumn], {
noReplace: true
});
}
newLines = helpers.count(fragment.code, "\n");
currentLine += newLines;
currentColumn = fragment.code.length - (newLines ? fragment.code.lastIndexOf("\n") : 0);
}
js += fragment.code;
}
} catch (err) {
if (options.filename) {
@@ -53,8 +81,22 @@
}
throw err;
}
header = "Generated by CoffeeScript " + this.VERSION;
return "// " + header + "\n" + js;
if (options.header) {
header = "Generated by CoffeeScript " + this.VERSION;
js = "// " + header + "\n" + js;
}
if (options.sourceMap) {
answer = {
js: js
};
if (sourceMap) {
answer.sourceMap = sourceMap;
answer.v3SourceMap = sourcemap.generateV3SourceMap(sourceMap, coffeeFile, jsFile);
}
return answer;
} else {
return js;
}
};
exports.tokens = function(code, options) {
@@ -70,7 +112,7 @@
};
exports.run = function(code, options) {
var mainModule, _ref;
var mainModule;
if (options == null) {
options = {};
}
@@ -78,7 +120,7 @@
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
mainModule.moduleCache && (mainModule.moduleCache = {});
mainModule.paths = require('module')._nodeModulePaths(path.dirname(fs.realpathSync(options.filename)));
if ((_ref = path.extname(mainModule.filename), __indexOf.call(extensions, _ref) < 0) || require.extensions) {
if (!helpers.isCoffee(mainModule.filename) || require.extensions) {
return mainModule._compile(compile(code, options), mainModule.filename);
} else {
return mainModule._compile(code, mainModule.filename);
@@ -86,7 +128,7 @@
};
exports["eval"] = function(code, options) {
var Module, Script, js, k, o, r, sandbox, v, _j, _len1, _module, _ref, _ref1, _require;
var Module, Script, js, k, o, r, sandbox, v, _j, _len1, _module, _ref1, _ref2, _require;
if (options == null) {
options = {};
}
@@ -100,10 +142,10 @@
sandbox = options.sandbox;
} else {
sandbox = Script.createContext();
_ref = options.sandbox;
for (k in _ref) {
if (!__hasProp.call(_ref, k)) continue;
v = _ref[k];
_ref1 = options.sandbox;
for (k in _ref1) {
if (!__hasProp.call(_ref1, k)) continue;
v = _ref1[k];
sandbox[k] = v;
}
}
@@ -120,9 +162,9 @@
return Module._load(path, _module, true);
};
_module.filename = sandbox.__filename;
_ref1 = Object.getOwnPropertyNames(require);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
r = _ref1[_j];
_ref2 = Object.getOwnPropertyNames(require);
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
r = _ref2[_j];
if (r !== 'paths') {
_require[r] = require[r];
}

View File

@@ -1,7 +1,6 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, coffee_exts, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, exists, forkNode, fs, helpers, hidden, joinTimeout, lint, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, exists, forkNode, fs, helpers, hidden, joinTimeout, lint, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, sourceCode, sources, spawn, timeLog, unwatchDir, usage, version, wait, watch, watchDir, watchers, writeJs, _ref;
fs = require('fs');
@@ -35,7 +34,7 @@
BANNER = 'Usage: coffee [options] path/to/script.coffee -- [args]\n\nIf called without options, `coffee` will run your script.';
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
SWITCHES = [['-b', '--bare', 'compile without a top-level function wrapper'], ['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-e', '--eval', 'pass a string from the command line as input'], ['-h', '--help', 'display this help message'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-m', '--map', 'generate source map and save as .map files'], ['-n', '--nodes', 'print out the parse tree that the parser produces'], ['--nodejs [ARGS]', 'pass options directly to the "node" binary'], ['-o', '--output [DIR]', 'set the output directory for compiled JavaScript'], ['-p', '--print', 'print out the compiled JavaScript'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-t', '--tokens', 'print out the tokens that the lexer/rewriter produce'], ['-v', '--version', 'display the version number'], ['-w', '--watch', 'watch scripts for changes and rerun commands']];
opts = {};
@@ -49,8 +48,6 @@
optionParser = null;
coffee_exts = ['.coffee', '.litcoffee'];
exports.run = function() {
var literals, source, _i, _len, _results;
parseOptions();
@@ -91,27 +88,19 @@
compilePath = function(source, topLevel, base) {
return fs.stat(source, function(err, stats) {
var _ref1, _ref2;
if (err && err.code !== 'ENOENT') {
throw err;
}
if ((err != null ? err.code : void 0) === 'ENOENT') {
if (topLevel && source && (_ref1 = path.extname(source), __indexOf.call(coffee_exts, _ref1) < 0)) {
source = sources[sources.indexOf(source)] = "" + source + ".coffee";
return compilePath(source, topLevel, base);
}
if (topLevel) {
console.error("File not found: " + source);
process.exit(1);
}
return;
console.error("File not found: " + source);
process.exit(1);
}
if (stats.isDirectory() && path.dirname(source) !== 'node_modules') {
if (opts.watch) {
watchDir(source, base);
}
return fs.readdir(source, function(err, files) {
var file, index, _ref2, _ref3;
var file, index, _ref1, _ref2;
if (err && err.code !== 'ENOENT') {
throw err;
}
@@ -122,7 +111,7 @@
files = files.filter(function(file) {
return !hidden(file);
});
[].splice.apply(sources, [index, index - index + 1].concat(_ref2 = (function() {
[].splice.apply(sources, [index, index - index + 1].concat(_ref1 = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = files.length; _i < _len; _i++) {
@@ -130,15 +119,15 @@
_results.push(path.join(source, file));
}
return _results;
})())), _ref2;
[].splice.apply(sourceCode, [index, index - index + 1].concat(_ref3 = files.map(function() {
})())), _ref1;
[].splice.apply(sourceCode, [index, index - index + 1].concat(_ref2 = files.map(function() {
return null;
}))), _ref3;
}))), _ref2;
return files.forEach(function(file) {
return compilePath(path.join(source, file), false, base);
});
});
} else if (topLevel || (_ref2 = path.extname(source), __indexOf.call(coffee_exts, _ref2) >= 0)) {
} else if (topLevel || helpers.isCoffee(source)) {
if (opts.watch) {
watch(source, base);
}
@@ -159,7 +148,7 @@
};
compileScript = function(file, input, base) {
var o, options, t, task;
var compiled, o, options, t, task;
o = opts;
options = compileOptions(file);
try {
@@ -179,12 +168,17 @@
sourceCode[sources.indexOf(t.file)] = t.input;
return compileJoin();
} else {
t.output = CoffeeScript.compile(t.input, t.options);
compiled = CoffeeScript.compile(t.input, t.options);
t.output = compiled;
if (o.map) {
t.output = compiled.js;
t.sourceMap = compiled.v3SourceMap;
}
CoffeeScript.emit('success', task);
if (o.print) {
return printLine(t.output.trim());
} else if (o.compile) {
return writeJs(t.file, t.output, base);
} else if (o.compile || o.map) {
return writeJs(base, t.file, t.output, t.sourceMap);
} else if (o.lint) {
return lint(t.file, t.output);
}
@@ -375,30 +369,49 @@
}
};
outputPath = function(source, base) {
var baseDir, dir, filename, srcDir;
filename = path.basename(source, path.extname(source)) + '.js';
outputPath = function(source, base, extension) {
var baseDir, basename, dir, srcDir;
if (extension == null) {
extension = ".js";
}
basename = helpers.baseFileName(source, true);
srcDir = path.dirname(source);
baseDir = base === '.' ? srcDir : srcDir.substring(base.length);
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
return path.join(dir, filename);
return path.join(dir, basename + extension);
};
writeJs = function(source, js, base) {
var compile, jsDir, jsPath;
jsPath = outputPath(source, base);
writeJs = function(base, sourcePath, js, generatedSourceMap) {
var compile, jsDir, jsPath, sourceMapPath;
if (generatedSourceMap == null) {
generatedSourceMap = null;
}
jsPath = outputPath(sourcePath, base);
sourceMapPath = outputPath(sourcePath, base, ".map");
jsDir = path.dirname(jsPath);
compile = function() {
if (js.length <= 0) {
js = ' ';
}
return fs.writeFile(jsPath, js, function(err) {
if (err) {
return printLine(err.message);
} else if (opts.compile && opts.watch) {
return timeLog("compiled " + source);
if (opts.compile) {
if (js.length <= 0) {
js = ' ';
}
});
if (generatedSourceMap) {
js = "//@ sourceMappingURL=" + (helpers.baseFileName(sourceMapPath)) + "\n" + js;
}
fs.writeFile(jsPath, js, function(err) {
if (err) {
return printLine(err.message);
} else if (opts.compile && opts.watch) {
return timeLog("compiled " + sourcePath);
}
});
}
if (generatedSourceMap) {
return fs.writeFile(sourceMapPath, generatedSourceMap, function(err) {
if (err) {
return printLine("Could not write source map: " + err.message);
}
});
}
};
return exists(jsDir, function(itExists) {
if (itExists) {
@@ -431,7 +444,7 @@
};
printTokens = function(tokens) {
var locationData, strings, tag, token, value;
var strings, tag, token, value;
strings = (function() {
var _i, _len, _results;
_results = [];
@@ -439,8 +452,7 @@
token = tokens[_i];
tag = token[0];
value = token[1].toString().replace(/\n/, '\\n');
locationData = helpers.locationDataToString(token[2]);
_results.push("[" + tag + " " + value + " " + locationData + "]");
_results.push("[" + tag + " " + value + "]");
}
return _results;
})();
@@ -452,7 +464,7 @@
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
o = opts = optionParser.parse(process.argv.slice(2));
o.compile || (o.compile = !!o.output);
o.run = !(o.compile || o.print || o.lint);
o.run = !(o.compile || o.print || o.lint || o.map);
o.print = !!(o.print || (o["eval"] || o.stdio && o.compile));
sources = o["arguments"];
for (i = _i = 0, _len = sources.length; _i < _len; i = ++_i) {
@@ -462,13 +474,12 @@
};
compileOptions = function(filename) {
var literate;
literate = path.extname(filename) === '.litcoffee';
return {
filename: filename,
literate: literate,
literate: helpers.isLiterate(filename),
bare: opts.bare,
header: opts.compile
header: opts.compile,
sourceMap: opts.map
};
};

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
@@ -16,7 +16,6 @@
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
action = action.replace(/\bnew /g, '$&yy.');
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
action = action.replace(/\b(Op|Value\.(create|wrap))\b/g, 'yy.$&');
addLocationDataFn = function(first, last) {
if (!last) {
return "yy.addLocationDataFn(@" + first + ")";
@@ -94,12 +93,12 @@
],
AssignObj: [
o('ObjAssignable', function() {
return Value.wrap($1);
return new Value($1);
}), o('ObjAssignable : Expression', function() {
return new Assign(LOC(1)(Value.wrap($1)), $3, 'object');
return new Assign(LOC(1)(new Value($1)), $3, 'object');
}), o('ObjAssignable :\
INDENT Expression OUTDENT', function() {
return new Assign(LOC(1)(Value.wrap($1)), $4, 'object');
return new Assign(LOC(1)(new Value($1)), $4, 'object');
}), o('Comment')
],
ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')],
@@ -160,27 +159,27 @@
],
SimpleAssignable: [
o('Identifier', function() {
return Value.wrap($1);
return new Value($1);
}), o('Value Accessor', function() {
return $1.add($2);
}), o('Invocation Accessor', function() {
return Value.wrap($1, [].concat($2));
return new Value($1, [].concat($2));
}), o('ThisProperty')
],
Assignable: [
o('SimpleAssignable'), o('Array', function() {
return Value.wrap($1);
return new Value($1);
}), o('Object', function() {
return Value.wrap($1);
return new Value($1);
})
],
Value: [
o('Assignable'), o('Literal', function() {
return Value.wrap($1);
return new Value($1);
}), o('Parenthetical', function() {
return Value.wrap($1);
return new Value($1);
}), o('Range', function() {
return Value.wrap($1);
return new Value($1);
}), o('This')
],
Accessor: [
@@ -190,6 +189,8 @@
return new Access($2, 'soak');
}), o(':: Identifier', function() {
return [LOC(1)(new Access(new Literal('prototype'))), LOC(2)(new Access($2))];
}), o('?:: Identifier', function() {
return [LOC(1)(new Access(new Literal('prototype'), 'soak')), LOC(2)(new Access($2))];
}), o('::', function() {
return new Access(new Literal('prototype'));
}), o('Index')
@@ -274,14 +275,14 @@
],
This: [
o('THIS', function() {
return Value.wrap(new Literal('this'));
return new Value(new Literal('this'));
}), o('@', function() {
return Value.wrap(new Literal('this'));
return new Value(new Literal('this'));
})
],
ThisProperty: [
o('@ Identifier', function() {
return Value.wrap(LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this');
return new Value(LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this');
})
],
Array: [
@@ -348,7 +349,7 @@
o('CATCH Identifier Block', function() {
return [$2, $3];
}), o('CATCH Object Block', function() {
return [LOC(2)(Value.wrap($2)), $3];
return [LOC(2)(new Value($2)), $3];
})
],
Throw: [
@@ -411,7 +412,7 @@
ForBody: [
o('FOR Range', function() {
return {
source: LOC(2)(Value.wrap($2))
source: LOC(2)(new Value($2))
};
}), o('ForStart ForSource', function() {
$2.own = $1.own;
@@ -430,9 +431,9 @@
],
ForValue: [
o('Identifier'), o('ThisProperty'), o('Array', function() {
return Value.wrap($1);
return new Value($1);
}), o('Object', function() {
return Value.wrap($1);
return new Value($1);
})
],
ForVariables: [
@@ -533,42 +534,42 @@
],
Operation: [
o('UNARY Expression', function() {
return Op.create($1, $2);
return new Op($1, $2);
}), o('- Expression', (function() {
return Op.create('-', $2);
return new Op('-', $2);
}), {
prec: 'UNARY'
}), o('+ Expression', (function() {
return Op.create('+', $2);
return new Op('+', $2);
}), {
prec: 'UNARY'
}), o('-- SimpleAssignable', function() {
return Op.create('--', $2);
return new Op('--', $2);
}), o('++ SimpleAssignable', function() {
return Op.create('++', $2);
return new Op('++', $2);
}), o('SimpleAssignable --', function() {
return Op.create('--', $1, null, true);
return new Op('--', $1, null, true);
}), o('SimpleAssignable ++', function() {
return Op.create('++', $1, null, true);
return new Op('++', $1, null, true);
}), o('Expression ?', function() {
return new Existence($1);
}), o('Expression + Expression', function() {
return Op.create('+', $1, $3);
return new Op('+', $1, $3);
}), o('Expression - Expression', function() {
return Op.create('-', $1, $3);
return new Op('-', $1, $3);
}), o('Expression MATH Expression', function() {
return Op.create($2, $1, $3);
return new Op($2, $1, $3);
}), o('Expression SHIFT Expression', function() {
return Op.create($2, $1, $3);
return new Op($2, $1, $3);
}), o('Expression COMPARE Expression', function() {
return Op.create($2, $1, $3);
return new Op($2, $1, $3);
}), o('Expression LOGIC Expression', function() {
return Op.create($2, $1, $3);
return new Op($2, $1, $3);
}), o('Expression RELATION Expression', function() {
if ($2.charAt(0) === '!') {
return Op.create($2.slice(1), $1, $3).invert();
return new Op($2.slice(1), $1, $3).invert();
} else {
return Op.create($2, $1, $3);
return new Op($2, $1, $3);
}
}), o('SimpleAssignable COMPOUND_ASSIGN\
Expression', function() {
@@ -585,7 +586,7 @@
]
};
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
tokens = [];

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var buildLocationData, extend, flatten, _ref;
@@ -121,4 +121,30 @@
}
};
exports.baseFileName = function(file, stripExt) {
var parts;
if (stripExt == null) {
stripExt = false;
}
parts = file.split('/');
file = parts[parts.length - 1];
if (!stripExt) {
return file;
}
parts = file.split('.');
parts.pop();
if (parts[parts.length - 1] === 'coffee') {
parts.pop();
}
return parts.join('.');
};
exports.isCoffee = function(file) {
return /\.((lit)?coffee|coffee\.md)$/.test(file);
};
exports.isLiterate = function(file) {
return /\.(litcoffee|coffee\.md)$/.test(file);
};
}).call(this);

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var key, val, _ref;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LITERATE, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, locationDataToString, starts, _ref, _ref1,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
@@ -17,7 +17,6 @@
opts = {};
}
this.literate = opts.literate;
code = this.clean(code);
this.indent = 0;
this.indebt = 0;
this.outdebt = 0;
@@ -26,6 +25,7 @@
this.tokens = [];
this.chunkLine = opts.line || 0;
this.chunkColumn = opts.column || 0;
code = this.clean(code);
i = 0;
while (this.chunk = code.slice(i)) {
consumed = this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
@@ -47,10 +47,11 @@
if (code.charCodeAt(0) === BOM) {
code = code.slice(1);
}
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
if (WHITESPACE.test(code)) {
code = "\n" + code;
this.chunkLine--;
}
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
if (this.literate) {
lines = (function() {
var _i, _len, _ref2, _results;
@@ -83,7 +84,7 @@
this.token('OWN', id);
return id.length;
}
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::' || _ref2 === '?::') || !prev.spaced && prev[0] === '@');
tag = 'IDENTIFIER';
if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
tag = id.toUpperCase();
@@ -526,6 +527,9 @@
if (indent) {
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
}
if (this.literate) {
doc = doc.replace(/\n# \n/g, '\n\n');
}
if (!herecomment) {
doc = doc.replace(/^\n/, '');
}
@@ -732,13 +736,15 @@
Lexer.prototype.makeToken = function(tag, value, offsetInChunk, length) {
var lastCharacter, locationData, token, _ref2, _ref3;
offsetInChunk = offsetInChunk || 0;
if (length === void 0) {
if (offsetInChunk == null) {
offsetInChunk = 0;
}
if (length == null) {
length = value.length;
}
locationData = {};
_ref2 = this.getLineAndColumnFromChunk(offsetInChunk), locationData.first_line = _ref2[0], locationData.first_column = _ref2[1];
lastCharacter = length > 0 ? length - 1 : 0;
lastCharacter = Math.max(0, length - 1);
_ref3 = this.getLineAndColumnFromChunk(offsetInChunk + (length - 1)), locationData.last_line = _ref3[0], locationData.last_column = _ref3[1];
token = [tag, value, locationData];
return token;
@@ -763,7 +769,7 @@
Lexer.prototype.unfinished = function() {
var _ref2;
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === '?::' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
};
Lexer.prototype.escapeLines = function(str, heredoc) {
@@ -838,7 +844,7 @@
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?(\.|::)|\.{2,3})/;
WHITESPACE = /^[^\n\S]+/;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var CoffeeScript, addMultilineHandler, merge, nodeREPL, replDefaults, vm;
@@ -16,7 +16,7 @@
var js;
input = input.replace(/\uFF00/g, '\n');
input = input.replace(/(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, '$1$2$3');
if (/^\s*$/.test(input)) {
if (/^(\s*|\(\s*\))$/.test(input)) {
return cb(null);
}
try {
@@ -24,10 +24,10 @@
filename: filename,
bare: true
});
return cb(null, vm.runInContext(js, context, filename));
} catch (err) {
cb(err);
return cb(err);
}
return cb(null, vm.runInContext(js, context, filename));
}
};

View File

@@ -1,9 +1,16 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
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 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, generate, left, rite, _i, _len, _ref,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
__slice = [].slice;
generate = function(tag, value) {
var tok;
tok = [tag, value];
tok.generated = true;
return tok;
};
exports.Rewriter = (function() {
function Rewriter() {}
@@ -16,8 +23,7 @@
this.closeOpenIndexes();
this.addImplicitIndentation();
this.tagPostfixConditionals();
this.addImplicitBraces();
this.addImplicitParentheses();
this.addImplicitBracesAndParens();
this.addLocationDataToGeneratedTokens();
return this.tokens;
};
@@ -112,140 +118,236 @@
});
};
Rewriter.prototype.addImplicitBraces = function() {
var action, condition, sameLine, stack, start, startIndent, startIndex, startsLine;
stack = [];
start = null;
startsLine = null;
sameLine = true;
startIndent = 0;
startIndex = 0;
condition = function(token, i) {
var one, tag, three, two, _ref, _ref1;
_ref = this.tokens.slice(i + 1, +(i + 3) + 1 || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
Rewriter.prototype.matchTags = function() {
var fuzz, i, j, pattern, _i, _ref, _ref1;
i = arguments[0], pattern = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
fuzz = 0;
for (j = _i = 0, _ref = pattern.length; 0 <= _ref ? _i < _ref : _i > _ref; j = 0 <= _ref ? ++_i : --_i) {
while (this.tag(i + j + fuzz) === 'HERECOMMENT') {
fuzz += 2;
}
if (pattern[j] == null) {
continue;
}
if (typeof pattern[j] === 'string') {
pattern[j] = [pattern[j]];
}
if (_ref1 = this.tag(i + j + fuzz), __indexOf.call(pattern[j], _ref1) < 0) {
return false;
}
tag = token[0];
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
sameLine = false;
}
return (((tag === 'TERMINATOR' || tag === 'OUTDENT') || (__indexOf.call(IMPLICIT_END, tag) >= 0 && sameLine && !(i - startIndex === 1))) && ((!startsLine && this.tag(i - 1) !== ',') || !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':'))) || (tag === ',' && one && ((_ref1 = one[0]) !== 'IDENTIFIER' && _ref1 !== 'NUMBER' && _ref1 !== 'STRING' && _ref1 !== '@' && _ref1 !== 'TERMINATOR' && _ref1 !== 'OUTDENT'));
};
action = function(token, i) {
var tok;
tok = this.generate('}', '}');
return this.tokens.splice(i, 0, tok);
};
return this.scanTokens(function(token, i, tokens) {
var ago, idx, prevTag, tag, tok, value, _ref, _ref1;
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
return 1;
}
if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
start = stack.pop();
return 1;
}
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref1 = stack[stack.length - 1]) != null ? _ref1[0] : void 0) !== '{'))) {
return 1;
}
sameLine = true;
startIndex = i + 1;
stack.push(['{']);
idx = ago === '@' ? i - 2 : i - 1;
while (this.tag(idx - 2) === 'HERECOMMENT') {
idx -= 2;
}
prevTag = this.tag(idx - 1);
startsLine = !prevTag || (__indexOf.call(LINEBREAKS, prevTag) >= 0);
value = new String('{');
value.generated = true;
tok = this.generate('{', value);
tokens.splice(idx, 0, tok);
this.detectEnd(i + 2, condition, action);
return 2;
});
}
return true;
};
Rewriter.prototype.addImplicitParentheses = function() {
var action, callIndex, condition, noCall, seenControl, seenSingle;
noCall = seenSingle = seenControl = false;
callIndex = null;
condition = function(token, i) {
var post, tag, _ref, _ref1;
tag = token[0];
if (!seenSingle && token.fromThen) {
return true;
Rewriter.prototype.looksObjectish = function(j) {
return this.matchTags(j, '@', null, ':') || this.matchTags(j, null, ':');
};
Rewriter.prototype.findTagsBackwards = function(i, tags) {
var backStack, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
backStack = [];
while (i >= 0 && (backStack.length || (_ref2 = this.tag(i), __indexOf.call(tags, _ref2) < 0) && ((_ref3 = this.tag(i), __indexOf.call(EXPRESSION_START, _ref3) < 0) || this.tokens[i].generated) && (_ref4 = this.tag(i), __indexOf.call(LINEBREAKS, _ref4) < 0))) {
if (_ref = this.tag(i), __indexOf.call(EXPRESSION_END, _ref) >= 0) {
backStack.push(this.tag(i));
}
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>' || tag === 'CLASS') {
seenSingle = true;
if ((_ref1 = this.tag(i), __indexOf.call(EXPRESSION_START, _ref1) >= 0) && backStack.length) {
backStack.pop();
}
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY' || tag === '=') {
seenControl = true;
}
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
return true;
}
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (((_ref = this.tag(i - 2)) !== 'CLASS' && _ref !== 'EXTENDS') && (_ref1 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref1) < 0) && !(callIndex === i - 1 && (post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
};
action = function(token, i) {
return this.tokens.splice(i, 0, this.generate('CALL_END', ')'));
};
i -= 1;
}
return _ref5 = this.tag(i), __indexOf.call(tags, _ref5) >= 0;
};
Rewriter.prototype.addImplicitBracesAndParens = function() {
var stack;
stack = [];
return this.scanTokens(function(token, i, tokens) {
var callObject, current, next, prev, tag, _ref, _ref1, _ref2;
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, nextTag, offset, prevTag, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
tag = token[0];
if (tag === 'CLASS' || tag === 'IF' || tag === 'FOR' || tag === 'WHILE') {
noCall = true;
prevTag = (i > 0 ? tokens[i - 1] : [])[0];
nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0];
stackTop = function() {
return stack[stack.length - 1];
};
startIdx = i;
forward = function(n) {
return i - startIdx + n;
};
inImplicit = function() {
var _ref, _ref1;
return (_ref = stackTop()) != null ? (_ref1 = _ref[2]) != null ? _ref1.ours : void 0 : void 0;
};
inImplicitCall = function() {
var _ref;
return inImplicit() && ((_ref = stackTop()) != null ? _ref[0] : void 0) === '(';
};
inImplicitObject = function() {
var _ref;
return inImplicit() && ((_ref = stackTop()) != null ? _ref[0] : void 0) === '{';
};
inImplicitControl = function() {
var _ref;
return inImplicit && ((_ref = stackTop()) != null ? _ref[0] : void 0) === 'CONTROL';
};
startImplicitCall = function(j) {
var idx;
idx = j != null ? j : i;
stack.push([
'(', idx, {
ours: true
}
]);
tokens.splice(idx, 0, generate('CALL_START', '('));
if (j == null) {
return i += 1;
}
};
endImplicitCall = function() {
stack.pop();
tokens.splice(i, 0, generate('CALL_END', ')'));
return i += 1;
};
startImplicitObject = function(j, startsLine) {
var idx;
if (startsLine == null) {
startsLine = true;
}
idx = j != null ? j : i;
stack.push([
'{', idx, {
sameLine: true,
startsLine: startsLine,
ours: true
}
]);
tokens.splice(idx, 0, generate('{', generate(new String('{'))));
if (j == null) {
return i += 1;
}
};
endImplicitObject = function(j) {
j = j != null ? j : i;
stack.pop();
tokens.splice(j, 0, generate('}', '}'));
return i += 1;
};
if (inImplicitCall() && (tag === 'IF' || tag === 'TRY' || tag === 'FINALLY' || tag === 'CATCH' || tag === 'CLASS' || tag === 'SWITCH')) {
stack.push([
'CONTROL', i, {
ours: true
}
]);
return forward(1);
}
_ref = tokens.slice(i - 1, +(i + 1) + 1 || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref1 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref1) >= 0);
seenSingle = false;
seenControl = false;
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
noCall = false;
if (tag === 'INDENT' && inImplicit()) {
if (prevTag !== '=>' && prevTag !== '->' && prevTag !== '[' && prevTag !== '(' && prevTag !== ',' && prevTag !== '{' && prevTag !== 'TRY' && prevTag !== 'ELSE' && prevTag !== '=') {
while (inImplicitCall()) {
endImplicitCall();
}
}
if (inImplicitControl()) {
stack.pop();
}
stack.push([tag, i]);
return forward(1);
}
if (prev && !prev.spaced && tag === '?') {
token.call = true;
if (__indexOf.call(EXPRESSION_START, tag) >= 0) {
stack.push([tag, i]);
return forward(1);
}
if (token.fromThen) {
return 1;
if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
while (inImplicit()) {
if (inImplicitCall()) {
endImplicitCall();
} else if (inImplicitObject()) {
endImplicitObject();
} else {
stack.pop();
}
}
stack.pop();
}
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))) {
return 1;
if ((__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (__indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || __indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((_ref = tokens[i + 1]) != null ? _ref.spaced : void 0) && !((_ref1 = tokens[i + 1]) != null ? _ref1.newLine : void 0))) {
if (tag === '?') {
tag = token[0] = 'FUNC_EXIST';
}
startImplicitCall(i + 1);
return forward(2);
}
callIndex = i;
tokens.splice(i, 0, this.generate('CALL_START', '(', token[2]));
this.detectEnd(i + 1, condition, action);
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
if (this.matchTags(i, IMPLICIT_FUNC, 'INDENT', null, ':') && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
startImplicitCall(i + 1);
stack.push(['INDENT', i + 2]);
return forward(3);
}
return 2;
if (tag === ':') {
if (this.tag(i - 2) === '@') {
s = i - 2;
} else {
s = i - 1;
}
while (this.tag(s - 2) === 'HERECOMMENT') {
s -= 2;
}
startsLine = s === 0 || (_ref2 = this.tag(s - 1), __indexOf.call(LINEBREAKS, _ref2) >= 0) || tokens[s - 1].newLine;
if (stackTop()) {
_ref3 = stackTop(), stackTag = _ref3[0], stackIdx = _ref3[1];
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
return forward(1);
}
}
startImplicitObject(s, !!startsLine);
return forward(2);
}
if (prevTag === 'OUTDENT' && inImplicitCall() && (tag === '.' || tag === '?.' || tag === '::' || tag === '?::')) {
endImplicitCall();
return forward(1);
}
if (inImplicitObject() && __indexOf.call(LINEBREAKS, tag) >= 0) {
stackTop()[2].sameLine = false;
}
if (__indexOf.call(IMPLICIT_END, tag) >= 0) {
while (inImplicit()) {
_ref4 = stackTop(), stackTag = _ref4[0], stackIdx = _ref4[1], (_ref5 = _ref4[2], sameLine = _ref5.sameLine, startsLine = _ref5.startsLine);
if (inImplicitCall() && prevTag !== ',') {
endImplicitCall();
} else if (inImplicitObject() && sameLine && !startsLine) {
endImplicitObject();
} else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
endImplicitObject();
} else {
break;
}
}
}
if (tag === ',' && !this.looksObjectish(i + 1) && inImplicitObject() && (nextTag !== 'TERMINATOR' || !this.looksObjectish(i + 2))) {
offset = nextTag === 'OUTDENT' ? 1 : 0;
while (inImplicitObject()) {
endImplicitObject(i + offset);
}
}
return forward(1);
});
};
Rewriter.prototype.addLocationDataToGeneratedTokens = function() {
return this.scanTokens(function(token, i, tokens) {
var prevToken, tag;
tag = token[0];
if ((token.generated || token.explicit) && (!token[2])) {
if (i > 0) {
prevToken = tokens[i - 1];
token[2] = {
first_line: prevToken[2].last_line,
first_column: prevToken[2].last_column,
last_line: prevToken[2].last_line,
last_column: prevToken[2].last_column
};
} else {
token[2] = {
first_line: 0,
first_column: 0,
last_line: 0,
last_column: 0
};
}
var last_column, last_line, _ref, _ref1, _ref2;
if (token[2]) {
return 1;
}
if (!(token.generated || token.explicit)) {
return 1;
}
_ref2 = (_ref = (_ref1 = tokens[i - 1]) != null ? _ref1[2] : void 0) != null ? _ref : {
last_line: 0,
last_column: 0
}, last_line = _ref2.last_line, last_column = _ref2.last_column;
token[2] = {
first_line: last_line,
first_column: last_column,
last_line: last_line,
last_column: last_column
};
return 1;
});
};
@@ -330,12 +432,7 @@
return [indent, outdent];
};
Rewriter.prototype.generate = function(tag, value) {
var tok;
tok = [tag, value];
tok.generated = true;
return tok;
};
Rewriter.prototype.generate = generate;
Rewriter.prototype.tag = function(i) {
var _ref;

View File

@@ -1,4 +1,4 @@
// Generated by CoffeeScript 1.5.0
// Generated by CoffeeScript 1.6.1
(function() {
var Scope, extend, last, _ref;
@@ -39,7 +39,8 @@
};
Scope.prototype.namedMethod = function() {
if (this.method.name || !this.parent) {
var _ref1;
if (((_ref1 = this.method) != null ? _ref1.name : void 0) || !this.parent) {
return this.method;
}
return this.parent.namedMethod();

View File

@@ -0,0 +1,237 @@
// Generated by CoffeeScript 1.6.1
(function() {
var BASE64_CHARS, LineMapping, MAX_BASE64_VALUE, VLQ_CONTINUATION_BIT, VLQ_SHIFT, VLQ_VALUE_MASK, decodeBase64Char, encodeBase64Char;
LineMapping = (function() {
function LineMapping(generatedLine) {
this.generatedLine = generatedLine;
this.columnMap = {};
this.columnMappings = [];
}
LineMapping.prototype.addMapping = function(generatedColumn, _arg, options) {
var sourceColumn, sourceLine;
sourceLine = _arg[0], sourceColumn = _arg[1];
if (options == null) {
options = {};
}
if (this.columnMap[generatedColumn] && options.noReplace) {
return;
}
this.columnMap[generatedColumn] = {
generatedLine: this.generatedLine,
generatedColumn: generatedColumn,
sourceLine: sourceLine,
sourceColumn: sourceColumn
};
this.columnMappings.push(this.columnMap[generatedColumn]);
return this.columnMappings.sort(function(a, b) {
return a.generatedColumn - b.generatedColumn;
});
};
LineMapping.prototype.getSourcePosition = function(generatedColumn) {
var answer, columnMapping, lastColumnMapping, _i, _len, _ref;
answer = null;
lastColumnMapping = null;
_ref = this.columnMappings;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
columnMapping = _ref[_i];
if (columnMapping.generatedColumn > generatedColumn) {
break;
} else {
lastColumnMapping = columnMapping;
}
}
if (lastColumnMapping) {
return answer = [lastColumnMapping.sourceLine, lastColumnMapping.sourceColumn];
}
};
return LineMapping;
})();
exports.SourceMap = (function() {
function SourceMap() {
this.generatedLines = [];
}
SourceMap.prototype.addMapping = function(sourceLocation, generatedLocation, options) {
var generatedColumn, generatedLine, lineMapping;
if (options == null) {
options = {};
}
generatedLine = generatedLocation[0], generatedColumn = generatedLocation[1];
lineMapping = this.generatedLines[generatedLine];
if (!lineMapping) {
lineMapping = this.generatedLines[generatedLine] = new LineMapping(generatedLine);
}
return lineMapping.addMapping(generatedColumn, sourceLocation, options);
};
SourceMap.prototype.getSourcePosition = function(_arg) {
var answer, generatedColumn, generatedLine, lineMapping;
generatedLine = _arg[0], generatedColumn = _arg[1];
answer = null;
lineMapping = this.generatedLines[generatedLine];
if (!lineMapping) {
} else {
answer = lineMapping.getSourcePosition(generatedColumn);
}
return answer;
};
SourceMap.prototype.forEachMapping = function(fn) {
var columnMapping, generatedLineNumber, lineMapping, _i, _len, _ref, _results;
_ref = this.generatedLines;
_results = [];
for (generatedLineNumber = _i = 0, _len = _ref.length; _i < _len; generatedLineNumber = ++_i) {
lineMapping = _ref[generatedLineNumber];
if (lineMapping) {
_results.push((function() {
var _j, _len1, _ref1, _results1;
_ref1 = lineMapping.columnMappings;
_results1 = [];
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
columnMapping = _ref1[_j];
_results1.push(fn(columnMapping));
}
return _results1;
})());
} else {
_results.push(void 0);
}
}
return _results;
};
return SourceMap;
})();
exports.generateV3SourceMap = function(sourceMap, sourceFile, generatedFile) {
var answer, lastGeneratedColumnWritten, lastSourceColumnWritten, lastSourceLineWritten, mappings, needComma, writingGeneratedLine;
if (sourceFile == null) {
sourceFile = null;
}
if (generatedFile == null) {
generatedFile = null;
}
writingGeneratedLine = 0;
lastGeneratedColumnWritten = 0;
lastSourceLineWritten = 0;
lastSourceColumnWritten = 0;
needComma = false;
mappings = "";
sourceMap.forEachMapping(function(mapping) {
while (writingGeneratedLine < mapping.generatedLine) {
lastGeneratedColumnWritten = 0;
needComma = false;
mappings += ";";
writingGeneratedLine++;
}
if (needComma) {
mappings += ",";
needComma = false;
}
mappings += exports.vlqEncodeValue(mapping.generatedColumn - lastGeneratedColumnWritten);
lastGeneratedColumnWritten = mapping.generatedColumn;
mappings += exports.vlqEncodeValue(0);
mappings += exports.vlqEncodeValue(mapping.sourceLine - lastSourceLineWritten);
lastSourceLineWritten = mapping.sourceLine;
mappings += exports.vlqEncodeValue(mapping.sourceColumn - lastSourceColumnWritten);
lastSourceColumnWritten = mapping.sourceColumn;
return needComma = true;
});
answer = {
version: 3,
file: generatedFile,
sourceRoot: "",
sources: sourceFile ? [sourceFile] : [],
names: [],
mappings: mappings
};
return JSON.stringify(answer, null, 2);
};
exports.loadV3SourceMap = function(sourceMap) {
return todo();
};
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
MAX_BASE64_VALUE = BASE64_CHARS.length - 1;
encodeBase64Char = function(value) {
if (value > MAX_BASE64_VALUE) {
throw new Error("Cannot encode value " + value + " > " + MAX_BASE64_VALUE);
} else if (value < 0) {
throw new Error("Cannot encode value " + value + " < 0");
}
return BASE64_CHARS[value];
};
decodeBase64Char = function(char) {
var value;
value = BASE64_CHARS.indexOf(char);
if (value === -1) {
throw new Error("Invalid Base 64 character: " + char);
}
return value;
};
VLQ_SHIFT = 5;
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT;
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1;
exports.vlqEncodeValue = function(value) {
var answer, nextVlqChunk, signBit, valueToEncode;
signBit = value < 0 ? 1 : 0;
valueToEncode = (Math.abs(value) << 1) + signBit;
answer = "";
while (valueToEncode || !answer) {
nextVlqChunk = valueToEncode & VLQ_VALUE_MASK;
valueToEncode = valueToEncode >> VLQ_SHIFT;
if (valueToEncode) {
nextVlqChunk |= VLQ_CONTINUATION_BIT;
}
answer += encodeBase64Char(nextVlqChunk);
}
return answer;
};
exports.vlqDecodeValue = function(str, offset) {
var consumed, continuationShift, done, nextChunkValue, nextVlqChunk, position, signBit, value;
if (offset == null) {
offset = 0;
}
position = offset;
done = false;
value = 0;
continuationShift = 0;
while (!done) {
nextVlqChunk = decodeBase64Char(str[position]);
position += 1;
nextChunkValue = nextVlqChunk & VLQ_VALUE_MASK;
value += nextChunkValue << continuationShift;
if (!(nextVlqChunk & VLQ_CONTINUATION_BIT)) {
done = true;
}
continuationShift += VLQ_SHIFT;
}
consumed = position - offset;
signBit = value & 1;
value = value >> 1;
if (signBit) {
value = -value;
}
return [value, consumed];
};
}).call(this);

View File

@@ -3,7 +3,7 @@
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language", "coffeescript", "compiler"],
"author": "Jeremy Ashkenas",
"version": "1.5.0",
"version": "1.6.1",
"licenses": [{
"type": "MIT",
"url": "https://raw.github.com/jashkenas/coffee-script/master/LICENSE"

View File

@@ -17,7 +17,7 @@ CoffeeScript.run = (code, options = {}) ->
return unless window?
# Load a remote script from the current domain via XHR.
CoffeeScript.load = (url, callback) ->
CoffeeScript.load = (url, callback, options = {}) ->
xhr = if window.ActiveXObject
new window.ActiveXObject('Microsoft.XMLHTTP')
else
@@ -27,7 +27,7 @@ CoffeeScript.load = (url, callback) ->
xhr.onreadystatechange = ->
if xhr.readyState is 4
if xhr.status in [0, 200]
CoffeeScript.run xhr.responseText
CoffeeScript.run xhr.responseText, options
else
throw new Error "Could not load #{url}"
callback() if callback
@@ -38,16 +38,19 @@ CoffeeScript.load = (url, callback) ->
# This happens on page load.
runScripts = ->
scripts = document.getElementsByTagName 'script'
coffees = (s for s in scripts when s.type is 'text/coffeescript')
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript']
coffees = (s for s in scripts when s.type in coffeetypes)
index = 0
length = coffees.length
do execute = ->
script = coffees[index++]
if script?.type is 'text/coffeescript'
mediatype = script?.type
if mediatype in coffeetypes
options = {literate: mediatype is 'text/literate-coffeescript'}
if script.src
CoffeeScript.load script.src, execute
CoffeeScript.load script.src, execute, options
else
CoffeeScript.run script.innerHTML
CoffeeScript.run script.innerHTML, options
execute()
null

View File

@@ -10,39 +10,81 @@ fs = require 'fs'
path = require 'path'
{Lexer} = require './lexer'
{parser} = require './parser'
helpers = require './helpers'
vm = require 'vm'
# The file extensions that are considered to be CoffeeScript.
extensions = ['.coffee', '.litcoffee']
sourcemap = require './sourcemap'
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) ->
raw = fs.readFileSync filename, 'utf8'
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
module._compile compile(stripped, {filename}), filename
module._compile compile(stripped, {filename, literate: helpers.isLiterate filename}), filename
if require.extensions
for ext in extensions
for ext in ['.coffee', '.litcoffee', '.md', '.coffee.md']
require.extensions[ext] = loadFile
# The current CoffeeScript version number.
exports.VERSION = '1.5.0'
exports.VERSION = '1.6.1'
# Expose helpers for testing.
exports.helpers = require './helpers'
exports.helpers = helpers
# Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
# compiler.
# Compile CoffeeScript code to JavaScript, using the Coffee/Jison compiler.
#
# If `options.sourceMap` is specified, then `options.filename` must also be specified.
#
# This returns a javascript string, unless `options.sourceMap` is passed,
# in which case this returns a `{js, v3SourceMap, sourceMap}
# object, where sourceMap is a sourcemap.coffee#SourceMap object, handy for doing programatic
# lookups.
exports.compile = compile = (code, options = {}) ->
{merge} = exports.helpers
try
js = (parser.parse lexer.tokenize(code, options)).compile options
return js unless options.header
if options.sourceMap
coffeeFile = helpers.baseFileName options.filename
jsFile = helpers.baseFileName(options.filename, yes) + ".js"
sourceMap = new sourcemap.SourceMap()
fragments = (parser.parse lexer.tokenize(code, options)).compileToFragments options
currentLine = 0
currentLine += 1 if options.header
currentLine += 1 if options.sourceMap
currentColumn = 0
js = ""
for fragment in fragments
# Update the sourcemap with data from each fragment
if sourceMap
if fragment.locationData
sourceMap.addMapping(
[fragment.locationData.first_line, fragment.locationData.first_column],
[currentLine, currentColumn],
{noReplace: true})
newLines = helpers.count fragment.code, "\n"
currentLine += newLines
currentColumn = fragment.code.length - (if newLines then fragment.code.lastIndexOf "\n" else 0)
# Copy the code from each fragment into the final JavaScript.
js += fragment.code
catch err
err.message = "In #{options.filename}, #{err.message}" if options.filename
throw err
header = "Generated by CoffeeScript #{@VERSION}"
"// #{header}\n#{js}"
if options.header
header = "Generated by CoffeeScript #{@VERSION}"
js = "// #{header}\n#{js}"
if options.sourceMap
answer = {js}
if sourceMap
answer.sourceMap = sourceMap
answer.v3SourceMap = sourcemap.generateV3SourceMap sourceMap, coffeeFile, jsFile
answer
else
js
# Tokenize a string of CoffeeScript code, and return the array of tokens.
exports.tokens = (code, options) ->
@@ -73,7 +115,7 @@ exports.run = (code, options = {}) ->
mainModule.paths = require('module')._nodeModulePaths path.dirname fs.realpathSync options.filename
# Compile.
if (path.extname(mainModule.filename) not in extensions) or require.extensions
if not helpers.isCoffee(mainModule.filename) or require.extensions
mainModule._compile compile(code, options), mainModule.filename
else
mainModule._compile code, mainModule.filename

View File

@@ -39,6 +39,7 @@ SWITCHES = [
['-i', '--interactive', 'run an interactive CoffeeScript REPL']
['-j', '--join [FILE]', 'concatenate the source CoffeeScript before compiling']
['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint']
['-m', '--map', 'generate source map and save as .map files']
['-n', '--nodes', 'print out the parse tree that the parser produces']
[ '--nodejs [ARGS]', 'pass options directly to the "node" binary']
['-o', '--output [DIR]', 'set the output directory for compiled JavaScript']
@@ -56,7 +57,6 @@ sourceCode = []
notSources = {}
watchers = {}
optionParser = null
coffee_exts = ['.coffee', '.litcoffee']
# Run `coffee` by parsing passed options and determining what action to take.
# Many flags cause us to divert before compiling anything. Flags passed after
@@ -79,19 +79,14 @@ exports.run = ->
compilePath source, yes, path.normalize source
# Compile a path, which could be a script or a directory. If a directory
# is passed, recursively compile all '.coffee' and '.litcoffee' extension source
# files in it and all subdirectories.
# is passed, recursively compile all '.coffee', '.litcoffee', and '.coffee.md'
# extension source files in it and all subdirectories.
compilePath = (source, topLevel, base) ->
fs.stat source, (err, stats) ->
throw err if err and err.code isnt 'ENOENT'
if err?.code is 'ENOENT'
if topLevel and source and path.extname(source) not in coffee_exts
source = sources[sources.indexOf(source)] = "#{source}.coffee"
return compilePath source, topLevel, base
if topLevel
console.error "File not found: #{source}"
process.exit 1
return
console.error "File not found: #{source}"
process.exit 1
if stats.isDirectory() and path.dirname(source) isnt 'node_modules'
watchDir source, base if opts.watch
fs.readdir source, (err, files) ->
@@ -103,7 +98,7 @@ compilePath = (source, topLevel, base) ->
sourceCode[index..index] = files.map -> null
files.forEach (file) ->
compilePath (path.join source, file), no, base
else if topLevel or path.extname(source) in coffee_exts
else if topLevel or helpers.isCoffee source
watch source, base if opts.watch
fs.readFile source, (err, code) ->
throw err if err and err.code isnt 'ENOENT'
@@ -130,11 +125,19 @@ compileScript = (file, input, base) ->
sourceCode[sources.indexOf(t.file)] = t.input
compileJoin()
else
t.output = CoffeeScript.compile t.input, t.options
compiled = CoffeeScript.compile t.input, t.options
t.output = compiled
if o.map
t.output = compiled.js
t.sourceMap = compiled.v3SourceMap
CoffeeScript.emit 'success', task
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
if o.print
printLine t.output.trim()
else if o.compile || o.map
writeJs base, t.file, t.output, t.sourceMap
else if o.lint
lint t.file, t.output
catch err
CoffeeScript.emit 'failure', err, task
return if CoffeeScript.listeners('failure').length
@@ -247,26 +250,36 @@ removeSource = (source, base, removeJs) ->
timeLog "removed #{source}"
# Get the corresponding output JavaScript path for a source file.
outputPath = (source, base) ->
filename = path.basename(source, path.extname(source)) + '.js'
outputPath = (source, base, extension=".js") ->
basename = helpers.baseFileName source, yes
srcDir = path.dirname source
baseDir = if base is '.' then srcDir else srcDir.substring base.length
dir = if opts.output then path.join opts.output, baseDir else srcDir
path.join dir, filename
path.join dir, basename + extension
# Write out a JavaScript source file with the compiled code. By default, files
# are written out in `cwd` as `.js` files with the same name, but the output
# directory can be customized with `--output`.
writeJs = (source, js, base) ->
jsPath = outputPath source, base
#
# If `generatedSourceMap` is provided, this will write a `.map` file into the
# same directory as the `.js` file.
writeJs = (base, sourcePath, js, generatedSourceMap = null) ->
jsPath = outputPath sourcePath, base
sourceMapPath = outputPath sourcePath, base, ".map"
jsDir = path.dirname jsPath
compile = ->
js = ' ' if js.length <= 0
fs.writeFile jsPath, js, (err) ->
if err
printLine err.message
else if opts.compile and opts.watch
timeLog "compiled #{source}"
if opts.compile
js = ' ' if js.length <= 0
if generatedSourceMap then js = "//@ sourceMappingURL=#{helpers.baseFileName sourceMapPath}\n#{js}"
fs.writeFile jsPath, js, (err) ->
if err
printLine err.message
else if opts.compile and opts.watch
timeLog "compiled #{sourcePath}"
if generatedSourceMap
fs.writeFile sourceMapPath, generatedSourceMap, (err) ->
if err
printLine "Could not write source map: #{err.message}"
exists jsDir, (itExists) ->
if itExists then compile() else exec "mkdir -p #{jsDir}", compile
@@ -288,13 +301,12 @@ lint = (file, js) ->
jsl.stdin.write js
jsl.stdin.end()
# Pretty-print a stream of tokens.
# Pretty-print a stream of tokens, sans location data.
printTokens = (tokens) ->
strings = for token in tokens
tag = token[0]
value = token[1].toString().replace(/\n/, '\\n')
locationData = helpers.locationDataToString token[2]
"[#{tag} #{value} #{locationData}]"
"[#{tag} #{value}]"
printLine strings.join(' ')
# Use the [OptionParser module](optparse.html) to extract all options from
@@ -303,7 +315,7 @@ parseOptions = ->
optionParser = new optparse.OptionParser SWITCHES, BANNER
o = opts = optionParser.parse process.argv[2..]
o.compile or= !!o.output
o.run = not (o.compile or o.print or o.lint)
o.run = not (o.compile or o.print or o.lint or o.map)
o.print = !! (o.print or (o.eval or o.stdio and o.compile))
sources = o.arguments
sourceCode[i] = null for source, i in sources
@@ -311,8 +323,13 @@ parseOptions = ->
# The compile-time options to pass to the CoffeeScript compiler.
compileOptions = (filename) ->
literate = path.extname(filename) is '.litcoffee'
{filename, literate, bare: opts.bare, header: opts.compile}
{
filename
literate: helpers.isLiterate(filename)
bare: opts.bare
header: opts.compile
sourceMap: opts.map
}
# Start up a new Node.js instance with the arguments in `--nodejs` passed to
# the `node` binary, preserving the other options.

View File

@@ -39,7 +39,6 @@ o = (patternString, action, options) ->
# All runtime functions we need are defined on "yy"
action = action.replace /\bnew /g, '$&yy.'
action = action.replace /\b(?:Block\.wrap|extend)\b/g, 'yy.$&'
action = action.replace /\b(Op|Value\.(create|wrap))\b/g, 'yy.$&'
# Returns a function which adds location data to the first parameter passed
# in, and returns the parameter. If the parameter is not a node, it will
@@ -159,10 +158,10 @@ grammar =
# Assignment when it happens within an object literal. The difference from
# the ordinary **Assign** is that these allow numbers and strings as keys.
AssignObj: [
o 'ObjAssignable', -> Value.wrap $1
o 'ObjAssignable : Expression', -> new Assign LOC(1)(Value.wrap($1)), $3, 'object'
o 'ObjAssignable', -> new Value $1
o 'ObjAssignable : Expression', -> new Assign LOC(1)(new Value($1)), $3, 'object'
o 'ObjAssignable :
INDENT Expression OUTDENT', -> new Assign LOC(1)(Value.wrap($1)), $4, 'object'
INDENT Expression OUTDENT', -> new Assign LOC(1)(new Value($1)), $4, 'object'
o 'Comment'
]
@@ -236,26 +235,26 @@ grammar =
# Variables and properties that can be assigned to.
SimpleAssignable: [
o 'Identifier', -> Value.wrap $1
o 'Identifier', -> new Value $1
o 'Value Accessor', -> $1.add $2
o 'Invocation Accessor', -> Value.wrap $1, [].concat $2
o 'Invocation Accessor', -> new Value $1, [].concat $2
o 'ThisProperty'
]
# Everything that can be assigned to.
Assignable: [
o 'SimpleAssignable'
o 'Array', -> Value.wrap $1
o 'Object', -> Value.wrap $1
o 'Array', -> new Value $1
o 'Object', -> new Value $1
]
# The types of things that can be treated as values -- assigned to, invoked
# as functions, indexed into, named as a class, etc.
Value: [
o 'Assignable'
o 'Literal', -> Value.wrap $1
o 'Parenthetical', -> Value.wrap $1
o 'Range', -> Value.wrap $1
o 'Literal', -> new Value $1
o 'Parenthetical', -> new Value $1
o 'Range', -> new Value $1
o 'This'
]
@@ -264,7 +263,8 @@ grammar =
Accessor: [
o '. Identifier', -> new Access $2
o '?. Identifier', -> new Access $2, 'soak'
o ':: Identifier', -> [LOC(1)(new Access new Literal 'prototype'), LOC(2)(new Access $2)]
o ':: Identifier', -> [LOC(1)(new Access new Literal('prototype')), LOC(2)(new Access $2)]
o '?:: Identifier', -> [LOC(1)(new Access new Literal('prototype'), 'soak'), LOC(2)(new Access $2)]
o '::', -> new Access new Literal 'prototype'
o 'Index'
]
@@ -330,13 +330,13 @@ grammar =
# A reference to the *this* current object.
This: [
o 'THIS', -> Value.wrap new Literal 'this'
o '@', -> Value.wrap new Literal 'this'
o 'THIS', -> new Value new Literal 'this'
o '@', -> new Value new Literal 'this'
]
# A reference to a property on *this*.
ThisProperty: [
o '@ Identifier', -> Value.wrap LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this'
o '@ Identifier', -> new Value LOC(1)(new Literal('this')), [LOC(2)(new Access($2))], 'this'
]
# The array literal.
@@ -400,7 +400,7 @@ grammar =
# A catch clause names its error and runs a block of code.
Catch: [
o 'CATCH Identifier Block', -> [$2, $3]
o 'CATCH Object Block', -> [LOC(2)(Value.wrap($2)), $3]
o 'CATCH Object Block', -> [LOC(2)(new Value($2)), $3]
]
# Throw an exception object.
@@ -449,7 +449,7 @@ grammar =
]
ForBody: [
o 'FOR Range', -> source: LOC(2) Value.wrap($2)
o 'FOR Range', -> source: LOC(2) new Value($2)
o 'ForStart ForSource', -> $2.own = $1.own; $2.name = $1[0]; $2.index = $1[1]; $2
]
@@ -463,8 +463,8 @@ grammar =
ForValue: [
o 'Identifier'
o 'ThisProperty'
o 'Array', -> Value.wrap $1
o 'Object', -> Value.wrap $1
o 'Array', -> new Value $1
o 'Object', -> new Value $1
]
# An array or range comprehension has variables for the current element
@@ -530,30 +530,30 @@ grammar =
# -type rule, but in order to make the precedence binding possible, separate
# rules are necessary.
Operation: [
o 'UNARY Expression', -> Op.create $1 , $2
o '- Expression', (-> Op.create '-', $2), prec: 'UNARY'
o '+ Expression', (-> Op.create '+', $2), prec: 'UNARY'
o 'UNARY Expression', -> new Op $1 , $2
o '- Expression', (-> new Op '-', $2), prec: 'UNARY'
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY'
o '-- SimpleAssignable', -> Op.create '--', $2
o '++ SimpleAssignable', -> Op.create '++', $2
o 'SimpleAssignable --', -> Op.create '--', $1, null, true
o 'SimpleAssignable ++', -> Op.create '++', $1, null, true
o '-- SimpleAssignable', -> new Op '--', $2
o '++ SimpleAssignable', -> new Op '++', $2
o 'SimpleAssignable --', -> new Op '--', $1, null, true
o 'SimpleAssignable ++', -> new Op '++', $1, null, true
# [The existential operator](http://jashkenas.github.com/coffee-script/#existence).
o 'Expression ?', -> new Existence $1
o 'Expression + Expression', -> Op.create '+' , $1, $3
o 'Expression - Expression', -> Op.create '-' , $1, $3
o 'Expression + Expression', -> new Op '+' , $1, $3
o 'Expression - Expression', -> new Op '-' , $1, $3
o 'Expression MATH Expression', -> Op.create $2, $1, $3
o 'Expression SHIFT Expression', -> Op.create $2, $1, $3
o 'Expression COMPARE Expression', -> Op.create $2, $1, $3
o 'Expression LOGIC Expression', -> Op.create $2, $1, $3
o 'Expression MATH Expression', -> new Op $2, $1, $3
o 'Expression SHIFT Expression', -> new Op $2, $1, $3
o 'Expression COMPARE Expression', -> new Op $2, $1, $3
o 'Expression LOGIC Expression', -> new Op $2, $1, $3
o 'Expression RELATION Expression', ->
if $2.charAt(0) is '!'
Op.create($2[1..], $1, $3).invert()
new Op($2[1..], $1, $3).invert()
else
Op.create $2, $1, $3
new Op $2, $1, $3
o 'SimpleAssignable COMPOUND_ASSIGN
Expression', -> new Assign $1, $3, $2
@@ -577,7 +577,7 @@ grammar =
#
# (2 + 3) * 4
operators = [
['left', '.', '?.', '::']
['left', '.', '?.', '::', '?::']
['left', 'CALL_START', 'CALL_END']
['nonassoc', '++', '--']
['left', '?']

View File

@@ -92,4 +92,20 @@ exports.locationDataToString = (obj) ->
else
"No location data"
# A `.coffee.md` compatible version of `basename`, that returns the file sans-extension.
exports.baseFileName = (file, stripExt = no) ->
parts = file.split('/')
file = parts[parts.length - 1]
return file unless stripExt
parts = file.split('.')
parts.pop()
parts.pop() if parts[parts.length - 1] is 'coffee'
parts.join('.')
# Determine if a filename represents a CoffeeScript file.
exports.isCoffee = (file) -> /\.((lit)?coffee|coffee\.md)$/.test file
# Determine if a filename represents a Literate CoffeeScript file.
exports.isLiterate = (file) -> /\.(litcoffee|coffee\.md)$/.test file

View File

@@ -35,7 +35,6 @@ exports.Lexer = class Lexer
# unless explicitly asked not to.
tokenize: (code, opts = {}) ->
@literate = opts.literate # Are we lexing literate CoffeeScript?
code = @clean code # The stripped, cleaned original source code.
@indent = 0 # The current indentation level.
@indebt = 0 # The over-indentation at the current level.
@outdebt = 0 # The under-outdentation at the current level.
@@ -47,6 +46,7 @@ exports.Lexer = class Lexer
opts.line or 0 # The start line for the current @chunk.
@chunkColumn =
opts.column or 0 # The start column of the current @chunk.
code = @clean code # The stripped, cleaned original source code.
# At every position, run through this list of attempted matches,
# short-circuiting if any of them succeed. Their order determines precedence:
@@ -80,8 +80,10 @@ exports.Lexer = class Lexer
# by removing all lines that aren't indented by at least four spaces or a tab.
clean: (code) ->
code = code.slice(1) if code.charCodeAt(0) is BOM
code = "\n#{code}" if WHITESPACE.test code
code = code.replace(/\r/g, '').replace TRAILING_SPACES, ''
if WHITESPACE.test code
code = "\n#{code}"
@chunkLine--
if @literate
lines = for line in code.split('\n')
if match = LITERATE.exec line
@@ -112,7 +114,7 @@ exports.Lexer = class Lexer
@token 'OWN', id
return id.length
forcedIdentifier = colon or
(prev = last @tokens) and (prev[0] in ['.', '?.', '::'] or
(prev = last @tokens) and (prev[0] in ['.', '?.', '::', '?::'] or
not prev.spaced and prev[0] is '@')
tag = 'IDENTIFIER'
@@ -441,6 +443,7 @@ exports.Lexer = class Lexer
attempt = match[1]
indent = attempt if indent is null or 0 < attempt.length < indent.length
doc = doc.replace /// \n #{indent} ///g, '\n' if indent
doc = doc.replace /\n# \n/g, '\n\n' if @literate
doc = doc.replace /^\n/, '' unless herecomment
doc
@@ -634,27 +637,24 @@ exports.Lexer = class Lexer
else
column += string.length
return [@chunkLine + lineCount, column]
[@chunkLine + lineCount, column]
# Same as "token", exception this just returns the token without adding it
# to the results.
makeToken: (tag, value, offsetInChunk, length) ->
offsetInChunk = offsetInChunk || 0
if length is undefined then length = value.length
makeToken: (tag, value, offsetInChunk = 0, length = value.length) ->
locationData = {}
[locationData.first_line, locationData.first_column] =
@getLineAndColumnFromChunk offsetInChunk
# Use length - 1 for the final offset - we're supplying the last_line and the last_column,
# so if last_column == first_column, then we're looking at a character of length 1.
lastCharacter = if length > 0 then (length - 1) else 0
lastCharacter = Math.max 0, length - 1
[locationData.last_line, locationData.last_column] =
@getLineAndColumnFromChunk offsetInChunk + (length - 1)
token = [tag, value, locationData]
return token
token
# Add a token to the results.
# `offset` is the offset into the current @chunk where the token starts.
@@ -665,7 +665,7 @@ exports.Lexer = class Lexer
token: (tag, value, offsetInChunk, length) ->
token = @makeToken tag, value, offsetInChunk, length
@tokens.push token
return token
token
# Peek at a tag in the current token stream.
tag: (index, tag) ->
@@ -678,7 +678,7 @@ exports.Lexer = class Lexer
# Are we in the midst of an unfinished expression?
unfinished: ->
LINE_CONTINUER.test(@chunk) or
@tag() in ['\\', '.', '?.', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
# Converts newlines for string literals.
@@ -771,7 +771,7 @@ OPERATOR = /// ^ (
| >>>=? # zero-fill right shift
| ([-+:])\1 # doubles
| ([&|<>])\2=? # logic / shift
| \?\. # soak access
| \?(\.|::) # soak access
| \.{2,3} # range or splat
) ///

File diff suppressed because it is too large Load Diff

View File

@@ -11,13 +11,13 @@ replDefaults =
# strip single-line comments
input = input.replace /(^|[\r\n]+)(\s*)##?(?:[^#\r\n][^\r\n]*|)($|[\r\n])/, '$1$2$3'
# empty command
return cb null if /^\s*$/.test input
return cb null if /^(\s*|\(\s*\))$/.test input
# TODO: fix #1829: pass in-scope vars and avoid accidentally shadowing them by omitting those declarations
try
js = CoffeeScript.compile "_=(#{input}\n)", {filename, bare: yes}
cb null, vm.runInContext(js, context, filename)
catch err
cb err
cb null, vm.runInContext(js, context, filename)
addMultilineHandler = (repl) ->
{rli, inputStream, outputStream} = repl

View File

@@ -5,6 +5,12 @@
# shorthand into the unambiguous long form, add implicit indentation and
# parentheses, and generally clean things up.
# Create a generated token: one that exists due to a use of implicit syntax.
generate = (tag, value) ->
tok = [tag, value]
tok.generated = yes
tok
# The **Rewriter** class is used by the [Lexer](lexer.html), directly against
# its internal array of tokens.
class exports.Rewriter
@@ -24,8 +30,7 @@ class exports.Rewriter
@closeOpenIndexes()
@addImplicitIndentation()
@tagPostfixConditionals()
@addImplicitBraces()
@addImplicitParentheses()
@addImplicitBracesAndParens()
@addLocationDataToGeneratedTokens()
@tokens
@@ -71,7 +76,6 @@ class exports.Rewriter
# its paired close. We have the mis-nested outdent case included here for
# calls that close on the same line, just before their outdent.
closeOpenCalls: ->
condition = (token, i) ->
token[0] in [')', 'CALL_END'] or
token[0] is 'OUTDENT' and @tag(i - 1) is ')'
@@ -86,7 +90,6 @@ class exports.Rewriter
# The lexer has tagged the opening parenthesis of an indexing operation call.
# Match it with its paired close.
closeOpenIndexes: ->
condition = (token, i) ->
token[0] in [']', 'INDEX_END']
@@ -97,121 +100,238 @@ class exports.Rewriter
@detectEnd i + 1, condition, action if token[0] is 'INDEX_START'
1
# Object literals may be written with implicit braces, for simple cases.
# Insert the missing braces here, so that the parser doesn't have to.
addImplicitBraces: ->
# Match tags in token stream starting at i with pattern, skipping HERECOMMENTs
# Pattern may consist of strings (equality), an array of strings (one of)
# or null (wildcard)
matchTags: (i, pattern...) ->
fuzz = 0
for j in [0 ... pattern.length]
fuzz += 2 while @tag(i + j + fuzz) is 'HERECOMMENT'
continue if not pattern[j]?
pattern[j] = [pattern[j]] if typeof pattern[j] is 'string'
return no if @tag(i + j + fuzz) not in pattern[j]
yes
stack = []
start = null
startsLine = null
sameLine = yes
startIndent = 0
startIndex = 0
# yes iff standing in front of something looking like
# @<x>: or <x>:, skipping over 'HERECOMMENT's
looksObjectish: (j) ->
@matchTags(j, '@', null, ':') or @matchTags(j, null, ':')
condition = (token, i) ->
[one, two, three] = @tokens[i + 1 .. i + 3]
return no if 'HERECOMMENT' is one?[0]
[tag] = token
sameLine = no if tag in LINEBREAKS
return (
(tag in ['TERMINATOR', 'OUTDENT'] or
(tag in IMPLICIT_END and sameLine and not (i - startIndex is 1))) and
((!startsLine and @tag(i - 1) isnt ',') or
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']
)
# yes iff current line of tokens contain an element of tags on same
# expression level. Stop searching at LINEBREAKS or explicit start of
# containing balanced expression.
findTagsBackwards: (i, tags) ->
backStack = []
while i >= 0 and (backStack.length or
@tag(i) not in tags and
(@tag(i) not in EXPRESSION_START or @tokens[i].generated) and
@tag(i) not in LINEBREAKS)
backStack.push @tag(i) if @tag(i) in EXPRESSION_END
backStack.pop() if @tag(i) in EXPRESSION_START and backStack.length
i -= 1
@tag(i) in tags
action = (token, i) ->
tok = @generate '}', '}'
@tokens.splice i, 0, tok
# Look for signs of implicit calls and objects in the token stream and
# add them.
addImplicitBracesAndParens: ->
# Track current balancing depth (both implicit and explicit) on stack.
stack = []
@scanTokens (token, i, tokens) ->
if (tag = token[0]) in EXPRESSION_START
stack.push [(if tag is 'INDENT' and @tag(i - 1) is '{' then '{' else tag), i]
return 1
[tag] = token
[prevTag] = if i > 0 then tokens[i - 1] else []
[nextTag] = if i < tokens.length - 1 then tokens[i + 1] else []
stackTop = -> stack[stack.length - 1]
startIdx = i
# Helper function, used for keeping track of the number of tokens consumed
# and spliced, when returning for getting a new token.
forward = (n) -> i - startIdx + n
# Helper functions
inImplicit = -> stackTop()?[2]?.ours
inImplicitCall = -> inImplicit() and stackTop()?[0] is '('
inImplicitObject = -> inImplicit() and stackTop()?[0] is '{'
# Unclosed control statement inside implicit parens (like
# class declaration or if-conditionals)
inImplicitControl = -> inImplicit and stackTop()?[0] is 'CONTROL'
startImplicitCall = (j) ->
idx = j ? i
stack.push ['(', idx, ours: yes]
tokens.splice idx, 0, generate 'CALL_START', '('
i += 1 if not j?
endImplicitCall = ->
stack.pop()
tokens.splice i, 0, generate 'CALL_END', ')'
i += 1
startImplicitObject = (j, startsLine = yes) ->
idx = j ? i
stack.push ['{', idx, sameLine: yes, startsLine: startsLine, ours: yes]
tokens.splice idx, 0, generate '{', generate(new String('{'))
i += 1 if not j?
endImplicitObject = (j) ->
j = j ? i
stack.pop()
tokens.splice j, 0, generate '}', '}'
i += 1
# Don't end an implicit call on next indent if any of these are in an argument
if inImplicitCall() and tag in ['IF', 'TRY', 'FINALLY', 'CATCH',
'CLASS', 'SWITCH']
stack.push ['CONTROL', i, ours: true]
return forward(1)
if tag is 'INDENT' and inImplicit()
# An INDENT closes an implicit call unless
# 1. We have seen a CONTROL argument on the line.
# 2. The last token before the indent is part of the list below
if prevTag not in ['=>', '->', '[', '(', ',', '{', 'TRY', 'ELSE', '=']
endImplicitCall() while inImplicitCall()
stack.pop() if inImplicitControl()
stack.push [tag, i]
return forward(1)
# Straightforward start of explicit expression
if tag in EXPRESSION_START
stack.push [tag, i]
return forward(1)
# Close all implicit expressions inside of explicitly closed expressions.
if tag in EXPRESSION_END
start = stack.pop()
return 1
return 1 unless tag is ':' and
((ago = @tag i - 2) is ':' or stack[stack.length - 1]?[0] isnt '{')
sameLine = yes
startIndex = i + 1
stack.push ['{']
idx = if ago is '@' then i - 2 else i - 1
idx -= 2 while @tag(idx - 2) is 'HERECOMMENT'
prevTag = @tag(idx - 1)
startsLine = not prevTag or (prevTag in LINEBREAKS)
value = new String('{')
value.generated = yes
tok = @generate '{', value
tokens.splice idx, 0, tok
@detectEnd i + 2, condition, action
2
while inImplicit()
if inImplicitCall()
endImplicitCall()
else if inImplicitObject()
endImplicitObject()
else
stack.pop()
stack.pop()
# Methods may be optionally called without parentheses, for simple cases.
# Insert the implicit parentheses here, so that the parser doesn't have to
# deal with them.
addImplicitParentheses: ->
# Recognize standard implicit calls like
# f a, f() b, f? c, h[0] d etc.
if (tag in IMPLICIT_FUNC and token.spaced or
tag is '?' and i > 0 and not tokens[i - 1].spaced) and
(nextTag in IMPLICIT_CALL or
nextTag in IMPLICIT_UNSPACED_CALL and
not tokens[i + 1]?.spaced and not tokens[i + 1]?.newLine)
tag = token[0] = 'FUNC_EXIST' if tag is '?'
startImplicitCall i + 1
return forward(2)
noCall = seenSingle = seenControl = no
callIndex = null
# Implicit call taking an implicit indented object as first argument.
# f
# a: b
# c: d
# and
# f
# 1
# a: b
# b: c
# Don't accept implicit calls of this type, when on the same line
# as the control strucutures below as that may misinterpret constructs like:
# if f
# a: 1
# as
# if f(a: 1)
# which is probably always unintended.
# Furthermore don't allow this in literal arrays, as
# that creates grammatical ambiguities.
if @matchTags(i, IMPLICIT_FUNC, 'INDENT', null, ':') and
not @findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH',
'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])
startImplicitCall i + 1
stack.push ['INDENT', i + 2]
return forward(3)
condition = (token, i) ->
[tag] = token
return yes if not seenSingle and token.fromThen
seenSingle = yes if tag in ['IF', 'ELSE', 'CATCH', '->', '=>', 'CLASS']
seenControl = yes if tag in ['IF', 'ELSE', 'SWITCH', 'TRY', '=']
return yes if tag in ['.', '?.', '::'] and @tag(i - 1) is 'OUTDENT'
not token.generated and @tag(i - 1) isnt ',' and (tag in IMPLICIT_END or
(tag is 'INDENT' and not seenControl)) and
(tag isnt 'INDENT' or
(@tag(i - 2) not in ['CLASS', 'EXTENDS'] and @tag(i - 1) not in IMPLICIT_BLOCK and
not (callIndex is i - 1 and (post = @tokens[i + 1]) and post.generated and post[0] is '{')))
# Implicit objects start here
if tag is ':'
# Go back to the (implicit) start of the object
if @tag(i - 2) is '@' then s = i - 2 else s = i - 1
s -= 2 while @tag(s - 2) is 'HERECOMMENT'
action = (token, i) ->
@tokens.splice i, 0, @generate 'CALL_END', ')'
startsLine = s is 0 or @tag(s - 1) in LINEBREAKS or tokens[s - 1].newLine
# Are we just continuing an already declared object?
if stackTop()
[stackTag, stackIdx] = stackTop()
if (stackTag is '{' or stackTag is 'INDENT' and @tag(stackIdx - 1) is '{') and
(startsLine or @tag(s - 1) is ',' or @tag(s - 1) is '{')
return forward(1)
@scanTokens (token, i, tokens) ->
tag = token[0]
noCall = yes if tag in ['CLASS', 'IF', 'FOR', 'WHILE']
[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
seenSingle = no
seenControl = no
noCall = no if tag in LINEBREAKS
token.call = yes if prev and not prev.spaced and tag is '?'
return 1 if token.fromThen
return 1 unless callObject or
prev?.spaced and (prev.call or prev[0] in IMPLICIT_FUNC) and
(tag in IMPLICIT_CALL or not (token.spaced or token.newLine) and tag in IMPLICIT_UNSPACED_CALL)
callIndex = i
tokens.splice i, 0, @generate 'CALL_START', '(', token[2]
@detectEnd i + 1, condition, action
prev[0] = 'FUNC_EXIST' if prev[0] is '?'
2
startImplicitObject(s, !!startsLine)
return forward(2)
# End implicit calls when chaining method calls
# like e.g.:
# f ->
# a
# .g b, ->
# c
# .h a
if prevTag is 'OUTDENT' and inImplicitCall() and tag in ['.', '?.', '::', '?::']
endImplicitCall()
return forward(1)
stackTop()[2].sameLine = no if inImplicitObject() and tag in LINEBREAKS
if tag in IMPLICIT_END
while inImplicit()
[stackTag, stackIdx, {sameLine, startsLine}] = stackTop()
# Close implicit calls when reached end of argument list
if inImplicitCall() and prevTag isnt ','
endImplicitCall()
# Close implicit objects such as:
# return a: 1, b: 2 unless true
else if inImplicitObject() and sameLine and not startsLine
endImplicitObject()
# Close implicit objects when at end of line, line didn't end with a comma
# and the implicit object didn't start the line or the next line doesn't look like
# the continuation of an object.
else if inImplicitObject() and tag is 'TERMINATOR' and prevTag isnt ',' and
not (startsLine and @looksObjectish(i + 1))
endImplicitObject()
else
break
# Close implicit object if comma is the last character
# and what comes after doesn't look like it belongs.
# This is used for trailing commas and calls, like:
# x =
# a: b,
# c: d,
# e = 2
#
# and
#
# f a, b: c, d: e, f, g: h: i, j
if tag is ',' and not @looksObjectish(i + 1) and inImplicitObject() and
(nextTag isnt 'TERMINATOR' or not @looksObjectish(i + 2))
# When nextTag is OUTDENT the comma is insignificant and
# should just be ignored so embed it in the implicit object.
#
# When it isn't the comma go on to play a role in a call or
# array further up the stack, so give it a chance.
offset = if nextTag is 'OUTDENT' then 1 else 0
while inImplicitObject()
endImplicitObject i + offset
return forward(1)
# Add location data to all tokens generated by the rewriter.
addLocationDataToGeneratedTokens: ->
@scanTokens (token, i, tokens) ->
tag = token[0]
if (token.generated or token.explicit) and (not token[2])
if i > 0
prevToken = tokens[i-1]
token[2] =
first_line: prevToken[2].last_line
first_column: prevToken[2].last_column
last_line: prevToken[2].last_line
last_column: prevToken[2].last_column
else
token[2] =
first_line: 0
first_column: 0
last_line: 0
last_column: 0
return 1
return 1 if token[2]
return 1 unless token.generated or token.explicit
{last_line, last_column} = tokens[i - 1]?[2] ? last_line: 0, last_column: 0
token[2] =
first_line: last_line
first_column: last_column
last_line: last_line
last_column: last_column
1
# Because our grammar is LALR(1), it can't handle some single-line
# expressions that lack ending delimiters. The **Rewriter** adds the implicit
@@ -276,11 +396,7 @@ class exports.Rewriter
indent.explicit = outdent.explicit = yes if not implicit
[indent, outdent]
# Create a generated token: one that exists due to a use of implicit syntax.
generate: (tag, value) ->
tok = [tag, value]
tok.generated = yes
tok
generate: generate
# Look up a tag by token index.
tag: (i) -> @tokens[i]?[0]
@@ -330,7 +446,8 @@ IMPLICIT_UNSPACED_CALL = ['+', '-']
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ',']
# Tokens that always mark the end of an implicit call for single-liners.
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR']
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY',
'LOOP', 'TERMINATOR']
# Single-line flavors of block expressions that have unclosed endings.
# The grammar can't disambiguate them, so we insert the implicit indentation.

View File

@@ -41,7 +41,7 @@ can get complicated if super is being called from an inner function.
function object that has a name filled in, or bottoms out.
namedMethod: ->
return @method if @method.name or !@parent
return @method if @method?.name or !@parent
@parent.namedMethod()
Look up a variable name in lexical scope, and declare it if it does not

246
src/sourcemap.coffee Normal file
View File

@@ -0,0 +1,246 @@
#### LineMapping
# Hold data about mappings for one line of generated source code.
class LineMapping
constructor: (@generatedLine) ->
# columnMap keeps track of which columns we've already mapped.
@columnMap = {}
# columnMappings is an array of all column mappings, sorted by generated-column.
@columnMappings = []
addMapping: (generatedColumn, [sourceLine, sourceColumn], options={}) ->
if @columnMap[generatedColumn] and options.noReplace
# We already have a mapping for this column.
return
@columnMap[generatedColumn] = {
generatedLine: @generatedLine
generatedColumn
sourceLine
sourceColumn
}
@columnMappings.push @columnMap[generatedColumn]
@columnMappings.sort (a,b) -> a.generatedColumn - b.generatedColumn
getSourcePosition: (generatedColumn) ->
answer = null
lastColumnMapping = null
for columnMapping in @columnMappings
if columnMapping.generatedColumn > generatedColumn
break
else
lastColumnMapping = columnMapping
if lastColumnMapping
answer = [lastColumnMapping.sourceLine, lastColumnMapping.sourceColumn]
#### SourceMap
# Maps locations in a generated source file back to locations in the original source file.
#
# This is intentionally agnostic towards how a source map might be represented on disk. A
# SourceMap can be converted to a "v3" style sourcemap with `#generateV3SourceMap()`, for example
# but the SourceMap class itself knows nothing about v3 source maps.
class exports.SourceMap
constructor: () ->
# `generatedLines` is an array of LineMappings, one per generated line.
@generatedLines = []
# Adds a mapping to this SourceMap.
#
# `sourceLocation` and `generatedLocation` are both [line, column] arrays.
#
# If `options.noReplace` is true, then if there is already a mapping for
# the specified `generatedLine` and `generatedColumn`, this will have no effect.
addMapping: (sourceLocation, generatedLocation, options={}) ->
[generatedLine, generatedColumn] = generatedLocation
lineMapping = @generatedLines[generatedLine]
if not lineMapping
lineMapping = @generatedLines[generatedLine] = new LineMapping(generatedLine)
lineMapping.addMapping generatedColumn, sourceLocation, options
# Returns [sourceLine, sourceColumn], or null if no mapping could be found.
getSourcePosition: ([generatedLine, generatedColumn]) ->
answer = null
lineMapping = @generatedLines[generatedLine]
if not lineMapping
# TODO: Search backwards for the line?
else
answer = lineMapping.getSourcePosition generatedColumn
answer
# `fn` will be called once for every recorded mapping, in the order in
# which they occur in the generated source. `fn` will be passed an object
# with four properties: sourceLine, sourceColumn, generatedLine, and
# generatedColumn.
forEachMapping: (fn) ->
for lineMapping, generatedLineNumber in @generatedLines
if lineMapping
for columnMapping in lineMapping.columnMappings
fn(columnMapping)
#### generateV3SourceMap
# Builds a V3 source map from a SourceMap object.
# Returns the generated JSON as a string.
exports.generateV3SourceMap = (sourceMap, sourceFile=null, generatedFile=null) ->
writingGeneratedLine = 0
lastGeneratedColumnWritten = 0
lastSourceLineWritten = 0
lastSourceColumnWritten = 0
needComma = no
mappings = ""
sourceMap.forEachMapping (mapping) ->
while writingGeneratedLine < mapping.generatedLine
lastGeneratedColumnWritten = 0
needComma = no
mappings += ";"
writingGeneratedLine++
# Write a comma if we've already written a segment on this line.
if needComma
mappings += ","
needComma = no
# Write the next segment.
# Segments can be 1, 4, or 5 values. If just one, then it is a generated column which
# doesn't match anything in the source code.
#
# Fields are all zero-based, and relative to the previous occurence unless otherwise noted:
# * starting-column in generated source, relative to previous occurence for the current line.
# * index into the "sources" list
# * starting line in the original source
# * starting column in the original source
# * index into the "names" list associated with this segment.
# Add the generated start-column
mappings += exports.vlqEncodeValue(mapping.generatedColumn - lastGeneratedColumnWritten)
lastGeneratedColumnWritten = mapping.generatedColumn
# Add the index into the sources list
mappings += exports.vlqEncodeValue(0)
# Add the source start-line
mappings += exports.vlqEncodeValue(mapping.sourceLine - lastSourceLineWritten)
lastSourceLineWritten = mapping.sourceLine
# Add the source start-column
mappings += exports.vlqEncodeValue(mapping.sourceColumn - lastSourceColumnWritten)
lastSourceColumnWritten = mapping.sourceColumn
# TODO: Do we care about symbol names for CoffeeScript? Probably not.
needComma = yes
answer = {
version: 3
file: generatedFile
sourceRoot: ""
sources: if sourceFile then [sourceFile] else []
names: []
mappings
}
return JSON.stringify answer, null, 2
# Load a SourceMap from a JSON string. Returns the SourceMap object.
exports.loadV3SourceMap = (sourceMap) ->
todo()
#### Base64 encoding helpers
BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
MAX_BASE64_VALUE = BASE64_CHARS.length - 1
encodeBase64Char = (value) ->
if value > MAX_BASE64_VALUE
throw new Error "Cannot encode value #{value} > #{MAX_BASE64_VALUE}"
else if value < 0
throw new Error "Cannot encode value #{value} < 0"
BASE64_CHARS[value]
decodeBase64Char = (char) ->
value = BASE64_CHARS.indexOf char
if value == -1
throw new Error "Invalid Base 64 character: #{char}"
value
#### Base 64 VLQ encoding/decoding helpers
# Note that SourceMap VLQ encoding is "backwards". MIDI style VLQ encoding puts the
# most-significant-bit (MSB) from the original value into the MSB of the VLQ encoded value
# (see http://en.wikipedia.org/wiki/File:Uintvar_coding.svg). SourceMap VLQ does things
# the other way around, with the least significat four bits of the original value encoded
# into the first byte of the VLQ encoded value.
VLQ_SHIFT = 5
VLQ_CONTINUATION_BIT = 1 << VLQ_SHIFT # 0010 0000
VLQ_VALUE_MASK = VLQ_CONTINUATION_BIT - 1 # 0001 1111
# Encode a value as Base 64 VLQ.
exports.vlqEncodeValue = (value) ->
# Least significant bit represents the sign.
signBit = if value < 0 then 1 else 0
# Next bits are the actual value
valueToEncode = (Math.abs(value) << 1) + signBit
answer = ""
# Make sure we encode at least one character, even if valueToEncode is 0.
while valueToEncode || !answer
nextVlqChunk = valueToEncode & VLQ_VALUE_MASK
valueToEncode = valueToEncode >> VLQ_SHIFT
if valueToEncode
nextVlqChunk |= VLQ_CONTINUATION_BIT
answer += encodeBase64Char(nextVlqChunk)
return answer
# Decode a Base 64 VLQ value.
#
# Returns `[value, consumed]` where `value` is the decoded value, and `consumed` is the number
# of characters consumed from `str`.
exports.vlqDecodeValue = (str, offset=0) ->
position = offset
done = false
value = 0
continuationShift = 0
while !done
nextVlqChunk = decodeBase64Char(str[position])
position += 1
nextChunkValue = nextVlqChunk & VLQ_VALUE_MASK
value += (nextChunkValue << continuationShift)
if !(nextVlqChunk & VLQ_CONTINUATION_BIT)
# We'll be done after this character.
done = true
# Bits are encoded least-significant first (opposite of MIDI VLQ). Increase the
# continuationShift, so the next byte will end up where it should in the value.
continuationShift += VLQ_SHIFT
consumed = position - offset
# Least significant bit represents the sign.
signBit = value & 1
value = value >> 1
if signBit then value = -value
return [value, consumed]

View File

@@ -117,24 +117,23 @@ test "basic classes, again, but in the manual prototype style", ->
ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing'
test "super with plain ol' functions as the original constructors", ->
test "super with plain ol' prototypes", ->
TopClass = (arg) ->
@prop = 'top-' + arg
this
TopClass = ->
TopClass::func = (arg) ->
'top-' + arg
SuperClass = (arg) ->
super 'super-' + arg
this
SuperClass = ->
SuperClass extends TopClass
SuperClass::func = (arg) ->
super 'super-' + arg
SubClass = ->
super 'sub'
this
SubClass = ->
SubClass extends SuperClass
SubClass::func = ->
super 'sub'
SuperClass extends TopClass
SubClass extends SuperClass
ok (new SubClass).prop is 'top-super-sub'
eq (new SubClass).func(), 'top-super-sub'
test "'@' referring to the current instance, and not being coerced into a call", ->
@@ -313,7 +312,7 @@ test "classes with value'd constructors", ->
eq (new Two).value, 2
test "exectuable class bodies", ->
test "executable class bodies", ->
class A
if true
@@ -327,6 +326,17 @@ test "exectuable class bodies", ->
eq a.c, undefined
test "#2502: parenthesizing inner object values", ->
class A
category: (type: 'string')
sections: (type: 'number', default: 0)
eq (new A).category.type, 'string'
eq (new A).sections.default, 0
test "mild metaprogramming", ->
class Base
@@ -595,6 +605,11 @@ test "#1813: Passing class definitions as expressions", ->
eq result, B
test "#1966: external constructors should produce their return value", ->
ctor = -> {}
class A then constructor: ctor
ok (new A) not instanceof A
test "#1980: regression with an inherited class with static function members", ->
class A
@@ -676,23 +691,52 @@ test "#2630: class bodies can't reference arguments", ->
throws ->
CoffeeScript.compile('class Test then arguments')
test "#2359: instanceof should work when extending native objects", ->
class MyError extends Error
ok new MyError instanceof MyError
test "#2319: fn class n extends o.p [INDENT] x = 123", ->
first = ->
test '#2359: external constructors returning "other typed" objets', ->
ctor = -> {}
class A then constructor: ctor
ok new A instanceof A
ok new ctor not instanceof A
ok new ctor not instanceof ctor
base = onebase: ->
test "#2359: constructors should not return an explicit value", ->
throws -> CoffeeScript.run "class then constructor: -> return 5"
throws -> CoffeeScript.run """
class
constructor: ->
if foo
return bar: 7
baz()
"""
first class OneKeeper extends base.onebase
one = 1
one: -> one
eq new OneKeeper().one(), 1
test "#2599: other typed constructors should be inherited", ->
class Base
constructor: -> return {}
class Derived extends Base
ok (new Derived) not instanceof Derived
ok (new Derived) not instanceof Base
ok (new Base) not instanceof Base
test "#2359: extending native objects that use other typed constructors requires defining a constructor", ->
class BrokenArray extends Array
method: -> 'no one will call me'
brokenArray = new BrokenArray
ok brokenArray not instanceof BrokenArray
ok typeof brokenArray.method is 'undefined'
class WorkingArray extends Array
constructor: -> super
method: -> 'yes!'
workingArray = new WorkingArray
ok workingArray instanceof WorkingArray
eq 'yes!', workingArray.method()
test "#2489: removing __bind", ->
class Thing
foo: (a, b, c) ->
bar: (a, b, c) =>
thing = new Thing
eq thing.foo.length, 3
eq thing.bar.length, 3

View File

@@ -422,7 +422,6 @@ test "Issue #997. Switch doesn't fallthrough.", ->
test "Throw should be usable as an expression.", ->
try
false or throw 'up'
throw new Error 'failed'

View File

@@ -99,17 +99,33 @@ test "try/catch with a reused variable name.", ->
catch inner
# nothing
eq typeof inner, 'undefined'
# Allowed to destructure exceptions: #2580
test "try/catch with destructuring the exception object", ->
result = try
missing.object
catch {message}
message
eq message, 'missing is not defined'
eq message, 'missing is not defined'
test "Try catch finally as implicit arguments", ->
first = (x) -> x
foo = no
try
first try iamwhoiam() finally foo = yes
catch e
eq foo, yes
bar = no
try
first try iamwhoiam() catch e finally
bar = yes
catch e
eq bar, yes

View File

@@ -129,8 +129,8 @@ test "Ensure that functions can have a trailing comma in their argument list", -
mult = (x, mids..., y) ->
x *= n for n in mids
x *= y
ok mult(1, 2,) is 2
ok mult(1, 2, 3,) is 6
#ok mult(1, 2,) is 2
#ok mult(1, 2, 3,) is 6
ok mult(10, (i for i in [1..6])...) is 7200
@@ -558,3 +558,94 @@ test "#2617: implicit call before unrelated implicit object", ->
result = if pass 1
one: 1
eq result.one, 1
test "#2292, b: f (z),(x)", ->
f = (x, y) -> y
one = 1
two = 2
o = b: f (one),(two)
eq o.b, 2
test "#2297, Different behaviors on interpreting literal", ->
foo = (x, y) -> y
bar =
baz: foo 100, on
eq bar.baz, on
qux = (x) -> x
quux = qux
corge: foo 100, true
eq quux.corge, on
xyzzy =
e: 1
f: foo
a: 1
b: 2
,
one: 1
two: 2
three: 3
g:
a: 1
b: 2
c: foo 2,
one: 1
two: 2
three: 3
d: 3
four: 4
h: foo one: 1, two: 2, three: three: three: 3,
2
eq xyzzy.f.two, 2
eq xyzzy.g.c.three, 3
eq xyzzy.four, 4
eq xyzzy.h, 2
test "#2715, Chained implicit calls", ->
first = (x) -> x
second = (x, y) -> y
foo = first first
one: 1
eq foo.one, 1
bar = first second
one: 1, 2
eq bar, 2
baz = first second
one: 1,
2
eq baz, 2
test "Implicit calls and new", ->
first = (x) -> x
foo = (@x) ->
bar = first new foo first 1
eq bar.x, 1
third = (x, y, z) -> z
baz = first new foo new foo third
one: 1
two: 2
1
three: 3
2
eq baz.x.x.three, 3
test "Loose tokens inside of explicit call lists", ->
first = (x) -> x
second = (x, y) -> y
one = 1
foo = second( one
2)
eq foo, 2
bar = first( first
one: 1)
eq bar.one, 1

View File

@@ -38,6 +38,26 @@ test "Verify location of generated tokens", ->
eq numberToken[2].last_line, 0
eq numberToken[2].last_column, 5
test "Verify location of generated tokens (with indented first line)", ->
tokens = CoffeeScript.tokens " a = 83"
eq tokens.length, 6
[IndentToken, aToken, equalsToken, numberToken] = tokens
eq aToken[2].first_line, 0
eq aToken[2].first_column, 2
eq aToken[2].last_line, 0
eq aToken[2].last_column, 2
eq equalsToken[2].first_line, 0
eq equalsToken[2].first_column, 4
eq equalsToken[2].last_line, 0
eq equalsToken[2].last_column, 4
eq numberToken[2].first_line, 0
eq numberToken[2].first_column, 6
eq numberToken[2].last_line, 0
eq numberToken[2].last_column, 7
test "Verify all tokens get a location", ->
doesNotThrow ->

View File

@@ -222,6 +222,141 @@ test "#1436: `for` etc. work as normal property names", ->
obj.for = 'foo' of obj
eq yes, obj.hasOwnProperty 'for'
test "#2706, Un-bracketed object as argument causes inconsistent behavior", ->
foo = (x, y) -> y
bar = baz: yes
eq yes, foo x: 1, bar.baz
test "#2608, Allow inline objects in arguments to be followed by more arguments", ->
foo = (x, y) -> y
eq yes, foo x: 1, y: 2, yes
test "#2308, a: b = c:1", ->
foo = a: b = c: yes
eq b.c, yes
eq foo.a.c, yes
test "#2317, a: b c: 1", ->
foo = (x) -> x
bar = a: foo c: yes
eq bar.a.c, yes
test "#1896, a: func b, {c: d}", ->
first = (x) -> x
second = (x, y) -> y
third = (x, y, z) -> z
one = 1
two = 2
three = 3
four = 4
foo = a: second one, {c: two}
eq foo.a.c, two
bar = a: second one, c: two
eq bar.a.c, two
baz = a: second one, {c: two}, e: first first h: three
eq baz.a.c, two
qux = a: third one, {c: two}, e: first first h: three
eq qux.a.e.h, three
quux = a: third one, {c: two}, e: first(three), h: four
eq quux.a.e, three
eq quux.a.h, four
corge = a: third one, {c: two}, e: second three, h: four
eq corge.a.e.h, four
test "Implicit objects, functions and arrays", ->
first = (x) -> x
second = (x, y) -> y
foo = [
1
one: 1
two: 2
three: 3
more:
four: 4
five: 5, six: 6
2, 3, 4
5]
eq foo[2], 2
eq foo[1].more.six, 6
bar = [
1
first first first second 1,
one: 1, twoandthree: twoandthree: two: 2, three: 3
2,
2
one: 1
two: 2
three: first second ->
no
, ->
3
3
4]
eq bar[2], 2
eq bar[1].twoandthree.twoandthree.two, 2
eq bar[3].three(), 3
eq bar[4], 3
test "#2549, Brace-less Object Literal as a Second Operand on a New Line", ->
foo = no or
one: 1
two: 2
three: 3
eq foo.one, 1
bar = yes and one: 1
eq bar.one, 1
baz = null ?
one: 1
two: 2
eq baz.two, 2
test "#2757, Nested", ->
foo =
bar:
one: 1,
eq foo.bar.one, 1
baz =
qux:
one: 1,
corge:
two: 2,
three: three: three: 3,
xyzzy:
thud:
four:
four: 4,
five: 5,
eq baz.qux.one, 1
eq baz.corge.three.three.three, 3
eq baz.xyzzy.thud.four.four, 4
eq baz.xyzzy.five, 5
test "#1865, syntax regression 1.1.3", ->
foo = (x, y) -> y
bar = a: foo (->),
c: yes
eq bar.a.c, yes
baz = a: foo (->), c: yes
eq baz.a.c, yes
test "#1322: implicit call against implicit object with block comments", ->
((obj, arg) ->
eq obj.x * obj.y, 6
@@ -273,7 +408,5 @@ test "#1961, #1974, regression with compound assigning to an implicit object", -
test "#2207: Immediate implicit closes don't close implicit objects", ->
func = ->
key: for i in [1, 2, 3] then i
eq func().key.join(' '), '1 2 3'

View File

@@ -293,4 +293,6 @@ test "#2567: Optimization of negated existential produces correct result", ->
ok !(!a?)
ok !b?
test "#2508: Existential access of the prototype", ->
eq NonExistent?::nothing, undefined
ok Object?::toString

46
test/sourcemap.coffee Normal file
View File

@@ -0,0 +1,46 @@
return if global.testingBrowser
sourcemap = require '../src/sourcemap'
vlqEncodedValues = [
[1, "C"],
[-1, "D"],
[2, "E"],
[-2, "F"],
[0, "A"],
[16, "gB"],
[948, "o7B"]
]
test "vlqEncodeValue tests", ->
for pair in vlqEncodedValues
eq (sourcemap.vlqEncodeValue pair[0]), pair[1]
test "vlqDecodeValue tests", ->
for pair in vlqEncodedValues
arrayEq (sourcemap.vlqDecodeValue pair[1]), [pair[0], pair[1].length]
test "vlqDecodeValue with offset", ->
for pair in vlqEncodedValues
# Try with an offset, and some cruft at the end.
arrayEq (sourcemap.vlqDecodeValue ("abc" + pair[1] + "efg"), 3), [pair[0], pair[1].length]
eqJson = (a, b) ->
eq (JSON.stringify JSON.parse a), (JSON.stringify JSON.parse b)
test "SourceMap tests", ->
map = new sourcemap.SourceMap()
map.addMapping [0, 0], [0, 0]
map.addMapping [1, 5], [2, 4]
map.addMapping [1, 6], [2, 7]
map.addMapping [1, 9], [2, 8]
map.addMapping [3, 0], [3, 4]
eqJson (sourcemap.generateV3SourceMap map, "source.coffee", "source.js"), '{"version":3,"file":"source.js","sourceRoot":"","sources":["source.coffee"],"names":[],"mappings":"AAAA;;IACK,GAAC,CAAG;IAET"}'
eqJson (sourcemap.generateV3SourceMap map), '{"version":3,"file":null,"sourceRoot":"","sources":[],"names":[],"mappings":"AAAA;;IACK,GAAC,CAAG;IAET"}'
# Look up a generated column - should get back the original source position.
arrayEq map.getSourcePosition([2,8]), [1,9]
# Look up a point futher along on the same line - should get back the same source position.
arrayEq map.getSourcePosition([2,10]), [1,9]