8bc6001d27 removed autocompletions of
non-enumerable own-properties in trying to add enumerable prototype
properties to the autocompletions. This commit adds them back and unions
them with the enumerable prototype properties.
case to show it's required.
What's going on: inside of Coffee-generated closures, calling `super()`
is implicitly making use of `this` (or explicitly doing so if you look
at the output code), so we have to pass `this` through closures as if
`@` is being accessed within the closure. So, just add one more
condition to the list in `Closure::literalThis`
Currently, the only mention of heregexes' support for interpolation is
in the change log. This feature is useful enough to warrant a mention in
the heregex section itself.
I also felt that the heregex section was a bit less clear than it could
be, so I slightly reworded it.
Make REPL continuation work better. Check for trailing "\" fails when
run function is called with buffer terminated by newline. Chomp'ing
buffer to remove newline fixes this issue.
This is only slightly problematic for the most pathological of cases
where a prelude is followed by a set of statements, none of which
generate top-level variables or attempt to return. In these cases, the
non-prelude statements will be indented. See related discussion at
e4b3e838e2.
This pleasently surprised but also confused me when it worked. Now it's
documented. No example (yet), alas, but better than nothing.
Originally added in/around 07e66dd2.
This confused me every time I Ctrl+F'ed the home page for "index" and only got
this cryptic statement:
"Comprehensions replace (and compile into) for loops, with optional guard clauses
and the value of the current array index."
Now I can see how the index is used in the code.
While recursively traversing a source directory, if a directory was encountered containing either no .coffee files (ex. an .svn metadata directory) or where the last file processed in that directory was not a .coffee file, compileJoin() might never be called.
This issue was originally introduced by a (well-needed) optimization in commit dc272a680b.
In join mode, anytime the 'unprocessed' count is decremented, the remaining file count should be evaluated to determine if it is time to run compileJoin(). Previously, compileJoin() would only ever be called in one of the four possible terminating branches of this recursive asynchronous operation.
CoffeeScript.eval. Instead of writing about all the changes and why I
made those decisions, I'll just answer any questions in the commit
comments, so add a commit comment if you want to question anything.
Thanks to @TrevorBurnham and @satyr for their help/contributions. Also,
closes#1487. And still no REPL tests...
CoffeeScript.eval. Instead of writing about all the changes and why I
made those decisions, I'll just answer any questions in the commit
comments, so add a commit comment if you want to question anything.
Thanks to @TrevorBurnham and @satyr for their help/contributions. Also,
closes#1487. And still no REPL tests...
Here's how the algorithm in balancedString() was modified. When we
encounter a slash in an interpolation, we:
* try to find a heregex right after it; if found---skip it. Three
slashes always terminate a heregex, no matter if there is an open
"#{" before them or not, so we don't have to bother about
sub-interpolations inside the heregex.
* try to find a regex right after it; if found---skip it. Simple
regexen can't contain interpolations.
* otherwise, assume that the slash means division and carry on.
x = 10
([x]) -> # used to not declare var x
this is one fix, the other way to fix
it is to remove the entire if ... olen is 1 ....
block... not sure if that's a good idea or not.
*why* `require` and only `require` was affected. All other globals that
I tried were unaffected: `console`, `parseInt`, `process`, `global`,
`Array`, `Object`, `Buffer`, `setTimeout`, ...
"[v] = a ? b" must compile to
v = (typeof a != "undefined" && a !== null ? a : b)[0];
and not to:
v = typeof a != "undefined" && a !== null ? a : b[0];
Check the readline.createInterface for arity. If it is 3,
assume the newer interface requiring separate stdin and stdout.
Otherwise, use the older calling style.
This change allows files to be `--require`d before entering the REPL. It's also
an opimization, since files are `--require`d only once, rather than being
required again every time a file is compiled.
A secondary change is that `module.filename` is temporarily modified. This is
somewhat less aesthetically appealing than the old approach of using
fs.realpathSync, but it allows you to run `coffee -r ./foo` rather than having
to write `coffee -r ./foo.coffee`, since Node does not accept absolute paths
without a file extension.
See the tests added to test_comprehensions.coffee. Previously, after
`for i in [1..3]`, i was 4. Also, index variables were never set to
any value in comprehensions containing both a closure and a break or
return.
Allows `path.join` to do some processing on the base path
that was also happening on the full path.
Fixes: `coffee -o ./ ./`
Still broken: `coffee -o . .`
coffee -e -r ./snarl 'Hello!'
Contents of 'snarl.coffee' in the working directory:
http = require 'http'
CoffeeScript.on 'exception', (err) ->
client = http.createClient 9889, 'localhost'
request = client.request 'GET', '/?d={"action":1,"applicationName":"CoffeeScript","title":' + JSON.stringify(err.message) + ',"description":' + JSON.stringify(err.stack) + ',"priority":3}'
request.end()
err.handled = yes
To examine arguments available for each event (for debugging and getting started), use `puts JSON.stringify arguments`.
See http://nodejs.org/api.html#modules-309 and NODE_PATH for more details on how -r looks for files.
- renamed rewrite_condition() to switches_over(),
and @switcher to @switch_subject
- removed unused else_body constructor parameter, as well
as unnecessary push() method
- ensure both @body and @else_body are always Expressions
(previously they could be either Expressions or IfNode)
- ReturnNodes are explicitly added during compilation
- ReturnNode is used instead of scattering "return" throughout
code compilation snippets
- nodes gain a make_return method in order to do the most useful
thing when a return is requested
- run synchronously, to ensure ordering is consistent
- big red error message (and exit status)
- don't bail early
- don't bother printing a stack trace (it's useless
until we can get line numbers in eval'd code)
<spanclass="nb">eval</span><spanclass="nx">CoffeeScript</span><spanclass="p">.</span><spanclass="nx">compile</span><spanclass="nx">code</span><spanclass="p">,</span><spanclass="nx">options</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>Running code does not provide access to this scope.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">CoffeeScript.run = </span><spanclass="nf">(code, options = {}) -></span>
<spanclass="nb">Function</span><spanclass="p">(</span><spanclass="nx">CoffeeScript</span><spanclass="p">.</span><spanclass="nx">compile</span><spanclass="nx">code</span><spanclass="p">,</span><spanclass="nx">options</span><spanclass="p">)()</span></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>If we're not in a browser environment, we're finished with the public API.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">return</span><spanclass="nx">unless</span><spanclass="nb">window</span><spanclass="o">?</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>Load a remote script from the current domain via XHR.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">CoffeeScript.load = </span><spanclass="nf">(url, callback) -></span>
<spanclass="nx">xhr</span><spanclass="p">.</span><spanclass="nx">send</span><spanclass="kc">null</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>Activate CoffeeScript in the browser by having it compile and evaluate
all script tags with a content-type of <code>text/coffeescript</code>.
This happens on page load.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">runScripts = </span><spanclass="o">-></span>
<spanclass="kc">null</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>Listen for window load, both in browsers and in IE.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="nb">window</span><spanclass="p">.</span><spanclass="nx">addEventListener</span>
<spanclass="nv">CoffeeScript = </span><spanclass="nx">require</span><spanclass="s1">'./coffee-script'</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>Keep track of the list of defined tasks, the accepted options, and so on.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">tasks = </span><spanclass="p">{}</span>
<spanclass="nv">oparse = </span><spanclass="kc">null</span></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>Mixin the top-level Cake functions for Cakefiles to use directly.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">helpers</span><spanclass="p">.</span><spanclass="nx">extend</span><spanclass="nx">global</span><spanclass="p">,</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>Define a Cake task with a short name, an optional sentence description,
and the function to run as the action itself.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">task: </span><spanclass="nf">(name, description, action) -></span>
<spanclass="nx">tasks</span><spanclass="p">[</span><spanclass="nx">name</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="p">{</span><spanclass="nx">name</span><spanclass="p">,</span><spanclass="nx">description</span><spanclass="p">,</span><spanclass="nx">action</span><spanclass="p">}</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>Define an option that the Cakefile accepts. The parsed options hash,
containing all of the command-line options passed, will be made available
as the first argument to the action.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">option: </span><spanclass="nf">(letter, flag, description) -></span>
<spanclass="nx">switches</span><spanclass="p">.</span><spanclass="nx">push</span><spanclass="p">[</span><spanclass="nx">letter</span><spanclass="p">,</span><spanclass="nx">flag</span><spanclass="p">,</span><spanclass="nx">description</span><spanclass="p">]</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>Invoke another task in the current Cakefile.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">invoke: </span><spanclass="nf">(name) -></span>
<spanclass="nx">tasks</span><spanclass="p">[</span><spanclass="nx">name</span><spanclass="p">].</span><spanclass="nx">action</span><spanclass="nx">options</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</a></div><p>Run <code>cake</code>. Executes all of the tasks you pass, in order. Note that Node's
asynchrony may cause tasks to execute in a different order than you'd expect.
If no tasks are passed, print the help screen. Keep a reference to the
original directory name, when running Cake tasks from subdirectories.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.run = </span><spanclass="o">-></span>
<spanclass="nx">invoke</span><spanclass="nx">arg</span><spanclass="k">for</span><spanclass="nx">arg</span><spanclass="k">in</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">arguments</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Display the list of Cake tasks in a format similar to <code>rake -T</code></p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">printTasks = </span><spanclass="o">-></span>
<spanclass="nx">console</span><spanclass="p">.</span><spanclass="nx">log</span><spanclass="s2">"#{cakefilePath} defines the following tasks:\n"</span>
<spanclass="nx">console</span><spanclass="p">.</span><spanclass="nx">log</span><spanclass="nx">oparse</span><spanclass="p">.</span><spanclass="nx">help</span><spanclass="p">()</span><spanclass="k">if</span><spanclass="nx">switches</span><spanclass="p">.</span><spanclass="nx">length</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Print an error and exit when attempting to use an invalid task/option.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">fatalError = </span><spanclass="nf">(message) -></span>
<spanclass="nx">console</span><spanclass="p">.</span><spanclass="nx">log</span><spanclass="s1">'To see a list of all tasks/options, run "cake"'</span>
<spanclass="nv">missingTask = </span><spanclass="nf">(task) -></span><spanclass="nx">fatalError</span><spanclass="s2">"No such task: #{task}"</span></pre></div></td></tr><trid="section-11"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-11">¶</a></div><p>When <code>cake</code> is invoked, search in the current and all parent directories
to find the relevant Cakefile.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">cakefileDirectory = </span><spanclass="nf">(dir) -></span>
<spanclass="k">throw</span><spanclass="k">new</span><spanclass="nb">Error</span><spanclass="s2">"Cakefile not found in #{process.cwd()}"</span>
<!DOCTYPE html><html><head><title>coffee-script.coffee</title><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><linkrel="stylesheet"media="all"href="docco.css"/></head><body><divid="container"><divid="background"></div><divid="jump_to"> Jump To …<divid="jump_wrapper"><divid="jump_page"><aclass="source"href="browser.html"> browser.coffee </a><aclass="source"href="cake.html"> cake.coffee </a><aclass="source"href="coffee-script.html"> coffee-script.coffee </a><aclass="source"href="command.html"> command.coffee </a><aclass="source"href="grammar.html"> grammar.coffee </a><aclass="source"href="helpers.html"> helpers.coffee </a><aclass="source"href="index.html"> index.coffee </a><aclass="source"href="lexer.html"> lexer.coffee </a><aclass="source"href="nodes.html"> nodes.coffee </a><aclass="source"href="optparse.html"> optparse.coffee </a><aclass="source"href="repl.html"> repl.coffee </a><aclass="source"href="rewriter.html"> rewriter.coffee </a><aclass="source"href="scope.html"> scope.coffee </a></div></div></div><tablecellpadding="0"cellspacing="0"><thead><tr><thclass="docs"><h1> coffee-script.coffee </h1></th><thclass="code"></th></tr></thead><tbody><trid="section-1"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-1">¶</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>
<p>If included on a webpage, it will automatically sniff out, compile, and
execute all scripts present in <code>text/coffeescript</code> tags.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">fs = </span><spanclass="nx">require</span><spanclass="s1">'fs'</span>
<spanclass="nx">require</span><spanclass="p">.</span><spanclass="nx">registerExtension</span><spanclass="s1">'.coffee'</span><spanclass="p">,</span><spanclass="nf">(content) -></span><spanclass="nx">compile</span><spanclass="nx">content</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>The current CoffeeScript version number.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.VERSION = </span><spanclass="s1">'1.3.3'</span></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>Words that cannot be used as identifiers in CoffeeScript code</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.RESERVED = </span><spanclass="nx">RESERVED</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>Expose helpers for testing.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.helpers = </span><spanclass="nx">require</span><spanclass="s1">'./helpers'</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>Compile a string of CoffeeScript code to JavaScript, using the Coffee/Jison
<spanclass="nv">header = </span><spanclass="s2">"Generated by CoffeeScript #{@VERSION}"</span>
<spanclass="s2">"// #{header}\n#{js}"</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.tokens = </span><spanclass="nf">(code, options) -></span>
<spanclass="nx">lexer</span><spanclass="p">.</span><spanclass="nx">tokenize</span><spanclass="nx">code</span><spanclass="p">,</span><spanclass="nx">options</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.nodes = </span><spanclass="nf">(source, options) -></span>
<spanclass="nx">parser</span><spanclass="p">.</span><spanclass="nx">parse</span><spanclass="nx">source</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Compile and execute a string of CoffeeScript (on the server), correctly
<spanclass="nv">mainModule = </span><spanclass="nx">require</span><spanclass="p">.</span><spanclass="nx">main</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Set the filename.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">mainModule.filename = </span><spanclass="nx">process</span><spanclass="p">.</span><spanclass="nx">argv</span><spanclass="p">[</span><spanclass="mi">1</span><spanclass="p">]</span><spanclass="o">=</span>
<spanclass="k">if</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">filename</span><spanclass="k">then</span><spanclass="nx">fs</span><spanclass="p">.</span><spanclass="nx">realpathSync</span><spanclass="p">(</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">filename</span><spanclass="p">)</span><spanclass="k">else</span><spanclass="s1">'.'</span></pre></div></td></tr><trid="section-11"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-11">¶</a></div><p>Clear the module cache.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">mainModule</span><spanclass="p">.</span><spanclass="nx">moduleCache</span><spanclass="o">and=</span><spanclass="p">{}</span></pre></div></td></tr><trid="section-12"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-12">¶</a></div><p>Assign paths for node_modules loading</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">mainModule.paths = </span><spanclass="nx">require</span><spanclass="p">(</span><spanclass="s1">'module'</span><spanclass="p">).</span><spanclass="nx">_nodeModulePaths</span><spanclass="nx">path</span><spanclass="p">.</span><spanclass="nx">dirname</span><spanclass="nx">fs</span><spanclass="p">.</span><spanclass="nx">realpathSync</span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">filename</span></pre></div></td></tr><trid="section-13"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-13">¶</a></div><p>Compile.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="nx">path</span><spanclass="p">.</span><spanclass="nx">extname</span><spanclass="p">(</span><spanclass="nx">mainModule</span><spanclass="p">.</span><spanclass="nx">filename</span><spanclass="p">)</span><spanclass="o">isnt</span><spanclass="s1">'.coffee'</span><spanclass="o">or</span><spanclass="nx">require</span><spanclass="p">.</span><spanclass="nx">extensions</span>
<spanclass="nx">mainModule</span><spanclass="p">.</span><spanclass="nx">_compile</span><spanclass="nx">code</span><spanclass="p">,</span><spanclass="nx">mainModule</span><spanclass="p">.</span><spanclass="nx">filename</span></pre></div></td></tr><trid="section-14"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-14">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.eval = </span><spanclass="nf">(code, options = {}) -></span>
<spanclass="nv">sandbox.__dirname = </span><spanclass="nx">path</span><spanclass="p">.</span><spanclass="nx">dirname</span><spanclass="nx">sandbox</span><spanclass="p">.</span><spanclass="nx">__filename</span></pre></div></td></tr><trid="section-15"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-15">¶</a></div><p>define module/require only if they chose not to specify their own</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">unless</span><spanclass="nx">sandbox</span><spanclass="o">isnt</span><spanclass="nx">global</span><spanclass="o">or</span><spanclass="nx">sandbox</span><spanclass="p">.</span><spanclass="nx">module</span><spanclass="o">or</span><spanclass="nx">sandbox</span><spanclass="p">.</span><spanclass="nx">require</span>
<spanclass="nx">_require</span><spanclass="p">[</span><spanclass="nx">r</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="nx">require</span><spanclass="p">[</span><spanclass="nx">r</span><spanclass="p">]</span><spanclass="k">for</span><spanclass="nx">r</span><spanclass="k">in</span><spanclass="nb">Object</span><spanclass="p">.</span><spanclass="nx">getOwnPropertyNames</span><spanclass="nx">require</span><spanclass="k">when</span><spanclass="nx">r</span><spanclass="o">isnt</span><spanclass="s1">'paths'</span></pre></div></td></tr><trid="section-16"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-16">¶</a></div><p>use the same hack node currently uses for their own REPL</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">_require.paths = _module.paths = </span><spanclass="nx">Module</span><spanclass="p">.</span><spanclass="nx">_nodeModulePaths</span><spanclass="nx">process</span><spanclass="p">.</span><spanclass="nx">cwd</span><spanclass="p">()</span>
<spanclass="nx">vm</span><spanclass="p">.</span><spanclass="nx">runInContext</span><spanclass="nx">js</span><spanclass="p">,</span><spanclass="nx">sandbox</span></pre></div></td></tr><trid="section-17"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-17">¶</a></div><p>Instantiate a Lexer for our use here.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">lexer = </span><spanclass="k">new</span><spanclass="nx">Lexer</span></pre></div></td></tr><trid="section-18"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-18">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">parser.lexer =</span>
<spanclass="nv">hidden = </span><spanclass="nf">(file) -></span><spanclass="o">/^</span><spanclass="err">\</span><spanclass="p">.</span><spanclass="o">|~</span><spanclass="nx">$</span><spanclass="err">/.test file</span></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>The help banner that is printed when <code>coffee</code> is called without arguments.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">BANNER = </span><spanclass="s1">'''</span>
<spanclass="s1"> If called without options, `coffee` will run your script.</span>
<spanclass="s1">'''</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>The list of all the valid option flags that <code>coffee</code> knows how to handle.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">SWITCHES = </span><spanclass="p">[</span>
<spanclass="p">[</span><spanclass="s1">'-b'</span><spanclass="p">,</span><spanclass="s1">'--bare'</span><spanclass="p">,</span><spanclass="s1">'compile without a top-level function wrapper'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-c'</span><spanclass="p">,</span><spanclass="s1">'--compile'</span><spanclass="p">,</span><spanclass="s1">'compile to JavaScript and save as .js files'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-e'</span><spanclass="p">,</span><spanclass="s1">'--eval'</span><spanclass="p">,</span><spanclass="s1">'pass a string from the command line as input'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-h'</span><spanclass="p">,</span><spanclass="s1">'--help'</span><spanclass="p">,</span><spanclass="s1">'display this help message'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-i'</span><spanclass="p">,</span><spanclass="s1">'--interactive'</span><spanclass="p">,</span><spanclass="s1">'run an interactive CoffeeScript REPL'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-j'</span><spanclass="p">,</span><spanclass="s1">'--join [FILE]'</span><spanclass="p">,</span><spanclass="s1">'concatenate the source CoffeeScript before compiling'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-l'</span><spanclass="p">,</span><spanclass="s1">'--lint'</span><spanclass="p">,</span><spanclass="s1">'pipe the compiled JavaScript through JavaScript Lint'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-n'</span><spanclass="p">,</span><spanclass="s1">'--nodes'</span><spanclass="p">,</span><spanclass="s1">'print out the parse tree that the parser produces'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'--nodejs [ARGS]'</span><spanclass="p">,</span><spanclass="s1">'pass options directly to the "node" binary'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-o'</span><spanclass="p">,</span><spanclass="s1">'--output [DIR]'</span><spanclass="p">,</span><spanclass="s1">'set the output directory for compiled JavaScript'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-p'</span><spanclass="p">,</span><spanclass="s1">'--print'</span><spanclass="p">,</span><spanclass="s1">'print out the compiled JavaScript'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-r'</span><spanclass="p">,</span><spanclass="s1">'--require [FILE*]'</span><spanclass="p">,</span><spanclass="s1">'require a library before executing your script'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-s'</span><spanclass="p">,</span><spanclass="s1">'--stdio'</span><spanclass="p">,</span><spanclass="s1">'listen for and compile scripts over stdio'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-t'</span><spanclass="p">,</span><spanclass="s1">'--tokens'</span><spanclass="p">,</span><spanclass="s1">'print out the tokens that the lexer/rewriter produce'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-v'</span><spanclass="p">,</span><spanclass="s1">'--version'</span><spanclass="p">,</span><spanclass="s1">'display the version number'</span><spanclass="p">]</span>
<spanclass="p">[</span><spanclass="s1">'-w'</span><spanclass="p">,</span><spanclass="s1">'--watch'</span><spanclass="p">,</span><spanclass="s1">'watch scripts for changes and rerun commands'</span><spanclass="p">]</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>Top-level objects shared by all the functions.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">opts = </span><spanclass="p">{}</span>
<spanclass="nv">optionParser = </span><spanclass="kc">null</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>Run <code>coffee</code> by parsing passed options and determining what action to take.
Many flags cause us to divert before compiling anything. Flags passed after
<code>--</code> will be passed verbatim to your script as arguments in <code>process.argv</code></p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.run = </span><spanclass="o">-></span>
<spanclass="k">return</span><spanclass="nx">printWarn</span><spanclass="s2">"The --watch feature depends on Node v0.6.0+. You are running #{process.version}."</span>
<spanclass="nx">compilePath</span><spanclass="nx">source</span><spanclass="p">,</span><spanclass="kc">yes</span><spanclass="p">,</span><spanclass="nx">path</span><spanclass="p">.</span><spanclass="nx">normalize</span><spanclass="nx">source</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</a></div><p>Compile a path, which could be a script or a directory. If a directory
is passed, recursively compile all '.coffee' extension source files in it
and all subdirectories.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">compilePath = </span><spanclass="nf">(source, topLevel, base) -></span>
<spanclass="nx">removeSource</span><spanclass="nx">source</span><spanclass="p">,</span><spanclass="nx">base</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Compile a single source script, containing the given code, according to the
requested options. If evaluating the script directly sets <code>__filename</code>,
<code>__dirname</code> and <code>module.filename</code> to be correct relative to the script's path.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">compileScript = </span><spanclass="nf">(file, input, base) -></span>
<spanclass="nx">process</span><spanclass="p">.</span><spanclass="nx">exit</span><spanclass="mi">1</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Attach the appropriate listeners to compile scripts incoming over <strong>stdin</strong>,
and write them back to <strong>stdout</strong>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">compileStdio = </span><spanclass="o">-></span>
<spanclass="nx">compileScript</span><spanclass="kc">null</span><spanclass="p">,</span><spanclass="nx">code</span></pre></div></td></tr><trid="section-11"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-11">¶</a></div><p>If all of the source files are done being read, concatenate and compile
them together.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">joinTimeout = </span><spanclass="kc">null</span>
<spanclass="nx">compileScript</span><spanclass="nx">opts</span><spanclass="p">.</span><spanclass="nx">join</span><spanclass="p">,</span><spanclass="nx">sourceCode</span><spanclass="p">.</span><spanclass="nx">join</span><spanclass="p">(</span><spanclass="s1">'\n'</span><spanclass="p">),</span><spanclass="nx">opts</span><spanclass="p">.</span><spanclass="nx">join</span></pre></div></td></tr><trid="section-12"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-12">¶</a></div><p>Load files that are to-be-required before compilation occurs.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">loadRequires = </span><spanclass="o">-></span>
<spanclass="nv">module.filename = </span><spanclass="nx">realFilename</span></pre></div></td></tr><trid="section-13"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-13">¶</a></div><p>Watch a source CoffeeScript file using <code>fs.watch</code>, recompiling it every
time the file is updated. May be used in combination with other options,
such as <code>--lint</code> or <code>--print</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">watch = </span><spanclass="nf">(source, base) -></span>
<spanclass="nv">watcher = </span><spanclass="nx">fs</span><spanclass="p">.</span><spanclass="nx">watch</span><spanclass="nx">source</span><spanclass="p">,</span><spanclass="nx">compile</span></pre></div></td></tr><trid="section-14"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-14">¶</a></div><p>Watch a directory of files for new additions.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">watchDir = </span><spanclass="nf">(source, base) -></span>
<spanclass="nx">compileJoin</span><spanclass="p">()</span></pre></div></td></tr><trid="section-15"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-15">¶</a></div><p>Remove a file from our source list, and source code cache. Optionally remove
the compiled JS version as well.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">removeSource = </span><spanclass="nf">(source, base, removeJs) -></span>
<spanclass="nx">timeLog</span><spanclass="s2">"removed #{source}"</span></pre></div></td></tr><trid="section-16"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-16">¶</a></div><p>Get the corresponding output JavaScript path for a source file.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">outputPath = </span><spanclass="nf">(source, base) -></span>
<spanclass="nx">path</span><spanclass="p">.</span><spanclass="nx">join</span><spanclass="nx">dir</span><spanclass="p">,</span><spanclass="nx">filename</span></pre></div></td></tr><trid="section-17"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-17">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">writeJs = </span><spanclass="nf">(source, js, base) -></span>
<spanclass="k">if</span><spanclass="nx">exists</span><spanclass="k">then</span><spanclass="nx">compile</span><spanclass="p">()</span><spanclass="k">else</span><spanclass="nx">exec</span><spanclass="s2">"mkdir -p #{jsDir}"</span><spanclass="p">,</span><spanclass="nx">compile</span></pre></div></td></tr><trid="section-18"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-18">¶</a></div><p>Convenience for cleaner setTimeouts.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">wait = </span><spanclass="nf">(milliseconds, func) -></span><spanclass="nx">setTimeout</span><spanclass="nx">func</span><spanclass="p">,</span><spanclass="nx">milliseconds</span></pre></div></td></tr><trid="section-19"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-19">¶</a></div><p>When watching scripts, it's useful to log changes with the timestamp.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">timeLog = </span><spanclass="nf">(message) -></span>
<spanclass="nx">console</span><spanclass="p">.</span><spanclass="nx">log</span><spanclass="s2">"#{(new Date).toLocaleTimeString()} - #{message}"</span></pre></div></td></tr><trid="section-20"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-20">¶</a></div><p>Pipe compiled JS through JSLint (requires a working <code>jsl</code> command), printing
any errors or warnings that arise.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">lint = </span><spanclass="nf">(file, js) -></span>
<spanclass="nx">jsl</span><spanclass="p">.</span><spanclass="nx">stdin</span><spanclass="p">.</span><spanclass="nx">end</span><spanclass="p">()</span></pre></div></td></tr><trid="section-21"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-21">¶</a></div><p>Pretty-print a stream of tokens.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">printTokens = </span><spanclass="nf">(tokens) -></span>
<spanclass="nx">printLine</span><spanclass="nx">strings</span><spanclass="p">.</span><spanclass="nx">join</span><spanclass="p">(</span><spanclass="s1">''</span><spanclass="p">)</span></pre></div></td></tr><trid="section-22"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-22">¶</a></div><p>Use the <ahref="optparse.html">OptionParser module</a> to extract all options from
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">parseOptions = </span><spanclass="o">-></span>
<spanclass="k">return</span></pre></div></td></tr><trid="section-23"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-23">¶</a></div><p>The compile-time options to pass to the CoffeeScript compiler.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">compileOptions = </span><spanclass="nf">(filename) -></span>
<spanclass="p">{</span><spanclass="nx">filename</span><spanclass="p">,</span><spanclass="nv">bare: </span><spanclass="nx">opts</span><spanclass="p">.</span><spanclass="nx">bare</span><spanclass="p">,</span><spanclass="nv">header: </span><spanclass="nx">opts</span><spanclass="p">.</span><spanclass="nx">compile</span><spanclass="p">}</span></pre></div></td></tr><trid="section-24"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-24">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">forkNode = </span><spanclass="o">-></span>
<spanclass="nv">customFds: </span><spanclass="p">[</span><spanclass="mi">0</span><spanclass="p">,</span><spanclass="mi">1</span><spanclass="p">,</span><spanclass="mi">2</span><spanclass="p">]</span></pre></div></td></tr><trid="section-25"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-25">¶</a></div><p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
<spanclass="nx">printLine</span><spanclass="p">(</span><spanclass="k">new</span><spanclass="nx">optparse</span><spanclass="p">.</span><spanclass="nx">OptionParser</span><spanclass="nx">SWITCHES</span><spanclass="p">,</span><spanclass="nx">BANNER</span><spanclass="p">).</span><spanclass="nx">help</span><spanclass="p">()</span></pre></div></td></tr><trid="section-26"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-26">¶</a></div><p>Print the <code>--version</code> message and exit.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">version = </span><spanclass="o">-></span>
<spanclass="nx">printLine</span><spanclass="s2">"CoffeeScript version #{CoffeeScript.VERSION}"</span>
from this grammar file. Jison is a bottom-up parser generator, similar in
style to <ahref="http://www.gnu.org/software/bison">Bison</a>, implemented in JavaScript.
It can recognize <ahref="http://en.wikipedia.org/wiki/LR_grammar">LALR(1), LR(0), SLR(1), and LR(1)</a>
type grammars. To create the Jison parser, we list the pattern to match
on the left-hand side, and the action to take (usually the creation of syntax
tree nodes) on the right. As the parser runs, it
shifts tokens from our token stream, from left to right, and
<ahref="http://en.wikipedia.org/wiki/Bottom-up_parsing">attempts to match</a>
the token sequence against the rules below. When a match can be made, it
reduces into the <ahref="http://en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols">nonterminal</a>
(the enclosing name at the top), and we proceed from there.</p>
<p>If you run the <code>cake build:parser</code> command, Jison constructs a parse table
from our rules and saves it into <code>lib/parser.js</code>.</p></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-2"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-2">¶</a></div><p>The only dependency is on the <strong>Jison.Parser</strong>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="p">{</span><spanclass="nx">Parser</span><spanclass="p">}</span><spanclass="o">=</span><spanclass="nx">require</span><spanclass="s1">'jison'</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><h2>Jison DSL</h2></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>Since we're going to be wrapped in a function by Jison in any case, if our
action immediately returns a value, we can optimize by removing the function
wrapper and just returning the value directly.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">unwrap = </span><spanclass="sr">/^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>Our handy DSL for Jison grammar generation, thanks to
<ahref="http://github.com/creationix">Tim Caswell</a>. For every rule in the grammar,
we pass the pattern-defining string, the action to run, and extra options,
optionally. If no action is specified, we simply pass the value of the
<spanclass="p">[</span><spanclass="nx">patternString</span><spanclass="p">,</span><spanclass="s2">"$$ = #{action};"</span><spanclass="p">,</span><spanclass="nx">options</span><spanclass="p">]</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><h2>Grammatical Rules</h2></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>In all of the rules that follow, you'll see the name of the nonterminal as
the key to a list of alternative matches. With each match's action, the
dollar-sign variables are provided by Jison as references to the value of
their numeric position, so in this rule:</p>
<pre><code>"Expression UNLESS Expression"
</code></pre>
<p><code>$1</code> would be the value of the first <code>Expression</code>, <code>$2</code> would be the token
for the <code>UNLESS</code> terminal, and <code>$3</code> would be the value of the second
<code>Expression</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">grammar =</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</a></div><p>The <strong>Root</strong> is the top-level node in the syntax tree. Since we parse bottom-up,
all parsing must end here.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Root: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Any list of statements and expressions, separated by line breaks or semicolons.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Body: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Block and statements, which make up a line in a body.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Line: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-11"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-11">¶</a></div><p>Pure statements which cannot be expressions.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Statement: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-12"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-12">¶</a></div><p>All the different types of expressions in our language. The basic unit of
CoffeeScript is the <strong>Expression</strong> -- everything that can be an expression
is one. Blocks serve as the building blocks of many other rules, making
them somewhat circular.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Expression: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-13"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-13">¶</a></div><p>An indented block of expressions. Note that the <ahref="rewriter.html">Rewriter</a>
will convert some postfix forms into blocks for us, by adjusting the
<spanclass="nx">o</span><spanclass="s1">'INDENT Body OUTDENT'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nx">$2</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-14"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-14">¶</a></div><p>A literal identifier, a variable name or property.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Identifier: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-15"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-15">¶</a></div><p>Alphanumerics are separated from the other <strong>Literal</strong> matchers because
they can also serve as keys in object literals.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">AlphaNumeric: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-16"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-16">¶</a></div><p>All of our immediate values. Generally these can be passed straight
through and printed to JavaScript.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Literal: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-17"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-17">¶</a></div><p>Assignment of a variable, property, or index to a value.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Assign: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-18"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-18">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">AssignObj: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-19"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-19">¶</a></div><p>A return statement from a function body.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Return: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-21"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-21">¶</a></div><p>The <strong>Code</strong> node is the function literal. It's defined by an indented block
of <strong>Block</strong> preceded by a function arrow, with an optional parameter
<spanclass="p">]</span></pre></div></td></tr><trid="section-22"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-22">¶</a></div><p>CoffeeScript has two different symbols for functions. <code>-></code> is for ordinary
functions, and <code>=></code> is for functions bound to the current value of <em>this</em>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">FuncGlyph: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-24"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-24">¶</a></div><p>The list of parameters that a function accepts can be of any length.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">ParamList: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-25"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-25">¶</a></div><p>A single parameter in a function definition can be ordinary, or a splat
that hoovers up the remaining arguments.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Param: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-27"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-27">¶</a></div><p>A splat that occurs outside of a parameter list.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Splat: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-28"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-28">¶</a></div><p>Variables and properties that can be assigned to.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">SimpleAssignable: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-29"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-29">¶</a></div><p>Everything that can be assigned to.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Assignable: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-30"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-30">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Value: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-31"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-31">¶</a></div><p>The general group of accessors into an object, by property, by prototype
or by array index or slice.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Accessor: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-32"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-32">¶</a></div><p>Indexing into an object or array using bracket notation.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Index: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-33"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-33">¶</a></div><p>In CoffeeScript, an object literal is simply a list of assignments.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nb">Object</span><spanclass="o">:</span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-34"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-34">¶</a></div><p>Assignment of properties within an object literal can be separated by
comma, as in JavaScript, or simply by newline.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">AssignList: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-35"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-35">¶</a></div><p>Class definitions have optional bodies of prototype property assignments,
and optional references to the superclass.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Class: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-36"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-36">¶</a></div><p>Ordinary function invocation, or a chained series of calls.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Invocation: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-37"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-37">¶</a></div><p>An optional existence check on a function.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">OptFuncExist: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-38"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-38">¶</a></div><p>The list of arguments to a function call.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Arguments: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-39"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-39">¶</a></div><p>A reference to the <em>this</em> current object.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">This: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-40"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-40">¶</a></div><p>A reference to a property on <em>this</em>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">ThisProperty: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-42"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-42">¶</a></div><p>Inclusive and exclusive range dots.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">RangeDots: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-43"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-43">¶</a></div><p>The CoffeeScript range literal.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Range: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-45"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-45">¶</a></div><p>The <strong>ArgList</strong> is both the list of objects passed into a function call,
as well as the contents of an array literal
(i.e. comma-separated expressions). Newlines work as well.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">ArgList: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-46"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-46">¶</a></div><p>Valid arguments are Blocks or Splats.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Arg: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-47"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-47">¶</a></div><p>Just simple, comma-separated, required arguments (no fancy syntax). We need
this to be separate from the <strong>ArgList</strong> for use in <strong>Switch</strong> blocks, where
having the newlines wouldn't make sense.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">SimpleArgs: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-49"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-49">¶</a></div><p>A catch clause names its error and runs a block of code.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Catch: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-50"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-50">¶</a></div><p>Throw an exception object.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Throw: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-51"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-51">¶</a></div><p>Parenthetical expressions. Note that the <strong>Parenthetical</strong> is a <strong>Value</strong>,
not an <strong>Expression</strong>, so if you need to use an expression in a place
where only values are accepted, wrapping it in parentheses will always do
the trick.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Parenthetical: </span><spanclass="p">[</span>
<spanclass="nx">o</span><spanclass="s1">'( Body )'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="k">new</span><spanclass="nx">Parens</span><spanclass="nx">$2</span>
<spanclass="nx">o</span><spanclass="s1">'( INDENT Body OUTDENT )'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="k">new</span><spanclass="nx">Parens</span><spanclass="nx">$3</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-52"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-52">¶</a></div><p>The condition portion of a while loop.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">WhileSource: </span><spanclass="p">[</span>
<spanclass="nx">o</span><spanclass="s1">'WHILE Expression WHEN Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="k">new</span><spanclass="nx">While</span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nv">guard: </span><spanclass="nx">$4</span>
<spanclass="nx">o</span><spanclass="s1">'UNTIL Expression WHEN Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="k">new</span><spanclass="nx">While</span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nv">invert: </span><spanclass="kc">true</span><spanclass="p">,</span><spanclass="nv">guard: </span><spanclass="nx">$4</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-53"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-53">¶</a></div><p>The while loop can either be normal, with a block of expressions to execute,
or postfix, with a single expression. There is no do..while.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">While: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-54"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-54">¶</a></div><p>Array, object, and range comprehensions, at the most generic level.
Comprehensions can either be normal, with a block of expressions to execute,
or postfix, with a single expression.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">For: </span><spanclass="p">[</span>
<spanclass="nx">o</span><spanclass="s1">'FOR OWN ForVariables'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nv">$3.own = </span><spanclass="kc">yes</span><spanclass="p">;</span><spanclass="nx">$3</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-55"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-55">¶</a></div><p>An array of all accepted values for a variable inside the loop.
This enables support for pattern matching.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">ForValue: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-56"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-56">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">ForVariables: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-57"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-57">¶</a></div><p>The source of a comprehension is an array or object with an optional guard
clause. If it's an array comprehension, you can also choose to step through
in fixed-size increments.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">ForSource: </span><spanclass="p">[</span>
<spanclass="nx">o</span><spanclass="s1">'FORIN Expression WHEN Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nv">source: </span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nv">guard: </span><spanclass="nx">$4</span>
<spanclass="nx">o</span><spanclass="s1">'FOROF Expression WHEN Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nv">source: </span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nv">guard: </span><spanclass="nx">$4</span><spanclass="p">,</span><spanclass="nv">object: </span><spanclass="kc">yes</span>
<spanclass="nx">o</span><spanclass="s1">'FORIN Expression BY Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nv">source: </span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nv">step: </span><spanclass="nx">$4</span>
<spanclass="nx">o</span><spanclass="s1">'FORIN Expression WHEN Expression BY Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nv">source: </span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nv">guard: </span><spanclass="nx">$4</span><spanclass="p">,</span><spanclass="nv">step: </span><spanclass="nx">$6</span>
<spanclass="nx">o</span><spanclass="s1">'FORIN Expression BY Expression WHEN Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nv">source: </span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nv">step: </span><spanclass="nx">$4</span><spanclass="p">,</span><spanclass="nv">guard: </span><spanclass="nx">$6</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-59"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-59">¶</a></div><p>The most basic form of <em>if</em> is a condition and an action. The following
if-related rules are broken up along these lines in order to avoid
<spanclass="nx">o</span><spanclass="s1">'IfBlock ELSE IF Expression Block'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="nx">$1</span><spanclass="p">.</span><spanclass="nx">addElse</span><spanclass="k">new</span><spanclass="nx">If</span><spanclass="nx">$4</span><spanclass="p">,</span><spanclass="nx">$5</span><spanclass="p">,</span><spanclass="nv">type: </span><spanclass="nx">$3</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-60"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-60">¶</a></div><p>The full complement of <em>if</em> expressions, including postfix one-liner
<em>if</em> and <em>unless</em>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">If: </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-61"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-61">¶</a></div><p>Arithmetic and logical operators, working on one or more operands.
Here they are grouped by order of precedence. The actual precedence rules
are defined at the bottom of the page. It would be shorter if we could
combine most of these rules into a single generic <em>Operand OpSymbol Operand</em>
-type rule, but in order to make the precedence binding possible, separate
rules are necessary.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">Operation: </span><spanclass="p">[</span>
<spanclass="nx">o</span><spanclass="s1">'Expression MATH Expression'</span><spanclass="p">,</span><spanclass="o">-></span><spanclass="k">new</span><spanclass="nx">Op</span><spanclass="nx">$2</span><spanclass="p">,</span><spanclass="nx">$1</span><spanclass="p">,</span><spanclass="nx">$3</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-63"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-63">¶</a></div><h2>Precedence</h2></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-64"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-64">¶</a></div><p>Operators at the top of this list have higher precedence than the ones lower
down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
<spanclass="p">]</span></pre></div></td></tr><trid="section-65"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-65">¶</a></div><h2>Wrapping Up</h2></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-66"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-66">¶</a></div><p>Finally, now that we have our <strong>grammar</strong> and our <strong>operators</strong>, we can create
our <strong>Jison.Parser</strong>. We do this by processing all of our rules, recording all
terminals (every symbol which does not appear as the name of a rule above)
as "tokens".</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">tokens = </span><spanclass="p">[]</span>
<spanclass="nx">alt</span></pre></div></td></tr><trid="section-67"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-67">¶</a></div><p>Initialize the <strong>Parser</strong> with our list of terminal <strong>tokens</strong>, our <strong>grammar</strong>
rules, and the name of the root. Reverse the operators because Jison orders
precedence from low to high, and we have it high to low
(as in <ahref="http://dinosaur.compilertools.net/yacc/index.html">Yacc</a>).</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.parser = </span><spanclass="k">new</span><spanclass="nx">Parser</span>
<!DOCTYPE html><html><head><title>helpers.coffee</title><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><linkrel="stylesheet"media="all"href="docco.css"/></head><body><divid="container"><divid="background"></div><divid="jump_to"> Jump To …<divid="jump_wrapper"><divid="jump_page"><aclass="source"href="browser.html"> browser.coffee </a><aclass="source"href="cake.html"> cake.coffee </a><aclass="source"href="coffee-script.html"> coffee-script.coffee </a><aclass="source"href="command.html"> command.coffee </a><aclass="source"href="grammar.html"> grammar.coffee </a><aclass="source"href="helpers.html"> helpers.coffee </a><aclass="source"href="index.html"> index.coffee </a><aclass="source"href="lexer.html"> lexer.coffee </a><aclass="source"href="nodes.html"> nodes.coffee </a><aclass="source"href="optparse.html"> optparse.coffee </a><aclass="source"href="repl.html"> repl.coffee </a><aclass="source"href="rewriter.html"> rewriter.coffee </a><aclass="source"href="scope.html"> scope.coffee </a></div></div></div><tablecellpadding="0"cellspacing="0"><thead><tr><thclass="docs"><h1> helpers.coffee </h1></th><thclass="code"></th></tr></thead><tbody><trid="section-1"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-1">¶</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><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-2"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-2">¶</a></div><p>Peek at the beginning of a given string to see if it matches a sequence.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.starts = </span><spanclass="nf">(string, literal, start) -></span>
<spanclass="nx">literal</span><spanclass="o">is</span><spanclass="nx">string</span><spanclass="p">.</span><spanclass="nx">substr</span><spanclass="nx">start</span><spanclass="p">,</span><spanclass="nx">literal</span><spanclass="p">.</span><spanclass="nx">length</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>Peek at the end of a given string to see if it matches a sequence.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.ends = </span><spanclass="nf">(string, literal, back) -></span>
<spanclass="nx">literal</span><spanclass="o">is</span><spanclass="nx">string</span><spanclass="p">.</span><spanclass="nx">substr</span><spanclass="nx">string</span><spanclass="p">.</span><spanclass="nx">length</span><spanclass="o">-</span><spanclass="nx">len</span><spanclass="o">-</span><spanclass="p">(</span><spanclass="nx">back</span><spanclass="o">or</span><spanclass="mi">0</span><spanclass="p">),</span><spanclass="nx">len</span></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>Trim out all falsy values from an array.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.compact = </span><spanclass="nf">(array) -></span>
<spanclass="nx">item</span><spanclass="k">for</span><spanclass="nx">item</span><spanclass="k">in</span><spanclass="nx">array</span><spanclass="k">when</span><spanclass="nx">item</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>Count the number of occurrences of a string in a string.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.count = </span><spanclass="nf">(string, substr) -></span>
<spanclass="nx">num</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>Merge objects, returning a fresh copy with attributes from both sides.
Used every time <code>Base#compile</code> is called, to allow properties in the
options hash to propagate down the tree without polluting other branches.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.merge = </span><spanclass="nf">(options, overrides) -></span>
<spanclass="nx">extend</span><spanclass="p">(</span><spanclass="nx">extend</span><spanclass="p">{},</span><spanclass="nx">options</span><spanclass="p">),</span><spanclass="nx">overrides</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>Extend a source object with the properties of another object (shallow copy).</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">extend = exports.extend = </span><spanclass="nf">(object, properties) -></span>
<spanclass="nx">object</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</a></div><p>Return a flattened version of an array.
Handy for getting a list of <code>children</code> from the nodes.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.flatten = flatten = </span><spanclass="nf">(array) -></span>
<spanclass="nx">flattened</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Delete a key from an object, returning the value. Useful when a node is
looking for a particular method in an options hash.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.del = </span><spanclass="nf">(obj, key) -></span>
<spanclass="nx">val</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Gets the last item of an array(-like) object.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.last = </span><spanclass="nf">(array, back) -></span><spanclass="nx">array</span><spanclass="p">[</span><spanclass="nx">array</span><spanclass="p">.</span><spanclass="nx">length</span><spanclass="o">-</span><spanclass="p">(</span><spanclass="nx">back</span><spanclass="o">or</span><spanclass="mi">0</span><spanclass="p">)</span><spanclass="o">-</span><spanclass="mi">1</span><spanclass="p">]</span>
<!DOCTYPE html><html><head><title>optparse.coffee</title><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><linkrel="stylesheet"media="all"href="docco.css"/></head><body><divid="container"><divid="background"></div><divid="jump_to"> Jump To …<divid="jump_wrapper"><divid="jump_page"><aclass="source"href="browser.html"> browser.coffee </a><aclass="source"href="cake.html"> cake.coffee </a><aclass="source"href="coffee-script.html"> coffee-script.coffee </a><aclass="source"href="command.html"> command.coffee </a><aclass="source"href="grammar.html"> grammar.coffee </a><aclass="source"href="helpers.html"> helpers.coffee </a><aclass="source"href="index.html"> index.coffee </a><aclass="source"href="lexer.html"> lexer.coffee </a><aclass="source"href="nodes.html"> nodes.coffee </a><aclass="source"href="optparse.html"> optparse.coffee </a><aclass="source"href="repl.html"> repl.coffee </a><aclass="source"href="rewriter.html"> rewriter.coffee </a><aclass="source"href="scope.html"> scope.coffee </a></div></div></div><tablecellpadding="0"cellspacing="0"><thead><tr><thclass="docs"><h1> optparse.coffee </h1></th><thclass="code"></th></tr></thead><tbody><trid="section-1"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-1">¶</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
options = parser.parse process.argv
</code></pre>
<p>The first non-option is considered to be the start of the file (and file
option) list, and all subsequent arguments are left unparsed.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.OptionParser = </span><spanclass="k">class</span><spanclass="nx">OptionParser</span></pre></div></td></tr><trid="section-2"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-2">¶</a></div><p>Initialize with a list of valid options, in the form:</p>
<pre><code>[short-flag, long-flag, description]
</code></pre>
<p>Along with an an optional banner for the usage help.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">constructor: </span><spanclass="nf">(rules, @banner) -></span>
<spanclass="vi">@rules = </span><spanclass="nx">buildRules</span><spanclass="nx">rules</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>Parse the list of arguments, populating an <code>options</code> object with all of the
specified options, and return it. Options after the first non-option
argument are treated as arguments. <code>options.arguments</code> will be an array
containing the remaining arguments. This is a simpler API than many option
parsers that allow you to attach callback actions for every flag. Instead,
you're responsible for interpreting the options object.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">parse: </span><spanclass="nf">(args) -></span>
<spanclass="nv">isOption = </span><spanclass="o">!!</span><spanclass="p">(</span><spanclass="nx">arg</span><spanclass="p">.</span><spanclass="nx">match</span><spanclass="p">(</span><spanclass="nx">LONG_FLAG</span><spanclass="p">)</span><spanclass="o">or</span><spanclass="nx">arg</span><spanclass="p">.</span><spanclass="nx">match</span><spanclass="p">(</span><spanclass="nx">SHORT_FLAG</span><spanclass="p">))</span></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>the CS option parser is a little odd; options after the first
non-option argument are treated as non-option arguments themselves</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">seenNonOptionArg = </span><spanclass="nx">options</span><spanclass="p">.</span><spanclass="nx">arguments</span><spanclass="p">.</span><spanclass="nx">length</span><spanclass="o">></span><spanclass="mi">0</span>
<spanclass="nx">options</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>Return the help text for this <strong>OptionParser</strong>, listing and describing all
of the valid options, for <code>--help</code> and such.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">help: </span><spanclass="o">-></span>
<spanclass="nv">OPTIONAL = </span><spanclass="sr">/\[(\w+(\*?))\]/</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</a></div><p>Build and return the list of option rules. If the optional <em>short-flag</em> is
unspecified, leave it out by padding with <code>null</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">buildRules = </span><spanclass="nf">(rules) -></span>
<spanclass="nx">buildRule</span><spanclass="nx">tuple</span><spanclass="p">...</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Build a rule from a <code>-o</code> short flag, a <code>--output [DIR]</code> long flag, and the
description of what the option does.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">buildRule = </span><spanclass="nf">(shortFlag, longFlag, description, options = {}) -></span>
<spanclass="p">}</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Normalize arguments by expanding merged flags into multiple flags. This allows
you to have <code>-wl</code> be the same as <code>--watch --lint</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">normalizeArguments = </span><spanclass="nf">(args) -></span>
<!DOCTYPE html><html><head><title>repl.coffee</title><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><linkrel="stylesheet"media="all"href="docco.css"/></head><body><divid="container"><divid="background"></div><divid="jump_to"> Jump To …<divid="jump_wrapper"><divid="jump_page"><aclass="source"href="browser.html"> browser.coffee </a><aclass="source"href="cake.html"> cake.coffee </a><aclass="source"href="coffee-script.html"> coffee-script.coffee </a><aclass="source"href="command.html"> command.coffee </a><aclass="source"href="grammar.html"> grammar.coffee </a><aclass="source"href="helpers.html"> helpers.coffee </a><aclass="source"href="index.html"> index.coffee </a><aclass="source"href="lexer.html"> lexer.coffee </a><aclass="source"href="nodes.html"> nodes.coffee </a><aclass="source"href="optparse.html"> optparse.coffee </a><aclass="source"href="repl.html"> repl.coffee </a><aclass="source"href="rewriter.html"> rewriter.coffee </a><aclass="source"href="scope.html"> scope.coffee </a></div></div></div><tablecellpadding="0"cellspacing="0"><thead><tr><thclass="docs"><h1> repl.coffee </h1></th><thclass="code"></th></tr></thead><tbody><trid="section-1"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-1">¶</a></div><p>A very simple Read-Eval-Print-Loop. Compiles one line at a time to JavaScript
and evaluates it. Good for simple tests, or poking around the <strong>Node.js</strong> API.
Using it looks like this:</p>
<pre><code>coffee> console.log "#{num} bottles of beer" for num in [99..1]
</code></pre></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-2"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-2">¶</a></div><p>Start by opening up <code>stdin</code> and <code>stdout</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">stdin = </span><spanclass="nx">process</span><spanclass="p">.</span><spanclass="nx">openStdin</span><spanclass="p">()</span>
<spanclass="nv">stdout = </span><spanclass="nx">process</span><spanclass="p">.</span><spanclass="nx">stdout</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>Require the <strong>coffee-script</strong> module to get access to the compiler.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">CoffeeScript = </span><spanclass="nx">require</span><spanclass="s1">'./coffee-script'</span>
<spanclass="nv">enableColours = </span><spanclass="o">not</span><spanclass="nx">process</span><spanclass="p">.</span><spanclass="nx">env</span><spanclass="p">.</span><spanclass="nx">NODE_DISABLE_COLORS</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>Log an error.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">error = </span><spanclass="nf">(err) -></span>
<spanclass="nx">stdout</span><spanclass="p">.</span><spanclass="nx">write</span><spanclass="p">(</span><spanclass="nx">err</span><spanclass="p">.</span><spanclass="nx">stack</span><spanclass="o">or</span><spanclass="nx">err</span><spanclass="p">.</span><spanclass="nx">toString</span><spanclass="p">())</span><spanclass="o">+</span><spanclass="s1">'\n'</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><h1>Autocompletion</h1></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</a></div><p>Regexes to match complete-able bits of text.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">ACCESSOR = </span><spanclass="sr">/\s*([\w\.]+)(?:\.(\w*))$/</span>
<spanclass="nv">SIMPLEVAR = </span><spanclass="sr">/(\w+)$/i</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Returns a list of completions, and the completed text.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">autocomplete = </span><spanclass="nf">(text) -></span>
<spanclass="nx">completeAttribute</span><spanclass="p">(</span><spanclass="nx">text</span><spanclass="p">)</span><spanclass="o">or</span><spanclass="nx">completeVariable</span><spanclass="p">(</span><spanclass="nx">text</span><spanclass="p">)</span><spanclass="o">or</span><spanclass="p">[[],</span><spanclass="nx">text</span><spanclass="p">]</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Attempt to autocomplete a chained dotted attribute: <code>one.two.three</code>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">completeAttribute = </span><spanclass="nf">(text) -></span>
<spanclass="p">[</span><spanclass="nx">completions</span><spanclass="p">,</span><spanclass="nx">free</span><spanclass="p">]</span></pre></div></td></tr><trid="section-12"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-12">¶</a></div><p>Return elements of candidates for which <code>prefix</code> is a prefix.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">getCompletions = </span><spanclass="nf">(prefix, candidates) -></span>
<spanclass="p">(</span><spanclass="nx">el</span><spanclass="k">for</span><spanclass="nx">el</span><spanclass="k">in</span><spanclass="nx">candidates</span><spanclass="k">when</span><spanclass="nx">el</span><spanclass="p">.</span><spanclass="nx">indexOf</span><spanclass="p">(</span><spanclass="nx">prefix</span><spanclass="p">)</span><spanclass="o">is</span><spanclass="mi">0</span><spanclass="p">)</span></pre></div></td></tr><trid="section-13"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-13">¶</a></div><p>Make sure that uncaught exceptions don't kill the REPL.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">process</span><spanclass="p">.</span><spanclass="kc">on</span><spanclass="s1">'uncaughtException'</span><spanclass="p">,</span><spanclass="nx">error</span></pre></div></td></tr><trid="section-14"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-14">¶</a></div><p>The current backlog of multi-line code.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">backlog = </span><spanclass="s1">''</span></pre></div></td></tr><trid="section-15"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-15">¶</a></div><p>The main REPL function. <strong>run</strong> is called every time a line of code is entered.
Attempt to evaluate the command. If there's an exception, print it out instead
<spanclass="nx">repl</span><spanclass="p">.</span><spanclass="nx">output</span><spanclass="p">.</span><spanclass="nx">write</span><spanclass="s2">"#{inspect returnValue, no, 2, enableColours}\n"</span>
<spanclass="k">else</span></pre></div></td></tr><trid="section-19"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-19">¶</a></div><p>Create the REPL by listening to <strong>stdin</strong>.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">if</span><spanclass="nx">readline</span><spanclass="p">.</span><spanclass="nx">createInterface</span><spanclass="p">.</span><spanclass="nx">length</span><spanclass="o"><</span><spanclass="mi">3</span>
<spanclass="nx">repl</span><spanclass="p">.</span><spanclass="nx">output</span><spanclass="p">.</span><spanclass="nx">cursorTo</span><spanclass="nx">newPrompt</span><spanclass="p">.</span><spanclass="nx">length</span><spanclass="o">+</span><spanclass="p">(</span><spanclass="nv">repl.cursor = </span><spanclass="nx">cursorPos</span><spanclass="p">)</span></pre></div></td></tr><trid="section-22"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-22">¶</a></div><p>Handle Ctrl-d press at end of last line in multiline mode</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nx">repl</span><spanclass="p">.</span><spanclass="nx">input</span><spanclass="p">.</span><spanclass="kc">on</span><spanclass="s1">'keypress'</span><spanclass="p">,</span><spanclass="nf">(char, key) -></span>
<spanclass="k">return</span><spanclass="nx">unless</span><spanclass="nx">multilineMode</span><spanclass="o">and</span><spanclass="nx">repl</span><spanclass="p">.</span><spanclass="nx">line</span></pre></div></td></tr><trid="section-23"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-23">¶</a></div><p>test for Ctrl-d</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">return</span><spanclass="nx">unless</span><spanclass="nx">key</span><spanclass="o">and</span><spanclass="nx">key</span><spanclass="p">.</span><spanclass="nx">ctrl</span><spanclass="o">and</span><spanclass="o">not</span><spanclass="nx">key</span><spanclass="p">.</span><spanclass="nx">meta</span><spanclass="o">and</span><spanclass="o">not</span><spanclass="nx">key</span><spanclass="p">.</span><spanclass="nx">shift</span><spanclass="o">and</span><spanclass="nx">key</span><spanclass="p">.</span><spanclass="nx">name</span><spanclass="o">is</span><spanclass="s1">'d'</span>
<!DOCTYPE html><html><head><title>rewriter.coffee</title><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><linkrel="stylesheet"media="all"href="docco.css"/></head><body><divid="container"><divid="background"></div><divid="jump_to"> Jump To …<divid="jump_wrapper"><divid="jump_page"><aclass="source"href="browser.html"> browser.coffee </a><aclass="source"href="cake.html"> cake.coffee </a><aclass="source"href="coffee-script.html"> coffee-script.coffee </a><aclass="source"href="command.html"> command.coffee </a><aclass="source"href="grammar.html"> grammar.coffee </a><aclass="source"href="helpers.html"> helpers.coffee </a><aclass="source"href="index.html"> index.coffee </a><aclass="source"href="lexer.html"> lexer.coffee </a><aclass="source"href="nodes.html"> nodes.coffee </a><aclass="source"href="optparse.html"> optparse.coffee </a><aclass="source"href="repl.html"> repl.coffee </a><aclass="source"href="rewriter.html"> rewriter.coffee </a><aclass="source"href="scope.html"> scope.coffee </a></div></div></div><tablecellpadding="0"cellspacing="0"><thead><tr><thclass="docs"><h1> rewriter.coffee </h1></th><thclass="code"></th></tr></thead><tbody><trid="section-1"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-1">¶</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><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-2"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-2">¶</a></div><p>The <strong>Rewriter</strong> class is used by the <ahref="lexer.html">Lexer</a>, directly against
its internal array of tokens.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="k">class</span><spanclass="nx">exports</span><spanclass="p">.</span><spanclass="nx">Rewriter</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>Helpful snippet for debugging:
console.log (t[0] + '/' + t[1] for t in @tokens).join ' '</p></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</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
corrected before implicit parentheses can be wrapped around blocks of code.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">rewrite: </span><spanclass="nf">(@tokens) -></span>
<spanclass="nx">@tokens</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</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
<spanclass="nx">i</span><spanclass="o">-</span><spanclass="mi">1</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>Leading newlines would introduce an ambiguity in the grammar, so we
dispatch them here.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">removeLeadingNewlines: </span><spanclass="o">-></span>
<spanclass="nx">@tokens</span><spanclass="p">.</span><spanclass="nx">splice</span><spanclass="mi">0</span><spanclass="p">,</span><spanclass="nx">i</span><spanclass="k">if</span><spanclass="nx">i</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>Some blocks occur in the middle of expressions -- when we're expecting
this, remove their trailing newlines.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">removeMidExpressionNewlines: </span><spanclass="o">-></span>
<spanclass="nx">@scanTokens</span><spanclass="nf">(token, i, tokens) -></span>
<spanclass="mi">0</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">closeOpenCalls: </span><spanclass="o">-></span>
<spanclass="mi">1</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>The lexer has tagged the opening parenthesis of an indexing operation call.
Match it with its paired close.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">closeOpenIndexes: </span><spanclass="o">-></span>
<spanclass="mi">1</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">addImplicitBraces: </span><spanclass="o">-></span>
<spanclass="mi">2</span></pre></div></td></tr><trid="section-11"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-11">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">addImplicitParentheses: </span><spanclass="o">-></span>
<spanclass="mi">2</span></pre></div></td></tr><trid="section-12"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-12">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">addImplicitIndentation: </span><spanclass="o">-></span>
<spanclass="k">return</span><spanclass="mi">1</span></pre></div></td></tr><trid="section-13"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-13">¶</a></div><p>Tag postfix conditionals as such, so that we can parse them with a
different precedence.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">tagPostfixConditionals: </span><spanclass="o">-></span>
<spanclass="mi">1</span></pre></div></td></tr><trid="section-14"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-14">¶</a></div><p>Generate the indentation tokens, based on another token on the same line.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">indentation: </span><spanclass="nf">(token, implicit = no) -></span>
<spanclass="p">[</span><spanclass="nx">indent</span><spanclass="p">,</span><spanclass="nx">outdent</span><spanclass="p">]</span></pre></div></td></tr><trid="section-15"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-15">¶</a></div><p>Create a generated token: one that exists due to a use of implicit syntax.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">generate: </span><spanclass="nf">(tag, value, line) -></span>
<spanclass="nx">tok</span></pre></div></td></tr><trid="section-16"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-16">¶</a></div><p>Look up a tag by token index.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">tag: </span><spanclass="nf">(i) -></span><spanclass="nx">@tokens</span><spanclass="p">[</span><spanclass="nx">i</span><spanclass="p">]</span><spanclass="o">?</span><spanclass="p">[</span><spanclass="mi">0</span><spanclass="p">]</span></pre></div></td></tr><trid="section-17"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-17">¶</a></div><h2>Constants</h2></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-18"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-18">¶</a></div><p>List of the token pairs that must be balanced.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">BALANCED_PAIRS = </span><spanclass="p">[</span>
<spanclass="p">]</span></pre></div></td></tr><trid="section-19"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-19">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">exports.INVERSES = INVERSES = </span><spanclass="p">{}</span></pre></div></td></tr><trid="section-20"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-20">¶</a></div><p>The tokens that signal the start/end of a balanced pair.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">EXPRESSION_START = </span><spanclass="p">[]</span>
<spanclass="nx">EXPRESSION_END</span><spanclass="p">.</span><spanclass="nx">push</span><spanclass="nx">INVERSES</span><spanclass="p">[</span><spanclass="nx">left</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="nx">rite</span></pre></div></td></tr><trid="section-21"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-21">¶</a></div><p>Tokens that indicate the close of a clause of an expression.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">EXPRESSION_CLOSE = </span><spanclass="p">[</span><spanclass="s1">'CATCH'</span><spanclass="p">,</span><spanclass="s1">'WHEN'</span><spanclass="p">,</span><spanclass="s1">'ELSE'</span><spanclass="p">,</span><spanclass="s1">'FINALLY'</span><spanclass="p">].</span><spanclass="nx">concat</span><spanclass="nx">EXPRESSION_END</span></pre></div></td></tr><trid="section-22"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-22">¶</a></div><p>Tokens that, if followed by an <code>IMPLICIT_CALL</code>, indicate a function invocation.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">IMPLICIT_FUNC = </span><spanclass="p">[</span><spanclass="s1">'IDENTIFIER'</span><spanclass="p">,</span><spanclass="s1">'SUPER'</span><spanclass="p">,</span><spanclass="s1">')'</span><spanclass="p">,</span><spanclass="s1">'CALL_END'</span><spanclass="p">,</span><spanclass="s1">']'</span><spanclass="p">,</span><spanclass="s1">'INDEX_END'</span><spanclass="p">,</span><spanclass="s1">'@'</span><spanclass="p">,</span><spanclass="s1">'THIS'</span><spanclass="p">]</span></pre></div></td></tr><trid="section-23"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-23">¶</a></div><p>If preceded by an <code>IMPLICIT_FUNC</code>, indicates a function invocation.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">IMPLICIT_CALL = </span><spanclass="p">[</span>
<spanclass="nv">IMPLICIT_UNSPACED_CALL = </span><spanclass="p">[</span><spanclass="s1">'+'</span><spanclass="p">,</span><spanclass="s1">'-'</span><spanclass="p">]</span></pre></div></td></tr><trid="section-24"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-24">¶</a></div><p>Tokens indicating that the implicit call must enclose a block of expressions.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">IMPLICIT_BLOCK = </span><spanclass="p">[</span><spanclass="s1">'->'</span><spanclass="p">,</span><spanclass="s1">'=>'</span><spanclass="p">,</span><spanclass="s1">'{'</span><spanclass="p">,</span><spanclass="s1">'['</span><spanclass="p">,</span><spanclass="s1">','</span><spanclass="p">]</span></pre></div></td></tr><trid="section-25"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-25">¶</a></div><p>Tokens that always mark the end of an implicit call for single-liners.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">IMPLICIT_END = </span><spanclass="p">[</span><spanclass="s1">'POST_IF'</span><spanclass="p">,</span><spanclass="s1">'FOR'</span><spanclass="p">,</span><spanclass="s1">'WHILE'</span><spanclass="p">,</span><spanclass="s1">'UNTIL'</span><spanclass="p">,</span><spanclass="s1">'WHEN'</span><spanclass="p">,</span><spanclass="s1">'BY'</span><spanclass="p">,</span><spanclass="s1">'LOOP'</span><spanclass="p">,</span><spanclass="s1">'TERMINATOR'</span><spanclass="p">]</span></pre></div></td></tr><trid="section-26"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-26">¶</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><tdclass="code"><divclass="highlight"><pre><spanclass="nv">SINGLE_LINERS = </span><spanclass="p">[</span><spanclass="s1">'ELSE'</span><spanclass="p">,</span><spanclass="s1">'->'</span><spanclass="p">,</span><spanclass="s1">'=>'</span><spanclass="p">,</span><spanclass="s1">'TRY'</span><spanclass="p">,</span><spanclass="s1">'FINALLY'</span><spanclass="p">,</span><spanclass="s1">'THEN'</span><spanclass="p">]</span>
<spanclass="nv">SINGLE_CLOSERS = </span><spanclass="p">[</span><spanclass="s1">'TERMINATOR'</span><spanclass="p">,</span><spanclass="s1">'CATCH'</span><spanclass="p">,</span><spanclass="s1">'FINALLY'</span><spanclass="p">,</span><spanclass="s1">'ELSE'</span><spanclass="p">,</span><spanclass="s1">'OUTDENT'</span><spanclass="p">,</span><spanclass="s1">'LEADING_WHEN'</span><spanclass="p">]</span></pre></div></td></tr><trid="section-27"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-27">¶</a></div><p>Tokens that end a line.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">LINEBREAKS = </span><spanclass="p">[</span><spanclass="s1">'TERMINATOR'</span><spanclass="p">,</span><spanclass="s1">'INDENT'</span><spanclass="p">,</span><spanclass="s1">'OUTDENT'</span><spanclass="p">]</span>
<!DOCTYPE html><html><head><title>scope.coffee</title><metahttp-equiv="content-type"content="text/html; charset=UTF-8"><linkrel="stylesheet"media="all"href="docco.css"/></head><body><divid="container"><divid="background"></div><divid="jump_to"> Jump To …<divid="jump_wrapper"><divid="jump_page"><aclass="source"href="browser.html"> browser.coffee </a><aclass="source"href="cake.html"> cake.coffee </a><aclass="source"href="coffee-script.html"> coffee-script.coffee </a><aclass="source"href="command.html"> command.coffee </a><aclass="source"href="grammar.html"> grammar.coffee </a><aclass="source"href="helpers.html"> helpers.coffee </a><aclass="source"href="index.html"> index.coffee </a><aclass="source"href="lexer.html"> lexer.coffee </a><aclass="source"href="nodes.html"> nodes.coffee </a><aclass="source"href="optparse.html"> optparse.coffee </a><aclass="source"href="repl.html"> repl.coffee </a><aclass="source"href="rewriter.html"> rewriter.coffee </a><aclass="source"href="scope.html"> scope.coffee </a></div></div></div><tablecellpadding="0"cellspacing="0"><thead><tr><thclass="docs"><h1> scope.coffee </h1></th><thclass="code"></th></tr></thead><tbody><trid="section-1"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-1">¶</a></div><p>The <strong>Scope</strong> class regulates lexical scoping within CoffeeScript. As you
generate code, you create a tree of scopes in the same shape as the nested
function bodies. Each scope knows about the variables declared within it,
and has a reference to its parent enclosing scope. In this way, we know which
variables are new and need to be declared with <code>var</code>, and which are shared
with the outside.</p></td><tdclass="code"><divclass="highlight"><pre></pre></div></td></tr><trid="section-2"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-2">¶</a></div><p>Import the helpers we plan to use.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="p">{</span><spanclass="nx">extend</span><spanclass="p">,</span><spanclass="nx">last</span><spanclass="p">}</span><spanclass="o">=</span><spanclass="nx">require</span><spanclass="s1">'./helpers'</span>
<spanclass="nv">exports.Scope = </span><spanclass="k">class</span><spanclass="nx">Scope</span></pre></div></td></tr><trid="section-3"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-3">¶</a></div><p>The top-level <strong>Scope</strong> object.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="vi">@root: </span><spanclass="kc">null</span></pre></div></td></tr><trid="section-4"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-4">¶</a></div><p>Initialize a scope with its parent, for lookups up the chain,
as well as a reference to the <strong>Block</strong> node it belongs to, which is
where it should declare its variables, and a reference to the function that
it wraps.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">constructor: </span><spanclass="nf">(@parent, @expressions, @method) -></span>
<spanclass="nv">Scope.root = </span><spanclass="k">this</span><spanclass="nx">unless</span><spanclass="nx">@parent</span></pre></div></td></tr><trid="section-5"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-5">¶</a></div><p>Adds a new variable or overrides an existing one.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">add: </span><spanclass="nf">(name, type, immediate) -></span>
<spanclass="nx">@positions</span><spanclass="p">[</span><spanclass="nx">name</span><spanclass="p">]</span><spanclass="o">=</span><spanclass="nx">@variables</span><spanclass="p">.</span><spanclass="nx">push</span><spanclass="p">({</span><spanclass="nx">name</span><spanclass="p">,</span><spanclass="nx">type</span><spanclass="p">})</span><spanclass="o">-</span><spanclass="mi">1</span></pre></div></td></tr><trid="section-6"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-6">¶</a></div><p>When <code>super</code> is called, we need to find the name of the current method we're
in, so that we know how to invoke the same method of the parent class. This
can get complicated if super is being called from an inner function.
<code>namedMethod</code> will walk up the scope tree until it either finds the first
function object that has a name filled in, or bottoms out.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">namedMethod: </span><spanclass="o">-></span>
<spanclass="nx">@parent</span><spanclass="p">.</span><spanclass="nx">namedMethod</span><spanclass="p">()</span></pre></div></td></tr><trid="section-7"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-7">¶</a></div><p>Look up a variable name in lexical scope, and declare it if it does not
<spanclass="kc">no</span></pre></div></td></tr><trid="section-8"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-8">¶</a></div><p>Reserve a variable name as originating from a function parameter for this
scope. No <code>var</code> required for internal references.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">parameter: </span><spanclass="nf">(name) -></span>
<spanclass="nx">@add</span><spanclass="nx">name</span><spanclass="p">,</span><spanclass="s1">'param'</span></pre></div></td></tr><trid="section-9"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-9">¶</a></div><p>Just check to see if a variable has already been declared, without reserving,
walks up to the root scope.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">check: </span><spanclass="nf">(name) -></span>
<spanclass="o">!!</span><spanclass="p">(</span><spanclass="nx">@type</span><spanclass="p">(</span><spanclass="nx">name</span><spanclass="p">)</span><spanclass="o">or</span><spanclass="nx">@parent</span><spanclass="o">?</span><spanclass="p">.</span><spanclass="nx">check</span><spanclass="p">(</span><spanclass="nx">name</span><spanclass="p">))</span></pre></div></td></tr><trid="section-10"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-10">¶</a></div><p>Generate a temporary variable name at the given index.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">temporary: </span><spanclass="nf">(name, index) -></span>
<spanclass="s1">'_'</span><spanclass="o">+</span><spanclass="p">(</span><spanclass="nx">index</span><spanclass="o">+</span><spanclass="nb">parseInt</span><spanclass="nx">name</span><spanclass="p">,</span><spanclass="mi">36</span><spanclass="p">).</span><spanclass="nx">toString</span><spanclass="p">(</span><spanclass="mi">36</span><spanclass="p">).</span><spanclass="nx">replace</span><spanclass="sr">/\d/g</span><spanclass="p">,</span><spanclass="s1">'a'</span></pre></div></td></tr><trid="section-11"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-11">¶</a></div><p>Gets the type of a variable.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">type: </span><spanclass="nf">(name) -></span>
<spanclass="kc">null</span></pre></div></td></tr><trid="section-12"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-12">¶</a></div><p>If we need to store an intermediate result, find an available name for a
compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on...</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">freeVariable: </span><spanclass="nf">(name, reserve=true) -></span>
<spanclass="nx">temp</span></pre></div></td></tr><trid="section-13"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-13">¶</a></div><p>Ensure that an assignment is made at the top of this scope
(or at the top-level scope, if requested).</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">assign: </span><spanclass="nf">(name, value) -></span>
<spanclass="vi">@hasAssignments = </span><spanclass="kc">yes</span></pre></div></td></tr><trid="section-14"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-14">¶</a></div><p>Does this scope have any declared variables?</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">hasDeclarations: </span><spanclass="o">-></span>
<spanclass="o">!!</span><spanclass="nx">@declaredVariables</span><spanclass="p">().</span><spanclass="nx">length</span></pre></div></td></tr><trid="section-15"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-15">¶</a></div><p>Return the list of variables first declared in this scope.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">declaredVariables: </span><spanclass="o">-></span>
<spanclass="nx">realVars</span><spanclass="p">.</span><spanclass="nx">sort</span><spanclass="p">().</span><spanclass="nx">concat</span><spanclass="nx">tempVars</span><spanclass="p">.</span><spanclass="nx">sort</span><spanclass="p">()</span></pre></div></td></tr><trid="section-16"><tdclass="docs"><divclass="pilwrap"><aclass="pilcrow"href="#section-16">¶</a></div><p>Return the list of assignments that are supposed to be made at the top
of this scope.</p></td><tdclass="code"><divclass="highlight"><pre><spanclass="nv">assignedVariables: </span><spanclass="o">-></span>
sentence=""+(22/7)+" is a decent approximation of π";
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.