mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 17:27:59 -05:00
Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
533ad8afe9 | ||
|
|
1961f06e08 | ||
|
|
4503e2716e | ||
|
|
e4d81005be | ||
|
|
b6012c4617 | ||
|
|
feee6954a6 | ||
|
|
fea058c53a | ||
|
|
25d97aa136 | ||
|
|
7c8849cc21 | ||
|
|
b362bd672c | ||
|
|
a4f510501c | ||
|
|
e3f6e19950 | ||
|
|
b49b41320e | ||
|
|
6bc3157793 | ||
|
|
dc8a2b17d0 | ||
|
|
c3ae2328af | ||
|
|
57846ea5c0 | ||
|
|
3da88b9b3f | ||
|
|
8130e63e43 | ||
|
|
dc44ebbdaa | ||
|
|
88ad059d54 | ||
|
|
76c076db55 | ||
|
|
5698e6c72a | ||
|
|
e0e4967ad8 | ||
|
|
53c7891599 | ||
|
|
94a17cb74a | ||
|
|
5d139596f8 | ||
|
|
213225418a | ||
|
|
3b3e52097a | ||
|
|
72ceec5680 | ||
|
|
5a220d4e13 | ||
|
|
92e5ab2857 | ||
|
|
64632e3332 | ||
|
|
c0e1f23f23 | ||
|
|
ee8f889cbd | ||
|
|
ffa25aae77 | ||
|
|
04b30a6cc4 | ||
|
|
996a171a4e | ||
|
|
17a271af06 | ||
|
|
f8c366c479 | ||
|
|
934bd2acc7 | ||
|
|
dd0ec84ebe | ||
|
|
e9a372dff5 | ||
|
|
4d7a0d2470 | ||
|
|
c2abe253a1 | ||
|
|
3ddd3115eb | ||
|
|
a3096eab91 | ||
|
|
3fd004b852 | ||
|
|
0a9c7a3257 | ||
|
|
f7692c92ce | ||
|
|
cdf69eb5bc | ||
|
|
9aeecf582b | ||
|
|
e0ec8a51e4 | ||
|
|
a62e49311e | ||
|
|
9a38486d08 | ||
|
|
06e8be5d94 | ||
|
|
90a1cbac49 | ||
|
|
3d58b4cda1 | ||
|
|
2f0724f0ad | ||
|
|
f288d20409 | ||
|
|
dca915af60 | ||
|
|
54a4560340 | ||
|
|
518d7c16b7 | ||
|
|
8ed691e266 | ||
|
|
74fc7128ab | ||
|
|
68c0e2dc0f | ||
|
|
42dde38842 | ||
|
|
7d6f6174d5 | ||
|
|
05b3707506 | ||
|
|
5d1d1b7999 | ||
|
|
3db029f2c1 | ||
|
|
67aaa8b57f | ||
|
|
28c07d30cb | ||
|
|
fce502ac98 | ||
|
|
669e7fed10 | ||
|
|
4bf45ff894 | ||
|
|
4c2c472e07 | ||
|
|
22f19522ff | ||
|
|
9fa77af576 | ||
|
|
efd7ebb066 | ||
|
|
62712060c0 | ||
|
|
a46978640b | ||
|
|
8ab15d7372 | ||
|
|
23a691ae87 | ||
|
|
bec8f27e8a | ||
|
|
ac2e540e1b | ||
|
|
e0ad0d795d | ||
|
|
a63009fccb | ||
|
|
8fd6258a46 | ||
|
|
24398774fc | ||
|
|
e769423d52 | ||
|
|
9ec427ba80 | ||
|
|
c478f283f4 | ||
|
|
8e299b09cc | ||
|
|
b70f6571bd | ||
|
|
ae6df88c5c | ||
|
|
0dcff507fb | ||
|
|
8e4fb1b937 | ||
|
|
931b74e449 | ||
|
|
4199f4f325 | ||
|
|
5950d6328d | ||
|
|
a9fbf14adf | ||
|
|
485aa8efcf | ||
|
|
a563e8f8fe | ||
|
|
4035e7caab | ||
|
|
2c6e6ca870 | ||
|
|
f2a3f7507e | ||
|
|
4f82e5912e | ||
|
|
dd5da7f5f2 | ||
|
|
ec44aba71a | ||
|
|
e8a4e93a72 | ||
|
|
158ca0d869 | ||
|
|
a78cbe78a1 | ||
|
|
77d5b95260 | ||
|
|
55e3b6b3c3 | ||
|
|
efca2861a6 | ||
|
|
781ea22d57 | ||
|
|
437b9ed65c | ||
|
|
c72556619f | ||
|
|
565d78f00b | ||
|
|
75900660fd | ||
|
|
b407a59baf | ||
|
|
9dfd71b0e4 | ||
|
|
872092f6de | ||
|
|
8b066f125d | ||
|
|
94c467b520 | ||
|
|
53aa50f785 | ||
|
|
e8c96de269 | ||
|
|
1157b32413 | ||
|
|
ba4157b5e2 | ||
|
|
6ae21ae461 | ||
|
|
f375394381 | ||
|
|
1e377ed59b | ||
|
|
64e78a2bec | ||
|
|
25b1eee293 | ||
|
|
dab4ae9416 | ||
|
|
56b04a58dc | ||
|
|
e1000205fd | ||
|
|
c02a403f2e | ||
|
|
f4b850d59c | ||
|
|
85c7fffd1a | ||
|
|
9d29a830df | ||
|
|
74a92db173 | ||
|
|
d712a6c0f4 | ||
|
|
7906a2b6c1 | ||
|
|
f11ca9888f | ||
|
|
9941050120 | ||
|
|
dafc7bdea5 | ||
|
|
f51cbd7117 |
6
Cakefile
6
Cakefile
@@ -276,6 +276,12 @@ runTests = (CoffeeScript) ->
|
||||
|
||||
# Run every test in the `test` folder, recording failures.
|
||||
files = fs.readdirSync 'test'
|
||||
|
||||
# Ignore generators test file if generators are not available
|
||||
generatorsAreAvailable = '--harmony' in process.execArgv or
|
||||
'--harmony-generators' in process.execArgv
|
||||
files.splice files.indexOf('generators.coffee'), 1 if not generatorsAreAvailable
|
||||
|
||||
for file in files when helpers.isCoffee file
|
||||
literate = helpers.isLiterate file
|
||||
currentFile = filename = path.join 'test', file
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2009-2014 Jeremy Ashkenas
|
||||
Copyright (c) 2009-2015 Jeremy Ashkenas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
||||
27
bower.json
Normal file
27
bower.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "coffee-script",
|
||||
"version": "1.9.1",
|
||||
"main": [
|
||||
"lib/coffee-script/coffee-script.js"
|
||||
],
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": [
|
||||
"javascript",
|
||||
"language",
|
||||
"coffeescript",
|
||||
"compiler"
|
||||
],
|
||||
"devDependencies": {
|
||||
"uglify-js": "~2.2",
|
||||
"jison": ">=0.2.0",
|
||||
"highlight.js": "~8.0.0",
|
||||
"underscore": "~1.5.2",
|
||||
"docco": "~0.6.2"
|
||||
},
|
||||
"author": {
|
||||
"name": "Jeremy Ashkenas"
|
||||
},
|
||||
"ignore": [
|
||||
"test"
|
||||
]
|
||||
}
|
||||
8
documentation/coffee/generators.coffee
Normal file
8
documentation/coffee/generators.coffee
Normal file
@@ -0,0 +1,8 @@
|
||||
perfectSquares = ->
|
||||
num = 0
|
||||
loop
|
||||
num += 1
|
||||
yield num * num
|
||||
return
|
||||
|
||||
window.ps or= perfectSquares()
|
||||
@@ -144,7 +144,7 @@ SourceMap = <span class="hljs-built_in">require</span> <span class="hljs-str
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.VERSION = <span class="hljs-string">'1.8.0'</span>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.VERSION = <span class="hljs-string">'1.9.1'</span>
|
||||
|
||||
<span class="hljs-built_in">exports</span>.FILE_EXTENSIONS = [<span class="hljs-string">'.coffee'</span>, <span class="hljs-string">'.litcoffee'</span>, <span class="hljs-string">'.coffee.md'</span>]</pre></div></div>
|
||||
|
||||
@@ -210,7 +210,27 @@ lookups.</p>
|
||||
<span class="hljs-keyword">if</span> options.sourceMap
|
||||
map = <span class="hljs-keyword">new</span> SourceMap
|
||||
|
||||
fragments = parser.parse(lexer.tokenize code, options).compileToFragments options
|
||||
tokens = lexer.tokenize code, options</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-6">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
</div>
|
||||
<p>Pass a list of referenced variables, so that generated variables won’t get
|
||||
the same name.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> options.referencedVars = (
|
||||
token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.variable
|
||||
)
|
||||
|
||||
fragments = parser.parse(tokens).compileToFragments options
|
||||
|
||||
currentLine = <span class="hljs-number">0</span>
|
||||
currentLine += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> options.header
|
||||
@@ -222,11 +242,11 @@ lookups.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-6">
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
</div>
|
||||
<p>Update the sourcemap with data from each fragment</p>
|
||||
|
||||
@@ -248,11 +268,11 @@ lookups.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-7">
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
</div>
|
||||
<p>Copy the code from each fragment into the final JavaScript.</p>
|
||||
|
||||
@@ -275,11 +295,11 @@ lookups.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-8">
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
</div>
|
||||
<p>Tokenize a string of CoffeeScript code, and return the array of tokens.</p>
|
||||
|
||||
@@ -291,11 +311,11 @@ lookups.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-9">
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<a class="pilcrow" href="#section-10">¶</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,
|
||||
@@ -312,11 +332,11 @@ or traverse it by using <code>.traverseChildren()</code> with a callback.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-10">
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
</div>
|
||||
<p>Compile and execute a string of CoffeeScript (on the server), correctly
|
||||
setting <code>__filename</code>, <code>__dirname</code>, and relative <code>require()</code>.</p>
|
||||
@@ -329,11 +349,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-11">
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
</div>
|
||||
<p>Set the filename.</p>
|
||||
|
||||
@@ -345,11 +365,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-12">
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
</div>
|
||||
<p>Clear the module cache.</p>
|
||||
|
||||
@@ -360,11 +380,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-13">
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
</div>
|
||||
<p>Assign paths for node_modules loading</p>
|
||||
|
||||
@@ -379,11 +399,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-14">
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
</div>
|
||||
<p>Compile.</p>
|
||||
|
||||
@@ -398,11 +418,11 @@ setting <code>__filename</code>, <code>__dirname</code>, and relative <code>requ
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-15">
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</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>
|
||||
@@ -411,13 +431,17 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.<span class="hljs-function"><span class="hljs-title">eval</span> = <span class="hljs-params">(code, options = {})</span> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-keyword">unless</span> code = code.trim()
|
||||
Script = vm.Script
|
||||
<span class="hljs-keyword">if</span> Script
|
||||
createContext = vm.Script.createContext ? vm.createContext
|
||||
|
||||
isContext = vm.isContext ? <span class="hljs-function"><span class="hljs-params">(ctx)</span> -></span>
|
||||
options.sandbox <span class="hljs-keyword">instanceof</span> createContext().constructor
|
||||
|
||||
<span class="hljs-keyword">if</span> createContext
|
||||
<span class="hljs-keyword">if</span> options.sandbox?
|
||||
<span class="hljs-keyword">if</span> options.sandbox <span class="hljs-keyword">instanceof</span> Script.createContext().constructor
|
||||
<span class="hljs-keyword">if</span> isContext options.sandbox
|
||||
sandbox = options.sandbox
|
||||
<span class="hljs-keyword">else</span>
|
||||
sandbox = Script.createContext()
|
||||
sandbox = createContext()
|
||||
sandbox[k] = v <span class="hljs-keyword">for</span> own k, v <span class="hljs-keyword">of</span> options.sandbox
|
||||
sandbox.<span class="hljs-built_in">global</span> = sandbox.root = sandbox.GLOBAL = sandbox
|
||||
<span class="hljs-keyword">else</span>
|
||||
@@ -428,11 +452,11 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-16">
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>define module/require only if they chose not to specify their own</p>
|
||||
|
||||
@@ -448,11 +472,11 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
</div>
|
||||
<p>use the same hack node currently uses for their own REPL</p>
|
||||
|
||||
@@ -474,11 +498,11 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
</div>
|
||||
<p>Throw error with deprecation warning when depending upon implicit <code>require.extensions</code> registration</p>
|
||||
|
||||
@@ -502,11 +526,11 @@ The CoffeeScript REPL uses this to run the input.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
</div>
|
||||
<p>As the filename and code of a dynamically loaded file will be different
|
||||
from the original file compiled with CoffeeScript.run, add that
|
||||
@@ -521,11 +545,11 @@ information to error so it can be pretty-printed later.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
</div>
|
||||
<p>Instantiate a Lexer for our use here.</p>
|
||||
|
||||
@@ -536,11 +560,11 @@ information to error so it can be pretty-printed later.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</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
|
||||
@@ -550,16 +574,17 @@ directly as a “Jison lexer”.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>parser.lexer =
|
||||
<span class="hljs-attribute">lex</span>:<span class="hljs-function"> -></span>
|
||||
token = <span class="hljs-property">@tokens</span>[<span class="hljs-property">@pos</span>++]
|
||||
token = parser.tokens[<span class="hljs-property">@pos</span>++]
|
||||
<span class="hljs-keyword">if</span> token
|
||||
[tag, <span class="hljs-property">@yytext</span>, <span class="hljs-property">@yylloc</span>] = token
|
||||
<span class="hljs-property">@errorToken</span> = token.origin <span class="hljs-keyword">or</span> token
|
||||
parser.errorToken = token.origin <span class="hljs-keyword">or</span> token
|
||||
<span class="hljs-property">@yylineno</span> = <span class="hljs-property">@yylloc</span>.first_line
|
||||
<span class="hljs-keyword">else</span>
|
||||
tag = <span class="hljs-string">''</span>
|
||||
|
||||
tag
|
||||
<span class="hljs-attribute">setInput</span>: <span class="hljs-function"><span class="hljs-params">(<span class="hljs-property">@tokens</span>)</span> -></span>
|
||||
<span class="hljs-attribute">setInput</span>: <span class="hljs-function"><span class="hljs-params">(tokens)</span> -></span>
|
||||
parser.tokens = tokens
|
||||
<span class="hljs-property">@pos</span> = <span class="hljs-number">0</span>
|
||||
<span class="hljs-attribute">upcomingInput</span>:<span class="hljs-function"> -></span>
|
||||
<span class="hljs-string">""</span></pre></div></div>
|
||||
@@ -567,32 +592,17 @@ directly as a “Jison lexer”.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
</div>
|
||||
<p>Make all the AST nodes visible to the parser.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>parser.yy = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
</div>
|
||||
<p>Override Jison’s default error handling function.</p>
|
||||
<p>Make all the AST nodes visible to the parser.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>parser.yy.<span class="hljs-function"><span class="hljs-title">parseError</span> = <span class="hljs-params">(message, {token})</span> -></span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>parser.yy = <span class="hljs-built_in">require</span> <span class="hljs-string">'./nodes'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -603,21 +613,11 @@ directly as a “Jison lexer”.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
</div>
|
||||
<p>Disregard Jison’s message, it contains redundant line numer information.
|
||||
Disregard the token, we take its value directly from the lexer in case
|
||||
the error is caused by a generated token which might refer to its origin.</p>
|
||||
<p>Override Jison’s default error handling function.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> {errorToken, tokens} = parser.lexer
|
||||
[errorTag, errorText, errorLoc] = errorToken
|
||||
|
||||
errorText = <span class="hljs-keyword">if</span> errorToken <span class="hljs-keyword">is</span> tokens[tokens.length - <span class="hljs-number">1</span>]
|
||||
<span class="hljs-string">'end of input'</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> errorTag <span class="hljs-keyword">in</span> [<span class="hljs-string">'INDENT'</span>, <span class="hljs-string">'OUTDENT'</span>]
|
||||
<span class="hljs-string">'indentation'</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
helpers.nameWhitespaceCharacter errorText</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre>parser.yy.<span class="hljs-function"><span class="hljs-title">parseError</span> = <span class="hljs-params">(message, {token})</span> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -628,6 +628,34 @@ the error is caused by a generated token which might refer to its origin.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
</div>
|
||||
<p>Disregard Jison’s message, it contains redundant line numer information.
|
||||
Disregard the token, we take its value directly from the lexer in case
|
||||
the error is caused by a generated token which might refer to its origin.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> {errorToken, tokens} = parser
|
||||
[errorTag, errorText, errorLoc] = errorToken
|
||||
|
||||
errorText = <span class="hljs-keyword">switch</span>
|
||||
<span class="hljs-keyword">when</span> errorToken <span class="hljs-keyword">is</span> tokens[tokens.length - <span class="hljs-number">1</span>]
|
||||
<span class="hljs-string">'end of input'</span>
|
||||
<span class="hljs-keyword">when</span> errorTag <span class="hljs-keyword">in</span> [<span class="hljs-string">'INDENT'</span>, <span class="hljs-string">'OUTDENT'</span>]
|
||||
<span class="hljs-string">'indentation'</span>
|
||||
<span class="hljs-keyword">when</span> errorTag <span class="hljs-keyword">in</span> [<span class="hljs-string">'IDENTIFIER'</span>, <span class="hljs-string">'NUMBER'</span>, <span class="hljs-string">'STRING'</span>, <span class="hljs-string">'STRING_START'</span>, <span class="hljs-string">'REGEX'</span>, <span class="hljs-string">'REGEX_START'</span>]
|
||||
errorTag.replace(<span class="hljs-regexp">/_START$/</span>, <span class="hljs-string">''</span>).toLowerCase()
|
||||
<span class="hljs-keyword">else</span>
|
||||
helpers.nameWhitespaceCharacter errorText</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
</div>
|
||||
<p>The second argument has a <code>loc</code> property, which should have the location
|
||||
data for this token. Unfortunately, Jison seems to send an outdated <code>loc</code>
|
||||
(from the previous token), so we take the location information directly
|
||||
@@ -640,11 +668,11 @@ from the lexer.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-26">
|
||||
<li id="section-27">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
</div>
|
||||
<p>Based on <a href="http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js">http://v8.googlecode.com/svn/branches/bleeding_edge/src/messages.js</a>
|
||||
Modified to handle sourceMap</p>
|
||||
@@ -672,11 +700,11 @@ Modified to handle sourceMap</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-27">
|
||||
<li id="section-28">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-27">¶</a>
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
</div>
|
||||
<p>Check for a sourceMap position</p>
|
||||
|
||||
@@ -717,11 +745,11 @@ Modified to handle sourceMap</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-28">
|
||||
<li id="section-29">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-28">¶</a>
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
</div>
|
||||
<p>Map of filenames -> sourceMap object.</p>
|
||||
|
||||
@@ -732,11 +760,11 @@ Modified to handle sourceMap</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-29">
|
||||
<li id="section-30">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-29">¶</a>
|
||||
<a class="pilcrow" href="#section-30">¶</a>
|
||||
</div>
|
||||
<p>Generates the source map for a coffee file and stores it in the local cache variable.</p>
|
||||
|
||||
@@ -751,11 +779,11 @@ Modified to handle sourceMap</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-30">
|
||||
<li id="section-31">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-30">¶</a>
|
||||
<a class="pilcrow" href="#section-31">¶</a>
|
||||
</div>
|
||||
<p>Based on <a href="http://goo.gl/ZTx1p">michaelficarra/CoffeeScriptRedux</a>
|
||||
NodeJS / V8 have no support for transforming positions in stack traces using
|
||||
|
||||
@@ -141,7 +141,6 @@ path = <span class="hljs-built_in">require</span> <span class="hljs-st
|
||||
helpers = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
optparse = <span class="hljs-built_in">require</span> <span class="hljs-string">'./optparse'</span>
|
||||
CoffeeScript = <span class="hljs-built_in">require</span> <span class="hljs-string">'./coffee-script'</span>
|
||||
mkdirp = <span class="hljs-built_in">require</span> <span class="hljs-string">'mkdirp'</span>
|
||||
{spawn, exec} = <span class="hljs-built_in">require</span> <span class="hljs-string">'child_process'</span>
|
||||
{EventEmitter} = <span class="hljs-built_in">require</span> <span class="hljs-string">'events'</span>
|
||||
|
||||
@@ -237,7 +236,8 @@ sources = []
|
||||
sourceCode = []
|
||||
notSources = {}
|
||||
watchedDirs = {}
|
||||
optionParser = <span class="hljs-literal">null</span></pre></div></div>
|
||||
optionParser = <span class="hljs-literal">null</span>
|
||||
jsToSources = {}</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -639,6 +639,32 @@ the compiled JS version as well.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>Recursively mkdir, like <code>mkdir -p</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">mkdirp</span> = <span class="hljs-params">(dir, fn)</span> -></span>
|
||||
mode = <span class="hljs-number">0</span>o777 & ~process.umask()
|
||||
|
||||
<span class="hljs-keyword">do</span> <span class="hljs-function"><span class="hljs-title">mkdirs</span> = <span class="hljs-params">(p = dir, fn)</span> -></span>
|
||||
fs.exists p, <span class="hljs-function"><span class="hljs-params">(exists)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> exists
|
||||
fn()
|
||||
<span class="hljs-keyword">else</span>
|
||||
mkdirs path.dirname(p),<span class="hljs-function"> -></span>
|
||||
fs.mkdir p, mode, <span class="hljs-function"><span class="hljs-params">(err)</span> -></span>
|
||||
<span class="hljs-keyword">return</span> fn err <span class="hljs-keyword">if</span> err
|
||||
fn()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</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>
|
||||
@@ -650,6 +676,12 @@ same directory as the <code>.js</code> file.</p>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">writeJs</span> = <span class="hljs-params">(base, sourcePath, js, jsPath, generatedSourceMap = <span class="hljs-literal">null</span>)</span> -></span>
|
||||
sourceMapPath = outputPath sourcePath, base, <span class="hljs-string">".js.map"</span>
|
||||
jsDir = path.dirname jsPath
|
||||
<span class="hljs-keyword">if</span> jsPath <span class="hljs-keyword">of</span> jsToSources
|
||||
printLine <span class="hljs-string">"Error: The two following source files have the same output file:"</span>
|
||||
printLine <span class="hljs-string">" "</span> + jsToSources[jsPath]
|
||||
printLine <span class="hljs-string">" "</span> + sourcePath
|
||||
process.exit <span class="hljs-number">1</span>
|
||||
jsToSources[jsPath] = sourcePath
|
||||
<span class="hljs-function"><span class="hljs-title">compile</span> = -></span>
|
||||
<span class="hljs-keyword">if</span> opts.compile
|
||||
js = <span class="hljs-string">' '</span> <span class="hljs-keyword">if</span> js.length <= <span class="hljs-number">0</span>
|
||||
@@ -671,11 +703,11 @@ same directory as the <code>.js</code> file.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
</div>
|
||||
<p>Convenience for cleaner setTimeouts.</p>
|
||||
|
||||
@@ -686,11 +718,11 @@ same directory as the <code>.js</code> file.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
</div>
|
||||
<p>When watching scripts, it’s useful to log changes with the timestamp.</p>
|
||||
|
||||
@@ -702,11 +734,11 @@ same directory as the <code>.js</code> file.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
</div>
|
||||
<p>Pretty-print a stream of tokens, sans location data.</p>
|
||||
|
||||
@@ -722,11 +754,11 @@ same directory as the <code>.js</code> file.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
</div>
|
||||
<p>Use the <a href="optparse.html">OptionParser module</a> to extract all options from
|
||||
<code>process.argv</code> that are specified in <code>SWITCHES</code>.</p>
|
||||
@@ -743,11 +775,11 @@ same directory as the <code>.js</code> file.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-22">
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
</div>
|
||||
<p>The compile-time options to pass to the CoffeeScript compiler.</p>
|
||||
|
||||
@@ -782,11 +814,11 @@ same directory as the <code>.js</code> file.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-23">
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<a class="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>
|
||||
@@ -806,11 +838,11 @@ the <code>node</code> binary, preserving the other options.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-24">
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
</div>
|
||||
<p>Print the <code>--help</code> usage message and exit. Deprecated switches are not
|
||||
shown.</p>
|
||||
@@ -823,11 +855,11 @@ shown.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-25">
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
</div>
|
||||
<p>Print the <code>--version</code> message and exit.</p>
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'novecento-bold';
|
||||
src: url('public/fonts/novecento-bold.eot');
|
||||
src: url('public/fonts/novecento-bold.eot?#iefix') format('embedded-opentype'),
|
||||
url('public/fonts/novecento-bold.woff') format('woff'),
|
||||
url('public/fonts/novecento-bold.ttf') format('truetype');
|
||||
font-family: 'roboto-black';
|
||||
src: url('public/fonts/roboto-black.eot');
|
||||
src: url('public/fonts/roboto-black.eot?#iefix') format('embedded-opentype'),
|
||||
url('public/fonts/roboto-black.woff') format('woff'),
|
||||
url('public/fonts/roboto-black.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ h1, h2, h3, h4, h5, h6 {
|
||||
color: #112233;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
font-family: "novecento-bold";
|
||||
font-family: "roboto-black";
|
||||
text-transform: uppercase;
|
||||
margin: 30px 0 15px 0;
|
||||
}
|
||||
@@ -75,6 +75,9 @@ h1, h2, h3, h4, h5, h6 {
|
||||
h1 {
|
||||
margin-top: 40px;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.26em;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
|
||||
@@ -460,7 +460,17 @@ they can also serve as keys in object literals.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">AlphaNumeric</span>: [
|
||||
o <span class="hljs-string">'NUMBER'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'String'</span>
|
||||
]
|
||||
|
||||
<span class="hljs-attribute">String</span>: [
|
||||
o <span class="hljs-string">'STRING'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'STRING_START Body STRING_END'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Parens $<span class="hljs-number">2</span>
|
||||
]
|
||||
|
||||
<span class="hljs-attribute">Regex</span>: [
|
||||
o <span class="hljs-string">'REGEX'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'REGEX_START Invocation REGEX_END'</span>,<span class="hljs-function"> -></span> $<span class="hljs-number">2</span>
|
||||
]</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -480,7 +490,7 @@ through and printed to JavaScript.</p>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">Literal</span>: [
|
||||
o <span class="hljs-string">'AlphaNumeric'</span>
|
||||
o <span class="hljs-string">'JS'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'REGEX'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'Regex'</span>
|
||||
o <span class="hljs-string">'DEBUGGER'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Literal $<span class="hljs-number">1</span>
|
||||
o <span class="hljs-string">'UNDEFINED'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Undefined
|
||||
o <span class="hljs-string">'NULL'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Null
|
||||
@@ -1247,7 +1257,8 @@ or postfix, with a single expression.</p>
|
||||
]
|
||||
|
||||
<span class="hljs-attribute">ForBody</span>: [
|
||||
o <span class="hljs-string">'FOR Range'</span>,<span class="hljs-function"> -></span> <span class="hljs-attribute">source</span>: LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>)
|
||||
o <span class="hljs-string">'FOR Range'</span>,<span class="hljs-function"> -></span> <span class="hljs-attribute">source</span>: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>))
|
||||
o <span class="hljs-string">'FOR Range BY Expression'</span>,<span class="hljs-function"> -></span> <span class="hljs-attribute">source</span>: (LOC(<span class="hljs-number">2</span>) <span class="hljs-keyword">new</span> Value($<span class="hljs-number">2</span>)), <span class="hljs-attribute">step</span>: $<span class="hljs-number">4</span>
|
||||
o <span class="hljs-string">'ForStart ForSource'</span>,<span class="hljs-function"> -></span> $<span class="hljs-number">2.</span>own = $<span class="hljs-number">1.</span>own; $<span class="hljs-number">2.</span>name = $<span class="hljs-number">1</span>[<span class="hljs-number">0</span>]; $<span class="hljs-number">2.</span>index = $<span class="hljs-number">1</span>[<span class="hljs-number">1</span>]; $<span class="hljs-number">2</span>
|
||||
]
|
||||
|
||||
@@ -1416,6 +1427,9 @@ rules are necessary.</p>
|
||||
o <span class="hljs-string">'UNARY_MATH Expression'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Op $<span class="hljs-number">1</span> , $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'- Expression'</span>, (<span class="hljs-function">-></span> <span class="hljs-keyword">new</span> Op <span class="hljs-string">'-'</span>, $<span class="hljs-number">2</span>), <span class="hljs-attribute">prec</span>: <span class="hljs-string">'UNARY_MATH'</span>
|
||||
o <span class="hljs-string">'+ Expression'</span>, (<span class="hljs-function">-></span> <span class="hljs-keyword">new</span> Op <span class="hljs-string">'+'</span>, $<span class="hljs-number">2</span>), <span class="hljs-attribute">prec</span>: <span class="hljs-string">'UNARY_MATH'</span>
|
||||
o <span class="hljs-string">'YIELD Statement'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Op $<span class="hljs-number">1</span> , $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'YIELD Expression'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Op $<span class="hljs-number">1</span> , $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'YIELD FROM Expression'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Op $<span class="hljs-number">1.</span>concat($<span class="hljs-number">2</span>) , $<span class="hljs-number">3</span>
|
||||
|
||||
o <span class="hljs-string">'-- SimpleAssignable'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Op <span class="hljs-string">'--'</span>, $<span class="hljs-number">2</span>
|
||||
o <span class="hljs-string">'++ SimpleAssignable'</span>,<span class="hljs-function"> -></span> <span class="hljs-keyword">new</span> Op <span class="hljs-string">'++'</span>, $<span class="hljs-number">2</span>
|
||||
@@ -1517,6 +1531,7 @@ down. Following these rules is what makes <code>2 + 3 * 4</code> parse as:</p>
|
||||
[<span class="hljs-string">'left'</span>, <span class="hljs-string">'COMPARE'</span>]
|
||||
[<span class="hljs-string">'left'</span>, <span class="hljs-string">'LOGIC'</span>]
|
||||
[<span class="hljs-string">'nonassoc'</span>, <span class="hljs-string">'INDENT'</span>, <span class="hljs-string">'OUTDENT'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'YIELD'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'='</span>, <span class="hljs-string">':'</span>, <span class="hljs-string">'COMPOUND_ASSIGN'</span>, <span class="hljs-string">'RETURN'</span>, <span class="hljs-string">'THROW'</span>, <span class="hljs-string">'EXTENDS'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'FORIN'</span>, <span class="hljs-string">'FOROF'</span>, <span class="hljs-string">'BY'</span>, <span class="hljs-string">'WHEN'</span>]
|
||||
[<span class="hljs-string">'right'</span>, <span class="hljs-string">'IF'</span>, <span class="hljs-string">'ELSE'</span>, <span class="hljs-string">'FOR'</span>, <span class="hljs-string">'WHILE'</span>, <span class="hljs-string">'UNTIL'</span>, <span class="hljs-string">'LOOP'</span>, <span class="hljs-string">'SUPER'</span>, <span class="hljs-string">'CLASS'</span>]
|
||||
|
||||
@@ -311,21 +311,6 @@ looking for a particular method in an options hash.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
</div>
|
||||
<p>Gets the last item of an array(-like) object.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.last = <span class="hljs-function"><span class="hljs-title">last</span> = <span class="hljs-params">(array, back)</span> -></span> array[array.length - (back <span class="hljs-keyword">or</span> <span class="hljs-number">0</span>) - <span class="hljs-number">1</span>]</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
</div>
|
||||
<p>Typical Array::some</p>
|
||||
|
||||
</div>
|
||||
@@ -337,11 +322,11 @@ looking for a particular method in an options hash.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-14">
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
</div>
|
||||
<p>Simple function for inverting Literate CoffeeScript code by putting the
|
||||
documentation in comments, producing a string of CoffeeScript code that
|
||||
@@ -363,11 +348,11 @@ can be compiled “normally”.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-15">
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
</div>
|
||||
<p>Merge two jison-style location data objects together.
|
||||
If <code>last</code> is not provided, this will simply return <code>first</code>.</p>
|
||||
@@ -386,11 +371,11 @@ If <code>last</code> is not provided, this will simply return <code>first</code>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-16">
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
</div>
|
||||
<p>This returns a function which takes an object as a parameter, and if that
|
||||
object is an AST node, updates that object’s locationData.
|
||||
@@ -408,11 +393,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
</div>
|
||||
<p>Convert jison location data to a string.
|
||||
<code>obj</code> can be a token, or a locationData.</p>
|
||||
@@ -432,11 +417,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>A <code>.coffee.md</code> compatible version of <code>basename</code>, that returns the file sans-extension.</p>
|
||||
|
||||
@@ -455,11 +440,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a CoffeeScript file.</p>
|
||||
|
||||
@@ -470,11 +455,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
</div>
|
||||
<p>Determine if a filename represents a Literate CoffeeScript file.</p>
|
||||
|
||||
@@ -485,11 +470,11 @@ The object is returned either way.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
</div>
|
||||
<p>Throws a SyntaxError from a given location.
|
||||
The error’s <code>toString</code> will return an error message following the “standard”
|
||||
@@ -506,11 +491,11 @@ marker showing where the error is.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-22">
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
</div>
|
||||
<p>Instead of showing the compiler’s stacktrace, show our custom error message
|
||||
(this is useful when the error bubbles up in Node.js applications that
|
||||
@@ -525,11 +510,11 @@ compile CoffeeScript for example).</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-23">
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
</div>
|
||||
<p>Update a compiler SyntaxError with source code information if it didn’t have
|
||||
it already.</p>
|
||||
@@ -541,11 +526,11 @@ it already.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-24">
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
</div>
|
||||
<p>Avoid screwing up the <code>stack</code> property of other errors (i.e. possible bugs).</p>
|
||||
|
||||
@@ -571,11 +556,11 @@ it already.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-25">
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
</div>
|
||||
<p>Show only the first line on multi-line errors.</p>
|
||||
|
||||
@@ -587,11 +572,11 @@ it already.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-26">
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
</div>
|
||||
<p>Check to see if we’re running on a color-enabled TTY.</p>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -141,7 +141,7 @@ Error.stackTraceLimit = Infinity
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>{compact, flatten, extend, merge, del, starts, ends, last, some,
|
||||
<div class="content"><div class='highlight'><pre>{compact, flatten, extend, merge, del, starts, ends, some,
|
||||
addLocationDataFn, locationDataToString, throwSyntaxError} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -327,7 +327,11 @@ object with their parent closure, to preserve the expected lexical scope.</p>
|
||||
<span class="hljs-keyword">else</span>
|
||||
meth = <span class="hljs-string">'call'</span>
|
||||
func = <span class="hljs-keyword">new</span> Value func, [<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> Literal meth]
|
||||
(<span class="hljs-keyword">new</span> Call func, args).compileNode o</pre></div></div>
|
||||
parts = (<span class="hljs-keyword">new</span> Call func, args).compileNode o
|
||||
<span class="hljs-keyword">if</span> func.isGenerator
|
||||
parts.unshift <span class="hljs-property">@makeCode</span> <span class="hljs-string">"(yield* "</span>
|
||||
parts.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">")"</span>
|
||||
parts</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -347,14 +351,15 @@ the two values are raw nodes which have not been compiled.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">cache</span>: <span class="hljs-function"><span class="hljs-params">(o, level, reused)</span> -></span>
|
||||
<span class="hljs-keyword">unless</span> <span class="hljs-property">@isComplex</span>()
|
||||
ref = <span class="hljs-keyword">if</span> level <span class="hljs-keyword">then</span> <span class="hljs-property">@compileToFragments</span> o, level <span class="hljs-keyword">else</span> <span class="hljs-keyword">this</span>
|
||||
[ref, ref]
|
||||
<span class="hljs-keyword">else</span>
|
||||
ref = <span class="hljs-keyword">new</span> Literal reused <span class="hljs-keyword">or</span> o.scope.freeVariable <span class="hljs-string">'ref'</span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">cache</span>: <span class="hljs-function"><span class="hljs-params">(o, level, isComplex)</span> -></span>
|
||||
complex = <span class="hljs-keyword">if</span> isComplex? <span class="hljs-keyword">then</span> isComplex <span class="hljs-keyword">this</span> <span class="hljs-keyword">else</span> <span class="hljs-property">@isComplex</span>()
|
||||
<span class="hljs-keyword">if</span> complex
|
||||
ref = <span class="hljs-keyword">new</span> Literal o.scope.freeVariable <span class="hljs-string">'ref'</span>
|
||||
sub = <span class="hljs-keyword">new</span> Assign ref, <span class="hljs-keyword">this</span>
|
||||
<span class="hljs-keyword">if</span> level <span class="hljs-keyword">then</span> [sub.compileToFragments(o, level), [<span class="hljs-property">@makeCode</span>(ref.value)]] <span class="hljs-keyword">else</span> [sub, ref]
|
||||
<span class="hljs-keyword">else</span>
|
||||
ref = <span class="hljs-keyword">if</span> level <span class="hljs-keyword">then</span> <span class="hljs-property">@compileToFragments</span> o, level <span class="hljs-keyword">else</span> <span class="hljs-keyword">this</span>
|
||||
[ref, ref]
|
||||
|
||||
<span class="hljs-attribute">cacheToCodeFragments</span>: <span class="hljs-function"><span class="hljs-params">(cacheValues)</span> -></span>
|
||||
[fragmentsToText(cacheValues[<span class="hljs-number">0</span>]), fragmentsToText(cacheValues[<span class="hljs-number">1</span>])]</pre></div></div>
|
||||
@@ -829,7 +834,7 @@ clean up obvious double-parentheses.</p>
|
||||
o.indent = <span class="hljs-keyword">if</span> o.bare <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> TAB
|
||||
o.level = LEVEL_TOP
|
||||
<span class="hljs-property">@spaced</span> = <span class="hljs-literal">yes</span>
|
||||
o.scope = <span class="hljs-keyword">new</span> Scope <span class="hljs-literal">null</span>, <span class="hljs-keyword">this</span>, <span class="hljs-literal">null</span></pre></div></div>
|
||||
o.scope = <span class="hljs-keyword">new</span> Scope <span class="hljs-literal">null</span>, <span class="hljs-keyword">this</span>, <span class="hljs-literal">null</span>, o.referencedVars ? []</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -1043,7 +1048,8 @@ make sense.</p>
|
||||
<span class="hljs-keyword">if</span> expr <span class="hljs-keyword">and</span> expr <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Return <span class="hljs-keyword">then</span> expr.compileToFragments o, level <span class="hljs-keyword">else</span> <span class="hljs-keyword">super</span> o, level
|
||||
|
||||
<span class="hljs-attribute">compileNode</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
answer = []</pre></div></div>
|
||||
answer = []
|
||||
exprIsYieldReturn = <span class="hljs-property">@expression</span>?.isYieldReturn?()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -1058,10 +1064,11 @@ make sense.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-property">@tab</span> + <span class="hljs-string">"return<span class="hljs-subst">#{<span class="hljs-keyword">if</span> <span class="hljs-property">@expression</span> <span class="hljs-keyword">then</span> <span class="hljs-string">" "</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>}</span>"</span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">unless</span> exprIsYieldReturn
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-property">@tab</span> + <span class="hljs-string">"return<span class="hljs-subst">#{<span class="hljs-keyword">if</span> <span class="hljs-property">@expression</span> <span class="hljs-keyword">then</span> <span class="hljs-string">" "</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>}</span>"</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@expression</span>
|
||||
answer = answer.concat <span class="hljs-property">@expression</span>.compileToFragments o, LEVEL_PAREN
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">";"</span>
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">";"</span> <span class="hljs-keyword">unless</span> exprIsYieldReturn
|
||||
<span class="hljs-keyword">return</span> answer</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -1161,10 +1168,11 @@ or vanilla.</p>
|
||||
(<span class="hljs-property">@base</span> <span class="hljs-keyword">instanceof</span> Obj) <span class="hljs-keyword">and</span> (<span class="hljs-keyword">not</span> onlyGenerated <span class="hljs-keyword">or</span> <span class="hljs-property">@base</span>.generated)
|
||||
|
||||
<span class="hljs-attribute">isSplice</span>:<span class="hljs-function"> -></span>
|
||||
last(<span class="hljs-property">@properties</span>) <span class="hljs-keyword">instanceof</span> Slice
|
||||
[..., lastProp] = <span class="hljs-property">@properties</span>
|
||||
lastProp <span class="hljs-keyword">instanceof</span> Slice
|
||||
|
||||
<span class="hljs-attribute">looksStatic</span>: <span class="hljs-function"><span class="hljs-params">(className)</span> -></span>
|
||||
<span class="hljs-property">@base</span>.value <span class="hljs-keyword">is</span> className <span class="hljs-keyword">and</span> <span class="hljs-property">@properties</span>.length <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-property">@base</span>.value <span class="hljs-keyword">is</span> className <span class="hljs-keyword">and</span> <span class="hljs-property">@properties</span>.length <span class="hljs-keyword">is</span> <span class="hljs-number">1</span> <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-property">@properties</span>[<span class="hljs-number">0</span>].name?.value <span class="hljs-keyword">isnt</span> <span class="hljs-string">'prototype'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -1200,7 +1208,7 @@ We cache them separately for compiling complex expressions.
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">cacheReference</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
name = last <span class="hljs-property">@properties</span>
|
||||
[..., name] = <span class="hljs-property">@properties</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@properties</span>.length < <span class="hljs-number">2</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> <span class="hljs-property">@base</span>.isComplex() <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> name?.isComplex()
|
||||
<span class="hljs-keyword">return</span> [<span class="hljs-keyword">this</span>, <span class="hljs-keyword">this</span>] <span class="hljs-comment"># `a` `a.b`</span>
|
||||
base = <span class="hljs-keyword">new</span> Value <span class="hljs-property">@base</span>, <span class="hljs-property">@properties</span>[...-<span class="hljs-number">1</span>]
|
||||
@@ -1303,7 +1311,7 @@ at the same position.</p>
|
||||
<span class="hljs-attribute">makeReturn</span>: THIS
|
||||
|
||||
<span class="hljs-attribute">compileNode</span>: <span class="hljs-function"><span class="hljs-params">(o, level)</span> -></span>
|
||||
comment = <span class="hljs-property">@comment</span>.replace <span class="hljs-regexp">/^(\s*)#/gm</span>, <span class="hljs-string">"$1 *"</span>
|
||||
comment = <span class="hljs-property">@comment</span>.replace <span class="hljs-regexp">/^(\s*)# /gm</span>, <span class="hljs-string">"$1 * "</span>
|
||||
code = <span class="hljs-string">"/*<span class="hljs-subst">#{multident comment, <span class="hljs-property">@tab</span>}</span><span class="hljs-subst">#{<span class="hljs-keyword">if</span> <span class="hljs-string">'\n'</span> <span class="hljs-keyword">in</span> comment <span class="hljs-keyword">then</span> <span class="hljs-string">"\n<span class="hljs-subst">#{<span class="hljs-property">@tab</span>}</span>"</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>}</span> */"</span>
|
||||
code = o.indent + code <span class="hljs-keyword">if</span> (level <span class="hljs-keyword">or</span> o.level) <span class="hljs-keyword">is</span> LEVEL_TOP
|
||||
[<span class="hljs-property">@makeCode</span>(<span class="hljs-string">"\n"</span>), <span class="hljs-property">@makeCode</span>(code)]</pre></div></div>
|
||||
@@ -1383,10 +1391,21 @@ method.</p>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">superReference</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
method = o.scope.namedMethod()
|
||||
<span class="hljs-keyword">if</span> method?.klass
|
||||
accesses = [<span class="hljs-keyword">new</span> Access(<span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__super__'</span>)]
|
||||
{klass, name, variable} = method
|
||||
<span class="hljs-keyword">if</span> klass.isComplex()
|
||||
bref = <span class="hljs-keyword">new</span> Literal o.scope.parent.freeVariable <span class="hljs-string">'base'</span>
|
||||
base = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Parens <span class="hljs-keyword">new</span> Assign bref, klass
|
||||
variable.base = base
|
||||
variable.properties.splice <span class="hljs-number">0</span>, klass.properties.length
|
||||
<span class="hljs-keyword">if</span> name.isComplex() <span class="hljs-keyword">or</span> (name <span class="hljs-keyword">instanceof</span> Index <span class="hljs-keyword">and</span> name.index.isAssignable())
|
||||
nref = <span class="hljs-keyword">new</span> Literal o.scope.parent.freeVariable <span class="hljs-string">'name'</span>
|
||||
name = <span class="hljs-keyword">new</span> Index <span class="hljs-keyword">new</span> Assign nref, name.index
|
||||
variable.properties.pop()
|
||||
variable.properties.push name
|
||||
accesses = [<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'__super__'</span>]
|
||||
accesses.push <span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'constructor'</span> <span class="hljs-keyword">if</span> method.static
|
||||
accesses.push <span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> Literal method.name
|
||||
(<span class="hljs-keyword">new</span> Value (<span class="hljs-keyword">new</span> Literal method.klass), accesses).compile o
|
||||
accesses.push <span class="hljs-keyword">if</span> nref? <span class="hljs-keyword">then</span> <span class="hljs-keyword">new</span> Index nref <span class="hljs-keyword">else</span> name
|
||||
(<span class="hljs-keyword">new</span> Value bref ? klass, accesses).compile o
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> method?.ctor
|
||||
<span class="hljs-string">"<span class="hljs-subst">#{method.name}</span>.__super__.constructor"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
@@ -1588,7 +1607,7 @@ After <code>goog.inherits</code> from the
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">compileToFragments</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
<span class="hljs-keyword">new</span> Call(<span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'extends'</span>), [<span class="hljs-property">@child</span>, <span class="hljs-property">@parent</span>]).compileToFragments o</pre></div></div>
|
||||
<span class="hljs-keyword">new</span> Call(<span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'extend'</span>, o), [<span class="hljs-property">@child</span>, <span class="hljs-property">@parent</span>]).compileToFragments o</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -1724,9 +1743,10 @@ But only if they need to be cached to avoid double evaluation.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">compileVariables</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
o = merge o, <span class="hljs-attribute">top</span>: <span class="hljs-literal">true</span>
|
||||
[<span class="hljs-property">@fromC</span>, <span class="hljs-property">@fromVar</span>] = <span class="hljs-property">@cacheToCodeFragments</span> <span class="hljs-property">@from</span>.cache o, LEVEL_LIST
|
||||
[<span class="hljs-property">@toC</span>, <span class="hljs-property">@toVar</span>] = <span class="hljs-property">@cacheToCodeFragments</span> <span class="hljs-property">@to</span>.cache o, LEVEL_LIST
|
||||
[<span class="hljs-property">@step</span>, <span class="hljs-property">@stepVar</span>] = <span class="hljs-property">@cacheToCodeFragments</span> step.cache o, LEVEL_LIST <span class="hljs-keyword">if</span> step = del o, <span class="hljs-string">'step'</span>
|
||||
isComplex = del o, <span class="hljs-string">'isComplex'</span>
|
||||
[<span class="hljs-property">@fromC</span>, <span class="hljs-property">@fromVar</span>] = <span class="hljs-property">@cacheToCodeFragments</span> <span class="hljs-property">@from</span>.cache o, LEVEL_LIST, isComplex
|
||||
[<span class="hljs-property">@toC</span>, <span class="hljs-property">@toVar</span>] = <span class="hljs-property">@cacheToCodeFragments</span> <span class="hljs-property">@to</span>.cache o, LEVEL_LIST, isComplex
|
||||
[<span class="hljs-property">@step</span>, <span class="hljs-property">@stepVar</span>] = <span class="hljs-property">@cacheToCodeFragments</span> step.cache o, LEVEL_LIST, isComplex <span class="hljs-keyword">if</span> step = del o, <span class="hljs-string">'step'</span>
|
||||
[<span class="hljs-property">@fromNum</span>, <span class="hljs-property">@toNum</span>] = [<span class="hljs-property">@fromVar</span>.match(NUMBER), <span class="hljs-property">@toVar</span>.match(NUMBER)]
|
||||
<span class="hljs-property">@stepNum</span> = <span class="hljs-property">@stepVar</span>.match(NUMBER) <span class="hljs-keyword">if</span> <span class="hljs-property">@stepVar</span></pre></div></div>
|
||||
|
||||
@@ -1855,7 +1875,7 @@ needed to iterate over the values in the range. Used by comprehensions.</p>
|
||||
range.pop() <span class="hljs-keyword">if</span> <span class="hljs-property">@exclusive</span>
|
||||
<span class="hljs-keyword">return</span> [<span class="hljs-property">@makeCode</span> <span class="hljs-string">"[<span class="hljs-subst">#{ range.join(<span class="hljs-string">', '</span>) }</span>]"</span>]
|
||||
idt = <span class="hljs-property">@tab</span> + TAB
|
||||
i = o.scope.freeVariable <span class="hljs-string">'i'</span>
|
||||
i = o.scope.freeVariable <span class="hljs-string">'i'</span>, <span class="hljs-attribute">single</span>: <span class="hljs-literal">true</span>
|
||||
result = o.scope.freeVariable <span class="hljs-string">'results'</span>
|
||||
pre = <span class="hljs-string">"\n<span class="hljs-subst">#{idt}</span><span class="hljs-subst">#{result}</span> = [];"</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@fromNum</span> <span class="hljs-keyword">and</span> <span class="hljs-property">@toNum</span>
|
||||
@@ -1984,35 +2004,54 @@ is the index of the beginning.</p>
|
||||
|
||||
<span class="hljs-attribute">compileNode</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
props = <span class="hljs-property">@properties</span>
|
||||
<span class="hljs-keyword">return</span> [<span class="hljs-property">@makeCode</span>(<span class="hljs-keyword">if</span> <span class="hljs-property">@front</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'({})'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'{}'</span>)] <span class="hljs-keyword">unless</span> props.length
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@generated</span>
|
||||
<span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> props <span class="hljs-keyword">when</span> node <span class="hljs-keyword">instanceof</span> Value
|
||||
node.error <span class="hljs-string">'cannot have an implicit value in an implicit object'</span>
|
||||
<span class="hljs-keyword">break</span> <span class="hljs-keyword">for</span> prop, dynamicIndex <span class="hljs-keyword">in</span> props <span class="hljs-keyword">when</span> (prop.variable <span class="hljs-keyword">or</span> prop).base <span class="hljs-keyword">instanceof</span> Parens
|
||||
hasDynamic = dynamicIndex < props.length
|
||||
idt = o.indent += TAB
|
||||
lastNoncom = <span class="hljs-property">@lastNonComment</span> <span class="hljs-property">@properties</span>
|
||||
answer = []
|
||||
<span class="hljs-keyword">if</span> hasDynamic
|
||||
oref = o.scope.freeVariable <span class="hljs-string">'obj'</span>
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">"(\n<span class="hljs-subst">#{idt}</span><span class="hljs-subst">#{oref}</span> = "</span>
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">"{<span class="hljs-subst">#{<span class="hljs-keyword">if</span> props.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span> <span class="hljs-keyword">or</span> dynamicIndex <span class="hljs-keyword">is</span> <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'}'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'\n'</span>}</span>"</span>
|
||||
<span class="hljs-keyword">for</span> prop, i <span class="hljs-keyword">in</span> props
|
||||
join = <span class="hljs-keyword">if</span> i <span class="hljs-keyword">is</span> props.length - <span class="hljs-number">1</span>
|
||||
<span class="hljs-keyword">if</span> i <span class="hljs-keyword">is</span> dynamicIndex
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">"\n<span class="hljs-subst">#{idt}</span>}"</span> <span class="hljs-keyword">unless</span> i <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">',\n'</span>
|
||||
join = <span class="hljs-keyword">if</span> i <span class="hljs-keyword">is</span> props.length - <span class="hljs-number">1</span> <span class="hljs-keyword">or</span> i <span class="hljs-keyword">is</span> dynamicIndex - <span class="hljs-number">1</span>
|
||||
<span class="hljs-string">''</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">is</span> lastNoncom <span class="hljs-keyword">or</span> prop <span class="hljs-keyword">instanceof</span> Comment
|
||||
<span class="hljs-string">'\n'</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-string">',\n'</span>
|
||||
indent = <span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Comment <span class="hljs-keyword">then</span> <span class="hljs-string">''</span> <span class="hljs-keyword">else</span> idt
|
||||
indent += TAB <span class="hljs-keyword">if</span> hasDynamic <span class="hljs-keyword">and</span> i < dynamicIndex
|
||||
<span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign <span class="hljs-keyword">and</span> prop.variable <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> prop.variable.hasProperties()
|
||||
prop.variable.error <span class="hljs-string">'Invalid object key'</span>
|
||||
<span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> prop.<span class="hljs-keyword">this</span>
|
||||
prop = <span class="hljs-keyword">new</span> Assign prop.properties[<span class="hljs-number">0</span>].name, prop, <span class="hljs-string">'object'</span>
|
||||
<span class="hljs-keyword">if</span> prop <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Comment
|
||||
<span class="hljs-keyword">if</span> prop <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Assign
|
||||
prop = <span class="hljs-keyword">new</span> Assign prop, prop, <span class="hljs-string">'object'</span>
|
||||
(prop.variable.base <span class="hljs-keyword">or</span> prop.variable).asKey = <span class="hljs-literal">yes</span>
|
||||
<span class="hljs-keyword">if</span> i < dynamicIndex
|
||||
<span class="hljs-keyword">if</span> prop <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Assign
|
||||
prop = <span class="hljs-keyword">new</span> Assign prop, prop, <span class="hljs-string">'object'</span>
|
||||
(prop.variable.base <span class="hljs-keyword">or</span> prop.variable).asKey = <span class="hljs-literal">yes</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-keyword">if</span> prop <span class="hljs-keyword">instanceof</span> Assign
|
||||
key = prop.variable
|
||||
value = prop.value
|
||||
<span class="hljs-keyword">else</span>
|
||||
[key, value] = prop.base.cache o
|
||||
prop = <span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value (<span class="hljs-keyword">new</span> Literal oref), [<span class="hljs-keyword">new</span> Access key]), value
|
||||
<span class="hljs-keyword">if</span> indent <span class="hljs-keyword">then</span> answer.push <span class="hljs-property">@makeCode</span> indent
|
||||
answer.push prop.compileToFragments(o, LEVEL_TOP)...
|
||||
<span class="hljs-keyword">if</span> join <span class="hljs-keyword">then</span> answer.push <span class="hljs-property">@makeCode</span> join
|
||||
answer.unshift <span class="hljs-property">@makeCode</span> <span class="hljs-string">"{<span class="hljs-subst">#{ props.length <span class="hljs-keyword">and</span> <span class="hljs-string">'\n'</span> }</span>"</span>
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">"<span class="hljs-subst">#{ props.length <span class="hljs-keyword">and</span> <span class="hljs-string">'\n'</span> + <span class="hljs-property">@tab</span> }</span>}"</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@front</span> <span class="hljs-keyword">then</span> <span class="hljs-property">@wrapInBraces</span> answer <span class="hljs-keyword">else</span> answer
|
||||
<span class="hljs-keyword">if</span> hasDynamic
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">",\n<span class="hljs-subst">#{idt}</span><span class="hljs-subst">#{oref}</span>\n<span class="hljs-subst">#{<span class="hljs-property">@tab</span>}</span>)"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">"\n<span class="hljs-subst">#{<span class="hljs-property">@tab</span>}</span>}"</span> <span class="hljs-keyword">unless</span> props.length <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@front</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> hasDynamic <span class="hljs-keyword">then</span> <span class="hljs-property">@wrapInBraces</span> answer <span class="hljs-keyword">else</span> answer
|
||||
|
||||
<span class="hljs-attribute">assigns</span>: <span class="hljs-function"><span class="hljs-params">(name)</span> -></span>
|
||||
<span class="hljs-keyword">for</span> prop <span class="hljs-keyword">in</span> <span class="hljs-property">@properties</span> <span class="hljs-keyword">when</span> prop.assigns name <span class="hljs-keyword">then</span> <span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span>
|
||||
@@ -2124,7 +2163,8 @@ list of prototype property assignments.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">determineName</span>:<span class="hljs-function"> -></span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span> <span class="hljs-keyword">unless</span> <span class="hljs-property">@variable</span>
|
||||
decl = <span class="hljs-keyword">if</span> tail = last <span class="hljs-property">@variable</span>.properties
|
||||
[..., tail] = <span class="hljs-property">@variable</span>.properties
|
||||
decl = <span class="hljs-keyword">if</span> tail
|
||||
tail <span class="hljs-keyword">instanceof</span> Access <span class="hljs-keyword">and</span> tail.name.value
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-property">@variable</span>.base.value
|
||||
@@ -2152,7 +2192,6 @@ list of prototype property assignments.</p>
|
||||
<span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Literal <span class="hljs-keyword">and</span> node.value <span class="hljs-keyword">is</span> <span class="hljs-string">'this'</span>
|
||||
node.value = name
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Code
|
||||
node.klass = name
|
||||
node.context = name <span class="hljs-keyword">if</span> node.bound</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -2172,7 +2211,7 @@ constructor.</p>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">addBoundFunctions</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
<span class="hljs-keyword">for</span> bvar <span class="hljs-keyword">in</span> <span class="hljs-property">@boundFuncs</span>
|
||||
lhs = (<span class="hljs-keyword">new</span> Value (<span class="hljs-keyword">new</span> Literal <span class="hljs-string">"this"</span>), [<span class="hljs-keyword">new</span> Access bvar]).compile o
|
||||
<span class="hljs-property">@ctor</span>.body.unshift <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"<span class="hljs-subst">#{lhs}</span> = <span class="hljs-subst">#{utility <span class="hljs-string">'bind'</span>}</span>(<span class="hljs-subst">#{lhs}</span>, this)"</span>
|
||||
<span class="hljs-property">@ctor</span>.body.unshift <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"<span class="hljs-subst">#{lhs}</span> = <span class="hljs-subst">#{utility <span class="hljs-string">'bind'</span>, o}</span>(<span class="hljs-subst">#{lhs}</span>, this)"</span>
|
||||
<span class="hljs-keyword">return</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -2210,7 +2249,8 @@ on the class.</p>
|
||||
<span class="hljs-keyword">if</span> assign.variable.<span class="hljs-keyword">this</span>
|
||||
func.static = <span class="hljs-literal">yes</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
assign.variable = <span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> Literal(name), [(<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'prototype'</span>), <span class="hljs-keyword">new</span> Access base])
|
||||
acc = <span class="hljs-keyword">if</span> base.isComplex() <span class="hljs-keyword">then</span> <span class="hljs-keyword">new</span> Index base <span class="hljs-keyword">else</span> <span class="hljs-keyword">new</span> Access base
|
||||
assign.variable = <span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> Literal(name), [(<span class="hljs-keyword">new</span> Access <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'prototype'</span>), acc])
|
||||
<span class="hljs-keyword">if</span> func <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> func.bound
|
||||
<span class="hljs-property">@boundFuncs</span>.push base
|
||||
func.bound = <span class="hljs-literal">no</span>
|
||||
@@ -2331,7 +2371,7 @@ constructor, property assignments, and inheritance getting built out below.</p>
|
||||
<span class="hljs-property">@body</span>.expressions.push lname
|
||||
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@parent</span>
|
||||
superClass = <span class="hljs-keyword">new</span> Literal o.classScope.freeVariable <span class="hljs-string">'super'</span>, <span class="hljs-literal">no</span>
|
||||
superClass = <span class="hljs-keyword">new</span> Literal o.classScope.freeVariable <span class="hljs-string">'superClass'</span>, <span class="hljs-attribute">reserve</span>: <span class="hljs-literal">no</span>
|
||||
<span class="hljs-property">@body</span>.expressions.unshift <span class="hljs-keyword">new</span> Extends lname, superClass
|
||||
func.params.push <span class="hljs-keyword">new</span> Param superClass
|
||||
args.push <span class="hljs-property">@parent</span>
|
||||
@@ -2410,21 +2450,28 @@ has not been seen yet within the current scope, declare it.</p>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-property">@compileSplice</span> o <span class="hljs-keyword">if</span> <span class="hljs-property">@variable</span>.isSplice()
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-property">@compileConditional</span> o <span class="hljs-keyword">if</span> <span class="hljs-property">@context</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'||='</span>, <span class="hljs-string">'&&='</span>, <span class="hljs-string">'?='</span>]
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-property">@compileSpecialMath</span> o <span class="hljs-keyword">if</span> <span class="hljs-property">@context</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'**='</span>, <span class="hljs-string">'//='</span>, <span class="hljs-string">'%%='</span>]
|
||||
compiledName = <span class="hljs-property">@variable</span>.compileToFragments o, LEVEL_LIST
|
||||
name = fragmentsToText compiledName
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@value</span> <span class="hljs-keyword">instanceof</span> Code
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@value</span>.static
|
||||
<span class="hljs-property">@value</span>.klass = <span class="hljs-property">@variable</span>.base
|
||||
<span class="hljs-property">@value</span>.name = <span class="hljs-property">@variable</span>.properties[<span class="hljs-number">0</span>]
|
||||
<span class="hljs-property">@value</span>.variable = <span class="hljs-property">@variable</span>
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@variable</span>.properties?.length >= <span class="hljs-number">2</span>
|
||||
[properties..., prototype, name] = <span class="hljs-property">@variable</span>.properties
|
||||
<span class="hljs-keyword">if</span> prototype.name?.value <span class="hljs-keyword">is</span> <span class="hljs-string">'prototype'</span>
|
||||
<span class="hljs-property">@value</span>.klass = <span class="hljs-keyword">new</span> Value <span class="hljs-property">@variable</span>.base, properties
|
||||
<span class="hljs-property">@value</span>.name = name
|
||||
<span class="hljs-property">@value</span>.variable = <span class="hljs-property">@variable</span>
|
||||
<span class="hljs-keyword">unless</span> <span class="hljs-property">@context</span>
|
||||
varBase = <span class="hljs-property">@variable</span>.unwrapAll()
|
||||
<span class="hljs-keyword">unless</span> varBase.isAssignable()
|
||||
<span class="hljs-property">@variable</span>.error <span class="hljs-string">"\"<span class="hljs-subst">#{<span class="hljs-property">@variable</span>.compile o}</span>\" cannot be assigned"</span>
|
||||
<span class="hljs-keyword">unless</span> varBase.hasProperties?()
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@param</span>
|
||||
o.scope.add name, <span class="hljs-string">'var'</span>
|
||||
o.scope.add varBase.value, <span class="hljs-string">'var'</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
o.scope.find name
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@value</span> <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> match = METHOD_DEF.exec name
|
||||
<span class="hljs-property">@value</span>.klass = match[<span class="hljs-number">1</span>] <span class="hljs-keyword">if</span> match[<span class="hljs-number">2</span>]
|
||||
<span class="hljs-property">@value</span>.name = match[<span class="hljs-number">3</span>] ? match[<span class="hljs-number">4</span>] ? match[<span class="hljs-number">5</span>]
|
||||
o.scope.find varBase.value
|
||||
val = <span class="hljs-property">@value</span>.compileToFragments o, LEVEL_LIST
|
||||
compiledName = <span class="hljs-property">@variable</span>.compileToFragments o, LEVEL_LIST
|
||||
<span class="hljs-keyword">return</span> (compiledName.concat <span class="hljs-property">@makeCode</span>(<span class="hljs-string">": "</span>), val) <span class="hljs-keyword">if</span> <span class="hljs-property">@context</span> <span class="hljs-keyword">is</span> <span class="hljs-string">'object'</span>
|
||||
answer = compiledName.concat <span class="hljs-property">@makeCode</span>(<span class="hljs-string">" <span class="hljs-subst">#{ <span class="hljs-property">@context</span> <span class="hljs-keyword">or</span> <span class="hljs-string">'='</span> }</span> "</span>), val
|
||||
<span class="hljs-keyword">if</span> o.level <= LEVEL_LIST <span class="hljs-keyword">then</span> answer <span class="hljs-keyword">else</span> <span class="hljs-property">@wrapInBraces</span> answer</pre></div></div>
|
||||
@@ -2558,9 +2605,9 @@ for details.</p>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> expandedIdx <span class="hljs-keyword">and</span> obj <span class="hljs-keyword">instanceof</span> Splat
|
||||
name = obj.name.unwrap().value
|
||||
obj = obj.unwrap()
|
||||
val = <span class="hljs-string">"<span class="hljs-subst">#{olen}</span> <= <span class="hljs-subst">#{vvarText}</span>.length ? <span class="hljs-subst">#{ utility <span class="hljs-string">'slice'</span> }</span>.call(<span class="hljs-subst">#{vvarText}</span>, <span class="hljs-subst">#{i}</span>"</span>
|
||||
val = <span class="hljs-string">"<span class="hljs-subst">#{olen}</span> <= <span class="hljs-subst">#{vvarText}</span>.length ? <span class="hljs-subst">#{ utility <span class="hljs-string">'slice'</span>, o }</span>.call(<span class="hljs-subst">#{vvarText}</span>, <span class="hljs-subst">#{i}</span>"</span>
|
||||
<span class="hljs-keyword">if</span> rest = olen - i - <span class="hljs-number">1</span>
|
||||
ivar = o.scope.freeVariable <span class="hljs-string">'i'</span>
|
||||
ivar = o.scope.freeVariable <span class="hljs-string">'i'</span>, <span class="hljs-attribute">single</span>: <span class="hljs-literal">true</span>
|
||||
val += <span class="hljs-string">", <span class="hljs-subst">#{ivar}</span> = <span class="hljs-subst">#{vvarText}</span>.length - <span class="hljs-subst">#{rest}</span>) : (<span class="hljs-subst">#{ivar}</span> = <span class="hljs-subst">#{i}</span>, [])"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
val += <span class="hljs-string">") : []"</span>
|
||||
@@ -2571,7 +2618,7 @@ for details.</p>
|
||||
<span class="hljs-keyword">if</span> rest <span class="hljs-keyword">is</span> <span class="hljs-number">1</span>
|
||||
expandedIdx = <span class="hljs-string">"<span class="hljs-subst">#{vvarText}</span>.length - 1"</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
ivar = o.scope.freeVariable <span class="hljs-string">'i'</span>
|
||||
ivar = o.scope.freeVariable <span class="hljs-string">'i'</span>, <span class="hljs-attribute">single</span>: <span class="hljs-literal">true</span>
|
||||
val = <span class="hljs-keyword">new</span> Literal <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span> = <span class="hljs-subst">#{vvarText}</span>.length - <span class="hljs-subst">#{rest}</span>"</span>
|
||||
expandedIdx = <span class="hljs-string">"<span class="hljs-subst">#{ivar}</span>++"</span>
|
||||
assigns.push val.compileToFragments o, LEVEL_LIST
|
||||
@@ -2717,9 +2764,11 @@ has no <em>children</em> — they’re within the inner scope.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.Code = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Code</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span></span>
|
||||
<span class="hljs-attribute">constructor</span>: <span class="hljs-function"><span class="hljs-params">(params, body, tag)</span> -></span>
|
||||
<span class="hljs-property">@params</span> = params <span class="hljs-keyword">or</span> []
|
||||
<span class="hljs-property">@body</span> = body <span class="hljs-keyword">or</span> <span class="hljs-keyword">new</span> Block
|
||||
<span class="hljs-property">@bound</span> = tag <span class="hljs-keyword">is</span> <span class="hljs-string">'boundfunc'</span>
|
||||
<span class="hljs-property">@params</span> = params <span class="hljs-keyword">or</span> []
|
||||
<span class="hljs-property">@body</span> = body <span class="hljs-keyword">or</span> <span class="hljs-keyword">new</span> Block
|
||||
<span class="hljs-property">@bound</span> = tag <span class="hljs-keyword">is</span> <span class="hljs-string">'boundfunc'</span>
|
||||
<span class="hljs-property">@isGenerator</span> = !!<span class="hljs-property">@body</span>.contains <span class="hljs-function"><span class="hljs-params">(node)</span> -></span>
|
||||
node <span class="hljs-keyword">instanceof</span> Op <span class="hljs-keyword">and</span> node.operator <span class="hljs-keyword">in</span> [<span class="hljs-string">'yield'</span>, <span class="hljs-string">'yield*'</span>]
|
||||
|
||||
<span class="hljs-attribute">children</span>: [<span class="hljs-string">'params'</span>, <span class="hljs-string">'body'</span>]
|
||||
|
||||
@@ -2781,9 +2830,8 @@ a closure.</p>
|
||||
<span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> <span class="hljs-property">@params</span> <span class="hljs-keyword">when</span> param <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Expansion
|
||||
o.scope.parameter param.asReference o
|
||||
<span class="hljs-keyword">for</span> param <span class="hljs-keyword">in</span> <span class="hljs-property">@params</span> <span class="hljs-keyword">when</span> param.splat <span class="hljs-keyword">or</span> param <span class="hljs-keyword">instanceof</span> Expansion
|
||||
<span class="hljs-keyword">for</span> {<span class="hljs-attribute">name</span>: p} <span class="hljs-keyword">in</span> <span class="hljs-property">@params</span> <span class="hljs-keyword">when</span> param <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Expansion
|
||||
<span class="hljs-keyword">if</span> p.<span class="hljs-keyword">this</span> <span class="hljs-keyword">then</span> p = p.properties[<span class="hljs-number">0</span>].name
|
||||
<span class="hljs-keyword">if</span> p.value <span class="hljs-keyword">then</span> o.scope.add p.value, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span>
|
||||
<span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> <span class="hljs-property">@params</span> <span class="hljs-keyword">when</span> p <span class="hljs-keyword">not</span> <span class="hljs-keyword">instanceof</span> Expansion <span class="hljs-keyword">and</span> p.name.value
|
||||
o.scope.add p.name.value, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span>
|
||||
splats = <span class="hljs-keyword">new</span> Assign <span class="hljs-keyword">new</span> Value(<span class="hljs-keyword">new</span> Arr(p.asReference o <span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> <span class="hljs-property">@params</span>)),
|
||||
<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'arguments'</span>
|
||||
<span class="hljs-keyword">break</span>
|
||||
@@ -2807,12 +2855,13 @@ a closure.</p>
|
||||
o.scope.parameter fragmentsToText params[i]
|
||||
uniqs = []
|
||||
<span class="hljs-property">@eachParamName</span> <span class="hljs-function"><span class="hljs-params">(name, node)</span> -></span>
|
||||
node.error <span class="hljs-string">"multiple parameters named '<span class="hljs-subst">#{name}</span>'"</span> <span class="hljs-keyword">if</span> name <span class="hljs-keyword">in</span> uniqs
|
||||
node.error <span class="hljs-string">"multiple parameters named <span class="hljs-subst">#{name}</span>"</span> <span class="hljs-keyword">if</span> name <span class="hljs-keyword">in</span> uniqs
|
||||
uniqs.push name
|
||||
<span class="hljs-property">@body</span>.makeReturn() <span class="hljs-keyword">unless</span> wasEmpty <span class="hljs-keyword">or</span> <span class="hljs-property">@noReturn</span>
|
||||
code = <span class="hljs-string">'function'</span>
|
||||
code += <span class="hljs-string">' '</span> + <span class="hljs-property">@name</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@ctor</span>
|
||||
code += <span class="hljs-string">'('</span>
|
||||
code = <span class="hljs-string">'function'</span>
|
||||
code += <span class="hljs-string">'*'</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@isGenerator</span>
|
||||
code += <span class="hljs-string">' '</span> + <span class="hljs-property">@name</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@ctor</span>
|
||||
code += <span class="hljs-string">'('</span>
|
||||
answer = [<span class="hljs-property">@makeCode</span>(code)]
|
||||
<span class="hljs-keyword">for</span> p, i <span class="hljs-keyword">in</span> params
|
||||
<span class="hljs-keyword">if</span> i <span class="hljs-keyword">then</span> answer.push <span class="hljs-property">@makeCode</span> <span class="hljs-string">", "</span>
|
||||
@@ -2886,9 +2935,9 @@ as well as be a splat, gathering up a group of parameters into an array.</p>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-property">@reference</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@reference</span>
|
||||
node = <span class="hljs-property">@name</span>
|
||||
<span class="hljs-keyword">if</span> node.<span class="hljs-keyword">this</span>
|
||||
node = node.properties[<span class="hljs-number">0</span>].name
|
||||
<span class="hljs-keyword">if</span> node.value.reserved
|
||||
node = <span class="hljs-keyword">new</span> Literal o.scope.freeVariable node.value
|
||||
name = node.properties[<span class="hljs-number">0</span>].name.value
|
||||
name = <span class="hljs-string">"_<span class="hljs-subst">#{name}</span>"</span> <span class="hljs-keyword">if</span> name.reserved
|
||||
node = <span class="hljs-keyword">new</span> Literal o.scope.freeVariable name
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> node.isComplex()
|
||||
node = <span class="hljs-keyword">new</span> Literal o.scope.freeVariable <span class="hljs-string">'arg'</span>
|
||||
node = <span class="hljs-keyword">new</span> Value node
|
||||
@@ -2918,9 +2967,7 @@ to that name.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">eachName</span>: <span class="hljs-function"><span class="hljs-params">(iterator, name = <span class="hljs-property">@name</span>)</span>-></span>
|
||||
<span class="hljs-function"><span class="hljs-title">atParam</span> = <span class="hljs-params">(obj)</span> -></span>
|
||||
node = obj.properties[<span class="hljs-number">0</span>].name
|
||||
iterator node.value, node <span class="hljs-keyword">unless</span> node.value.reserved</pre></div></div>
|
||||
<span class="hljs-function"><span class="hljs-title">atParam</span> = <span class="hljs-params">(obj)</span> -></span> iterator <span class="hljs-string">"@<span class="hljs-subst">#{obj.properties[<span class="hljs-number">0</span>].name.value}</span>"</span>, obj</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -3117,12 +3164,12 @@ splats, to a proper array.</p>
|
||||
node = list[<span class="hljs-number">0</span>]
|
||||
fragments = node.compileToFragments o, LEVEL_LIST
|
||||
<span class="hljs-keyword">return</span> fragments <span class="hljs-keyword">if</span> apply
|
||||
<span class="hljs-keyword">return</span> [].concat node.makeCode(<span class="hljs-string">"<span class="hljs-subst">#{ utility <span class="hljs-string">'slice'</span> }</span>.call("</span>), fragments, node.makeCode(<span class="hljs-string">")"</span>)
|
||||
<span class="hljs-keyword">return</span> [].concat node.makeCode(<span class="hljs-string">"<span class="hljs-subst">#{ utility <span class="hljs-string">'slice'</span>, o }</span>.call("</span>), fragments, node.makeCode(<span class="hljs-string">")"</span>)
|
||||
args = list[index..]
|
||||
<span class="hljs-keyword">for</span> node, i <span class="hljs-keyword">in</span> args
|
||||
compiledNode = node.compileToFragments o, LEVEL_LIST
|
||||
args[i] = <span class="hljs-keyword">if</span> node <span class="hljs-keyword">instanceof</span> Splat
|
||||
<span class="hljs-keyword">then</span> [].concat node.makeCode(<span class="hljs-string">"<span class="hljs-subst">#{ utility <span class="hljs-string">'slice'</span> }</span>.call("</span>), compiledNode, node.makeCode(<span class="hljs-string">")"</span>)
|
||||
<span class="hljs-keyword">then</span> [].concat node.makeCode(<span class="hljs-string">"<span class="hljs-subst">#{ utility <span class="hljs-string">'slice'</span>, o }</span>.call("</span>), compiledNode, node.makeCode(<span class="hljs-string">")"</span>)
|
||||
<span class="hljs-keyword">else</span> [].concat node.makeCode(<span class="hljs-string">"["</span>), compiledNode, node.makeCode(<span class="hljs-string">"]"</span>)
|
||||
<span class="hljs-keyword">if</span> index <span class="hljs-keyword">is</span> <span class="hljs-number">0</span>
|
||||
node = list[<span class="hljs-number">0</span>]
|
||||
@@ -3131,7 +3178,8 @@ splats, to a proper array.</p>
|
||||
base = (node.compileToFragments o, LEVEL_LIST <span class="hljs-keyword">for</span> node <span class="hljs-keyword">in</span> list[...index])
|
||||
base = list[<span class="hljs-number">0</span>].joinFragmentArrays base, <span class="hljs-string">', '</span>
|
||||
concatPart = list[index].joinFragmentArrays args, <span class="hljs-string">', '</span>
|
||||
[].concat list[<span class="hljs-number">0</span>].makeCode(<span class="hljs-string">"["</span>), base, list[index].makeCode(<span class="hljs-string">"].concat("</span>), concatPart, (last list).makeCode(<span class="hljs-string">")"</span>)</pre></div></div>
|
||||
[..., last] = list
|
||||
[].concat list[<span class="hljs-number">0</span>].makeCode(<span class="hljs-string">"["</span>), base, list[index].makeCode(<span class="hljs-string">"].concat("</span>), concatPart, last.makeCode(<span class="hljs-string">")"</span>)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -3318,9 +3366,10 @@ CoffeeScript operations into their JavaScript equivalents.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> CONVERSIONS =
|
||||
<span class="hljs-string">'=='</span>: <span class="hljs-string">'==='</span>
|
||||
<span class="hljs-string">'!='</span>: <span class="hljs-string">'!=='</span>
|
||||
<span class="hljs-string">'of'</span>: <span class="hljs-string">'in'</span></pre></div></div>
|
||||
<span class="hljs-string">'=='</span>: <span class="hljs-string">'==='</span>
|
||||
<span class="hljs-string">'!='</span>: <span class="hljs-string">'!=='</span>
|
||||
<span class="hljs-string">'of'</span>: <span class="hljs-string">'in'</span>
|
||||
<span class="hljs-string">'yieldfrom'</span>: <span class="hljs-string">'yield*'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -3343,11 +3392,18 @@ CoffeeScript operations into their JavaScript equivalents.</p>
|
||||
|
||||
<span class="hljs-attribute">isSimpleNumber</span>: NO
|
||||
|
||||
<span class="hljs-attribute">isYield</span>:<span class="hljs-function"> -></span>
|
||||
<span class="hljs-property">@operator</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'yield'</span>, <span class="hljs-string">'yield*'</span>]
|
||||
|
||||
<span class="hljs-attribute">isYieldReturn</span>:<span class="hljs-function"> -></span>
|
||||
<span class="hljs-property">@isYield</span>() <span class="hljs-keyword">and</span> <span class="hljs-property">@first</span> <span class="hljs-keyword">instanceof</span> Return
|
||||
|
||||
<span class="hljs-attribute">isUnary</span>:<span class="hljs-function"> -></span>
|
||||
<span class="hljs-keyword">not</span> <span class="hljs-property">@second</span>
|
||||
|
||||
<span class="hljs-attribute">isComplex</span>:<span class="hljs-function"> -></span>
|
||||
<span class="hljs-keyword">not</span> (<span class="hljs-property">@isUnary</span>() <span class="hljs-keyword">and</span> <span class="hljs-property">@operator</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'+'</span>, <span class="hljs-string">'-'</span>]) <span class="hljs-keyword">or</span> <span class="hljs-property">@first</span>.isComplex()</pre></div></div>
|
||||
<span class="hljs-keyword">not</span> (<span class="hljs-property">@isUnary</span>() <span class="hljs-keyword">and</span> <span class="hljs-property">@operator</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'+'</span>, <span class="hljs-string">'-'</span>] <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-property">@first</span> <span class="hljs-keyword">instanceof</span> Value <span class="hljs-keyword">and</span> <span class="hljs-property">@first</span>.isSimpleNumber())</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -3434,6 +3490,7 @@ as the chained expression is wrapped.</p>
|
||||
<span class="hljs-property">@error</span> <span class="hljs-string">'delete operand may not be argument or var'</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@operator</span> <span class="hljs-keyword">in</span> [<span class="hljs-string">'--'</span>, <span class="hljs-string">'++'</span>] <span class="hljs-keyword">and</span> <span class="hljs-property">@first</span>.unwrapAll().value <span class="hljs-keyword">in</span> STRICT_PROSCRIBED
|
||||
<span class="hljs-property">@error</span> <span class="hljs-string">"cannot increment/decrement \"<span class="hljs-subst">#{<span class="hljs-property">@first</span>.unwrapAll().value}</span>\""</span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-property">@compileYield</span> o <span class="hljs-keyword">if</span> <span class="hljs-property">@isYield</span>()
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-property">@compileUnary</span> o <span class="hljs-keyword">if</span> <span class="hljs-property">@isUnary</span>()
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-property">@compileChain</span> o <span class="hljs-keyword">if</span> isChain
|
||||
<span class="hljs-keyword">switch</span> <span class="hljs-property">@operator</span>
|
||||
@@ -3523,6 +3580,22 @@ used sequentially. For example:</p>
|
||||
parts.reverse() <span class="hljs-keyword">if</span> <span class="hljs-property">@flip</span>
|
||||
<span class="hljs-property">@joinFragmentArrays</span> parts, <span class="hljs-string">''</span>
|
||||
|
||||
<span class="hljs-attribute">compileYield</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
parts = []
|
||||
op = <span class="hljs-property">@operator</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> o.scope.parent?
|
||||
<span class="hljs-property">@error</span> <span class="hljs-string">'yield statements must occur within a function generator.'</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-string">'expression'</span> <span class="hljs-keyword">in</span> Object.keys(<span class="hljs-property">@first</span>) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> (<span class="hljs-property">@first</span> <span class="hljs-keyword">instanceof</span> Throw)
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@isYieldReturn</span>()
|
||||
parts.push <span class="hljs-property">@first</span>.compileToFragments o, LEVEL_TOP
|
||||
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@first</span>.expression?
|
||||
parts.push <span class="hljs-property">@first</span>.expression.compileToFragments o, LEVEL_OP
|
||||
<span class="hljs-keyword">else</span>
|
||||
parts.push [<span class="hljs-property">@makeCode</span> <span class="hljs-string">"(<span class="hljs-subst">#{op}</span> "</span>]
|
||||
parts.push <span class="hljs-property">@first</span>.compileToFragments o, LEVEL_OP
|
||||
parts.push [<span class="hljs-property">@makeCode</span> <span class="hljs-string">")"</span>]
|
||||
<span class="hljs-property">@joinFragmentArrays</span> parts, <span class="hljs-string">''</span>
|
||||
|
||||
<span class="hljs-attribute">compilePower</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -3547,7 +3620,7 @@ used sequentially. For example:</p>
|
||||
<span class="hljs-keyword">new</span> Call(floor, [div]).compileToFragments o
|
||||
|
||||
<span class="hljs-attribute">compileModulo</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
mod = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'modulo'</span>
|
||||
mod = <span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal utility <span class="hljs-string">'modulo'</span>, o
|
||||
<span class="hljs-keyword">new</span> Call(mod, [<span class="hljs-property">@first</span>, <span class="hljs-property">@second</span>]).compileToFragments o
|
||||
|
||||
<span class="hljs-attribute">toString</span>: <span class="hljs-function"><span class="hljs-params">(idt)</span> -></span>
|
||||
@@ -3606,7 +3679,7 @@ used sequentially. For example:</p>
|
||||
|
||||
<span class="hljs-attribute">compileLoopTest</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
[sub, ref] = <span class="hljs-property">@object</span>.cache o, LEVEL_LIST
|
||||
fragments = [].concat <span class="hljs-property">@makeCode</span>(utility(<span class="hljs-string">'indexOf'</span>) + <span class="hljs-string">".call("</span>), <span class="hljs-property">@array</span>.compileToFragments(o, LEVEL_LIST),
|
||||
fragments = [].concat <span class="hljs-property">@makeCode</span>(utility(<span class="hljs-string">'indexOf'</span>, o) + <span class="hljs-string">".call("</span>), <span class="hljs-property">@array</span>.compileToFragments(o, LEVEL_LIST),
|
||||
<span class="hljs-property">@makeCode</span>(<span class="hljs-string">", "</span>), ref, <span class="hljs-property">@makeCode</span>(<span class="hljs-string">") "</span> + <span class="hljs-keyword">if</span> <span class="hljs-property">@negated</span> <span class="hljs-keyword">then</span> <span class="hljs-string">'< 0'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'>= 0'</span>)
|
||||
<span class="hljs-keyword">return</span> fragments <span class="hljs-keyword">if</span> fragmentsToText(sub) <span class="hljs-keyword">is</span> fragmentsToText(ref)
|
||||
fragments = sub.concat <span class="hljs-property">@makeCode</span>(<span class="hljs-string">', '</span>), fragments
|
||||
@@ -3913,29 +3986,30 @@ some cannot.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">compileNode</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span>
|
||||
body = Block.wrap [<span class="hljs-property">@body</span>]
|
||||
lastJumps = last(body.expressions)?.jumps()
|
||||
<span class="hljs-property">@returns</span> = <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> lastJumps <span class="hljs-keyword">and</span> lastJumps <span class="hljs-keyword">instanceof</span> Return
|
||||
source = <span class="hljs-keyword">if</span> <span class="hljs-property">@range</span> <span class="hljs-keyword">then</span> <span class="hljs-property">@source</span>.base <span class="hljs-keyword">else</span> <span class="hljs-property">@source</span>
|
||||
scope = o.scope
|
||||
name = <span class="hljs-property">@name</span> <span class="hljs-keyword">and</span> (<span class="hljs-property">@name</span>.compile o, LEVEL_LIST) <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-property">@pattern</span>
|
||||
index = <span class="hljs-property">@index</span> <span class="hljs-keyword">and</span> (<span class="hljs-property">@index</span>.compile o, LEVEL_LIST)
|
||||
body = Block.wrap [<span class="hljs-property">@body</span>]
|
||||
[..., last] = body.expressions
|
||||
<span class="hljs-property">@returns</span> = <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> last?.jumps() <span class="hljs-keyword">instanceof</span> Return
|
||||
source = <span class="hljs-keyword">if</span> <span class="hljs-property">@range</span> <span class="hljs-keyword">then</span> <span class="hljs-property">@source</span>.base <span class="hljs-keyword">else</span> <span class="hljs-property">@source</span>
|
||||
scope = o.scope
|
||||
name = <span class="hljs-property">@name</span> <span class="hljs-keyword">and</span> (<span class="hljs-property">@name</span>.compile o, LEVEL_LIST) <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-property">@pattern</span>
|
||||
index = <span class="hljs-property">@index</span> <span class="hljs-keyword">and</span> (<span class="hljs-property">@index</span>.compile o, LEVEL_LIST)
|
||||
scope.find(name) <span class="hljs-keyword">if</span> name <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> <span class="hljs-property">@pattern</span>
|
||||
scope.find(index) <span class="hljs-keyword">if</span> index
|
||||
rvar = scope.freeVariable <span class="hljs-string">'results'</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@returns</span>
|
||||
ivar = (<span class="hljs-property">@object</span> <span class="hljs-keyword">and</span> index) <span class="hljs-keyword">or</span> scope.freeVariable <span class="hljs-string">'i'</span>
|
||||
kvar = (<span class="hljs-property">@range</span> <span class="hljs-keyword">and</span> name) <span class="hljs-keyword">or</span> index <span class="hljs-keyword">or</span> ivar
|
||||
kvarAssign = <span class="hljs-keyword">if</span> kvar <span class="hljs-keyword">isnt</span> ivar <span class="hljs-keyword">then</span> <span class="hljs-string">"<span class="hljs-subst">#{kvar}</span> = "</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>
|
||||
rvar = scope.freeVariable <span class="hljs-string">'results'</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@returns</span>
|
||||
ivar = (<span class="hljs-property">@object</span> <span class="hljs-keyword">and</span> index) <span class="hljs-keyword">or</span> scope.freeVariable <span class="hljs-string">'i'</span>, <span class="hljs-attribute">single</span>: <span class="hljs-literal">true</span>
|
||||
kvar = (<span class="hljs-property">@range</span> <span class="hljs-keyword">and</span> name) <span class="hljs-keyword">or</span> index <span class="hljs-keyword">or</span> ivar
|
||||
kvarAssign = <span class="hljs-keyword">if</span> kvar <span class="hljs-keyword">isnt</span> ivar <span class="hljs-keyword">then</span> <span class="hljs-string">"<span class="hljs-subst">#{kvar}</span> = "</span> <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@step</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> <span class="hljs-property">@range</span>
|
||||
[step, stepVar] = <span class="hljs-property">@cacheToCodeFragments</span> <span class="hljs-property">@step</span>.cache o, LEVEL_LIST
|
||||
[step, stepVar] = <span class="hljs-property">@cacheToCodeFragments</span> <span class="hljs-property">@step</span>.cache o, LEVEL_LIST, isComplexOrAssignable
|
||||
stepNum = stepVar.match NUMBER
|
||||
name = ivar <span class="hljs-keyword">if</span> <span class="hljs-property">@pattern</span>
|
||||
varPart = <span class="hljs-string">''</span>
|
||||
guardPart = <span class="hljs-string">''</span>
|
||||
defPart = <span class="hljs-string">''</span>
|
||||
idt1 = <span class="hljs-property">@tab</span> + TAB
|
||||
name = ivar <span class="hljs-keyword">if</span> <span class="hljs-property">@pattern</span>
|
||||
varPart = <span class="hljs-string">''</span>
|
||||
guardPart = <span class="hljs-string">''</span>
|
||||
defPart = <span class="hljs-string">''</span>
|
||||
idt1 = <span class="hljs-property">@tab</span> + TAB
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@range</span>
|
||||
forPartFragments = source.compileToFragments merge(o, {<span class="hljs-attribute">index</span>: ivar, name, <span class="hljs-property">@step</span>})
|
||||
forPartFragments = source.compileToFragments merge o,
|
||||
{<span class="hljs-attribute">index</span>: ivar, name, <span class="hljs-property">@step</span>, <span class="hljs-attribute">isComplex</span>: isComplexOrAssignable}
|
||||
<span class="hljs-keyword">else</span>
|
||||
svar = <span class="hljs-property">@source</span>.compile o, LEVEL_LIST
|
||||
<span class="hljs-keyword">if</span> (name <span class="hljs-keyword">or</span> <span class="hljs-property">@own</span>) <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> IDENTIFIER.test svar
|
||||
@@ -3977,7 +4051,7 @@ some cannot.</p>
|
||||
varPart = <span class="hljs-string">"\n<span class="hljs-subst">#{idt1}</span><span class="hljs-subst">#{namePart}</span>;"</span> <span class="hljs-keyword">if</span> namePart
|
||||
<span class="hljs-keyword">if</span> <span class="hljs-property">@object</span>
|
||||
forPartFragments = [<span class="hljs-property">@makeCode</span>(<span class="hljs-string">"<span class="hljs-subst">#{kvar}</span> in <span class="hljs-subst">#{svar}</span>"</span>)]
|
||||
guardPart = <span class="hljs-string">"\n<span class="hljs-subst">#{idt1}</span>if (!<span class="hljs-subst">#{utility <span class="hljs-string">'hasProp'</span>}</span>.call(<span class="hljs-subst">#{svar}</span>, <span class="hljs-subst">#{kvar}</span>)) continue;"</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@own</span>
|
||||
guardPart = <span class="hljs-string">"\n<span class="hljs-subst">#{idt1}</span>if (!<span class="hljs-subst">#{utility <span class="hljs-string">'hasProp'</span>, o}</span>.call(<span class="hljs-subst">#{svar}</span>, <span class="hljs-subst">#{kvar}</span>)) continue;"</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@own</span>
|
||||
bodyFragments = body.compileToFragments merge(o, <span class="hljs-attribute">indent</span>: idt1), LEVEL_TOP
|
||||
<span class="hljs-keyword">if</span> bodyFragments <span class="hljs-keyword">and</span> (bodyFragments.length > <span class="hljs-number">0</span>)
|
||||
bodyFragments = [].concat <span class="hljs-property">@makeCode</span>(<span class="hljs-string">"\n"</span>), bodyFragments, <span class="hljs-property">@makeCode</span>(<span class="hljs-string">"\n"</span>)
|
||||
@@ -4264,10 +4338,10 @@ to the superclass for <code>super()</code> calls, and copies of any static prope
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">extends</span>:<span class="hljs-function"> -></span> <span class="hljs-string">"
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">extend</span>: <span class="hljs-function"><span class="hljs-params">(o)</span> -></span> <span class="hljs-string">"
|
||||
function(child, parent) {
|
||||
for (var key in parent) {
|
||||
if (<span class="hljs-subst">#{utility <span class="hljs-string">'hasProp'</span>}</span>.call(parent, key)) child[key] = parent[key];
|
||||
if (<span class="hljs-subst">#{utility <span class="hljs-string">'hasProp'</span>, o}</span>.call(parent, key)) child[key] = parent[key];
|
||||
}
|
||||
function ctor() {
|
||||
this.constructor = child;
|
||||
@@ -4378,23 +4452,13 @@ LEVEL_ACCESS = <span class="hljs-number">6</span> <span class="hljs-comment">#
|
||||
|
||||
<div class="content"><div class='highlight'><pre>TAB = <span class="hljs-string">' '</span>
|
||||
|
||||
IDENTIFIER_STR = <span class="hljs-string">"[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"</span>
|
||||
IDENTIFIER = <span class="hljs-regexp">/// ^ <span class="hljs-subst">#{IDENTIFIER_STR}</span> $ ///</span>
|
||||
IDENTIFIER = <span class="hljs-regexp">/// ^ (?!\d) [$\w\x7f-\uffff]+ $ ///</span>
|
||||
SIMPLENUM = <span class="hljs-regexp">/^[+-]?\d+$/</span>
|
||||
HEXNUM = <span class="hljs-regexp">/^[+-]?0x[\da-f]+/i</span>
|
||||
NUMBER = <span class="hljs-regexp">///^[+-]?(?:
|
||||
0x[\da-f]+ | <span class="hljs-comment"># hex</span>
|
||||
\d*\.?\d+ (?:e[+-]?\d+)? <span class="hljs-comment"># decimal</span>
|
||||
)$///</span>i
|
||||
|
||||
METHOD_DEF = <span class="hljs-regexp">/// ^
|
||||
(<span class="hljs-subst">#{IDENTIFIER_STR}</span>)
|
||||
(\.prototype)?
|
||||
(?: \.(<span class="hljs-subst">#{IDENTIFIER_STR}</span>)
|
||||
| \[("(?:[^\\"\r\n]|\\.)*"|'(?:[^\\'\r\n]|\\.)*')\]
|
||||
| \[(0x[\da-fA-F]+ | \d*\.?\d+ (?:[eE][+-]?\d+)?)\]
|
||||
)
|
||||
$ ///</span></pre></div></div>
|
||||
)$///</span>i</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -4450,10 +4514,14 @@ IS_REGEX = <span class="hljs-regexp">/^\//</span></pre></div></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">utility</span> = <span class="hljs-params">(name)</span> -></span>
|
||||
ref = <span class="hljs-string">"__<span class="hljs-subst">#{name}</span>"</span>
|
||||
Scope.root.assign ref, UTILITIES[name]()
|
||||
ref
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-function"><span class="hljs-title">utility</span> = <span class="hljs-params">(name, o)</span> -></span>
|
||||
{root} = o.scope
|
||||
<span class="hljs-keyword">if</span> name <span class="hljs-keyword">of</span> root.utilities
|
||||
root.utilities[name]
|
||||
<span class="hljs-keyword">else</span>
|
||||
ref = root.freeVariable name
|
||||
root.assign ref, UTILITIES[name] o
|
||||
root.utilities[name] = ref
|
||||
|
||||
<span class="hljs-function"><span class="hljs-title">multident</span> = <span class="hljs-params">(code, tab)</span> -></span>
|
||||
code = code.replace <span class="hljs-regexp">/\n/g</span>, <span class="hljs-string">'$&'</span> + tab
|
||||
@@ -4487,7 +4555,9 @@ Examples: 0, -1, 1, 2e3, 2e-3, -0xfe, 0xfe</p>
|
||||
<span class="hljs-function"><span class="hljs-title">isLiteralThis</span> = <span class="hljs-params">(node)</span> -></span>
|
||||
(node <span class="hljs-keyword">instanceof</span> Literal <span class="hljs-keyword">and</span> node.value <span class="hljs-keyword">is</span> <span class="hljs-string">'this'</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> node.asKey) <span class="hljs-keyword">or</span>
|
||||
(node <span class="hljs-keyword">instanceof</span> Code <span class="hljs-keyword">and</span> node.bound) <span class="hljs-keyword">or</span>
|
||||
(node <span class="hljs-keyword">instanceof</span> Call <span class="hljs-keyword">and</span> node.isSuper)</pre></div></div>
|
||||
(node <span class="hljs-keyword">instanceof</span> Call <span class="hljs-keyword">and</span> node.isSuper)
|
||||
|
||||
<span class="hljs-function"><span class="hljs-title">isComplexOrAssignable</span> = <span class="hljs-params">(node)</span> -></span> node.isComplex() <span class="hljs-keyword">or</span> node.isAssignable?()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
0
documentation/docs/public/fonts/aller-bold.eot
Executable file → Normal file
0
documentation/docs/public/fonts/aller-bold.eot
Executable file → Normal file
0
documentation/docs/public/fonts/aller-bold.ttf
Executable file → Normal file
0
documentation/docs/public/fonts/aller-bold.ttf
Executable file → Normal file
0
documentation/docs/public/fonts/aller-bold.woff
Executable file → Normal file
0
documentation/docs/public/fonts/aller-bold.woff
Executable file → Normal file
0
documentation/docs/public/fonts/aller-light.eot
Executable file → Normal file
0
documentation/docs/public/fonts/aller-light.eot
Executable file → Normal file
0
documentation/docs/public/fonts/aller-light.ttf
Executable file → Normal file
0
documentation/docs/public/fonts/aller-light.ttf
Executable file → Normal file
0
documentation/docs/public/fonts/aller-light.woff
Executable file → Normal file
0
documentation/docs/public/fonts/aller-light.woff
Executable file → Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
documentation/docs/public/fonts/roboto-black.eot
Executable file
BIN
documentation/docs/public/fonts/roboto-black.eot
Executable file
Binary file not shown.
BIN
documentation/docs/public/fonts/roboto-black.ttf
Executable file
BIN
documentation/docs/public/fonts/roboto-black.ttf
Executable file
Binary file not shown.
BIN
documentation/docs/public/fonts/roboto-black.woff
Executable file
BIN
documentation/docs/public/fonts/roboto-black.woff
Executable file
Binary file not shown.
@@ -188,11 +188,11 @@ parens. Unwrap all that.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-5">¶</a>
|
||||
</div>
|
||||
<p>Generate the AST of the clean input.</p>
|
||||
<p>Tokenize the clean input.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes input</pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> tokens = CoffeeScript.tokens input</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -203,6 +203,38 @@ parens. Unwrap all that.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-6">¶</a>
|
||||
</div>
|
||||
<p>Collect referenced variable names just like in <code>CoffeeScript.compile</code>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> referencedVars = (
|
||||
token[<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> token <span class="hljs-keyword">in</span> tokens <span class="hljs-keyword">when</span> token.variable
|
||||
)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-7">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
</div>
|
||||
<p>Generate the AST of the tokens.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> ast = CoffeeScript.nodes tokens</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-8">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
</div>
|
||||
<p>Add assignment to <code>_</code> variable to force the input to be an expression.</p>
|
||||
|
||||
</div>
|
||||
@@ -210,7 +242,7 @@ parens. Unwrap all that.</p>
|
||||
<div class="content"><div class='highlight'><pre> ast = <span class="hljs-keyword">new</span> Block [
|
||||
<span class="hljs-keyword">new</span> Assign (<span class="hljs-keyword">new</span> Value <span class="hljs-keyword">new</span> Literal <span class="hljs-string">'_'</span>), ast, <span class="hljs-string">'='</span>
|
||||
]
|
||||
js = ast.compile <span class="hljs-attribute">bare</span>: <span class="hljs-literal">yes</span>, <span class="hljs-attribute">locals</span>: Object.keys(context)
|
||||
js = ast.compile {<span class="hljs-attribute">bare</span>: <span class="hljs-literal">yes</span>, <span class="hljs-attribute">locals</span>: Object.keys(context), referencedVars}
|
||||
result = <span class="hljs-keyword">if</span> context <span class="hljs-keyword">is</span> <span class="hljs-built_in">global</span>
|
||||
vm.runInThisContext js, filename
|
||||
<span class="hljs-keyword">else</span>
|
||||
@@ -221,11 +253,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-7">
|
||||
<li id="section-9">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-7">¶</a>
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
</div>
|
||||
<p>AST’s <code>compile</code> does not add source code information to syntax errors.</p>
|
||||
|
||||
@@ -240,11 +272,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-8">
|
||||
<li id="section-10">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-8">¶</a>
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
</div>
|
||||
<p>Node 0.11.12 changed API, prompt is now _prompt.</p>
|
||||
|
||||
@@ -261,11 +293,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-9">
|
||||
<li id="section-11">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-9">¶</a>
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
</div>
|
||||
<p>Proxy node’s line listener</p>
|
||||
|
||||
@@ -286,11 +318,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-10">
|
||||
<li id="section-12">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
</div>
|
||||
<p>Handle Ctrl-v</p>
|
||||
|
||||
@@ -303,11 +335,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-11">
|
||||
<li id="section-13">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
</div>
|
||||
<p>allow arbitrarily switching between modes any time before multiple lines are entered</p>
|
||||
|
||||
@@ -322,11 +354,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-12">
|
||||
<li id="section-14">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
</div>
|
||||
<p>no-op unless the current line is empty</p>
|
||||
|
||||
@@ -337,11 +369,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-13">
|
||||
<li id="section-15">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-13">¶</a>
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
</div>
|
||||
<p>eval, print, loop</p>
|
||||
|
||||
@@ -356,11 +388,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-14">
|
||||
<li id="section-16">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-14">¶</a>
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
</div>
|
||||
<p>XXX: multiline hack</p>
|
||||
|
||||
@@ -378,11 +410,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-15">
|
||||
<li id="section-17">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-15">¶</a>
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
</div>
|
||||
<p>Store and load command history from a file</p>
|
||||
|
||||
@@ -395,11 +427,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-16">
|
||||
<li id="section-18">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-16">¶</a>
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
</div>
|
||||
<p>Get file info and at most maxSize of command history</p>
|
||||
|
||||
@@ -411,11 +443,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-17">
|
||||
<li id="section-19">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-17">¶</a>
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
</div>
|
||||
<p>Read last <code>size</code> bytes from the file</p>
|
||||
|
||||
@@ -428,11 +460,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-18">
|
||||
<li id="section-20">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-18">¶</a>
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
</div>
|
||||
<p>Set the history on the interpreter</p>
|
||||
|
||||
@@ -443,11 +475,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-19">
|
||||
<li id="section-21">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-19">¶</a>
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
</div>
|
||||
<p>If the history file was truncated we should pop off a potential partial line</p>
|
||||
|
||||
@@ -458,11 +490,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-20">
|
||||
<li id="section-22">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-20">¶</a>
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
</div>
|
||||
<p>Shift off the final blank newline</p>
|
||||
|
||||
@@ -480,11 +512,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-21">
|
||||
<li id="section-23">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-21">¶</a>
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
</div>
|
||||
<p>Save the latest command in the file</p>
|
||||
|
||||
@@ -498,11 +530,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-22">
|
||||
<li id="section-24">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-22">¶</a>
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
</div>
|
||||
<p>Add a command to show the history stack</p>
|
||||
|
||||
@@ -519,11 +551,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-23">
|
||||
<li id="section-25">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-23">¶</a>
|
||||
<a class="pilcrow" href="#section-25">¶</a>
|
||||
</div>
|
||||
<p>Node 0.11 changed API, a command such as ‘.help’ is now stored as ‘help’</p>
|
||||
|
||||
@@ -551,11 +583,11 @@ parens. Unwrap all that.</p>
|
||||
</li>
|
||||
|
||||
|
||||
<li id="section-24">
|
||||
<li id="section-26">
|
||||
<div class="annotation">
|
||||
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-24">¶</a>
|
||||
<a class="pilcrow" href="#section-26">¶</a>
|
||||
</div>
|
||||
<p>Adapt help inherited from the node REPL</p>
|
||||
|
||||
|
||||
@@ -315,20 +315,20 @@ Match it with its paired close.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-10">¶</a>
|
||||
</div>
|
||||
<p>Match tags in token stream starting at i with pattern, skipping HERECOMMENTs
|
||||
Pattern may consist of strings (equality), an array of strings (one of)
|
||||
or null (wildcard)</p>
|
||||
<p>Match tags in token stream starting at <code>i</code> with <code>pattern</code>, skipping ‘HERECOMMENT’s.
|
||||
<code>pattern</code> may consist of strings (equality), an array of strings (one of)
|
||||
or null (wildcard). Returns the index of the match or -1 if no match.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">matchTags</span>: <span class="hljs-function"><span class="hljs-params">(i, pattern...)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">indexOfTag</span>: <span class="hljs-function"><span class="hljs-params">(i, pattern...)</span> -></span>
|
||||
fuzz = <span class="hljs-number">0</span>
|
||||
<span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span> ... pattern.length]
|
||||
fuzz += <span class="hljs-number">2</span> <span class="hljs-keyword">while</span> <span class="hljs-property">@tag</span>(i + j + fuzz) <span class="hljs-keyword">is</span> <span class="hljs-string">'HERECOMMENT'</span>
|
||||
<span class="hljs-keyword">continue</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> pattern[j]?
|
||||
pattern[j] = [pattern[j]] <span class="hljs-keyword">if</span> <span class="hljs-keyword">typeof</span> pattern[j] <span class="hljs-keyword">is</span> <span class="hljs-string">'string'</span>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">no</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@tag</span>(i + j + fuzz) <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> pattern[j]
|
||||
<span class="hljs-literal">yes</span></pre></div></div>
|
||||
<span class="hljs-keyword">return</span> -<span class="hljs-number">1</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@tag</span>(i + j + fuzz) <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> pattern[j]
|
||||
i + j + fuzz - <span class="hljs-number">1</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -339,13 +339,22 @@ or null (wildcard)</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-11">¶</a>
|
||||
</div>
|
||||
<p>yes iff standing in front of something looking like
|
||||
@<x>: or <x>:, skipping over ‘HERECOMMENT’s</p>
|
||||
<p>Returns <code>yes</code> if standing in front of something looking like
|
||||
<code>@<x>:</code>, <code><x>:</code> or <code><EXPRESSION_START><x>...<EXPRESSION_END>:</code>,
|
||||
skipping over ‘HERECOMMENT’s.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">looksObjectish</span>: <span class="hljs-function"><span class="hljs-params">(j)</span> -></span>
|
||||
<span class="hljs-property">@matchTags</span>(j, <span class="hljs-string">'@'</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">':'</span>) <span class="hljs-keyword">or</span> <span class="hljs-property">@matchTags</span>(j, <span class="hljs-literal">null</span>, <span class="hljs-string">':'</span>)</pre></div></div>
|
||||
<span class="hljs-keyword">return</span> <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> <span class="hljs-property">@indexOfTag</span>(j, <span class="hljs-string">'@'</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">':'</span>) > -<span class="hljs-number">1</span> <span class="hljs-keyword">or</span> <span class="hljs-property">@indexOfTag</span>(j, <span class="hljs-literal">null</span>, <span class="hljs-string">':'</span>) > -<span class="hljs-number">1</span>
|
||||
index = <span class="hljs-property">@indexOfTag</span>(j, EXPRESSION_START)
|
||||
<span class="hljs-keyword">if</span> index > -<span class="hljs-number">1</span>
|
||||
end = <span class="hljs-literal">null</span>
|
||||
<span class="hljs-property">@detectEnd</span> index + <span class="hljs-number">1</span>, <span class="hljs-function"><span class="hljs-params">((token) -> token[<span class="hljs-number">0</span>] <span class="hljs-keyword">in</span> EXPRESSION_END)</span>, <span class="hljs-params">((token, i) -> end = i)</span>
|
||||
<span class="hljs-title">return</span> <span class="hljs-title">yes</span> <span class="hljs-title">if</span> @<span class="hljs-title">tag</span><span class="hljs-params">(end + <span class="hljs-number">1</span>)</span> <span class="hljs-title">is</span> ':'
|
||||
<span class="hljs-title">no</span>
|
||||
|
||||
</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -356,7 +365,7 @@ or null (wildcard)</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-12">¶</a>
|
||||
</div>
|
||||
<p>yes iff current line of tokens contain an element of tags on same
|
||||
<p>Returns <code>yes</code> if current line of tokens contain an element of tags on same
|
||||
expression level. Stop searching at LINEBREAKS or explicit start of
|
||||
containing balanced expression.</p>
|
||||
|
||||
@@ -403,6 +412,7 @@ add them.</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> stack = []
|
||||
start = <span class="hljs-literal">null</span>
|
||||
|
||||
<span class="hljs-property">@scanTokens</span> <span class="hljs-function"><span class="hljs-params">(token, i, tokens)</span> -></span>
|
||||
[tag] = token
|
||||
@@ -468,13 +478,15 @@ class declaration or if-conditionals)</p>
|
||||
|
||||
<span class="hljs-function"><span class="hljs-title">endImplicitCall</span> = -></span>
|
||||
stack.pop()
|
||||
tokens.splice i, <span class="hljs-number">0</span>, generate <span class="hljs-string">'CALL_END'</span>, <span class="hljs-string">')'</span>
|
||||
tokens.splice i, <span class="hljs-number">0</span>, generate <span class="hljs-string">'CALL_END'</span>, <span class="hljs-string">')'</span>, [<span class="hljs-string">''</span>, <span class="hljs-string">'end of input'</span>, token[<span class="hljs-number">2</span>]]
|
||||
i += <span class="hljs-number">1</span>
|
||||
|
||||
<span class="hljs-function"><span class="hljs-title">startImplicitObject</span> = <span class="hljs-params">(j, startsLine = <span class="hljs-literal">yes</span>)</span> -></span>
|
||||
idx = j ? i
|
||||
stack.push [<span class="hljs-string">'{'</span>, idx, <span class="hljs-attribute">sameLine</span>: <span class="hljs-literal">yes</span>, <span class="hljs-attribute">startsLine</span>: startsLine, <span class="hljs-attribute">ours</span>: <span class="hljs-literal">yes</span>]
|
||||
tokens.splice idx, <span class="hljs-number">0</span>, generate <span class="hljs-string">'{'</span>, generate(<span class="hljs-keyword">new</span> String(<span class="hljs-string">'{'</span>)), token
|
||||
val = <span class="hljs-keyword">new</span> String <span class="hljs-string">'{'</span>
|
||||
val.generated = <span class="hljs-literal">yes</span>
|
||||
tokens.splice idx, <span class="hljs-number">0</span>, generate <span class="hljs-string">'{'</span>, val, token
|
||||
i += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> j?
|
||||
|
||||
<span class="hljs-function"><span class="hljs-title">endImplicitObject</span> = <span class="hljs-params">(j)</span> -></span>
|
||||
@@ -564,7 +576,7 @@ class declaration or if-conditionals)</p>
|
||||
endImplicitObject()
|
||||
<span class="hljs-keyword">else</span>
|
||||
stack.pop()
|
||||
stack.pop()</pre></div></div>
|
||||
start = stack.pop()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -580,7 +592,7 @@ f a, f() b, f? c, h[0] d etc.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tag <span class="hljs-keyword">in</span> IMPLICIT_FUNC <span class="hljs-keyword">and</span> token.spaced <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> token.stringEnd <span class="hljs-keyword">or</span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (tag <span class="hljs-keyword">in</span> IMPLICIT_FUNC <span class="hljs-keyword">and</span> token.spaced <span class="hljs-keyword">or</span>
|
||||
tag <span class="hljs-keyword">is</span> <span class="hljs-string">'?'</span> <span class="hljs-keyword">and</span> i > <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> tokens[i - <span class="hljs-number">1</span>].spaced) <span class="hljs-keyword">and</span>
|
||||
(nextTag <span class="hljs-keyword">in</span> IMPLICIT_CALL <span class="hljs-keyword">or</span>
|
||||
nextTag <span class="hljs-keyword">in</span> IMPLICIT_UNSPACED_CALL <span class="hljs-keyword">and</span>
|
||||
@@ -619,7 +631,8 @@ that creates grammatical ambiguities.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">in</span> IMPLICIT_FUNC <span class="hljs-keyword">and</span> <span class="hljs-property">@matchTags</span>(i + <span class="hljs-number">1</span>, <span class="hljs-string">'INDENT'</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">':'</span>) <span class="hljs-keyword">and</span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> tag <span class="hljs-keyword">in</span> IMPLICIT_FUNC <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-property">@indexOfTag</span>(i + <span class="hljs-number">1</span>, <span class="hljs-string">'INDENT'</span>, <span class="hljs-literal">null</span>, <span class="hljs-string">':'</span>) > -<span class="hljs-number">1</span> <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> <span class="hljs-property">@findTagsBackwards</span>(i, [<span class="hljs-string">'CLASS'</span>, <span class="hljs-string">'EXTENDS'</span>, <span class="hljs-string">'IF'</span>, <span class="hljs-string">'CATCH'</span>,
|
||||
<span class="hljs-string">'SWITCH'</span>, <span class="hljs-string">'LEADING_WHEN'</span>, <span class="hljs-string">'FOR'</span>, <span class="hljs-string">'WHILE'</span>, <span class="hljs-string">'UNTIL'</span>])
|
||||
startImplicitCall i + <span class="hljs-number">1</span>
|
||||
@@ -654,7 +667,10 @@ that creates grammatical ambiguities.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> <span class="hljs-property">@tag</span>(i - <span class="hljs-number">2</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'@'</span> <span class="hljs-keyword">then</span> s = i - <span class="hljs-number">2</span> <span class="hljs-keyword">else</span> s = i - <span class="hljs-number">1</span>
|
||||
<div class="content"><div class='highlight'><pre> s = <span class="hljs-keyword">switch</span>
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-property">@tag</span>(i - <span class="hljs-number">1</span>) <span class="hljs-keyword">in</span> EXPRESSION_END <span class="hljs-keyword">then</span> start[<span class="hljs-number">1</span>]
|
||||
<span class="hljs-keyword">when</span> <span class="hljs-property">@tag</span>(i - <span class="hljs-number">2</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'@'</span> <span class="hljs-keyword">then</span> i - <span class="hljs-number">2</span>
|
||||
<span class="hljs-keyword">else</span> i - <span class="hljs-number">1</span>
|
||||
s -= <span class="hljs-number">2</span> <span class="hljs-keyword">while</span> <span class="hljs-property">@tag</span>(s - <span class="hljs-number">2</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'HERECOMMENT'</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -758,7 +774,7 @@ return a: 1, b: 2 unless true</p>
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> inImplicitObject() <span class="hljs-keyword">and</span> <span class="hljs-keyword">not</span> <span class="hljs-property">@insideForDeclaration</span> <span class="hljs-keyword">and</span> sameLine <span class="hljs-keyword">and</span>
|
||||
tag <span class="hljs-keyword">isnt</span> <span class="hljs-string">'TERMINATOR'</span> <span class="hljs-keyword">and</span> prevTag <span class="hljs-keyword">isnt</span> <span class="hljs-string">':'</span> <span class="hljs-keyword">and</span>
|
||||
tag <span class="hljs-keyword">isnt</span> <span class="hljs-string">'TERMINATOR'</span> <span class="hljs-keyword">and</span> prevTag <span class="hljs-keyword">isnt</span> <span class="hljs-string">':'</span>
|
||||
endImplicitObject()</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -778,6 +794,7 @@ the continuation of an object.</p>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> inImplicitObject() <span class="hljs-keyword">and</span> tag <span class="hljs-keyword">is</span> <span class="hljs-string">'TERMINATOR'</span> <span class="hljs-keyword">and</span> prevTag <span class="hljs-keyword">isnt</span> <span class="hljs-string">','</span> <span class="hljs-keyword">and</span>
|
||||
<span class="hljs-keyword">not</span> (startsLine <span class="hljs-keyword">and</span> <span class="hljs-property">@looksObjectish</span>(i + <span class="hljs-number">1</span>))
|
||||
<span class="hljs-keyword">return</span> forward <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> nextTag <span class="hljs-keyword">is</span> <span class="hljs-string">'HERECOMMENT'</span>
|
||||
endImplicitObject()
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-keyword">break</span></pre></div></div>
|
||||
@@ -1032,6 +1049,8 @@ different precedence.</p>
|
||||
[<span class="hljs-string">'CALL_START'</span>, <span class="hljs-string">'CALL_END'</span>]
|
||||
[<span class="hljs-string">'PARAM_START'</span>, <span class="hljs-string">'PARAM_END'</span>]
|
||||
[<span class="hljs-string">'INDEX_START'</span>, <span class="hljs-string">'INDEX_END'</span>]
|
||||
[<span class="hljs-string">'STRING_START'</span>, <span class="hljs-string">'STRING_END'</span>]
|
||||
[<span class="hljs-string">'REGEX_START'</span>, <span class="hljs-string">'REGEX_END'</span>]
|
||||
]</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -1114,9 +1133,10 @@ EXPRESSION_END = []
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>IMPLICIT_CALL = [
|
||||
<span class="hljs-string">'IDENTIFIER'</span>, <span class="hljs-string">'NUMBER'</span>, <span class="hljs-string">'STRING'</span>, <span class="hljs-string">'JS'</span>, <span class="hljs-string">'REGEX'</span>, <span class="hljs-string">'NEW'</span>, <span class="hljs-string">'PARAM_START'</span>, <span class="hljs-string">'CLASS'</span>
|
||||
<span class="hljs-string">'IF'</span>, <span class="hljs-string">'TRY'</span>, <span class="hljs-string">'SWITCH'</span>, <span class="hljs-string">'THIS'</span>, <span class="hljs-string">'BOOL'</span>, <span class="hljs-string">'NULL'</span>, <span class="hljs-string">'UNDEFINED'</span>, <span class="hljs-string">'UNARY'</span>,
|
||||
<span class="hljs-string">'UNARY_MATH'</span>, <span class="hljs-string">'SUPER'</span>, <span class="hljs-string">'THROW'</span>, <span class="hljs-string">'@'</span>, <span class="hljs-string">'->'</span>, <span class="hljs-string">'=>'</span>, <span class="hljs-string">'['</span>, <span class="hljs-string">'('</span>, <span class="hljs-string">'{'</span>, <span class="hljs-string">'--'</span>, <span class="hljs-string">'++'</span>
|
||||
<span class="hljs-string">'IDENTIFIER'</span>, <span class="hljs-string">'NUMBER'</span>, <span class="hljs-string">'STRING'</span>, <span class="hljs-string">'STRING_START'</span>, <span class="hljs-string">'JS'</span>, <span class="hljs-string">'REGEX'</span>, <span class="hljs-string">'REGEX_START'</span>
|
||||
<span class="hljs-string">'NEW'</span>, <span class="hljs-string">'PARAM_START'</span>, <span class="hljs-string">'CLASS'</span>, <span class="hljs-string">'IF'</span>, <span class="hljs-string">'TRY'</span>, <span class="hljs-string">'SWITCH'</span>, <span class="hljs-string">'THIS'</span>, <span class="hljs-string">'BOOL'</span>, <span class="hljs-string">'NULL'</span>
|
||||
<span class="hljs-string">'UNDEFINED'</span>, <span class="hljs-string">'UNARY'</span>, <span class="hljs-string">'YIELD'</span>, <span class="hljs-string">'UNARY_MATH'</span>, <span class="hljs-string">'SUPER'</span>, <span class="hljs-string">'THROW'</span>
|
||||
<span class="hljs-string">'@'</span>, <span class="hljs-string">'->'</span>, <span class="hljs-string">'=>'</span>, <span class="hljs-string">'['</span>, <span class="hljs-string">'('</span>, <span class="hljs-string">'{'</span>, <span class="hljs-string">'--'</span>, <span class="hljs-string">'++'</span>
|
||||
]
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = [<span class="hljs-string">'+'</span>, <span class="hljs-string">'-'</span>]</pre></div></div>
|
||||
|
||||
@@ -121,13 +121,10 @@ 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 external scopes.</p>
|
||||
<p>Import the helpers we plan to use.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre>{extend, last} = <span class="hljs-built_in">require</span> <span class="hljs-string">'./helpers'</span>
|
||||
|
||||
<span class="hljs-built_in">exports</span>.Scope = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scope</span></span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre><span class="hljs-built_in">exports</span>.Scope = <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Scope</span></span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -138,11 +135,18 @@ with external scopes.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-2">¶</a>
|
||||
</div>
|
||||
<p>The <code>root</code> is the top-level <strong>Scope</strong> object for a given file.</p>
|
||||
<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, a reference to the function that
|
||||
it belongs to, and a list of variables referenced in the source code
|
||||
and therefore should be avoided when generating variables.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-property">@root</span>: <span class="hljs-literal">null</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">constructor</span>: <span class="hljs-function"><span class="hljs-params">(<span class="hljs-property">@parent</span>, <span class="hljs-property">@expressions</span>, <span class="hljs-property">@method</span>, <span class="hljs-property">@referencedVars</span>)</span> -></span>
|
||||
<span class="hljs-property">@variables</span> = [{<span class="hljs-attribute">name</span>: <span class="hljs-string">'arguments'</span>, <span class="hljs-attribute">type</span>: <span class="hljs-string">'arguments'</span>}]
|
||||
<span class="hljs-property">@positions</span> = {}
|
||||
<span class="hljs-property">@utilities</span> = {} <span class="hljs-keyword">unless</span> <span class="hljs-property">@parent</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -153,17 +157,11 @@ with external scopes.</p>
|
||||
<div class="pilwrap ">
|
||||
<a class="pilcrow" href="#section-3">¶</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 belongs to.</p>
|
||||
<p>The <code>@root</code> is the top-level <strong>Scope</strong> object for a given file.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">constructor</span>: <span class="hljs-function"><span class="hljs-params">(<span class="hljs-property">@parent</span>, <span class="hljs-property">@expressions</span>, <span class="hljs-property">@method</span>)</span> -></span>
|
||||
<span class="hljs-property">@variables</span> = [{<span class="hljs-attribute">name</span>: <span class="hljs-string">'arguments'</span>, <span class="hljs-attribute">type</span>: <span class="hljs-string">'arguments'</span>}]
|
||||
<span class="hljs-property">@positions</span> = {}
|
||||
Scope.root = <span class="hljs-keyword">this</span> <span class="hljs-keyword">unless</span> <span class="hljs-property">@parent</span></pre></div></div>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-property">@root</span> = <span class="hljs-property">@parent</span>?.root ? <span class="hljs-keyword">this</span></pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -273,11 +271,11 @@ walks up to the root scope.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">temporary</span>: <span class="hljs-function"><span class="hljs-params">(name, index)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> name.length > <span class="hljs-number">1</span>
|
||||
<span class="hljs-string">'_'</span> + name + <span class="hljs-keyword">if</span> index > <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> index - <span class="hljs-number">1</span> <span class="hljs-keyword">else</span> <span class="hljs-string">''</span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">temporary</span>: <span class="hljs-function"><span class="hljs-params">(name, index, single=<span class="hljs-literal">false</span>)</span> -></span>
|
||||
<span class="hljs-keyword">if</span> single
|
||||
(index + parseInt name, <span class="hljs-number">36</span>).toString(<span class="hljs-number">36</span>).replace <span class="hljs-regexp">/\d/g</span>, <span class="hljs-string">'a'</span>
|
||||
<span class="hljs-keyword">else</span>
|
||||
<span class="hljs-string">'_'</span> + (index + parseInt name, <span class="hljs-number">36</span>).toString(<span class="hljs-number">36</span>).replace <span class="hljs-regexp">/\d/g</span>, <span class="hljs-string">'a'</span></pre></div></div>
|
||||
name + (index <span class="hljs-keyword">or</span> <span class="hljs-string">''</span>)</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -310,10 +308,13 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
|
||||
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">freeVariable</span>: <span class="hljs-function"><span class="hljs-params">(name, reserve=<span class="hljs-literal">true</span>)</span> -></span>
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">freeVariable</span>: <span class="hljs-function"><span class="hljs-params">(name, options={})</span> -></span>
|
||||
index = <span class="hljs-number">0</span>
|
||||
index++ <span class="hljs-keyword">while</span> <span class="hljs-property">@check</span>((temp = <span class="hljs-property">@temporary</span> name, index))
|
||||
<span class="hljs-property">@add</span> temp, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> reserve
|
||||
<span class="hljs-keyword">loop</span>
|
||||
temp = <span class="hljs-property">@temporary</span> name, index, options.single
|
||||
<span class="hljs-keyword">break</span> <span class="hljs-keyword">unless</span> <span class="hljs-property">@check</span>(temp) <span class="hljs-keyword">or</span> temp <span class="hljs-keyword">in</span> <span class="hljs-property">@root</span>.referencedVars
|
||||
index++
|
||||
<span class="hljs-property">@add</span> temp, <span class="hljs-string">'var'</span>, <span class="hljs-literal">yes</span> <span class="hljs-keyword">if</span> options.reserve ? <span class="hljs-literal">true</span>
|
||||
temp</pre></div></div>
|
||||
|
||||
</li>
|
||||
@@ -364,11 +365,7 @@ compiler-generated variable. <code>_var</code>, <code>_var2</code>, and so on…
|
||||
</div>
|
||||
|
||||
<div class="content"><div class='highlight'><pre> <span class="hljs-attribute">declaredVariables</span>:<span class="hljs-function"> -></span>
|
||||
realVars = []
|
||||
tempVars = []
|
||||
<span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> <span class="hljs-property">@variables</span> <span class="hljs-keyword">when</span> v.type <span class="hljs-keyword">is</span> <span class="hljs-string">'var'</span>
|
||||
(<span class="hljs-keyword">if</span> v.name.charAt(<span class="hljs-number">0</span>) <span class="hljs-keyword">is</span> <span class="hljs-string">'_'</span> <span class="hljs-keyword">then</span> tempVars <span class="hljs-keyword">else</span> realVars).push v.name
|
||||
realVars.sort().concat tempVars.sort()</pre></div></div>
|
||||
(v.name <span class="hljs-keyword">for</span> v <span class="hljs-keyword">in</span> <span class="hljs-property">@variables</span> <span class="hljs-keyword">when</span> v.type <span class="hljs-keyword">is</span> <span class="hljs-string">'var'</span>).sort()</pre></div></div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 6.4 KiB |
25
documentation/images/just_logo.svg
Normal file
25
documentation/images/just_logo.svg
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="-76 212 458 369" enable-background="new -76 212 458 369" xml:space="preserve">
|
||||
<title>CoffeeScript Logo</title>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#28334C" d="M106,228.6c0.5,2.3-0.9,4.4-5,6.5c-5.5-3.1-16.9-4.4-26.7-3.5c-10.4,0.9-19.4,4.2-17.9,11.3
|
||||
c1.5,7.1,11.7,11,29.5,9.5c43.6-3.8,43.4-33.3,107.4-39c49.8-4.4,77.8,11,81.8,29.7c3.1,14.7-9.1,28.6-45.2,31.8
|
||||
c-32,2.8-50.7-5.6-52.6-14.6c-1-4.5,1.8-11.3,17.2-13.1c1.5,7,10.6,14.4,31.1,12.6c14.8-1.3,27.6-6.6,25.9-14.9
|
||||
c-1.8-8.6-17.7-13.7-42.6-11.5c-50.7,4.5-63.2,32.5-106.8,36.3c-30.8,2.7-55.9-8.5-59.4-25.1c-1.3-6.1-1.4-21,31.2-23.9
|
||||
C91,219.2,104.6,222.2,106,228.6L106,228.6z M-56.4,402.5c-14.3,18-20.4,38.8-19.2,59.2c1.2,20.4,11.4,37.1,26.9,50.2
|
||||
C-32,525-14,528.6,6.4,525c7.8-1.2,16.7-5.3,24.5-7.8c-16.7,0-31-5.3-44.9-16.7c-15.5-11.4-25.7-26.9-28.2-46.1
|
||||
c-3.7-18,0-34.7,10.2-49c11.4-14.3,25.7-22,44.9-24.5c19.2-1.2,35.9,3.7,52.6,15.5c-3.7-5.3-9-9-14.3-14.3
|
||||
c-16.7-11.4-34.7-16.7-56.7-11.4C-25.4,374.3-42.2,384.5-56.4,402.5z M167.2,306.2c-53.9,0-101.6-5.3-136.3-13.1
|
||||
c-37.1-9-56.7-19.2-56.7-32.2c0-5.3,2.4-10.2,10.2-15.5c-23.3,9-35.9,16.7-35.9,28.2c1.2,13.1,22,25.7,64.5,35.9
|
||||
c40,10.2,91.4,15.5,153,15.5c62.8,0,113-5.3,153-15.5c42.4-10.2,62.8-23.3,62.8-35.9c0-9-9-18-25.7-24.5c3.7,2.4,6.5,6.5,6.5,11.4
|
||||
c0,13.1-19.2,23.3-57.9,32.2C268.7,300.9,222.6,306.2,167.2,306.2L167.2,306.2z M320.2,342.1c-40,9-91.4,15.5-153,15.5
|
||||
c-62.8,0-114.2-6.5-154.2-15.5c-35.9-9-55.1-19.2-61.6-29.4c6.5,44.9,22,87.3,42.4,124.8c15.5,23.3,31,43.7,46.1,65.7
|
||||
c6.5,13.1,11.4,25.7,14.3,38.8c10.2,14.3,24.5,23.3,42.4,28.2c22,7.8,44.9,11.4,68.1,10.2h2.4c23.3,1.2,47.7-2.4,70.6-10.2
|
||||
c16.7-5.3,31-14.3,41.2-28.2h1.2c2.4-13.1,6.5-25.7,13.1-38.8c15.5-22,31-42.4,46.1-65.7c20.4-37.1,34.7-79.6,42.4-124.8
|
||||
C374,324.1,354.8,334.3,320.2,342.1L320.2,342.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
59
documentation/images/logo.svg
Normal file
59
documentation/images/logo.svg
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="-22 347 566 100" enable-background="new -22 347 566 100" xml:space="preserve">
|
||||
<title>CoffeeScript Logo</title>
|
||||
<g>
|
||||
<g>
|
||||
<path id="Shape" fill="#28334C" d="M21.7,351.1c0.1,0.6-0.2,1.1-1.2,1.6c-1.3-0.7-4.1-1.1-6.4-0.9c-2.5,0.2-4.6,1-4.3,2.7
|
||||
c0.4,1.7,2.8,2.7,7.1,2.3c10.5-0.9,10.4-8,25.8-9.4c12-1.1,18.7,2.6,19.6,7.1c0.7,3.5-2.2,6.9-10.9,7.6
|
||||
c-7.7,0.7-12.2-1.4-12.6-3.5c-0.2-1.1,0.4-2.7,4.1-3.1c0.4,1.7,2.5,3.5,7.5,3c3.6-0.3,6.6-1.6,6.2-3.6c-0.4-2.1-4.2-3.3-10.2-2.8
|
||||
c-12.2,1.1-15.2,7.8-25.6,8.7c-7.4,0.7-13.4-2-14.2-6c-0.3-1.5-0.3-5,7.5-5.7C18.1,348.8,21.3,349.5,21.7,351.1z M-17.3,392.9
|
||||
c-3.4,4.3-4.9,9.3-4.6,14.2c0.3,4.9,2.7,8.9,6.5,12c4,3.1,8.3,4,13.2,3.1c1.9-0.3,4-1.3,5.9-1.9c-4,0-7.4-1.3-10.8-4
|
||||
c-3.7-2.7-6.2-6.5-6.8-11.1c-0.9-4.3,0-8.3,2.4-11.8c2.7-3.4,6.2-5.3,10.8-5.9c4.6-0.3,8.6,0.9,12.6,3.7c-0.9-1.3-2.2-2.2-3.4-3.4
|
||||
c-4-2.7-8.3-4-13.6-2.7C-9.9,386.1-13.9,388.6-17.3,392.9z M36.3,369.8c-12.9,0-24.4-1.3-32.7-3.1c-8.9-2.2-13.6-4.6-13.6-7.7
|
||||
c0-1.3,0.6-2.4,2.4-3.7c-5.6,2.2-8.6,4-8.6,6.8c0.3,3.1,5.3,6.2,15.5,8.6c9.6,2.4,21.9,3.7,36.7,3.7c15.1,0,27.1-1.3,36.7-3.7
|
||||
c10.2-2.4,15.1-5.6,15.1-8.6c0-2.2-2.2-4.3-6.2-5.9c0.9,0.6,1.6,1.6,1.6,2.7c0,3.1-4.6,5.6-13.9,7.7
|
||||
C60.7,368.5,49.7,369.8,36.3,369.8z M73.1,378.4c-9.6,2.2-21.9,3.7-36.7,3.7c-15.1,0-27.4-1.6-37-3.7c-8.6-2.2-13.2-4.6-14.8-7.1
|
||||
c1.6,10.8,5.3,21,10.2,30c3.7,5.6,7.4,10.5,11.1,15.8c1.6,3.1,2.7,6.2,3.4,9.3c2.4,3.4,5.9,5.6,10.2,6.8
|
||||
c5.3,1.9,10.8,2.7,16.4,2.4h0.6c5.6,0.3,11.5-0.6,16.9-2.4c4-1.3,7.4-3.4,9.9-6.8h0.3c0.6-3.1,1.6-6.2,3.1-9.3
|
||||
c3.7-5.3,7.4-10.2,11.1-15.8c4.9-8.9,8.3-19.1,10.2-30C86,374.1,81.4,376.5,73.1,378.4z"/>
|
||||
<g>
|
||||
<path fill="#28334C" d="M179.3,408.5c-4.8,12.1-17.6,16.9-25.9,16.9c-13.4,0-19.9-6-19.9-22.3c0-16.5,7.9-47.3,31.7-47.3
|
||||
c8.5,0,15.2,3.3,15.2,12.1c0,4.8-1.8,8.3-6.4,8.3c-1.5,0-3.4-0.4-5.2-2.4c2.2-1.1,4.2-4.9,4.2-8.3c0-2.9-1.5-5.6-5.6-5.6
|
||||
c-10,0-18.9,23.9-18.9,42.4c0,8.3,2.2,14.2,10.9,14.2c7.1,0,13.5-3.4,17.7-9.1L179.3,408.5z M212.2,392.2c0.4,0.2,0.7,0.2,1,0.2
|
||||
c4.2,0,10.1-2.7,14-5.5l0.8,2.4c-3.4,3.7-9.5,6.5-16.1,7.5c-1.5,16.8-10.6,27.3-21.7,27.3c-8.4,0-14.5-4-14.5-14.4
|
||||
c0-10.5,6.2-32.2,24.9-32.2C208.4,377.8,212.2,382.8,212.2,392.2z M204.5,397.2c-1.9-0.5-2.4-2-2.4-3.8c0-2.5,1.2-4.2,2.8-4.9
|
||||
c-0.2-3.8-1.1-5.3-3.4-5.3c-6.5,0-12,16.6-12,25.6c0,6,1.2,7.3,4.6,7.3C198.3,416.2,203,408.1,204.5,397.2L204.5,397.2z
|
||||
M197.9,436.9c0-8.3,7.1-11,15.8-13.6l10.9-51.9c2.7-13,10.6-15.5,16.5-15.5c4.1,0,8,2.2,9.7,5.7c3.6-4.6,8.4-5.7,12.4-5.7
|
||||
c5.6,0,10.8,3.9,10.8,9.8c0,1.5-0.1,2.6-0.3,3.7h-4.3c0.1-0.9,0.2-1.7,0.2-2.4c0-2.1-1.7-3.1-3.4-3.1c-2,0-4.8,1.1-6.2,7.1
|
||||
l-1.7,7.4h9.1l-0.8,3.6h-9l-10.3,49.1c-2.7,13-10.6,15.5-16.5,15.5c-5.2,0-8.3-2.3-9.8-5.7c-3.5,4.6-8.3,5.7-12.3,5.7
|
||||
C203.1,446.7,197.9,442.8,197.9,436.9L197.9,436.9z M207,438.7c1.9,0,4.2-1.8,5.4-7.1l1.1-5.3c-5.7,2-10.1,4.4-10.1,9.4
|
||||
C203.4,436.9,205.1,438.7,207,438.7z M228.7,438.7c1.9,0,4.2-1.8,5.4-7.1l2.2-10.4l-9.4,1.8l-1.8,8.3c-0.5,2.1-1.1,4-1.8,5.6
|
||||
C224.2,438.2,226.3,438.7,228.7,438.7L228.7,438.7z M227.3,420.7l9.4-1.7l7.7-36.8h-9L227.3,420.7L227.3,420.7z M243.9,364
|
||||
c-2,0-4.8,1.1-6.2,7.1l-1.7,7.4h9l2.1-9.5c0.2-0.7,0.2-1.3,0.2-2C247.4,365,245.8,364,243.9,364z M281.8,417
|
||||
c7.1,0,11.6-4,16.1-9.2h3.1c-5.2,8.3-12.9,16.8-25,16.8c-8.5,0-14.2-4.2-14.2-14.5c0-10.5,5.9-32.3,24.6-32.3
|
||||
c8.1,0,10,4.2,10,8.7c0,10.5-10,18.5-20.9,19.2c-0.1,1.3-0.2,2.5-0.2,3.6C275.3,415.5,277.5,417,281.8,417z M287.1,382.6
|
||||
c-4.6,0-9.1,9.7-10.9,18.7c7-0.5,13.2-7.4,13.2-15C289.4,384.1,288.9,382.6,287.1,382.6L287.1,382.6z M315.7,416
|
||||
c3.4,0,7.8-2.3,10.8-4.8c-2,10.4-8.4,13.4-15.8,13.4c-8.4,0-14.1-4.2-14.1-14.5c0-10.5,5.9-32.3,24.6-32.3c8.1,0,10,4.2,10,8.7
|
||||
c0,10.6-10,18.5-20.9,19.2c-0.1,0.9-0.2,2-0.2,2.7C310.1,414.1,312.6,416,315.7,416z M321.9,382.6c-4.5,0-9.1,10.1-11,18.7
|
||||
c7.1-0.4,13.3-7.3,13.3-15C324.2,384.1,323.6,382.6,321.9,382.6z M373.2,375.9c-1.7,0-3-0.6-4.2-1.9c2.4-1.5,4.1-4.8,4.1-7.8
|
||||
c0-3.1-1.8-6.1-6.8-6.1s-8.3,2.8-8.3,8.2c0,13.3,20.5,15.2,20.5,34.8c0,15.3-12.3,22.7-25.6,22.7c-10.4,0-19.3-4.5-19.3-15.7
|
||||
c0-9.8,7-14.9,13.3-14.9c3.1,0,7.7,1.3,8,6c-4.9,0-10.7,2.3-10.7,8.5c0,4.5,2.9,8.7,8.7,8.7c6.1,0,10.6-4.4,10.6-12
|
||||
c0-15.6-18.6-21.1-18.6-34.5c0-9.5,9.3-16.3,21-16.3c4.3,0,14.6,0.9,14.6,10.9C380.6,372,377.7,375.9,373.2,375.9L373.2,375.9z
|
||||
M409.4,386.2c0-2.3-0.8-3.7-2.5-3.7c-5.7,0-11.7,16.6-11.7,26.7c0,6.2,2.2,7.6,6.6,7.6c7.1,0,11.6-4,16.1-9.2h3.1
|
||||
c-5.2,8.3-12.9,16.8-25,16.8c-8.5,0-14.2-4.2-14.2-14.5c0-10.6,6-32.3,24.5-32.3c8.1,0,10.1,4.2,10.1,8.3c0,4.4-2.2,6.7-4.8,6.7
|
||||
c-1,0-2.1-0.4-3.1-1.1C409,389.6,409.4,387.9,409.4,386.2z M437.1,378.6l-1.2,5.7c3.1-2.7,6.7-5.7,11-5.7c4.1,0,6.3,3.3,6.3,6.9
|
||||
c0,3.1-2.1,6.7-6.6,6.7c-5.1,0-2.5-6-5.3-6c-2.7,0-4.4,1.4-6.7,3.4l-7.2,34.6h-13.1l9.6-45.4L437.1,378.6L437.1,378.6z
|
||||
M471.3,378.6l-6.6,30.9c-0.3,1.2-0.4,2.1-0.4,2.9c0,2.5,1.2,3.3,3.7,3.3c3.5,0,6.9-3.4,8.1-8h3.8c-5.2,14.8-14.2,16.8-19.1,16.8
|
||||
c-5.5,0-9.7-3.2-9.7-10.9c0-1.8,0.3-3.7,0.7-5.9l6.2-29.2C458,378.5,471.3,378.6,471.3,378.6z M467.2,359.2c4,0,7.2,3.2,7.2,7.2
|
||||
s-3.2,7.1-7.2,7.1s-7.1-3.1-7.1-7.1C460,362.4,463.3,359.2,467.2,359.2z M496.3,375.2l-1.5,6.9c2.6-2.3,6.1-3.9,10.7-3.9
|
||||
c6.2,0,11.1,3.5,11.1,14.4c0,12.2-4.7,32.1-22.3,32.1c-4.5,0-6.8-1.6-7.7-3.2l-4.7,22.1l-13.7,3.2l15.2-71.5
|
||||
C483.4,375.3,496.3,375.2,496.3,375.2z M504.1,392.2c0-7-2.9-7.5-4.5-7.5c-2,0-4.5,1.6-6.3,4.4l-5.4,25.5c0.4,1,1.4,2.1,3.4,2.1
|
||||
C501,416.7,504.1,400.8,504.1,392.2z M531.9,409.5c-0.3,1.1-0.5,2.2-0.5,3.1c0,1.9,0.7,3.2,3.1,3.2c0.7,0,1.7,0,2.4-0.3
|
||||
c-2.5,7.8-6.6,8.9-9.6,8.9c-6.4,0-9.1-4.4-9.1-10.3c0-1.6,0.2-3.1,0.6-4.8l5.8-27.2h-3l0.7-3.6h3L528,366l13.4-1.9
|
||||
c0,0-1.4,6.2-3.1,14.4h5.5l-0.7,3.6h-5.5L531.9,409.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.9 KiB |
@@ -34,7 +34,7 @@
|
||||
<a href="#operators">Operators and Aliases</a>
|
||||
<a href="#classes">Classes, Inheritance, and Super</a>
|
||||
<a href="#destructuring">Destructuring Assignment</a>
|
||||
<a href="#fat-arrow">Function Binding</a>
|
||||
<a href="#fat-arrow">Bound and Generator Functions</a>
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch and Try/Catch</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffeescript/tarball/1.8.0">1.8.0</a>
|
||||
<a href="http://github.com/jashkenas/coffeescript/tarball/1.9.1">1.9.1</a>
|
||||
</p>
|
||||
|
||||
<pre>npm install -g coffee-script</pre>
|
||||
@@ -142,8 +142,8 @@
|
||||
|
||||
<p>
|
||||
To install, first make sure you have a working copy of the latest stable version of
|
||||
<a href="http://nodejs.org/">Node.js</a>, and <a href="http://npmjs.org">npm</a>
|
||||
(the Node Package Manager). You can then install CoffeeScript globally with npm:
|
||||
<a href="http://nodejs.org/">Node.js</a>. You can then install CoffeeScript globally
|
||||
with <a href="http://npmjs.org">npm</a>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -707,7 +707,7 @@ Expressions
|
||||
<%= codeFor('soaks') %>
|
||||
<p>
|
||||
Soaking up nulls is similar to Ruby's
|
||||
<a href="http://andand.rubyforge.org/">andand gem</a>, and to the
|
||||
<a href="https://rubygems.org/gems/andand">andand gem</a>, and to the
|
||||
<a href="http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator%28%3F.%29">safe navigation operator</a>
|
||||
in Groovy.
|
||||
</p>
|
||||
@@ -793,7 +793,7 @@ Expressions
|
||||
|
||||
<p>
|
||||
<span id="fat-arrow" class="bookmark"></span>
|
||||
<b class="header">Function binding</b>
|
||||
<b class="header">Bound Functions, Generator Functions</b>
|
||||
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
|
||||
object that the current function is attached to. If you pass a function as
|
||||
a callback or attach it to a different object, the original value of <tt>this</tt>
|
||||
@@ -820,6 +820,13 @@ Expressions
|
||||
be automatically bound to each instance of the class when the instance is
|
||||
constructed.
|
||||
</p>
|
||||
<p>
|
||||
CoffeeScript functions also support
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*">ES6 generator functions</a>
|
||||
through the <tt>yield</tt> keyword. There's no <tt>function*(){}</tt>
|
||||
nonsense — a generator in CoffeeScript is simply a function that yields.
|
||||
</p>
|
||||
<%= codeFor('generators', 'ps.next().value') %>
|
||||
|
||||
<p>
|
||||
<span id="embedded" class="bookmark"></span>
|
||||
@@ -1045,14 +1052,18 @@ Expressions
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.packtpub.com/coffeescript-application-development/book">CoffeeScript Application Development</a>
|
||||
is a new book from Packt Publishing that introduces CoffeeScript while
|
||||
from Packt, introduces CoffeeScript while
|
||||
walking through the process of building a demonstration web application.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.manning.com/lee/">CoffeeScript in Action</a>
|
||||
is a new book from Manning Publications that covers CoffeeScript syntax, composition techniques
|
||||
from Manning Publications, covers CoffeeScript syntax, composition techniques
|
||||
and application development.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.dpunkt.de/buecher/4021/coffeescript.html">CoffeeScript: Die Alternative zu JavaScript</a>
|
||||
from dpunkt.verlag, is the first CoffeeScript book in Deutsch.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
@@ -1115,8 +1126,8 @@ Expressions
|
||||
the Bolo tank game for modern browsers.
|
||||
</li>
|
||||
<li>
|
||||
<b>josh</b>'s <a href="http://josh.github.com/nack/">nack</a>, a Node.js-powered
|
||||
<a href="http://rack.rubyforge.org/">Rack</a> server.
|
||||
<b>github</b>'s <a href="https://atom.io/">Atom</a>,
|
||||
a hackable text editor built on web technologies.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1192,6 +1203,53 @@ Expressions
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<%= releaseHeader('2015-02-18', '1.9.1', '1.9.0') %>
|
||||
<ul>
|
||||
<li>
|
||||
Interpolation now works in object literal keys (again). You can use this to
|
||||
dynamically name properties.
|
||||
</li>
|
||||
<li>
|
||||
Internal compiler names no longer start with underscores. This makes
|
||||
the generated JavaScript a bit prettier, and also fixes an issue with
|
||||
the completely broken and ungodly way that AngularJS "parses" function
|
||||
arguments.
|
||||
</li>
|
||||
<li>
|
||||
Fixed a few <tt>yield</tt>-related bugs.
|
||||
</li>
|
||||
<li>
|
||||
Minor bug fixes and various improvements to compiler error messages.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<%= releaseHeader('2015-01-29', '1.9.0', '1.8.0') %>
|
||||
<ul>
|
||||
<li>
|
||||
CoffeeScript now supports ES6 generators. A generator is simply a function
|
||||
that <tt>yield</tt>s.
|
||||
</li>
|
||||
<li>
|
||||
More robust parsing and improved error messages for strings and regexes —
|
||||
especially with respect to interpolation.
|
||||
</li>
|
||||
<li>
|
||||
Changed strategy for the generation of internal compiler variable names.
|
||||
Note that this means that <tt>@example</tt> function parameters are no longer
|
||||
available as naked <tt>example</tt> variables within the function body.
|
||||
</li>
|
||||
<li>
|
||||
Fixed REPL compatibility with latest versions of Node and Io.js.
|
||||
</li>
|
||||
<li>
|
||||
Various minor bug fixes.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<%= releaseHeader('2014-08-26', '1.8.0', '1.7.1') %>
|
||||
<ul>
|
||||
@@ -1463,7 +1521,7 @@ Expressions
|
||||
effectively creating a shallow copy of the list.
|
||||
</li>
|
||||
<li>
|
||||
Additional tweaks and improvments to <tt>coffee --watch</tt> under
|
||||
Additional tweaks and improvements to <tt>coffee --watch</tt> under
|
||||
Node's "new" file watching API. Watch will now beep by default
|
||||
if you introduce a syntax error into a watched script. We also now
|
||||
ignore hidden directories by default when watching recursively.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var volume, winner;
|
||||
|
||||
if (ignition === true) {
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var courses, dish, food, foods, i, j, k, l, len, len1, len2, ref;
|
||||
|
||||
_ref = ['toast', 'cheese', 'wine'];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
food = _ref[_i];
|
||||
ref = ['toast', 'cheese', 'wine'];
|
||||
for (j = 0, len = ref.length; j < len; j++) {
|
||||
food = ref[j];
|
||||
eat(food);
|
||||
}
|
||||
|
||||
courses = ['greens', 'caviar', 'truffles', 'roast', 'cake'];
|
||||
|
||||
for (i = _j = 0, _len1 = courses.length; _j < _len1; i = ++_j) {
|
||||
for (i = k = 0, len1 = courses.length; k < len1; i = ++k) {
|
||||
dish = courses[i];
|
||||
menu(i + 1, dish);
|
||||
}
|
||||
|
||||
foods = ['broccoli', 'spinach', 'chocolate'];
|
||||
|
||||
for (_k = 0, _len2 = foods.length; _k < _len2; _k++) {
|
||||
food = foods[_k];
|
||||
for (l = 0, len2 = foods.length; l < len2; l++) {
|
||||
food = foods[l];
|
||||
if (food !== 'chocolate') {
|
||||
eat(food);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
|
||||
/*
|
||||
SkinnyMochaHalfCaffScript Compiler v1.0
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var fs;
|
||||
|
||||
fs = require('fs');
|
||||
@@ -10,5 +10,5 @@ task('build:parser', 'rebuild the Jison parser', function(options) {
|
||||
require('jison');
|
||||
code = require('./lib/grammar').parser.generate();
|
||||
dir = options.output || 'lib';
|
||||
return fs.writeFile("" + dir + "/parser.js", code);
|
||||
return fs.writeFile(dir + "/parser.js", code);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
$('body').click(function(e) {
|
||||
return $('.box').fadeIn('fast').addClass('.active');
|
||||
}).css('background', 'white');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var Animal, Horse, Snake, sam, tom,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
Animal = (function() {
|
||||
function Animal(name) {
|
||||
@@ -16,8 +16,8 @@ Animal = (function() {
|
||||
|
||||
})();
|
||||
|
||||
Snake = (function(_super) {
|
||||
__extends(Snake, _super);
|
||||
Snake = (function(superClass) {
|
||||
extend(Snake, superClass);
|
||||
|
||||
function Snake() {
|
||||
return Snake.__super__.constructor.apply(this, arguments);
|
||||
@@ -32,8 +32,8 @@ Snake = (function(_super) {
|
||||
|
||||
})(Animal);
|
||||
|
||||
Horse = (function(_super) {
|
||||
__extends(Horse, _super);
|
||||
Horse = (function(superClass) {
|
||||
extend(Horse, superClass);
|
||||
|
||||
function Horse() {
|
||||
return Horse.__super__.constructor.apply(this, arguments);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var cholesterol, healthy;
|
||||
|
||||
cholesterol = 127;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var date, mood;
|
||||
|
||||
if (singing) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var Person, tim;
|
||||
|
||||
Person = (function() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var fill;
|
||||
|
||||
fill = function(container, liquid) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var filename, _fn, _i, _len;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var filename, fn, i, len;
|
||||
|
||||
_fn = function(filename) {
|
||||
fn = function(filename) {
|
||||
return fs.readFile(filename, function(err, contents) {
|
||||
return compile(filename, contents.toString());
|
||||
});
|
||||
};
|
||||
for (_i = 0, _len = list.length; _i < _len; _i++) {
|
||||
filename = list[_i];
|
||||
_fn(filename);
|
||||
for (i = 0, len = list.length; i < len; i++) {
|
||||
filename = list[i];
|
||||
fn(filename);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var hi;
|
||||
|
||||
hi = function() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var footprints, solipsism, speed;
|
||||
|
||||
if ((typeof mind !== "undefined" && mind !== null) && (typeof world === "undefined" || world === null)) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var first, last, text, _ref;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var first, last, ref, text;
|
||||
|
||||
text = "Every literary critic believes he will outwit history and have the last word";
|
||||
|
||||
_ref = text.split(" "), first = _ref[0], last = _ref[_ref.length - 1];
|
||||
ref = text.split(" "), first = ref[0], last = ref[ref.length - 1];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var eldest, grade;
|
||||
|
||||
grade = function(student) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var one, six, three, two;
|
||||
|
||||
six = (one = 1) + (two = 2) + (three = 3);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var globals, name;
|
||||
|
||||
globals = ((function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
var results;
|
||||
results = [];
|
||||
for (name in window) {
|
||||
_results.push(name);
|
||||
results.push(name);
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})()).slice(0, 10);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var error;
|
||||
|
||||
alert((function() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var Account;
|
||||
|
||||
Account = function(customer, cart) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var cube, square;
|
||||
|
||||
square = function(x) {
|
||||
|
||||
13
documentation/js/generators.js
Normal file
13
documentation/js/generators.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var perfectSquares;
|
||||
|
||||
perfectSquares = function*() {
|
||||
var num;
|
||||
num = 0;
|
||||
while (true) {
|
||||
num += 1;
|
||||
(yield num * num);
|
||||
}
|
||||
};
|
||||
|
||||
window.ps || (window.ps = perfectSquares());
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var html;
|
||||
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var OPERATOR;
|
||||
|
||||
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var author, quote, sentence;
|
||||
|
||||
author = "Wittgenstein";
|
||||
|
||||
quote = "A picture is a fact. -- " + author;
|
||||
|
||||
sentence = "" + (22 / 7) + " is a decent approximation of π";
|
||||
sentence = (22 / 7) + " is a decent approximation of π";
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var city, forecast, temp, weatherReport, _ref;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var city, forecast, ref, temp, weatherReport;
|
||||
|
||||
weatherReport = function(location) {
|
||||
return [location, 72, "Mostly Sunny"];
|
||||
};
|
||||
|
||||
_ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast = _ref[2];
|
||||
ref = weatherReport("Berkeley, CA"), city = ref[0], temp = ref[1], forecast = ref[2];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var age, ages, child, yearsOld;
|
||||
|
||||
yearsOld = {
|
||||
@@ -8,11 +8,11 @@ yearsOld = {
|
||||
};
|
||||
|
||||
ages = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
var results;
|
||||
results = [];
|
||||
for (child in yearsOld) {
|
||||
age = yearsOld[child];
|
||||
_results.push("" + child + " is " + age);
|
||||
results.push(child + " is " + age);
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var city, futurists, name, street, _ref, _ref1;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var city, futurists, name, ref, ref1, street;
|
||||
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
@@ -10,4 +10,4 @@ futurists = {
|
||||
}
|
||||
};
|
||||
|
||||
_ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[0], city = _ref1[1]);
|
||||
ref = futurists.poet, name = ref.name, (ref1 = ref.address, street = ref1[0], city = ref1[1]);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var bitlist, kids, singers, song;
|
||||
|
||||
song = ["do", "re", "mi", "fa", "so"];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
$('.account').attr({
|
||||
"class": 'active'
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var cubes, list, math, num, number, opposite, race, square,
|
||||
__slice = [].slice;
|
||||
slice = [].slice;
|
||||
|
||||
number = 42;
|
||||
|
||||
@@ -26,7 +26,7 @@ math = {
|
||||
|
||||
race = function() {
|
||||
var runners, winner;
|
||||
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||
winner = arguments[0], runners = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
||||
return print(winner, runners);
|
||||
};
|
||||
|
||||
@@ -35,11 +35,11 @@ if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
}
|
||||
|
||||
cubes = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = list.length; _i < _len; _i++) {
|
||||
num = list[_i];
|
||||
_results.push(math.cube(num));
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = list.length; i < len; i++) {
|
||||
num = list[i];
|
||||
results.push(math.cube(num));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var theBait, theSwitch, _ref;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var ref, theBait, theSwitch;
|
||||
|
||||
theBait = 1000;
|
||||
|
||||
theSwitch = 0;
|
||||
|
||||
_ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
|
||||
ref = [theSwitch, theBait], theBait = ref[0], theSwitch = ref[1];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var close, contents, open, tag, _i, _ref,
|
||||
__slice = [].slice;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var close, contents, i, open, ref, tag,
|
||||
slice = [].slice;
|
||||
|
||||
tag = "<impossible>";
|
||||
|
||||
_ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];
|
||||
ref = tag.split(""), open = ref[0], contents = 3 <= ref.length ? slice.call(ref, 1, i = ref.length - 1) : (i = 1, []), close = ref[i++];
|
||||
|
||||
2
documentation/js/prototypes.js
vendored
2
documentation/js/prototypes.js
vendored
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
String.prototype.dasherize = function() {
|
||||
return this.replace(/_/g, "-");
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var countdown, num;
|
||||
|
||||
countdown = (function() {
|
||||
var _i, _results;
|
||||
_results = [];
|
||||
for (num = _i = 10; _i >= 1; num = --_i) {
|
||||
_results.push(num);
|
||||
var i, results;
|
||||
results = [];
|
||||
for (num = i = 10; i >= 1; num = --i) {
|
||||
results.push(num);
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var changeNumbers, inner, outer;
|
||||
|
||||
outer = 1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var copy, end, middle, numbers, start;
|
||||
|
||||
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var zip, _ref;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var ref, zip;
|
||||
|
||||
zip = typeof lottery.drawWinner === "function" ? (_ref = lottery.drawWinner().address) != null ? _ref.zipcode : void 0 : void 0;
|
||||
zip = typeof lottery.drawWinner === "function" ? (ref = lottery.drawWinner().address) != null ? ref.zipcode : void 0 : void 0;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var awardMedals, contenders, gold, rest, silver,
|
||||
__slice = [].slice;
|
||||
slice = [].slice;
|
||||
|
||||
gold = silver = rest = "unknown";
|
||||
|
||||
awardMedals = function() {
|
||||
var first, others, second;
|
||||
first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
|
||||
first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? slice.call(arguments, 2) : [];
|
||||
gold = first;
|
||||
silver = second;
|
||||
return rest = others;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
var numbers, _ref;
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var numbers, ref;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
[].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;
|
||||
[].splice.apply(numbers, [3, 4].concat(ref = [-3, -4, -5, -6])), ref;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var mobyDick;
|
||||
|
||||
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
switch (day) {
|
||||
case "Mon":
|
||||
go(work);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var grade, score;
|
||||
|
||||
score = 76;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var error;
|
||||
|
||||
try {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
var lyrics, num;
|
||||
|
||||
if (this.studyingEconomics) {
|
||||
@@ -13,10 +13,10 @@ if (this.studyingEconomics) {
|
||||
num = 6;
|
||||
|
||||
lyrics = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
var results;
|
||||
results = [];
|
||||
while (num -= 1) {
|
||||
_results.push("" + num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
|
||||
results.push(num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
|
||||
File diff suppressed because one or more lines are too long
361
index.html
361
index.html
@@ -34,7 +34,7 @@
|
||||
<a href="#operators">Operators and Aliases</a>
|
||||
<a href="#classes">Classes, Inheritance, and Super</a>
|
||||
<a href="#destructuring">Destructuring Assignment</a>
|
||||
<a href="#fat-arrow">Function Binding</a>
|
||||
<a href="#fat-arrow">Bound and Generator Functions</a>
|
||||
<a href="#embedded">Embedded JavaScript</a>
|
||||
<a href="#switch">Switch and Try/Catch</a>
|
||||
<a href="#comparisons">Chained Comparisons</a>
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
<p>
|
||||
<b>Latest Version:</b>
|
||||
<a href="http://github.com/jashkenas/coffeescript/tarball/1.8.0">1.8.0</a>
|
||||
<a href="http://github.com/jashkenas/coffeescript/tarball/1.9.1">1.9.1</a>
|
||||
</p>
|
||||
|
||||
<pre>npm install -g coffee-script</pre>
|
||||
@@ -151,7 +151,7 @@ alert <span class="string">"I knew it!"</span> <span class="keyword">if</span> e
|
||||
<span class="comment"># Array comprehensions:</span>
|
||||
cubes = (math.cube num <span class="keyword">for</span> num <span class="keyword">in</span> list)
|
||||
</code></pre><pre><code><span class="keyword">var</span> cubes, list, math, num, number, opposite, race, square,
|
||||
__slice = [].slice;
|
||||
slice = [].slice;
|
||||
|
||||
number = <span class="number">42</span>;
|
||||
|
||||
@@ -177,7 +177,7 @@ math = {
|
||||
|
||||
race = <span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> runners, winner;
|
||||
winner = <span class="built_in">arguments</span>[<span class="number">0</span>], runners = <span class="number">2</span> <= <span class="built_in">arguments</span>.length ? __slice.call(<span class="built_in">arguments</span>, <span class="number">1</span>) : [];
|
||||
winner = <span class="built_in">arguments</span>[<span class="number">0</span>], runners = <span class="number">2</span> <= <span class="built_in">arguments</span>.length ? slice.call(<span class="built_in">arguments</span>, <span class="number">1</span>) : [];
|
||||
<span class="keyword">return</span> print(winner, runners);
|
||||
};
|
||||
|
||||
@@ -186,16 +186,16 @@ race = <span class="function"><span class="keyword">function</span><span class="
|
||||
}
|
||||
|
||||
cubes = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> _i, _len, _results;
|
||||
_results = [];
|
||||
<span class="keyword">for</span> (_i = <span class="number">0</span>, _len = list.length; _i < _len; _i++) {
|
||||
num = list[_i];
|
||||
_results.push(math.cube(num));
|
||||
<span class="keyword">var</span> i, len, results;
|
||||
results = [];
|
||||
<span class="keyword">for</span> (i = <span class="number">0</span>, len = list.length; i < len; i++) {
|
||||
num = list[i];
|
||||
results.push(math.cube(num));
|
||||
}
|
||||
<span class="keyword">return</span> _results;
|
||||
<span class="keyword">return</span> results;
|
||||
})();
|
||||
</code></pre><script>window.example1 = "# Assignment:\nnumber = 42\nopposite = true\n\n# Conditions:\nnumber = -42 if opposite\n\n# Functions:\nsquare = (x) -> x * x\n\n# Arrays:\nlist = [1, 2, 3, 4, 5]\n\n# Objects:\nmath =\n root: Math.sqrt\n square: square\n cube: (x) -> x * square x\n\n# Splats:\nrace = (winner, runners...) ->\n print winner, runners\n\n# Existence:\nalert \"I knew it!\" if elvis?\n\n# Array comprehensions:\ncubes = (math.cube num for num in list)\n"</script><div class='minibutton ok' onclick='javascript: var cubes, list, math, num, number, opposite, race, square,
|
||||
__slice = [].slice;
|
||||
slice = [].slice;
|
||||
|
||||
number = 42;
|
||||
|
||||
@@ -221,7 +221,7 @@ math = {
|
||||
|
||||
race = function() {
|
||||
var runners, winner;
|
||||
winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||
winner = arguments[0], runners = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
||||
return print(winner, runners);
|
||||
};
|
||||
|
||||
@@ -230,13 +230,13 @@ if (typeof elvis !== "undefined" && elvis !== null) {
|
||||
}
|
||||
|
||||
cubes = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = list.length; _i < _len; _i++) {
|
||||
num = list[_i];
|
||||
_results.push(math.cube(num));
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = list.length; i < len; i++) {
|
||||
num = list[i];
|
||||
results.push(math.cube(num));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
;alert(cubes);'>run: cubes</div><br class='clear' /></div>
|
||||
|
||||
@@ -258,8 +258,8 @@ cubes = (function() {
|
||||
|
||||
<p>
|
||||
To install, first make sure you have a working copy of the latest stable version of
|
||||
<a href="http://nodejs.org/">Node.js</a>, and <a href="http://npmjs.org">npm</a>
|
||||
(the Node Package Manager). You can then install CoffeeScript globally with npm:
|
||||
<a href="http://nodejs.org/">Node.js</a>. You can then install CoffeeScript globally
|
||||
with <a href="http://npmjs.org">npm</a>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
@@ -807,13 +807,13 @@ alert <span class="string">"The Field: "</span> + rest
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> awardMedals, contenders, gold, rest, silver,
|
||||
__slice = [].slice;
|
||||
slice = [].slice;
|
||||
|
||||
gold = silver = rest = <span class="string">"unknown"</span>;
|
||||
|
||||
awardMedals = <span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> first, others, second;
|
||||
first = <span class="built_in">arguments</span>[<span class="number">0</span>], second = <span class="built_in">arguments</span>[<span class="number">1</span>], others = <span class="number">3</span> <= <span class="built_in">arguments</span>.length ? __slice.call(<span class="built_in">arguments</span>, <span class="number">2</span>) : [];
|
||||
first = <span class="built_in">arguments</span>[<span class="number">0</span>], second = <span class="built_in">arguments</span>[<span class="number">1</span>], others = <span class="number">3</span> <= <span class="built_in">arguments</span>.length ? slice.call(<span class="built_in">arguments</span>, <span class="number">2</span>) : [];
|
||||
gold = first;
|
||||
silver = second;
|
||||
<span class="keyword">return</span> rest = others;
|
||||
@@ -829,13 +829,13 @@ alert(<span class="string">"Silver: "</span> + silver);
|
||||
|
||||
alert(<span class="string">"The Field: "</span> + rest);
|
||||
</code></pre><script>window.example8 = "gold = silver = rest = \"unknown\"\n\nawardMedals = (first, second, others...) ->\n gold = first\n silver = second\n rest = others\n\ncontenders = [\n \"Michael Phelps\"\n \"Liu Xiang\"\n \"Yao Ming\"\n \"Allyson Felix\"\n \"Shawn Johnson\"\n \"Roman Sebrle\"\n \"Guo Jingjing\"\n \"Tyson Gay\"\n \"Asafa Powell\"\n \"Usain Bolt\"\n]\n\nawardMedals contenders...\n\nalert \"Gold: \" + gold\nalert \"Silver: \" + silver\nalert \"The Field: \" + rest\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example8);'>load</div><div class='minibutton ok' onclick='javascript: var awardMedals, contenders, gold, rest, silver,
|
||||
__slice = [].slice;
|
||||
slice = [].slice;
|
||||
|
||||
gold = silver = rest = "unknown";
|
||||
|
||||
awardMedals = function() {
|
||||
var first, others, second;
|
||||
first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
|
||||
first = arguments[0], second = arguments[1], others = 3 <= arguments.length ? slice.call(arguments, 2) : [];
|
||||
gold = first;
|
||||
silver = second;
|
||||
return rest = others;
|
||||
@@ -871,25 +871,25 @@ menu i + <span class="number">1</span>, dish <span class="keyword">for</span> di
|
||||
<span class="comment"># Health conscious meal.</span>
|
||||
foods = [<span class="string">'broccoli'</span>, <span class="string">'spinach'</span>, <span class="string">'chocolate'</span>]
|
||||
eat food <span class="keyword">for</span> food <span class="keyword">in</span> foods <span class="keyword">when</span> food <span class="keyword">isnt</span> <span class="string">'chocolate'</span>
|
||||
</code></pre><pre><code><span class="keyword">var</span> courses, dish, food, foods, i, _i, _j, _k, _len, _len1, _len2, _ref;
|
||||
</code></pre><pre><code><span class="keyword">var</span> courses, dish, food, foods, i, j, k, l, len, len1, len2, ref;
|
||||
|
||||
_ref = [<span class="string">'toast'</span>, <span class="string">'cheese'</span>, <span class="string">'wine'</span>];
|
||||
<span class="keyword">for</span> (_i = <span class="number">0</span>, _len = _ref.length; _i < _len; _i++) {
|
||||
food = _ref[_i];
|
||||
ref = [<span class="string">'toast'</span>, <span class="string">'cheese'</span>, <span class="string">'wine'</span>];
|
||||
<span class="keyword">for</span> (j = <span class="number">0</span>, len = ref.length; j < len; j++) {
|
||||
food = ref[j];
|
||||
eat(food);
|
||||
}
|
||||
|
||||
courses = [<span class="string">'greens'</span>, <span class="string">'caviar'</span>, <span class="string">'truffles'</span>, <span class="string">'roast'</span>, <span class="string">'cake'</span>];
|
||||
|
||||
<span class="keyword">for</span> (i = _j = <span class="number">0</span>, _len1 = courses.length; _j < _len1; i = ++_j) {
|
||||
<span class="keyword">for</span> (i = k = <span class="number">0</span>, len1 = courses.length; k < len1; i = ++k) {
|
||||
dish = courses[i];
|
||||
menu(i + <span class="number">1</span>, dish);
|
||||
}
|
||||
|
||||
foods = [<span class="string">'broccoli'</span>, <span class="string">'spinach'</span>, <span class="string">'chocolate'</span>];
|
||||
|
||||
<span class="keyword">for</span> (_k = <span class="number">0</span>, _len2 = foods.length; _k < _len2; _k++) {
|
||||
food = foods[_k];
|
||||
<span class="keyword">for</span> (l = <span class="number">0</span>, len2 = foods.length; l < len2; l++) {
|
||||
food = foods[l];
|
||||
<span class="keyword">if</span> (food !== <span class="string">'chocolate'</span>) {
|
||||
eat(food);
|
||||
}
|
||||
@@ -908,22 +908,22 @@ foods = [<span class="string">'broccoli'</span>, <span class="string">'spinach'<
|
||||
</code></pre><pre><code><span class="keyword">var</span> countdown, num;
|
||||
|
||||
countdown = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> _i, _results;
|
||||
_results = [];
|
||||
<span class="keyword">for</span> (num = _i = <span class="number">10</span>; _i >= <span class="number">1</span>; num = --_i) {
|
||||
_results.push(num);
|
||||
<span class="keyword">var</span> i, results;
|
||||
results = [];
|
||||
<span class="keyword">for</span> (num = i = <span class="number">10</span>; i >= <span class="number">1</span>; num = --i) {
|
||||
results.push(num);
|
||||
}
|
||||
<span class="keyword">return</span> _results;
|
||||
<span class="keyword">return</span> results;
|
||||
})();
|
||||
</code></pre><script>window.example10 = "countdown = (num for num in [10..1])\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example10);'>load</div><div class='minibutton ok' onclick='javascript: var countdown, num;
|
||||
|
||||
countdown = (function() {
|
||||
var _i, _results;
|
||||
_results = [];
|
||||
for (num = _i = 10; _i >= 1; num = --_i) {
|
||||
_results.push(num);
|
||||
var i, results;
|
||||
results = [];
|
||||
for (num = i = 10; i >= 1; num = --i) {
|
||||
results.push(num);
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
;alert(countdown);'>run: countdown</div><br class='clear' /></div>
|
||||
<p>
|
||||
@@ -958,13 +958,13 @@ yearsOld = {
|
||||
};
|
||||
|
||||
ages = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> _results;
|
||||
_results = [];
|
||||
<span class="keyword">var</span> results;
|
||||
results = [];
|
||||
<span class="keyword">for</span> (child <span class="keyword">in</span> yearsOld) {
|
||||
age = yearsOld[child];
|
||||
_results.push(<span class="string">""</span> + child + <span class="string">" is "</span> + age);
|
||||
results.push(child + <span class="string">" is "</span> + age);
|
||||
}
|
||||
<span class="keyword">return</span> _results;
|
||||
<span class="keyword">return</span> results;
|
||||
})();
|
||||
</code></pre><script>window.example11 = "yearsOld = max: 10, ida: 9, tim: 11\n\nages = for child, age of yearsOld\n \"#{child} is #{age}\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example11);'>load</div><div class='minibutton ok' onclick='javascript: var age, ages, child, yearsOld;
|
||||
|
||||
@@ -975,13 +975,13 @@ yearsOld = {
|
||||
};
|
||||
|
||||
ages = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
var results;
|
||||
results = [];
|
||||
for (child in yearsOld) {
|
||||
age = yearsOld[child];
|
||||
_results.push("" + child + " is " + age);
|
||||
results.push(child + " is " + age);
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
;alert(ages.join(", "));'>run: ages.join(", ")</div><br class='clear' /></div>
|
||||
<p>
|
||||
@@ -1020,12 +1020,12 @@ lyrics = <span class="keyword">while</span> num -= <span class="number">1</span>
|
||||
num = <span class="number">6</span>;
|
||||
|
||||
lyrics = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> _results;
|
||||
_results = [];
|
||||
<span class="keyword">var</span> results;
|
||||
results = [];
|
||||
<span class="keyword">while</span> (num -= <span class="number">1</span>) {
|
||||
_results.push(<span class="string">""</span> + num + <span class="string">" little monkeys, jumping on the bed. One fell out and bumped his head."</span>);
|
||||
results.push(num + <span class="string">" little monkeys, jumping on the bed. One fell out and bumped his head."</span>);
|
||||
}
|
||||
<span class="keyword">return</span> _results;
|
||||
<span class="keyword">return</span> results;
|
||||
})();
|
||||
</code></pre><script>window.example12 = "# Econ 101\nif this.studyingEconomics\n buy() while supply > demand\n sell() until supply > demand\n\n# Nursery Rhyme\nnum = 6\nlyrics = while num -= 1\n \"#{num} little monkeys, jumping on the bed.\n One fell out and bumped his head.\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example12);'>load</div><div class='minibutton ok' onclick='javascript: var lyrics, num;
|
||||
|
||||
@@ -1041,12 +1041,12 @@ if (this.studyingEconomics) {
|
||||
num = 6;
|
||||
|
||||
lyrics = (function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
var results;
|
||||
results = [];
|
||||
while (num -= 1) {
|
||||
_results.push("" + num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
|
||||
results.push(num + " little monkeys, jumping on the bed. One fell out and bumped his head.");
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
;alert(lyrics.join("
|
||||
"));'>run: lyrics.join("
|
||||
@@ -1065,16 +1065,16 @@ lyrics = (function() {
|
||||
<div class='code'><pre><code><span class="keyword">for</span> filename <span class="keyword">in</span> list
|
||||
<span class="keyword">do</span> <span class="function"><span class="params">(filename)</span> -></span>
|
||||
fs.readFile filename, <span class="function"><span class="params">(err, contents)</span> -></span>
|
||||
compile filename, contents.toString()</code></pre><pre><code><span class="keyword">var</span> filename, _fn, _i, _len;
|
||||
compile filename, contents.toString()</code></pre><pre><code><span class="keyword">var</span> filename, fn, i, len;
|
||||
|
||||
_fn = <span class="function"><span class="keyword">function</span><span class="params">(filename)</span> {</span>
|
||||
fn = <span class="function"><span class="keyword">function</span><span class="params">(filename)</span> {</span>
|
||||
<span class="keyword">return</span> fs.readFile(filename, <span class="function"><span class="keyword">function</span><span class="params">(err, contents)</span> {</span>
|
||||
<span class="keyword">return</span> compile(filename, contents.toString());
|
||||
});
|
||||
};
|
||||
<span class="keyword">for</span> (_i = <span class="number">0</span>, _len = list.length; _i < _len; _i++) {
|
||||
filename = list[_i];
|
||||
_fn(filename);
|
||||
<span class="keyword">for</span> (i = <span class="number">0</span>, len = list.length; i < len; i++) {
|
||||
filename = list[i];
|
||||
fn(filename);
|
||||
}
|
||||
</code></pre><script>window.example13 = "for filename in list\n do (filename) ->\n fs.readFile filename, (err, contents) ->\n compile filename, contents.toString()"</script><div class='minibutton load' onclick='javascript: loadConsole(example13);'>load</div><br class='clear' /></div>
|
||||
|
||||
@@ -1129,16 +1129,16 @@ numbers[<span class="number">3.</span><span class="number">.6</span>] = [-<span
|
||||
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> numbers, _ref;
|
||||
</code></pre><pre><code><span class="keyword">var</span> numbers, ref;
|
||||
|
||||
numbers = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>];
|
||||
|
||||
[].splice.apply(numbers, [<span class="number">3</span>, <span class="number">4</span>].concat(_ref = [-<span class="number">3</span>, -<span class="number">4</span>, -<span class="number">5</span>, -<span class="number">6</span>])), _ref;
|
||||
</code></pre><script>window.example15 = "numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n\nnumbers[3..6] = [-3, -4, -5, -6]\n\n\n\n "</script><div class='minibutton load' onclick='javascript: loadConsole(example15);'>load</div><div class='minibutton ok' onclick='javascript: var numbers, _ref;
|
||||
[].splice.apply(numbers, [<span class="number">3</span>, <span class="number">4</span>].concat(ref = [-<span class="number">3</span>, -<span class="number">4</span>, -<span class="number">5</span>, -<span class="number">6</span>])), ref;
|
||||
</code></pre><script>window.example15 = "numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n\nnumbers[3..6] = [-3, -4, -5, -6]\n\n\n\n "</script><div class='minibutton load' onclick='javascript: loadConsole(example15);'>load</div><div class='minibutton ok' onclick='javascript: var numbers, ref;
|
||||
|
||||
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
|
||||
[].splice.apply(numbers, [3, 4].concat(_ref = [-3, -4, -5, -6])), _ref;
|
||||
[].splice.apply(numbers, [3, 4].concat(ref = [-3, -4, -5, -6])), ref;
|
||||
;alert(numbers);'>run: numbers</div><br class='clear' /></div>
|
||||
<p>
|
||||
Note that JavaScript strings are immutable, and can't be spliced.
|
||||
@@ -1226,22 +1226,22 @@ six = (one = 1) + (two = 2) + (three = 3);
|
||||
globals = (name <span class="keyword">for</span> name <span class="keyword">of</span> <span class="built_in">window</span>)[<span class="number">0.</span>.<span class="number">.10</span>]</code></pre><pre><code><span class="keyword">var</span> globals, name;
|
||||
|
||||
globals = ((<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> _results;
|
||||
_results = [];
|
||||
<span class="keyword">var</span> results;
|
||||
results = [];
|
||||
<span class="keyword">for</span> (name <span class="keyword">in</span> window) {
|
||||
_results.push(name);
|
||||
results.push(name);
|
||||
}
|
||||
<span class="keyword">return</span> _results;
|
||||
<span class="keyword">return</span> results;
|
||||
})()).slice(<span class="number">0</span>, <span class="number">10</span>);
|
||||
</code></pre><script>window.example18 = "# The first ten global properties.\n\nglobals = (name for name of window)[0...10]"</script><div class='minibutton load' onclick='javascript: loadConsole(example18);'>load</div><div class='minibutton ok' onclick='javascript: var globals, name;
|
||||
|
||||
globals = ((function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
var results;
|
||||
results = [];
|
||||
for (name in window) {
|
||||
_results.push(name);
|
||||
results.push(name);
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})()).slice(0, 10);
|
||||
;alert(globals);'>run: globals</div><br class='clear' /></div>
|
||||
<p>
|
||||
@@ -1439,13 +1439,13 @@ footprints = typeof yeti !== "undefined" && yeti !== null ? yeti : "bear";
|
||||
the <b>TypeError</b> that would be raised otherwise.
|
||||
</p>
|
||||
<div class='code'><pre><code>zip = lottery.drawWinner?().address?.zipcode
|
||||
</code></pre><pre><code><span class="keyword">var</span> zip, _ref;
|
||||
</code></pre><pre><code><span class="keyword">var</span> ref, zip;
|
||||
|
||||
zip = <span class="keyword">typeof</span> lottery.drawWinner === <span class="string">"function"</span> ? (_ref = lottery.drawWinner().address) != <span class="literal">null</span> ? _ref.zipcode : <span class="keyword">void</span> <span class="number">0</span> : <span class="keyword">void</span> <span class="number">0</span>;
|
||||
zip = <span class="keyword">typeof</span> lottery.drawWinner === <span class="string">"function"</span> ? (ref = lottery.drawWinner().address) != <span class="literal">null</span> ? ref.zipcode : <span class="keyword">void</span> <span class="number">0</span> : <span class="keyword">void</span> <span class="number">0</span>;
|
||||
</code></pre><script>window.example22 = "zip = lottery.drawWinner?().address?.zipcode\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example22);'>load</div><br class='clear' /></div>
|
||||
<p>
|
||||
Soaking up nulls is similar to Ruby's
|
||||
<a href="http://andand.rubyforge.org/">andand gem</a>, and to the
|
||||
<a href="https://rubygems.org/gems/andand">andand gem</a>, and to the
|
||||
<a href="http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator%28%3F.%29">safe navigation operator</a>
|
||||
in Groovy.
|
||||
</p>
|
||||
@@ -1501,8 +1501,8 @@ tom.move()
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> Animal, Horse, Snake, sam, tom,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = <span class="function"><span class="keyword">function</span><span class="params">(child, parent)</span> {</span> <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> parent) { <span class="keyword">if</span> (__hasProp.call(parent, key)) child[key] = parent[key]; } <span class="function"><span class="keyword">function</span> <span class="title">ctor</span><span class="params">()</span> {</span> <span class="keyword">this</span>.constructor = child; } ctor.prototype = parent.prototype; child.prototype = <span class="keyword">new</span> ctor(); child.__super__ = parent.prototype; <span class="keyword">return</span> child; };
|
||||
extend = <span class="function"><span class="keyword">function</span><span class="params">(child, parent)</span> {</span> <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> parent) { <span class="keyword">if</span> (hasProp.call(parent, key)) child[key] = parent[key]; } <span class="function"><span class="keyword">function</span> <span class="title">ctor</span><span class="params">()</span> {</span> <span class="keyword">this</span>.constructor = child; } ctor.prototype = parent.prototype; child.prototype = <span class="keyword">new</span> ctor(); child.__super__ = parent.prototype; <span class="keyword">return</span> child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
Animal = (<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="function"><span class="keyword">function</span> <span class="title">Animal</span><span class="params">(name)</span> {</span>
|
||||
@@ -1517,8 +1517,8 @@ Animal = (<span class="function"><span class="keyword">function</span><span clas
|
||||
|
||||
})();
|
||||
|
||||
Snake = (<span class="function"><span class="keyword">function</span><span class="params">(_super)</span> {</span>
|
||||
__extends(Snake, _super);
|
||||
Snake = (<span class="function"><span class="keyword">function</span><span class="params">(superClass)</span> {</span>
|
||||
extend(Snake, superClass);
|
||||
|
||||
<span class="function"><span class="keyword">function</span> <span class="title">Snake</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">return</span> Snake.__super__.constructor.apply(<span class="keyword">this</span>, <span class="built_in">arguments</span>);
|
||||
@@ -1533,8 +1533,8 @@ Snake = (<span class="function"><span class="keyword">function</span><span class
|
||||
|
||||
})(Animal);
|
||||
|
||||
Horse = (<span class="function"><span class="keyword">function</span><span class="params">(_super)</span> {</span>
|
||||
__extends(Horse, _super);
|
||||
Horse = (<span class="function"><span class="keyword">function</span><span class="params">(superClass)</span> {</span>
|
||||
extend(Horse, superClass);
|
||||
|
||||
<span class="function"><span class="keyword">function</span> <span class="title">Horse</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">return</span> Horse.__super__.constructor.apply(<span class="keyword">this</span>, <span class="built_in">arguments</span>);
|
||||
@@ -1557,8 +1557,8 @@ sam.move();
|
||||
|
||||
tom.move();
|
||||
</code></pre><script>window.example23 = "class Animal\n constructor: (@name) ->\n\n move: (meters) ->\n alert @name + \" moved #{meters}m.\"\n\nclass Snake extends Animal\n move: ->\n alert \"Slithering...\"\n super 5\n\nclass Horse extends Animal\n move: ->\n alert \"Galloping...\"\n super 45\n\nsam = new Snake \"Sammy the Python\"\ntom = new Horse \"Tommy the Palomino\"\n\nsam.move()\ntom.move()\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example23);'>load</div><div class='minibutton ok' onclick='javascript: var Animal, Horse, Snake, sam, tom,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
||||
hasProp = {}.hasOwnProperty;
|
||||
|
||||
Animal = (function() {
|
||||
function Animal(name) {
|
||||
@@ -1573,8 +1573,8 @@ Animal = (function() {
|
||||
|
||||
})();
|
||||
|
||||
Snake = (function(_super) {
|
||||
__extends(Snake, _super);
|
||||
Snake = (function(superClass) {
|
||||
extend(Snake, superClass);
|
||||
|
||||
function Snake() {
|
||||
return Snake.__super__.constructor.apply(this, arguments);
|
||||
@@ -1589,8 +1589,8 @@ Snake = (function(_super) {
|
||||
|
||||
})(Animal);
|
||||
|
||||
Horse = (function(_super) {
|
||||
__extends(Horse, _super);
|
||||
Horse = (function(superClass) {
|
||||
extend(Horse, superClass);
|
||||
|
||||
function Horse() {
|
||||
return Horse.__super__.constructor.apply(this, arguments);
|
||||
@@ -1658,20 +1658,20 @@ theSwitch = <span class="number">0</span>
|
||||
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> theBait, theSwitch, _ref;
|
||||
</code></pre><pre><code><span class="keyword">var</span> ref, theBait, theSwitch;
|
||||
|
||||
theBait = <span class="number">1000</span>;
|
||||
|
||||
theSwitch = <span class="number">0</span>;
|
||||
|
||||
_ref = [theSwitch, theBait], theBait = _ref[<span class="number">0</span>], theSwitch = _ref[<span class="number">1</span>];
|
||||
</code></pre><script>window.example25 = "theBait = 1000\ntheSwitch = 0\n\n[theBait, theSwitch] = [theSwitch, theBait]\n\n\n\n\n "</script><div class='minibutton load' onclick='javascript: loadConsole(example25);'>load</div><div class='minibutton ok' onclick='javascript: var theBait, theSwitch, _ref;
|
||||
ref = [theSwitch, theBait], theBait = ref[<span class="number">0</span>], theSwitch = ref[<span class="number">1</span>];
|
||||
</code></pre><script>window.example25 = "theBait = 1000\ntheSwitch = 0\n\n[theBait, theSwitch] = [theSwitch, theBait]\n\n\n\n\n "</script><div class='minibutton load' onclick='javascript: loadConsole(example25);'>load</div><div class='minibutton ok' onclick='javascript: var ref, theBait, theSwitch;
|
||||
|
||||
theBait = 1000;
|
||||
|
||||
theSwitch = 0;
|
||||
|
||||
_ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
|
||||
ref = [theSwitch, theBait], theBait = ref[0], theSwitch = ref[1];
|
||||
;alert(theBait);'>run: theBait</div><br class='clear' /></div>
|
||||
<p>
|
||||
But it's also helpful for dealing with functions that return multiple
|
||||
@@ -1686,20 +1686,20 @@ _ref = [theSwitch, theBait], theBait = _ref[0], theSwitch = _ref[1];
|
||||
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> city, forecast, temp, weatherReport, _ref;
|
||||
</code></pre><pre><code><span class="keyword">var</span> city, forecast, ref, temp, weatherReport;
|
||||
|
||||
weatherReport = <span class="function"><span class="keyword">function</span><span class="params">(location)</span> {</span>
|
||||
<span class="keyword">return</span> [location, <span class="number">72</span>, <span class="string">"Mostly Sunny"</span>];
|
||||
};
|
||||
|
||||
_ref = weatherReport(<span class="string">"Berkeley, CA"</span>), city = _ref[<span class="number">0</span>], temp = _ref[<span class="number">1</span>], forecast = _ref[<span class="number">2</span>];
|
||||
</code></pre><script>window.example26 = "weatherReport = (location) ->\n # Make an Ajax request to fetch the weather...\n [location, 72, \"Mostly Sunny\"]\n\n[city, temp, forecast] = weatherReport \"Berkeley, CA\"\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example26);'>load</div><div class='minibutton ok' onclick='javascript: var city, forecast, temp, weatherReport, _ref;
|
||||
ref = weatherReport(<span class="string">"Berkeley, CA"</span>), city = ref[<span class="number">0</span>], temp = ref[<span class="number">1</span>], forecast = ref[<span class="number">2</span>];
|
||||
</code></pre><script>window.example26 = "weatherReport = (location) ->\n # Make an Ajax request to fetch the weather...\n [location, 72, \"Mostly Sunny\"]\n\n[city, temp, forecast] = weatherReport \"Berkeley, CA\"\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example26);'>load</div><div class='minibutton ok' onclick='javascript: var city, forecast, ref, temp, weatherReport;
|
||||
|
||||
weatherReport = function(location) {
|
||||
return [location, 72, "Mostly Sunny"];
|
||||
};
|
||||
|
||||
_ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast = _ref[2];
|
||||
ref = weatherReport("Berkeley, CA"), city = ref[0], temp = ref[1], forecast = ref[2];
|
||||
;alert(forecast);'>run: forecast</div><br class='clear' /></div>
|
||||
<p>
|
||||
Destructuring assignment can be used with any depth of array and object nesting,
|
||||
@@ -1719,7 +1719,7 @@ _ref = weatherReport("Berkeley, CA"), city = _ref[0], temp = _ref[1], forecast =
|
||||
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> city, futurists, name, street, _ref, _ref1;
|
||||
</code></pre><pre><code><span class="keyword">var</span> city, futurists, name, ref, ref1, street;
|
||||
|
||||
futurists = {
|
||||
sculptor: <span class="string">"Umberto Boccioni"</span>,
|
||||
@@ -1730,8 +1730,8 @@ futurists = {
|
||||
}
|
||||
};
|
||||
|
||||
_ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[<span class="number">0</span>], city = _ref1[<span class="number">1</span>]);
|
||||
</code></pre><script>window.example27 = "futurists =\n sculptor: \"Umberto Boccioni\"\n painter: \"Vladimir Burliuk\"\n poet:\n name: \"F.T. Marinetti\"\n address: [\n \"Via Roma 42R\"\n \"Bellagio, Italy 22021\"\n ]\n\n{poet: {name, address: [street, city]}} = futurists\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example27);'>load</div><div class='minibutton ok' onclick='javascript: var city, futurists, name, street, _ref, _ref1;
|
||||
ref = futurists.poet, name = ref.name, (ref1 = ref.address, street = ref1[<span class="number">0</span>], city = ref1[<span class="number">1</span>]);
|
||||
</code></pre><script>window.example27 = "futurists =\n sculptor: \"Umberto Boccioni\"\n painter: \"Vladimir Burliuk\"\n poet:\n name: \"F.T. Marinetti\"\n address: [\n \"Via Roma 42R\"\n \"Bellagio, Italy 22021\"\n ]\n\n{poet: {name, address: [street, city]}} = futurists\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example27);'>load</div><div class='minibutton ok' onclick='javascript: var city, futurists, name, ref, ref1, street;
|
||||
|
||||
futurists = {
|
||||
sculptor: "Umberto Boccioni",
|
||||
@@ -1742,7 +1742,7 @@ futurists = {
|
||||
}
|
||||
};
|
||||
|
||||
_ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[0], city = _ref1[1]);
|
||||
ref = futurists.poet, name = ref.name, (ref1 = ref.address, street = ref1[0], city = ref1[1]);
|
||||
;alert(name + "-" + street);'>run: name + "-" + street</div><br class='clear' /></div>
|
||||
<p>
|
||||
Destructuring assignment can even be combined with splats.
|
||||
@@ -1756,18 +1756,18 @@ _ref = futurists.poet, name = _ref.name, (_ref1 = _ref.address, street = _ref1[0
|
||||
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> close, contents, open, tag, _i, _ref,
|
||||
__slice = [].slice;
|
||||
</code></pre><pre><code><span class="keyword">var</span> close, contents, i, open, ref, tag,
|
||||
slice = [].slice;
|
||||
|
||||
tag = <span class="string">"<impossible>"</span>;
|
||||
|
||||
_ref = tag.split(<span class="string">""</span>), open = _ref[<span class="number">0</span>], contents = <span class="number">3</span> <= _ref.length ? __slice.call(_ref, <span class="number">1</span>, _i = _ref.length - <span class="number">1</span>) : (_i = <span class="number">1</span>, []), close = _ref[_i++];
|
||||
</code></pre><script>window.example28 = "tag = \"<impossible>\"\n\n[open, contents..., close] = tag.split(\"\")\n\n\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example28);'>load</div><div class='minibutton ok' onclick='javascript: var close, contents, open, tag, _i, _ref,
|
||||
__slice = [].slice;
|
||||
ref = tag.split(<span class="string">""</span>), open = ref[<span class="number">0</span>], contents = <span class="number">3</span> <= ref.length ? slice.call(ref, <span class="number">1</span>, i = ref.length - <span class="number">1</span>) : (i = <span class="number">1</span>, []), close = ref[i++];
|
||||
</code></pre><script>window.example28 = "tag = \"<impossible>\"\n\n[open, contents..., close] = tag.split(\"\")\n\n\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example28);'>load</div><div class='minibutton ok' onclick='javascript: var close, contents, i, open, ref, tag,
|
||||
slice = [].slice;
|
||||
|
||||
tag = "<impossible>";
|
||||
|
||||
_ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call(_ref, 1, _i = _ref.length - 1) : (_i = 1, []), close = _ref[_i++];
|
||||
ref = tag.split(""), open = ref[0], contents = 3 <= ref.length ? slice.call(ref, 1, i = ref.length - 1) : (i = 1, []), close = ref[i++];
|
||||
;alert(contents.join(""));'>run: contents.join("")</div><br class='clear' /></div>
|
||||
<p>
|
||||
Expansion can be used to retrieve elements from the end of an array without having to assign the rest of its values. It works in function parameter lists as well.
|
||||
@@ -1779,16 +1779,16 @@ _ref = tag.split(""), open = _ref[0], contents = 3 <= _ref.length ? __slice.call
|
||||
|
||||
|
||||
|
||||
</code></pre><pre><code><span class="keyword">var</span> first, last, text, _ref;
|
||||
</code></pre><pre><code><span class="keyword">var</span> first, last, ref, text;
|
||||
|
||||
text = <span class="string">"Every literary critic believes he will outwit history and have the last word"</span>;
|
||||
|
||||
_ref = text.split(<span class="string">" "</span>), first = _ref[<span class="number">0</span>], last = _ref[_ref.length - <span class="number">1</span>];
|
||||
</code></pre><script>window.example29 = "text = \"Every literary critic believes he will\n outwit history and have the last word\"\n\n[first, ..., last] = text.split \" \"\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example29);'>load</div><div class='minibutton ok' onclick='javascript: var first, last, text, _ref;
|
||||
ref = text.split(<span class="string">" "</span>), first = ref[<span class="number">0</span>], last = ref[ref.length - <span class="number">1</span>];
|
||||
</code></pre><script>window.example29 = "text = \"Every literary critic believes he will\n outwit history and have the last word\"\n\n[first, ..., last] = text.split \" \"\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example29);'>load</div><div class='minibutton ok' onclick='javascript: var first, last, ref, text;
|
||||
|
||||
text = "Every literary critic believes he will outwit history and have the last word";
|
||||
|
||||
_ref = text.split(" "), first = _ref[0], last = _ref[_ref.length - 1];
|
||||
ref = text.split(" "), first = ref[0], last = ref[ref.length - 1];
|
||||
;alert(first + " " + last);'>run: first + " " + last</div><br class='clear' /></div>
|
||||
<p>
|
||||
Destructuring assignment is also useful when combined with class constructors
|
||||
@@ -1832,7 +1832,7 @@ tim = new Person({
|
||||
|
||||
<p>
|
||||
<span id="fat-arrow" class="bookmark"></span>
|
||||
<b class="header">Function binding</b>
|
||||
<b class="header">Bound Functions, Generator Functions</b>
|
||||
In JavaScript, the <tt>this</tt> keyword is dynamically scoped to mean the
|
||||
object that the current function is attached to. If you pass a function as
|
||||
a callback or attach it to a different object, the original value of <tt>this</tt>
|
||||
@@ -1875,6 +1875,44 @@ Account = <span class="function"><span class="keyword">function</span><span clas
|
||||
be automatically bound to each instance of the class when the instance is
|
||||
constructed.
|
||||
</p>
|
||||
<p>
|
||||
CoffeeScript functions also support
|
||||
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*">ES6 generator functions</a>
|
||||
through the <tt>yield</tt> keyword. There's no <tt>function*(){}</tt>
|
||||
nonsense — a generator in CoffeeScript is simply a function that yields.
|
||||
</p>
|
||||
<div class='code'><pre><code><span class="function"><span class="title">perfectSquares</span> = -></span>
|
||||
num = <span class="number">0</span>
|
||||
<span class="keyword">loop</span>
|
||||
num += <span class="number">1</span>
|
||||
yield num * num
|
||||
<span class="keyword">return</span>
|
||||
|
||||
<span class="built_in">window</span>.ps <span class="keyword">or</span>= perfectSquares()</code></pre><pre><code><span class="keyword">var</span> perfectSquares;
|
||||
|
||||
perfectSquares = <span class="function"><span class="keyword">function</span>*<span class="params">()</span> {</span>
|
||||
<span class="keyword">var</span> num;
|
||||
num = <span class="number">0</span>;
|
||||
<span class="keyword">while</span> (<span class="literal">true</span>) {
|
||||
num += <span class="number">1</span>;
|
||||
(<span class="keyword">yield</span> num * num);
|
||||
}
|
||||
};
|
||||
|
||||
window.ps || (window.ps = perfectSquares());
|
||||
</code></pre><script>window.example32 = "perfectSquares = ->\n num = 0\n loop\n num += 1\n yield num * num\n return\n\nwindow.ps or= perfectSquares()"</script><div class='minibutton load' onclick='javascript: loadConsole(example32);'>load</div><div class='minibutton ok' onclick='javascript: var perfectSquares;
|
||||
|
||||
perfectSquares = function*() {
|
||||
var num;
|
||||
num = 0;
|
||||
while (true) {
|
||||
num += 1;
|
||||
(yield num * num);
|
||||
}
|
||||
};
|
||||
|
||||
window.ps || (window.ps = perfectSquares());
|
||||
;alert(ps.next().value);'>run: ps.next().value</div><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="embedded" class="bookmark"></span>
|
||||
@@ -1894,7 +1932,7 @@ Account = <span class="function"><span class="keyword">function</span><span clas
|
||||
hi = <span class="function"><span class="keyword">function</span><span class="params">()</span> {</span>
|
||||
<span class="keyword">return</span> [document.title, <span class="string">"Hello JavaScript"</span>].join(<span class="string">": "</span>);
|
||||
};
|
||||
</code></pre><script>window.example32 = "hi = `function() {\n return [document.title, \"Hello JavaScript\"].join(\": \");\n}`\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example32);'>load</div><div class='minibutton ok' onclick='javascript: var hi;
|
||||
</code></pre><script>window.example33 = "hi = `function() {\n return [document.title, \"Hello JavaScript\"].join(\": \");\n}`\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example33);'>load</div><div class='minibutton ok' onclick='javascript: var hi;
|
||||
|
||||
hi = function() {
|
||||
return [document.title, "Hello JavaScript"].join(": ");
|
||||
@@ -1948,7 +1986,7 @@ hi = function() {
|
||||
<span class="keyword">default</span>:
|
||||
go(work);
|
||||
}
|
||||
</code></pre><script>window.example33 = "switch day\n when \"Mon\" then go work\n when \"Tue\" then go relax\n when \"Thu\" then go iceFishing\n when \"Fri\", \"Sat\"\n if day is bingoDay\n go bingo\n go dancing\n when \"Sun\" then go church\n else go work"</script><div class='minibutton load' onclick='javascript: loadConsole(example33);'>load</div><br class='clear' /></div>
|
||||
</code></pre><script>window.example34 = "switch day\n when \"Mon\" then go work\n when \"Tue\" then go relax\n when \"Thu\" then go iceFishing\n when \"Fri\", \"Sat\"\n if day is bingoDay\n go bingo\n go dancing\n when \"Sun\" then go church\n else go work"</script><div class='minibutton load' onclick='javascript: loadConsole(example34);'>load</div><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
Switch statements can also be used without a control expression, turning them in to a cleaner alternative to if/else chains.
|
||||
@@ -1979,7 +2017,7 @@ grade = (<span class="function"><span class="keyword">function</span><span class
|
||||
<span class="keyword">return</span> <span class="string">'A'</span>;
|
||||
}
|
||||
})();
|
||||
</code></pre><script>window.example34 = "score = 76\ngrade = switch\n when score < 60 then 'F'\n when score < 70 then 'D'\n when score < 80 then 'C'\n when score < 90 then 'B'\n else 'A'\n# grade == 'C'\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example34);'>load</div><br class='clear' /></div>
|
||||
</code></pre><script>window.example35 = "score = 76\ngrade = switch\n when score < 60 then 'F'\n when score < 70 then 'D'\n when score < 80 then 'C'\n when score < 90 then 'B'\n else 'A'\n# grade == 'C'\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example35);'>load</div><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="try" class="bookmark"></span>
|
||||
@@ -2006,7 +2044,7 @@ grade = (<span class="function"><span class="keyword">function</span><span class
|
||||
} <span class="keyword">finally</span> {
|
||||
cleanUp();
|
||||
}
|
||||
</code></pre><script>window.example35 = "try\n allHellBreaksLoose()\n catsAndDogsLivingTogether()\ncatch error\n print error\nfinally\n cleanUp()\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example35);'>load</div><br class='clear' /></div>
|
||||
</code></pre><script>window.example36 = "try\n allHellBreaksLoose()\n catsAndDogsLivingTogether()\ncatch error\n print error\nfinally\n cleanUp()\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example36);'>load</div><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="comparisons" class="bookmark"></span>
|
||||
@@ -2026,7 +2064,7 @@ healthy = <span class="number">200</span> > cholesterol > <span class="num
|
||||
cholesterol = <span class="number">127</span>;
|
||||
|
||||
healthy = (<span class="number">200</span> > cholesterol && cholesterol > <span class="number">60</span>);
|
||||
</code></pre><script>window.example36 = "cholesterol = 127\n\nhealthy = 200 > cholesterol > 60\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example36);'>load</div><div class='minibutton ok' onclick='javascript: var cholesterol, healthy;
|
||||
</code></pre><script>window.example37 = "cholesterol = 127\n\nhealthy = 200 > cholesterol > 60\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><div class='minibutton ok' onclick='javascript: var cholesterol, healthy;
|
||||
|
||||
cholesterol = 127;
|
||||
|
||||
@@ -2055,14 +2093,14 @@ author = <span class="string">"Wittgenstein"</span>;
|
||||
|
||||
quote = <span class="string">"A picture is a fact. -- "</span> + author;
|
||||
|
||||
sentence = <span class="string">""</span> + (<span class="number">22</span> / <span class="number">7</span>) + <span class="string">" is a decent approximation of π"</span>;
|
||||
</code></pre><script>window.example37 = "author = \"Wittgenstein\"\nquote = \"A picture is a fact. -- #{ author }\"\n\nsentence = \"#{ 22 / 7 } is a decent approximation of π\"\n\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example37);'>load</div><div class='minibutton ok' onclick='javascript: var author, quote, sentence;
|
||||
sentence = (<span class="number">22</span> / <span class="number">7</span>) + <span class="string">" is a decent approximation of π"</span>;
|
||||
</code></pre><script>window.example38 = "author = \"Wittgenstein\"\nquote = \"A picture is a fact. -- #{ author }\"\n\nsentence = \"#{ 22 / 7 } is a decent approximation of π\"\n\n\n\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example38);'>load</div><div class='minibutton ok' onclick='javascript: var author, quote, sentence;
|
||||
|
||||
author = "Wittgenstein";
|
||||
|
||||
quote = "A picture is a fact. -- " + author;
|
||||
|
||||
sentence = "" + (22 / 7) + " is a decent approximation of π";
|
||||
sentence = (22 / 7) + " is a decent approximation of π";
|
||||
;alert(sentence);'>run: sentence</div><br class='clear' /></div>
|
||||
<p>
|
||||
Multiline strings are allowed in CoffeeScript. Lines are joined by a single space unless they end with a backslash. Indentation is ignored.
|
||||
@@ -2076,7 +2114,7 @@ sentence = "" + (22 / 7) + " is a decent approximation of π";
|
||||
</code></pre><pre><code><span class="keyword">var</span> mobyDick;
|
||||
|
||||
mobyDick = <span class="string">"Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world..."</span>;
|
||||
</code></pre><script>window.example38 = "mobyDick = \"Call me Ishmael. Some years ago --\n never mind how long precisely -- having little\n or no money in my purse, and nothing particular\n to interest me on shore, I thought I would sail\n about a little and see the watery part of the\n world...\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example38);'>load</div><div class='minibutton ok' onclick='javascript: var mobyDick;
|
||||
</code></pre><script>window.example39 = "mobyDick = \"Call me Ishmael. Some years ago --\n never mind how long precisely -- having little\n or no money in my purse, and nothing particular\n to interest me on shore, I thought I would sail\n about a little and see the watery part of the\n world...\"\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example39);'>load</div><div class='minibutton ok' onclick='javascript: var mobyDick;
|
||||
|
||||
mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...";
|
||||
;alert(mobyDick);'>run: mobyDick</div><br class='clear' /></div>
|
||||
@@ -2095,7 +2133,7 @@ mobyDick = "Call me Ishmael. Some years ago -- never mind how long precisely --
|
||||
</code></pre><pre><code><span class="keyword">var</span> html;
|
||||
|
||||
html = <span class="string">"<strong>\n cup of coffeescript\n</strong>"</span>;
|
||||
</code></pre><script>window.example39 = "html = \"\"\"\n <strong>\n cup of coffeescript\n </strong>\n \"\"\"\n \n"</script><div class='minibutton load' onclick='javascript: loadConsole(example39);'>load</div><div class='minibutton ok' onclick='javascript: var html;
|
||||
</code></pre><script>window.example40 = "html = \"\"\"\n <strong>\n cup of coffeescript\n </strong>\n \"\"\"\n \n"</script><div class='minibutton load' onclick='javascript: loadConsole(example40);'>load</div><div class='minibutton ok' onclick='javascript: var html;
|
||||
|
||||
html = "<strong>\n cup of coffeescript\n</strong>";
|
||||
;alert(html);'>run: html</div><br class='clear' /></div>
|
||||
@@ -2120,7 +2158,7 @@ SkinnyMochaHalfCaffScript Compiler v1.0
|
||||
Released under the MIT License
|
||||
*/</span>
|
||||
|
||||
</code></pre><script>window.example40 = "###\nSkinnyMochaHalfCaffScript Compiler v1.0\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example40);'>load</div><br class='clear' /></div>
|
||||
</code></pre><script>window.example41 = "###\nSkinnyMochaHalfCaffScript Compiler v1.0\nReleased under the MIT License\n###\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example41);'>load</div><br class='clear' /></div>
|
||||
|
||||
<p>
|
||||
<span id="regexes" class="bookmark"></span>
|
||||
@@ -2145,7 +2183,7 @@ Released under the MIT License
|
||||
</code></pre><pre><code><span class="keyword">var</span> OPERATOR;
|
||||
|
||||
OPERATOR = <span class="regexp">/^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/</span>;
|
||||
</code></pre><script>window.example41 = "OPERATOR = /// ^ (\n ?: [-=]> # function\n | [-+*/%<>&|^!?=]= # compound assign / compare\n | >>>=? # zero-fill right shift\n | ([-+:])\\1 # doubles\n | ([&|<>])\\2=? # logic / shift\n | \\?\\. # soak access\n | \\.{2,3} # range or splat\n) ///\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example41);'>load</div><br class='clear' /></div>
|
||||
</code></pre><script>window.example42 = "OPERATOR = /// ^ (\n ?: [-=]> # function\n | [-+*/%<>&|^!?=]= # compound assign / compare\n | >>>=? # zero-fill right shift\n | ([-+:])\\1 # doubles\n | ([&|<>])\\2=? # logic / shift\n | \\?\\. # soak access\n | \\.{2,3} # range or splat\n) ///\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example42);'>load</div><br class='clear' /></div>
|
||||
|
||||
|
||||
<h2>
|
||||
@@ -2190,9 +2228,9 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
|
||||
<span class="built_in">require</span>(<span class="string">'jison'</span>);
|
||||
code = <span class="built_in">require</span>(<span class="string">'./lib/grammar'</span>).parser.generate();
|
||||
dir = options.output || <span class="string">'lib'</span>;
|
||||
<span class="keyword">return</span> fs.writeFile(<span class="string">""</span> + dir + <span class="string">"/parser.js"</span>, code);
|
||||
<span class="keyword">return</span> fs.writeFile(dir + <span class="string">"/parser.js"</span>, code);
|
||||
});
|
||||
</code></pre><script>window.example42 = "fs = require 'fs'\n\noption '-o', '--output [DIR]', 'directory for compiled code'\n\ntask 'build:parser', 'rebuild the Jison parser', (options) ->\n require 'jison'\n code = require('./lib/grammar').parser.generate()\n dir = options.output or 'lib'\n fs.writeFile \"#{dir}/parser.js\", code"</script><div class='minibutton load' onclick='javascript: loadConsole(example42);'>load</div><br class='clear' /></div>
|
||||
</code></pre><script>window.example43 = "fs = require 'fs'\n\noption '-o', '--output [DIR]', 'directory for compiled code'\n\ntask 'build:parser', 'rebuild the Jison parser', (options) ->\n require 'jison'\n code = require('./lib/grammar').parser.generate()\n dir = options.output or 'lib'\n fs.writeFile \"#{dir}/parser.js\", code"</script><div class='minibutton load' onclick='javascript: loadConsole(example43);'>load</div><br class='clear' /></div>
|
||||
<p>
|
||||
If you need to invoke one task before another — for example, running
|
||||
<tt>build</tt> before <tt>test</tt>, you can use the <tt>invoke</tt> function:
|
||||
@@ -2302,14 +2340,18 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.packtpub.com/coffeescript-application-development/book">CoffeeScript Application Development</a>
|
||||
is a new book from Packt Publishing that introduces CoffeeScript while
|
||||
from Packt, introduces CoffeeScript while
|
||||
walking through the process of building a demonstration web application.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.manning.com/lee/">CoffeeScript in Action</a>
|
||||
is a new book from Manning Publications that covers CoffeeScript syntax, composition techniques
|
||||
from Manning Publications, covers CoffeeScript syntax, composition techniques
|
||||
and application development.
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://www.dpunkt.de/buecher/4021/coffeescript.html">CoffeeScript: Die Alternative zu JavaScript</a>
|
||||
from dpunkt.verlag, is the first CoffeeScript book in Deutsch.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>
|
||||
@@ -2372,8 +2414,8 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
|
||||
the Bolo tank game for modern browsers.
|
||||
</li>
|
||||
<li>
|
||||
<b>josh</b>'s <a href="http://josh.github.com/nack/">nack</a>, a Node.js-powered
|
||||
<a href="http://rack.rubyforge.org/">Rack</a> server.
|
||||
<b>github</b>'s <a href="https://atom.io/">Atom</a>,
|
||||
a hackable text editor built on web technologies.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -2449,6 +2491,61 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
|
||||
Change Log
|
||||
</h2>
|
||||
|
||||
<p>
|
||||
<div class="anchor" id="1.9.1"></div>
|
||||
<b class="header">
|
||||
<a href="https://github.com/jashkenas/coffeescript/compare/1.9.0...1.9.1">1.9.1</a>
|
||||
<span class="timestamp"> — <time datetime="2015-02-18">February 18, 2015</time></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
Interpolation now works in object literal keys (again). You can use this to
|
||||
dynamically name properties.
|
||||
</li>
|
||||
<li>
|
||||
Internal compiler names no longer start with underscores. This makes
|
||||
the generated JavaScript a bit prettier, and also fixes an issue with
|
||||
the completely broken and ungodly way that AngularJS "parses" function
|
||||
arguments.
|
||||
</li>
|
||||
<li>
|
||||
Fixed a few <tt>yield</tt>-related bugs.
|
||||
</li>
|
||||
<li>
|
||||
Minor bug fixes and various improvements to compiler error messages.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<div class="anchor" id="1.9.0"></div>
|
||||
<b class="header">
|
||||
<a href="https://github.com/jashkenas/coffeescript/compare/1.8.0...1.9.0">1.9.0</a>
|
||||
<span class="timestamp"> — <time datetime="2015-01-29">January 29, 2015</time></span>
|
||||
</b>
|
||||
<ul>
|
||||
<li>
|
||||
CoffeeScript now supports ES6 generators. A generator is simply a function
|
||||
that <tt>yield</tt>s.
|
||||
</li>
|
||||
<li>
|
||||
More robust parsing and improved error messages for strings and regexes —
|
||||
especially with respect to interpolation.
|
||||
</li>
|
||||
<li>
|
||||
Changed strategy for the generation of internal compiler variable names.
|
||||
Note that this means that <tt>@example</tt> function parameters are no longer
|
||||
available as naked <tt>example</tt> variables within the function body.
|
||||
</li>
|
||||
<li>
|
||||
Fixed REPL compatibility with latest versions of Node and Io.js.
|
||||
</li>
|
||||
<li>
|
||||
Various minor bug fixes.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<div class="anchor" id="1.8.0"></div>
|
||||
<b class="header">
|
||||
@@ -2532,7 +2629,7 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
|
||||
</code></pre><pre><code>$(<span class="string">'body'</span>).click(<span class="function"><span class="keyword">function</span><span class="params">(e)</span> {</span>
|
||||
<span class="keyword">return</span> $(<span class="string">'.box'</span>).fadeIn(<span class="string">'fast'</span>).addClass(<span class="string">'.active'</span>);
|
||||
}).css(<span class="string">'background'</span>, <span class="string">'white'</span>);
|
||||
</code></pre><script>window.example43 = "$ 'body'\n.click (e) ->\n $ '.box'\n .fadeIn 'fast'\n .addClass '.active'\n.css 'background', 'white'\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example43);'>load</div><br class='clear' /></div>
|
||||
</code></pre><script>window.example44 = "$ 'body'\n.click (e) ->\n $ '.box'\n .fadeIn 'fast'\n .addClass '.active'\n.css 'background', 'white'\n\n\n"</script><div class='minibutton load' onclick='javascript: loadConsole(example44);'>load</div><br class='clear' /></div>
|
||||
<ul>
|
||||
<li>
|
||||
Added <tt>**</tt>, <tt>//</tt> and <tt>%%</tt> operators and <tt>...</tt> expansion in parameter lists and destructuring expressions.
|
||||
@@ -2771,7 +2868,7 @@ task(<span class="string">'build:parser'</span>, <span class="string">'rebuild t
|
||||
effectively creating a shallow copy of the list.
|
||||
</li>
|
||||
<li>
|
||||
Additional tweaks and improvments to <tt>coffee --watch</tt> under
|
||||
Additional tweaks and improvements to <tt>coffee --watch</tt> under
|
||||
Node's "new" file watching API. Watch will now beep by default
|
||||
if you introduce a syntax error into a watched script. We also now
|
||||
ignore hidden directories by default when watching recursively.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var CoffeeScript, compile, runScripts,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
@@ -34,14 +34,14 @@
|
||||
|
||||
if ((typeof btoa !== "undefined" && btoa !== null) && (typeof JSON !== "undefined" && JSON !== null) && (typeof unescape !== "undefined" && unescape !== null) && (typeof encodeURIComponent !== "undefined" && encodeURIComponent !== null)) {
|
||||
compile = function(code, options) {
|
||||
var js, v3SourceMap, _ref;
|
||||
var js, ref, v3SourceMap;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
options.sourceMap = true;
|
||||
options.inline = true;
|
||||
_ref = CoffeeScript.compile(code, options), js = _ref.js, v3SourceMap = _ref.v3SourceMap;
|
||||
return "" + js + "\n//# sourceMappingURL=data:application/json;base64," + (btoa(unescape(encodeURIComponent(v3SourceMap)))) + "\n//# sourceURL=coffeescript";
|
||||
ref = CoffeeScript.compile(code, options), js = ref.js, v3SourceMap = ref.v3SourceMap;
|
||||
return js + "\n//# sourceMappingURL=data:application/json;base64," + (btoa(unescape(encodeURIComponent(v3SourceMap)))) + "\n//# sourceURL=coffeescript";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -60,9 +60,9 @@
|
||||
xhr.overrideMimeType('text/plain');
|
||||
}
|
||||
xhr.onreadystatechange = function() {
|
||||
var param, _ref;
|
||||
var param, ref;
|
||||
if (xhr.readyState === 4) {
|
||||
if ((_ref = xhr.status) === 0 || _ref === 200) {
|
||||
if ((ref = xhr.status) === 0 || ref === 200) {
|
||||
param = [xhr.responseText, options];
|
||||
if (!hold) {
|
||||
CoffeeScript.run.apply(CoffeeScript, param);
|
||||
@@ -79,19 +79,19 @@
|
||||
};
|
||||
|
||||
runScripts = function() {
|
||||
var coffees, coffeetypes, execute, i, index, s, script, scripts, _fn, _i, _len;
|
||||
var coffees, coffeetypes, execute, fn, i, index, j, len, s, script, scripts;
|
||||
scripts = window.document.getElementsByTagName('script');
|
||||
coffeetypes = ['text/coffeescript', 'text/literate-coffeescript'];
|
||||
coffees = (function() {
|
||||
var _i, _len, _ref, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
|
||||
s = scripts[_i];
|
||||
if (_ref = s.type, __indexOf.call(coffeetypes, _ref) >= 0) {
|
||||
_results.push(s);
|
||||
var j, len, ref, results;
|
||||
results = [];
|
||||
for (j = 0, len = scripts.length; j < len; j++) {
|
||||
s = scripts[j];
|
||||
if (ref = s.type, indexOf.call(coffeetypes, ref) >= 0) {
|
||||
results.push(s);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
index = 0;
|
||||
execute = function() {
|
||||
@@ -103,7 +103,7 @@
|
||||
return execute();
|
||||
}
|
||||
};
|
||||
_fn = function(script, i) {
|
||||
fn = function(script, i) {
|
||||
var options;
|
||||
options = {
|
||||
literate: script.type === coffeetypes[1]
|
||||
@@ -118,9 +118,9 @@
|
||||
return coffees[i] = [script.innerHTML, options];
|
||||
}
|
||||
};
|
||||
for (i = _i = 0, _len = coffees.length; _i < _len; i = ++_i) {
|
||||
for (i = j = 0, len = coffees.length; j < len; i = ++j) {
|
||||
script = coffees[i];
|
||||
_fn(script, i);
|
||||
fn(script, i);
|
||||
}
|
||||
return execute();
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var CoffeeScript, cakefileDirectory, fatalError, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
|
||||
helpers.extend(global, {
|
||||
task: function(name, description, action) {
|
||||
var _ref;
|
||||
var ref;
|
||||
if (!action) {
|
||||
_ref = [description, action], action = _ref[0], description = _ref[1];
|
||||
ref = [description, action], action = ref[0], description = ref[1];
|
||||
}
|
||||
return tasks[name] = {
|
||||
name: name,
|
||||
@@ -46,7 +46,7 @@
|
||||
});
|
||||
|
||||
exports.run = function() {
|
||||
var arg, args, e, _i, _len, _ref, _results;
|
||||
var arg, args, e, i, len, ref, results;
|
||||
global.__originalDirname = fs.realpathSync('.');
|
||||
process.chdir(cakefileDirectory(__originalDirname));
|
||||
args = process.argv.slice(2);
|
||||
@@ -63,20 +63,20 @@
|
||||
e = _error;
|
||||
return fatalError("" + e);
|
||||
}
|
||||
_ref = options["arguments"];
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
arg = _ref[_i];
|
||||
_results.push(invoke(arg));
|
||||
ref = options["arguments"];
|
||||
results = [];
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
arg = ref[i];
|
||||
results.push(invoke(arg));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
};
|
||||
|
||||
printTasks = function() {
|
||||
var cakefilePath, desc, name, relative, spaces, task;
|
||||
relative = path.relative || path.resolve;
|
||||
cakefilePath = path.join(relative(__originalDirname, process.cwd()), 'Cakefile');
|
||||
console.log("" + cakefilePath + " defines the following tasks:\n");
|
||||
console.log(cakefilePath + " defines the following tasks:\n");
|
||||
for (name in tasks) {
|
||||
task = tasks[name];
|
||||
spaces = 20 - name.length;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var Lexer, SourceMap, compile, ext, formatSourcePosition, fs, getSourceMap, helpers, lexer, parser, path, sourceMaps, vm, withPrettyErrors, _base, _i, _len, _ref,
|
||||
__hasProp = {}.hasOwnProperty,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
var Lexer, SourceMap, base, compile, ext, formatSourcePosition, fs, getSourceMap, helpers, i, len, lexer, parser, path, ref, sourceMaps, vm, withPrettyErrors,
|
||||
hasProp = {}.hasOwnProperty,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
SourceMap = require('./sourcemap');
|
||||
|
||||
exports.VERSION = '1.8.0';
|
||||
exports.VERSION = '1.9.1';
|
||||
|
||||
exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md'];
|
||||
|
||||
@@ -40,13 +40,25 @@
|
||||
};
|
||||
|
||||
exports.compile = compile = withPrettyErrors(function(code, options) {
|
||||
var answer, currentColumn, currentLine, extend, fragment, fragments, header, js, map, merge, newLines, _i, _len;
|
||||
var answer, currentColumn, currentLine, extend, fragment, fragments, header, i, js, len, map, merge, newLines, token, tokens;
|
||||
merge = helpers.merge, extend = helpers.extend;
|
||||
options = extend({}, options);
|
||||
if (options.sourceMap) {
|
||||
map = new SourceMap;
|
||||
}
|
||||
fragments = parser.parse(lexer.tokenize(code, options)).compileToFragments(options);
|
||||
tokens = lexer.tokenize(code, options);
|
||||
options.referencedVars = (function() {
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = tokens.length; i < len; i++) {
|
||||
token = tokens[i];
|
||||
if (token.variable) {
|
||||
results.push(token[1]);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
fragments = parser.parse(tokens).compileToFragments(options);
|
||||
currentLine = 0;
|
||||
if (options.header) {
|
||||
currentLine += 1;
|
||||
@@ -56,8 +68,8 @@
|
||||
}
|
||||
currentColumn = 0;
|
||||
js = "";
|
||||
for (_i = 0, _len = fragments.length; _i < _len; _i++) {
|
||||
fragment = fragments[_i];
|
||||
for (i = 0, len = fragments.length; i < len; i++) {
|
||||
fragment = fragments[i];
|
||||
if (options.sourceMap) {
|
||||
if (fragment.locationData) {
|
||||
map.add([fragment.locationData.first_line, fragment.locationData.first_column], [currentLine, currentColumn], {
|
||||
@@ -103,7 +115,7 @@
|
||||
});
|
||||
|
||||
exports.run = function(code, options) {
|
||||
var answer, dir, mainModule, _ref;
|
||||
var answer, dir, mainModule, ref;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
@@ -114,30 +126,33 @@
|
||||
mainModule.paths = require('module')._nodeModulePaths(dir);
|
||||
if (!helpers.isCoffee(mainModule.filename) || require.extensions) {
|
||||
answer = compile(code, options);
|
||||
code = (_ref = answer.js) != null ? _ref : answer;
|
||||
code = (ref = answer.js) != null ? ref : answer;
|
||||
}
|
||||
return mainModule._compile(code, mainModule.filename);
|
||||
};
|
||||
|
||||
exports["eval"] = function(code, options) {
|
||||
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref, _ref1, _require;
|
||||
var Module, _module, _require, createContext, i, isContext, js, k, len, o, r, ref, ref1, ref2, ref3, sandbox, v;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
if (!(code = code.trim())) {
|
||||
return;
|
||||
}
|
||||
Script = vm.Script;
|
||||
if (Script) {
|
||||
createContext = (ref = vm.Script.createContext) != null ? ref : vm.createContext;
|
||||
isContext = (ref1 = vm.isContext) != null ? ref1 : function(ctx) {
|
||||
return options.sandbox instanceof createContext().constructor;
|
||||
};
|
||||
if (createContext) {
|
||||
if (options.sandbox != null) {
|
||||
if (options.sandbox instanceof Script.createContext().constructor) {
|
||||
if (isContext(options.sandbox)) {
|
||||
sandbox = options.sandbox;
|
||||
} else {
|
||||
sandbox = Script.createContext();
|
||||
_ref = options.sandbox;
|
||||
for (k in _ref) {
|
||||
if (!__hasProp.call(_ref, k)) continue;
|
||||
v = _ref[k];
|
||||
sandbox = createContext();
|
||||
ref2 = options.sandbox;
|
||||
for (k in ref2) {
|
||||
if (!hasProp.call(ref2, k)) continue;
|
||||
v = ref2[k];
|
||||
sandbox[k] = v;
|
||||
}
|
||||
}
|
||||
@@ -154,9 +169,9 @@
|
||||
return Module._load(path, _module, true);
|
||||
};
|
||||
_module.filename = sandbox.__filename;
|
||||
_ref1 = Object.getOwnPropertyNames(require);
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
r = _ref1[_i];
|
||||
ref3 = Object.getOwnPropertyNames(require);
|
||||
for (i = 0, len = ref3.length; i < len; i++) {
|
||||
r = ref3[i];
|
||||
if (r !== 'paths') {
|
||||
_require[r] = require[r];
|
||||
}
|
||||
@@ -169,7 +184,7 @@
|
||||
}
|
||||
o = {};
|
||||
for (k in options) {
|
||||
if (!__hasProp.call(options, k)) continue;
|
||||
if (!hasProp.call(options, k)) continue;
|
||||
v = options[k];
|
||||
o[k] = v;
|
||||
}
|
||||
@@ -187,11 +202,11 @@
|
||||
};
|
||||
|
||||
if (require.extensions) {
|
||||
_ref = this.FILE_EXTENSIONS;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
ext = _ref[_i];
|
||||
if ((_base = require.extensions)[ext] == null) {
|
||||
_base[ext] = function() {
|
||||
ref = this.FILE_EXTENSIONS;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
ext = ref[i];
|
||||
if ((base = require.extensions)[ext] == null) {
|
||||
base[ext] = function() {
|
||||
throw new Error("Use CoffeeScript.register() or require the coffee-script/register module to require " + ext + " files.");
|
||||
};
|
||||
}
|
||||
@@ -223,10 +238,10 @@
|
||||
parser.lexer = {
|
||||
lex: function() {
|
||||
var tag, token;
|
||||
token = this.tokens[this.pos++];
|
||||
token = parser.tokens[this.pos++];
|
||||
if (token) {
|
||||
tag = token[0], this.yytext = token[1], this.yylloc = token[2];
|
||||
this.errorToken = token.origin || token;
|
||||
parser.errorToken = token.origin || token;
|
||||
this.yylineno = this.yylloc.first_line;
|
||||
} else {
|
||||
tag = '';
|
||||
@@ -234,7 +249,7 @@
|
||||
return tag;
|
||||
},
|
||||
setInput: function(tokens) {
|
||||
this.tokens = tokens;
|
||||
parser.tokens = tokens;
|
||||
return this.pos = 0;
|
||||
},
|
||||
upcomingInput: function() {
|
||||
@@ -244,12 +259,23 @@
|
||||
|
||||
parser.yy = require('./nodes');
|
||||
|
||||
parser.yy.parseError = function(message, _arg) {
|
||||
var errorLoc, errorTag, errorText, errorToken, token, tokens, _ref1;
|
||||
token = _arg.token;
|
||||
_ref1 = parser.lexer, errorToken = _ref1.errorToken, tokens = _ref1.tokens;
|
||||
parser.yy.parseError = function(message, arg) {
|
||||
var errorLoc, errorTag, errorText, errorToken, token, tokens;
|
||||
token = arg.token;
|
||||
errorToken = parser.errorToken, tokens = parser.tokens;
|
||||
errorTag = errorToken[0], errorText = errorToken[1], errorLoc = errorToken[2];
|
||||
errorText = errorToken === tokens[tokens.length - 1] ? 'end of input' : errorTag === 'INDENT' || errorTag === 'OUTDENT' ? 'indentation' : helpers.nameWhitespaceCharacter(errorText);
|
||||
errorText = (function() {
|
||||
switch (false) {
|
||||
case errorToken !== tokens[tokens.length - 1]:
|
||||
return 'end of input';
|
||||
case errorTag !== 'INDENT' && errorTag !== 'OUTDENT':
|
||||
return 'indentation';
|
||||
case errorTag !== 'IDENTIFIER' && errorTag !== 'NUMBER' && errorTag !== 'STRING' && errorTag !== 'STRING_START' && errorTag !== 'REGEX' && errorTag !== 'REGEX_START':
|
||||
return errorTag.replace(/_START$/, '').toLowerCase();
|
||||
default:
|
||||
return helpers.nameWhitespaceCharacter(errorText);
|
||||
}
|
||||
})();
|
||||
return helpers.throwSyntaxError("unexpected " + errorText, errorLoc);
|
||||
};
|
||||
|
||||
@@ -263,7 +289,7 @@
|
||||
if (frame.isEval()) {
|
||||
fileName = frame.getScriptNameOrSourceURL();
|
||||
if (!fileName) {
|
||||
fileLocation = "" + (frame.getEvalOrigin()) + ", ";
|
||||
fileLocation = (frame.getEvalOrigin()) + ", ";
|
||||
}
|
||||
} else {
|
||||
fileName = frame.getFileName();
|
||||
@@ -272,7 +298,7 @@
|
||||
line = frame.getLineNumber();
|
||||
column = frame.getColumnNumber();
|
||||
source = getSourceMapping(fileName, line, column);
|
||||
fileLocation = source ? "" + fileName + ":" + source[0] + ":" + source[1] : "" + fileName + ":" + line + ":" + column;
|
||||
fileLocation = source ? fileName + ":" + source[0] + ":" + source[1] : fileName + ":" + line + ":" + column;
|
||||
}
|
||||
functionName = frame.getFunctionName();
|
||||
isConstructor = frame.isConstructor();
|
||||
@@ -283,19 +309,19 @@
|
||||
if (functionName) {
|
||||
tp = as = '';
|
||||
if (typeName && functionName.indexOf(typeName)) {
|
||||
tp = "" + typeName + ".";
|
||||
tp = typeName + ".";
|
||||
}
|
||||
if (methodName && functionName.indexOf("." + methodName) !== functionName.length - methodName.length - 1) {
|
||||
as = " [as " + methodName + "]";
|
||||
}
|
||||
return "" + tp + functionName + as + " (" + fileLocation + ")";
|
||||
} else {
|
||||
return "" + typeName + "." + (methodName || '<anonymous>') + " (" + fileLocation + ")";
|
||||
return typeName + "." + (methodName || '<anonymous>') + " (" + fileLocation + ")";
|
||||
}
|
||||
} else if (isConstructor) {
|
||||
return "new " + (functionName || '<anonymous>') + " (" + fileLocation + ")";
|
||||
} else if (functionName) {
|
||||
return "" + functionName + " (" + fileLocation + ")";
|
||||
return functionName + " (" + fileLocation + ")";
|
||||
} else {
|
||||
return fileLocation;
|
||||
}
|
||||
@@ -304,11 +330,11 @@
|
||||
sourceMaps = {};
|
||||
|
||||
getSourceMap = function(filename) {
|
||||
var answer, _ref1;
|
||||
var answer, ref1;
|
||||
if (sourceMaps[filename]) {
|
||||
return sourceMaps[filename];
|
||||
}
|
||||
if (_ref1 = path != null ? path.extname(filename) : void 0, __indexOf.call(exports.FILE_EXTENSIONS, _ref1) < 0) {
|
||||
if (ref1 = path != null ? path.extname(filename) : void 0, indexOf.call(exports.FILE_EXTENSIONS, ref1) < 0) {
|
||||
return;
|
||||
}
|
||||
answer = exports._compileFile(filename, true);
|
||||
@@ -330,18 +356,18 @@
|
||||
}
|
||||
};
|
||||
frames = (function() {
|
||||
var _j, _len1, _results;
|
||||
_results = [];
|
||||
for (_j = 0, _len1 = stack.length; _j < _len1; _j++) {
|
||||
frame = stack[_j];
|
||||
var j, len1, results;
|
||||
results = [];
|
||||
for (j = 0, len1 = stack.length; j < len1; j++) {
|
||||
frame = stack[j];
|
||||
if (frame.getFunction() === exports.run) {
|
||||
break;
|
||||
}
|
||||
_results.push(" at " + (formatSourcePosition(frame, getSourceMapping)));
|
||||
results.push(" at " + (formatSourcePosition(frame, getSourceMapping)));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
return "" + (err.toString()) + "\n" + (frames.join('\n')) + "\n";
|
||||
return (err.toString()) + "\n" + (frames.join('\n')) + "\n";
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs, _ref,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compilePath, compileScript, compileStdio, exec, findDirectoryIndex, forkNode, fs, helpers, hidden, joinTimeout, jsToSources, mkdirp, notSources, optionParser, optparse, opts, outputPath, parseOptions, path, printLine, printTokens, printWarn, ref, removeSource, removeSourceDir, silentUnlink, sourceCode, sources, spawn, timeLog, usage, useWinPathSep, version, wait, watch, watchDir, watchedDirs, writeJs,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -13,9 +13,7 @@
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
mkdirp = require('mkdirp');
|
||||
|
||||
_ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
|
||||
ref = require('child_process'), spawn = ref.spawn, exec = ref.exec;
|
||||
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
|
||||
@@ -51,8 +49,10 @@
|
||||
|
||||
optionParser = null;
|
||||
|
||||
jsToSources = {};
|
||||
|
||||
exports.run = function() {
|
||||
var literals, replCliOpts, source, _i, _len, _ref1, _results;
|
||||
var i, len, literals, ref1, replCliOpts, results, source;
|
||||
parseOptions();
|
||||
replCliOpts = {
|
||||
useGlobal: true
|
||||
@@ -88,19 +88,19 @@
|
||||
opts.join = path.resolve(opts.join);
|
||||
console.error('\nThe --join option is deprecated and will be removed in a future version.\n\nIf for some reason it\'s necessary to share local variables between files,\nreplace...\n\n $ coffee --compile --join bundle.js -- a.coffee b.coffee c.coffee\n\nwith...\n\n $ cat a.coffee b.coffee c.coffee | coffee --compile --stdio > bundle.js\n');
|
||||
}
|
||||
_ref1 = opts["arguments"];
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
source = _ref1[_i];
|
||||
ref1 = opts["arguments"];
|
||||
results = [];
|
||||
for (i = 0, len = ref1.length; i < len; i++) {
|
||||
source = ref1[i];
|
||||
source = path.resolve(source);
|
||||
_results.push(compilePath(source, true, source));
|
||||
results.push(compilePath(source, true, source));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
};
|
||||
|
||||
compilePath = function(source, topLevel, base) {
|
||||
var code, err, file, files, stats, _i, _len, _results;
|
||||
if (__indexOf.call(sources, source) >= 0 || watchedDirs[source] || !topLevel && (notSources[source] || hidden(source))) {
|
||||
var code, err, file, files, i, len, results, stats;
|
||||
if (indexOf.call(sources, source) >= 0 || watchedDirs[source] || !topLevel && (notSources[source] || hidden(source))) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -135,12 +135,12 @@
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
_results.push(compilePath(path.join(source, file), false, base));
|
||||
results = [];
|
||||
for (i = 0, len = files.length; i < len; i++) {
|
||||
file = files[i];
|
||||
results.push(compilePath(path.join(source, file), false, base));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
} else if (topLevel || helpers.isCoffee(source)) {
|
||||
sources.push(source);
|
||||
sourceCode.push(null);
|
||||
@@ -165,10 +165,10 @@
|
||||
};
|
||||
|
||||
findDirectoryIndex = function(source) {
|
||||
var err, ext, index, _i, _len, _ref1;
|
||||
_ref1 = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
ext = _ref1[_i];
|
||||
var err, ext, i, index, len, ref1;
|
||||
ref1 = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (i = 0, len = ref1.length; i < len; i++) {
|
||||
ext = ref1[i];
|
||||
index = path.join(source, "index" + ext);
|
||||
try {
|
||||
if ((fs.statSync(index)).isFile()) {
|
||||
@@ -281,7 +281,7 @@
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
if (__indexOf.call(sources, source) < 0) {
|
||||
if (indexOf.call(sources, source) < 0) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -348,7 +348,7 @@
|
||||
}).on('change', function() {
|
||||
clearTimeout(readdirTimeout);
|
||||
return readdirTimeout = wait(25, function() {
|
||||
var err, file, files, _i, _len, _results;
|
||||
var err, file, files, i, len, results;
|
||||
try {
|
||||
files = fs.readdirSync(source);
|
||||
} catch (_error) {
|
||||
@@ -358,12 +358,12 @@
|
||||
}
|
||||
return stopWatcher();
|
||||
}
|
||||
_results = [];
|
||||
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
||||
file = files[_i];
|
||||
_results.push(compilePath(path.join(source, file), false, base));
|
||||
results = [];
|
||||
for (i = 0, len = files.length; i < len; i++) {
|
||||
file = files[i];
|
||||
results.push(compilePath(path.join(source, file), false, base));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -383,11 +383,11 @@
|
||||
};
|
||||
|
||||
removeSourceDir = function(source, base) {
|
||||
var file, sourcesChanged, _i, _len;
|
||||
var file, i, len, sourcesChanged;
|
||||
delete watchedDirs[source];
|
||||
sourcesChanged = false;
|
||||
for (_i = 0, _len = sources.length; _i < _len; _i++) {
|
||||
file = sources[_i];
|
||||
for (i = 0, len = sources.length; i < len; i++) {
|
||||
file = sources[i];
|
||||
if (!(source === path.dirname(file))) {
|
||||
continue;
|
||||
}
|
||||
@@ -412,12 +412,12 @@
|
||||
};
|
||||
|
||||
silentUnlink = function(path) {
|
||||
var err, _ref1;
|
||||
var err, ref1;
|
||||
try {
|
||||
return fs.unlinkSync(path);
|
||||
} catch (_error) {
|
||||
err = _error;
|
||||
if ((_ref1 = err.code) !== 'ENOENT' && _ref1 !== 'EPERM') {
|
||||
if ((ref1 = err.code) !== 'ENOENT' && ref1 !== 'EPERM') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
@@ -440,6 +440,27 @@
|
||||
return path.join(dir, basename + extension);
|
||||
};
|
||||
|
||||
mkdirp = function(dir, fn) {
|
||||
var mkdirs, mode;
|
||||
mode = 0x1ff & ~process.umask();
|
||||
return (mkdirs = function(p, fn) {
|
||||
return fs.exists(p, function(exists) {
|
||||
if (exists) {
|
||||
return fn();
|
||||
} else {
|
||||
return mkdirs(path.dirname(p), function() {
|
||||
return fs.mkdir(p, mode, function(err) {
|
||||
if (err) {
|
||||
return fn(err);
|
||||
}
|
||||
return fn();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
})(dir, fn);
|
||||
};
|
||||
|
||||
writeJs = function(base, sourcePath, js, jsPath, generatedSourceMap) {
|
||||
var compile, jsDir, sourceMapPath;
|
||||
if (generatedSourceMap == null) {
|
||||
@@ -447,13 +468,20 @@
|
||||
}
|
||||
sourceMapPath = outputPath(sourcePath, base, ".js.map");
|
||||
jsDir = path.dirname(jsPath);
|
||||
if (jsPath in jsToSources) {
|
||||
printLine("Error: The two following source files have the same output file:");
|
||||
printLine(" " + jsToSources[jsPath]);
|
||||
printLine(" " + sourcePath);
|
||||
process.exit(1);
|
||||
}
|
||||
jsToSources[jsPath] = sourcePath;
|
||||
compile = function() {
|
||||
if (opts.compile) {
|
||||
if (js.length <= 0) {
|
||||
js = ' ';
|
||||
}
|
||||
if (generatedSourceMap) {
|
||||
js = "" + js + "\n//# sourceMappingURL=" + (helpers.baseFileName(sourceMapPath, false, useWinPathSep)) + "\n";
|
||||
js = js + "\n//# sourceMappingURL=" + (helpers.baseFileName(sourceMapPath, false, useWinPathSep)) + "\n";
|
||||
}
|
||||
fs.writeFile(jsPath, js, function(err) {
|
||||
if (err) {
|
||||
@@ -487,21 +515,21 @@
|
||||
};
|
||||
|
||||
timeLog = function(message) {
|
||||
return console.log("" + ((new Date).toLocaleTimeString()) + " - " + message);
|
||||
return console.log(((new Date).toLocaleTimeString()) + " - " + message);
|
||||
};
|
||||
|
||||
printTokens = function(tokens) {
|
||||
var strings, tag, token, value;
|
||||
strings = (function() {
|
||||
var _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = tokens.length; _i < _len; _i++) {
|
||||
token = tokens[_i];
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = tokens.length; i < len; i++) {
|
||||
token = tokens[i];
|
||||
tag = token[0];
|
||||
value = token[1].toString().replace(/\n/, '\\n');
|
||||
_results.push("[" + tag + " " + value + "]");
|
||||
results.push("[" + tag + " " + value + "]");
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
return printLine(strings.join(' '));
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
|
||||
|
||||
@@ -63,16 +63,26 @@
|
||||
AlphaNumeric: [
|
||||
o('NUMBER', function() {
|
||||
return new Literal($1);
|
||||
}), o('STRING', function() {
|
||||
}), o('String')
|
||||
],
|
||||
String: [
|
||||
o('STRING', function() {
|
||||
return new Literal($1);
|
||||
}), o('STRING_START Body STRING_END', function() {
|
||||
return new Parens($2);
|
||||
})
|
||||
],
|
||||
Regex: [
|
||||
o('REGEX', function() {
|
||||
return new Literal($1);
|
||||
}), o('REGEX_START Invocation REGEX_END', function() {
|
||||
return $2;
|
||||
})
|
||||
],
|
||||
Literal: [
|
||||
o('AlphaNumeric'), o('JS', function() {
|
||||
return new Literal($1);
|
||||
}), o('REGEX', function() {
|
||||
return new Literal($1);
|
||||
}), o('DEBUGGER', function() {
|
||||
}), o('Regex'), o('DEBUGGER', function() {
|
||||
return new Literal($1);
|
||||
}), o('UNDEFINED', function() {
|
||||
return new Undefined;
|
||||
@@ -421,6 +431,11 @@
|
||||
return {
|
||||
source: LOC(2)(new Value($2))
|
||||
};
|
||||
}), o('FOR Range BY Expression', function() {
|
||||
return {
|
||||
source: LOC(2)(new Value($2)),
|
||||
step: $4
|
||||
};
|
||||
}), o('ForStart ForSource', function() {
|
||||
$2.own = $1.own;
|
||||
$2.name = $1[0];
|
||||
@@ -552,6 +567,12 @@
|
||||
return new Op('+', $2);
|
||||
}), {
|
||||
prec: 'UNARY_MATH'
|
||||
}), o('YIELD Statement', function() {
|
||||
return new Op($1, $2);
|
||||
}), o('YIELD Expression', function() {
|
||||
return new Op($1, $2);
|
||||
}), o('YIELD FROM Expression', function() {
|
||||
return new Op($1.concat($2), $3);
|
||||
}), o('-- SimpleAssignable', function() {
|
||||
return new Op('--', $2);
|
||||
}), o('++ SimpleAssignable', function() {
|
||||
@@ -594,20 +615,20 @@
|
||||
]
|
||||
};
|
||||
|
||||
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['left', 'POST_IF']];
|
||||
operators = [['left', '.', '?.', '::', '?::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['right', '**'], ['right', 'UNARY_MATH'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', 'YIELD'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['left', 'POST_IF']];
|
||||
|
||||
tokens = [];
|
||||
|
||||
for (name in grammar) {
|
||||
alternatives = grammar[name];
|
||||
grammar[name] = (function() {
|
||||
var _i, _j, _len, _len1, _ref, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = alternatives.length; _i < _len; _i++) {
|
||||
alt = alternatives[_i];
|
||||
_ref = alt[0].split(' ');
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
token = _ref[_j];
|
||||
var i, j, len, len1, ref, results;
|
||||
results = [];
|
||||
for (i = 0, len = alternatives.length; i < len; i++) {
|
||||
alt = alternatives[i];
|
||||
ref = alt[0].split(' ');
|
||||
for (j = 0, len1 = ref.length; j < len1; j++) {
|
||||
token = ref[j];
|
||||
if (!grammar[token]) {
|
||||
tokens.push(token);
|
||||
}
|
||||
@@ -615,9 +636,9 @@
|
||||
if (name === 'Root') {
|
||||
alt[1] = "return " + alt[1];
|
||||
}
|
||||
_results.push(alt);
|
||||
results.push(alt);
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var buildLocationData, extend, flatten, last, repeat, syntaxErrorToString, _ref;
|
||||
var buildLocationData, extend, flatten, ref, repeat, syntaxErrorToString;
|
||||
|
||||
exports.starts = function(string, literal, start) {
|
||||
return literal === string.substr(start, literal.length);
|
||||
@@ -26,15 +26,15 @@
|
||||
};
|
||||
|
||||
exports.compact = function(array) {
|
||||
var item, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||||
item = array[_i];
|
||||
var i, item, len1, results;
|
||||
results = [];
|
||||
for (i = 0, len1 = array.length; i < len1; i++) {
|
||||
item = array[i];
|
||||
if (item) {
|
||||
_results.push(item);
|
||||
results.push(item);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
};
|
||||
|
||||
exports.count = function(string, substr) {
|
||||
@@ -63,10 +63,10 @@
|
||||
};
|
||||
|
||||
exports.flatten = flatten = function(array) {
|
||||
var element, flattened, _i, _len;
|
||||
var element, flattened, i, len1;
|
||||
flattened = [];
|
||||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||||
element = array[_i];
|
||||
for (i = 0, len1 = array.length; i < len1; i++) {
|
||||
element = array[i];
|
||||
if (element instanceof Array) {
|
||||
flattened = flattened.concat(flatten(element));
|
||||
} else {
|
||||
@@ -83,14 +83,10 @@
|
||||
return val;
|
||||
};
|
||||
|
||||
exports.last = last = function(array, back) {
|
||||
return array[array.length - (back || 0) - 1];
|
||||
};
|
||||
|
||||
exports.some = (_ref = Array.prototype.some) != null ? _ref : function(fn) {
|
||||
var e, _i, _len;
|
||||
for (_i = 0, _len = this.length; _i < _len; _i++) {
|
||||
e = this[_i];
|
||||
exports.some = (ref = Array.prototype.some) != null ? ref : function(fn) {
|
||||
var e, i, len1;
|
||||
for (i = 0, len1 = this.length; i < len1; i++) {
|
||||
e = this[i];
|
||||
if (fn(e)) {
|
||||
return true;
|
||||
}
|
||||
@@ -102,20 +98,20 @@
|
||||
var line, lines, maybe_code;
|
||||
maybe_code = true;
|
||||
lines = (function() {
|
||||
var _i, _len, _ref1, _results;
|
||||
_ref1 = code.split('\n');
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
line = _ref1[_i];
|
||||
var i, len1, ref1, results;
|
||||
ref1 = code.split('\n');
|
||||
results = [];
|
||||
for (i = 0, len1 = ref1.length; i < len1; i++) {
|
||||
line = ref1[i];
|
||||
if (maybe_code && /^([ ]{4}|[ ]{0,3}\t)/.test(line)) {
|
||||
_results.push(line);
|
||||
results.push(line);
|
||||
} else if (maybe_code = /^\s*$/.test(line)) {
|
||||
_results.push(line);
|
||||
results.push(line);
|
||||
} else {
|
||||
_results.push('# ' + line);
|
||||
results.push('# ' + line);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
})();
|
||||
return lines.join('\n');
|
||||
};
|
||||
@@ -150,7 +146,7 @@
|
||||
locationData = obj;
|
||||
}
|
||||
if (locationData) {
|
||||
return ("" + (locationData.first_line + 1) + ":" + (locationData.first_column + 1) + "-") + ("" + (locationData.last_line + 1) + ":" + (locationData.last_column + 1));
|
||||
return ((locationData.first_line + 1) + ":" + (locationData.first_column + 1) + "-") + ((locationData.last_line + 1) + ":" + (locationData.last_column + 1));
|
||||
} else {
|
||||
return "No location data";
|
||||
}
|
||||
@@ -205,11 +201,11 @@
|
||||
};
|
||||
|
||||
syntaxErrorToString = function() {
|
||||
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, start, _ref1, _ref2;
|
||||
var codeLine, colorize, colorsEnabled, end, filename, first_column, first_line, last_column, last_line, marker, ref1, ref2, start;
|
||||
if (!(this.code && this.location)) {
|
||||
return Error.prototype.toString.call(this);
|
||||
}
|
||||
_ref1 = this.location, first_line = _ref1.first_line, first_column = _ref1.first_column, last_line = _ref1.last_line, last_column = _ref1.last_column;
|
||||
ref1 = this.location, first_line = ref1.first_line, first_column = ref1.first_column, last_line = ref1.last_line, last_column = ref1.last_column;
|
||||
if (last_line == null) {
|
||||
last_line = first_line;
|
||||
}
|
||||
@@ -224,14 +220,14 @@
|
||||
if (typeof process !== "undefined" && process !== null) {
|
||||
colorsEnabled = process.stdout.isTTY && !process.env.NODE_DISABLE_COLORS;
|
||||
}
|
||||
if ((_ref2 = this.colorful) != null ? _ref2 : colorsEnabled) {
|
||||
if ((ref2 = this.colorful) != null ? ref2 : colorsEnabled) {
|
||||
colorize = function(str) {
|
||||
return "\x1B[1;31m" + str + "\x1B[0m";
|
||||
};
|
||||
codeLine = codeLine.slice(0, start) + colorize(codeLine.slice(start, end)) + codeLine.slice(end);
|
||||
marker = colorize(marker);
|
||||
}
|
||||
return "" + filename + ":" + (first_line + 1) + ":" + (first_column + 1) + ": error: " + this.message + "\n" + codeLine + "\n" + marker;
|
||||
return filename + ":" + (first_line + 1) + ":" + (first_column + 1) + ": error: " + this.message + "\n" + codeLine + "\n" + marker;
|
||||
};
|
||||
|
||||
exports.nameWhitespaceCharacter = function(string) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var key, val, _ref;
|
||||
var key, ref, val;
|
||||
|
||||
_ref = require('./coffee-script');
|
||||
for (key in _ref) {
|
||||
val = _ref[key];
|
||||
ref = require('./coffee-script');
|
||||
for (key in ref) {
|
||||
val = ref[key];
|
||||
exports[key] = val;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments, repeat;
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
}
|
||||
|
||||
OptionParser.prototype.parse = function(args) {
|
||||
var arg, i, isOption, matchedRule, options, originalArgs, pos, rule, seenNonOptionArg, skippingArgument, value, _i, _j, _len, _len1, _ref;
|
||||
var arg, i, isOption, j, k, len, len1, matchedRule, options, originalArgs, pos, ref, rule, seenNonOptionArg, skippingArgument, value;
|
||||
options = {
|
||||
"arguments": []
|
||||
};
|
||||
skippingArgument = false;
|
||||
originalArgs = args;
|
||||
args = normalizeArguments(args);
|
||||
for (i = _i = 0, _len = args.length; _i < _len; i = ++_i) {
|
||||
for (i = j = 0, len = args.length; j < len; i = ++j) {
|
||||
arg = args[i];
|
||||
if (skippingArgument) {
|
||||
skippingArgument = false;
|
||||
@@ -33,9 +33,9 @@
|
||||
seenNonOptionArg = options["arguments"].length > 0;
|
||||
if (!seenNonOptionArg) {
|
||||
matchedRule = false;
|
||||
_ref = this.rules;
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
rule = _ref[_j];
|
||||
ref = this.rules;
|
||||
for (k = 0, len1 = ref.length; k < len1; k++) {
|
||||
rule = ref[k];
|
||||
if (rule.shortFlag === arg || rule.longFlag === arg) {
|
||||
value = true;
|
||||
if (rule.hasArgument) {
|
||||
@@ -59,14 +59,14 @@
|
||||
};
|
||||
|
||||
OptionParser.prototype.help = function() {
|
||||
var letPart, lines, rule, spaces, _i, _len, _ref;
|
||||
var j, len, letPart, lines, ref, rule, spaces;
|
||||
lines = [];
|
||||
if (this.banner) {
|
||||
lines.unshift("" + this.banner + "\n");
|
||||
lines.unshift(this.banner + "\n");
|
||||
}
|
||||
_ref = this.rules;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
rule = _ref[_i];
|
||||
ref = this.rules;
|
||||
for (j = 0, len = ref.length; j < len; j++) {
|
||||
rule = ref[j];
|
||||
spaces = 15 - rule.longFlag.length;
|
||||
spaces = spaces > 0 ? repeat(' ', spaces) : '';
|
||||
letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' ';
|
||||
@@ -88,16 +88,16 @@
|
||||
OPTIONAL = /\[(\w+(\*?))\]/;
|
||||
|
||||
buildRules = function(rules) {
|
||||
var tuple, _i, _len, _results;
|
||||
_results = [];
|
||||
for (_i = 0, _len = rules.length; _i < _len; _i++) {
|
||||
tuple = rules[_i];
|
||||
var j, len, results, tuple;
|
||||
results = [];
|
||||
for (j = 0, len = rules.length; j < len; j++) {
|
||||
tuple = rules[j];
|
||||
if (tuple.length < 3) {
|
||||
tuple.unshift(null);
|
||||
}
|
||||
_results.push(buildRule.apply(null, tuple));
|
||||
results.push(buildRule.apply(null, tuple));
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
};
|
||||
|
||||
buildRule = function(shortFlag, longFlag, description, options) {
|
||||
@@ -118,15 +118,15 @@
|
||||
};
|
||||
|
||||
normalizeArguments = function(args) {
|
||||
var arg, l, match, result, _i, _j, _len, _len1, _ref;
|
||||
var arg, j, k, l, len, len1, match, ref, result;
|
||||
args = args.slice(0);
|
||||
result = [];
|
||||
for (_i = 0, _len = args.length; _i < _len; _i++) {
|
||||
arg = args[_i];
|
||||
for (j = 0, len = args.length; j < len; j++) {
|
||||
arg = args[j];
|
||||
if (match = arg.match(MULTI_FLAG)) {
|
||||
_ref = match[1].split('');
|
||||
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
|
||||
l = _ref[_j];
|
||||
ref = match[1].split('');
|
||||
for (k = 0, len1 = ref.length; k < len1; k++) {
|
||||
l = ref[k];
|
||||
result.push('-' + l);
|
||||
}
|
||||
} else {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, loadFile, path, _i, _len, _ref;
|
||||
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, i, len, loadFile, path, ref;
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
};
|
||||
|
||||
if (require.extensions) {
|
||||
_ref = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||||
ext = _ref[_i];
|
||||
ref = CoffeeScript.FILE_EXTENSIONS;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
ext = ref[i];
|
||||
require.extensions[ext] = loadFile;
|
||||
}
|
||||
Module = require('module');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, replDefaults, updateSyntaxError, vm, _ref;
|
||||
var CoffeeScript, addHistory, addMultilineHandler, fs, getCommandId, merge, nodeREPL, path, ref, replDefaults, updateSyntaxError, vm;
|
||||
|
||||
fs = require('fs');
|
||||
|
||||
@@ -12,23 +12,36 @@
|
||||
|
||||
CoffeeScript = require('./coffee-script');
|
||||
|
||||
_ref = require('./helpers'), merge = _ref.merge, updateSyntaxError = _ref.updateSyntaxError;
|
||||
ref = require('./helpers'), merge = ref.merge, updateSyntaxError = ref.updateSyntaxError;
|
||||
|
||||
replDefaults = {
|
||||
prompt: 'coffee> ',
|
||||
historyFile: process.env.HOME ? path.join(process.env.HOME, '.coffee_history') : void 0,
|
||||
historyMaxInputSize: 10240,
|
||||
"eval": function(input, context, filename, cb) {
|
||||
var Assign, Block, Literal, Value, ast, err, js, result, _ref1;
|
||||
var Assign, Block, Literal, Value, ast, err, js, ref1, referencedVars, result, token, tokens;
|
||||
input = input.replace(/\uFF00/g, '\n');
|
||||
input = input.replace(/^\(([\s\S]*)\n\)$/m, '$1');
|
||||
_ref1 = require('./nodes'), Block = _ref1.Block, Assign = _ref1.Assign, Value = _ref1.Value, Literal = _ref1.Literal;
|
||||
ref1 = require('./nodes'), Block = ref1.Block, Assign = ref1.Assign, Value = ref1.Value, Literal = ref1.Literal;
|
||||
try {
|
||||
ast = CoffeeScript.nodes(input);
|
||||
tokens = CoffeeScript.tokens(input);
|
||||
referencedVars = (function() {
|
||||
var i, len, results;
|
||||
results = [];
|
||||
for (i = 0, len = tokens.length; i < len; i++) {
|
||||
token = tokens[i];
|
||||
if (token.variable) {
|
||||
results.push(token[1]);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
})();
|
||||
ast = CoffeeScript.nodes(tokens);
|
||||
ast = new Block([new Assign(new Value(new Literal('_')), ast, '=')]);
|
||||
js = ast.compile({
|
||||
bare: true,
|
||||
locals: Object.keys(context)
|
||||
locals: Object.keys(context),
|
||||
referencedVars: referencedVars
|
||||
});
|
||||
result = context === global ? vm.runInThisContext(js, filename) : vm.runInContext(js, context, filename);
|
||||
return cb(null, result);
|
||||
@@ -41,9 +54,9 @@
|
||||
};
|
||||
|
||||
addMultilineHandler = function(repl) {
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, rli, _ref1;
|
||||
var inputStream, multiline, nodeLineListener, origPrompt, outputStream, ref1, rli;
|
||||
rli = repl.rli, inputStream = repl.inputStream, outputStream = repl.outputStream;
|
||||
origPrompt = (_ref1 = repl._prompt) != null ? _ref1 : repl.prompt;
|
||||
origPrompt = (ref1 = repl._prompt) != null ? ref1 : repl.prompt;
|
||||
multiline = {
|
||||
enabled: false,
|
||||
initialPrompt: origPrompt.replace(/^[^> ]*/, function(x) {
|
||||
@@ -58,7 +71,7 @@
|
||||
rli.removeListener('line', nodeLineListener);
|
||||
rli.on('line', function(cmd) {
|
||||
if (multiline.enabled) {
|
||||
multiline.buffer += "" + cmd + "\n";
|
||||
multiline.buffer += cmd + "\n";
|
||||
rli.setPrompt(multiline.prompt);
|
||||
rli.prompt(true);
|
||||
} else {
|
||||
@@ -118,7 +131,7 @@
|
||||
fd = fs.openSync(filename, 'a');
|
||||
repl.rli.addListener('line', function(code) {
|
||||
if (code && code.length && code !== '.history' && lastLine !== code) {
|
||||
fs.write(fd, "" + code + "\n");
|
||||
fs.write(fd, code + "\n");
|
||||
return lastLine = code;
|
||||
}
|
||||
});
|
||||
@@ -128,7 +141,7 @@
|
||||
return repl.commands[getCommandId(repl, 'history')] = {
|
||||
help: 'Show command history',
|
||||
action: function() {
|
||||
repl.outputStream.write("" + (repl.rli.history.slice(0).reverse().join('\n')) + "\n");
|
||||
repl.outputStream.write((repl.rli.history.slice(0).reverse().join('\n')) + "\n");
|
||||
return repl.displayPrompt();
|
||||
}
|
||||
};
|
||||
@@ -146,13 +159,13 @@
|
||||
|
||||
module.exports = {
|
||||
start: function(opts) {
|
||||
var build, major, minor, repl, _ref1;
|
||||
var build, major, minor, ref1, repl;
|
||||
if (opts == null) {
|
||||
opts = {};
|
||||
}
|
||||
_ref1 = process.versions.node.split('.').map(function(n) {
|
||||
ref1 = process.versions.node.split('.').map(function(n) {
|
||||
return parseInt(n);
|
||||
}), major = _ref1[0], minor = _ref1[1], build = _ref1[2];
|
||||
}), major = ref1[0], minor = ref1[1], build = ref1[2];
|
||||
if (major === 0 && minor < 8) {
|
||||
console.warn("Node 0.8.0+ required for CoffeeScript REPL");
|
||||
process.exit(1);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, left, rite, _i, _len, _ref,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
__slice = [].slice;
|
||||
var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, ref, rite,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
slice = [].slice;
|
||||
|
||||
generate = function(tag, value, origin) {
|
||||
var tok;
|
||||
@@ -17,8 +17,8 @@
|
||||
exports.Rewriter = (function() {
|
||||
function Rewriter() {}
|
||||
|
||||
Rewriter.prototype.rewrite = function(tokens) {
|
||||
this.tokens = tokens;
|
||||
Rewriter.prototype.rewrite = function(tokens1) {
|
||||
this.tokens = tokens1;
|
||||
this.removeLeadingNewlines();
|
||||
this.closeOpenCalls();
|
||||
this.closeOpenIndexes();
|
||||
@@ -40,7 +40,7 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.detectEnd = function(i, condition, action) {
|
||||
var levels, token, tokens, _ref, _ref1;
|
||||
var levels, ref, ref1, token, tokens;
|
||||
tokens = this.tokens;
|
||||
levels = 0;
|
||||
while (token = tokens[i]) {
|
||||
@@ -50,9 +50,9 @@
|
||||
if (!token || levels < 0) {
|
||||
return action.call(this, token, i - 1);
|
||||
}
|
||||
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
|
||||
if (ref = token[0], indexOf.call(EXPRESSION_START, ref) >= 0) {
|
||||
levels += 1;
|
||||
} else if (_ref1 = token[0], __indexOf.call(EXPRESSION_END, _ref1) >= 0) {
|
||||
} else if (ref1 = token[0], indexOf.call(EXPRESSION_END, ref1) >= 0) {
|
||||
levels -= 1;
|
||||
}
|
||||
i += 1;
|
||||
@@ -61,10 +61,10 @@
|
||||
};
|
||||
|
||||
Rewriter.prototype.removeLeadingNewlines = function() {
|
||||
var i, tag, _i, _len, _ref;
|
||||
_ref = this.tokens;
|
||||
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
|
||||
tag = _ref[i][0];
|
||||
var i, k, len, ref, tag;
|
||||
ref = this.tokens;
|
||||
for (i = k = 0, len = ref.length; k < len; i = ++k) {
|
||||
tag = ref[i][0];
|
||||
if (tag !== 'TERMINATOR') {
|
||||
break;
|
||||
}
|
||||
@@ -77,8 +77,8 @@
|
||||
Rewriter.prototype.closeOpenCalls = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
|
||||
var ref;
|
||||
return ((ref = token[0]) === ')' || ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
|
||||
@@ -94,8 +94,8 @@
|
||||
Rewriter.prototype.closeOpenIndexes = function() {
|
||||
var action, condition;
|
||||
condition = function(token, i) {
|
||||
var _ref;
|
||||
return (_ref = token[0]) === ']' || _ref === 'INDEX_END';
|
||||
var ref;
|
||||
return (ref = token[0]) === ']' || ref === 'INDEX_END';
|
||||
};
|
||||
action = function(token, i) {
|
||||
return token[0] = 'INDEX_END';
|
||||
@@ -108,11 +108,11 @@
|
||||
});
|
||||
};
|
||||
|
||||
Rewriter.prototype.matchTags = function() {
|
||||
var fuzz, i, j, pattern, _i, _ref, _ref1;
|
||||
i = arguments[0], pattern = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||||
Rewriter.prototype.indexOfTag = function() {
|
||||
var fuzz, i, j, k, pattern, ref, ref1;
|
||||
i = arguments[0], pattern = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
||||
fuzz = 0;
|
||||
for (j = _i = 0, _ref = pattern.length; 0 <= _ref ? _i < _ref : _i > _ref; j = 0 <= _ref ? ++_i : --_i) {
|
||||
for (j = k = 0, ref = pattern.length; 0 <= ref ? k < ref : k > ref; j = 0 <= ref ? ++k : --k) {
|
||||
while (this.tag(i + j + fuzz) === 'HERECOMMENT') {
|
||||
fuzz += 2;
|
||||
}
|
||||
@@ -122,37 +122,55 @@
|
||||
if (typeof pattern[j] === 'string') {
|
||||
pattern[j] = [pattern[j]];
|
||||
}
|
||||
if (_ref1 = this.tag(i + j + fuzz), __indexOf.call(pattern[j], _ref1) < 0) {
|
||||
return false;
|
||||
if (ref1 = this.tag(i + j + fuzz), indexOf.call(pattern[j], ref1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return i + j + fuzz - 1;
|
||||
};
|
||||
|
||||
Rewriter.prototype.looksObjectish = function(j) {
|
||||
return this.matchTags(j, '@', null, ':') || this.matchTags(j, null, ':');
|
||||
var end, index;
|
||||
if (this.indexOfTag(j, '@', null, ':') > -1 || this.indexOfTag(j, null, ':') > -1) {
|
||||
return true;
|
||||
}
|
||||
index = this.indexOfTag(j, EXPRESSION_START);
|
||||
if (index > -1) {
|
||||
end = null;
|
||||
this.detectEnd(index + 1, (function(token) {
|
||||
var ref;
|
||||
return ref = token[0], indexOf.call(EXPRESSION_END, ref) >= 0;
|
||||
}), (function(token, i) {
|
||||
return end = i;
|
||||
}));
|
||||
if (this.tag(end + 1) === ':') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Rewriter.prototype.findTagsBackwards = function(i, tags) {
|
||||
var backStack, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
||||
var backStack, ref, ref1, ref2, ref3, ref4, ref5;
|
||||
backStack = [];
|
||||
while (i >= 0 && (backStack.length || (_ref2 = this.tag(i), __indexOf.call(tags, _ref2) < 0) && ((_ref3 = this.tag(i), __indexOf.call(EXPRESSION_START, _ref3) < 0) || this.tokens[i].generated) && (_ref4 = this.tag(i), __indexOf.call(LINEBREAKS, _ref4) < 0))) {
|
||||
if (_ref = this.tag(i), __indexOf.call(EXPRESSION_END, _ref) >= 0) {
|
||||
while (i >= 0 && (backStack.length || (ref2 = this.tag(i), indexOf.call(tags, ref2) < 0) && ((ref3 = this.tag(i), indexOf.call(EXPRESSION_START, ref3) < 0) || this.tokens[i].generated) && (ref4 = this.tag(i), indexOf.call(LINEBREAKS, ref4) < 0))) {
|
||||
if (ref = this.tag(i), indexOf.call(EXPRESSION_END, ref) >= 0) {
|
||||
backStack.push(this.tag(i));
|
||||
}
|
||||
if ((_ref1 = this.tag(i), __indexOf.call(EXPRESSION_START, _ref1) >= 0) && backStack.length) {
|
||||
if ((ref1 = this.tag(i), indexOf.call(EXPRESSION_START, ref1) >= 0) && backStack.length) {
|
||||
backStack.pop();
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
return _ref5 = this.tag(i), __indexOf.call(tags, _ref5) >= 0;
|
||||
return ref5 = this.tag(i), indexOf.call(tags, ref5) >= 0;
|
||||
};
|
||||
|
||||
Rewriter.prototype.addImplicitBracesAndParens = function() {
|
||||
var stack;
|
||||
var stack, start;
|
||||
stack = [];
|
||||
start = null;
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
||||
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, newLine, nextTag, offset, prevTag, prevToken, ref, ref1, ref2, ref3, ref4, ref5, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag;
|
||||
tag = token[0];
|
||||
prevTag = (prevToken = i > 0 ? tokens[i - 1] : [])[0];
|
||||
nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0];
|
||||
@@ -164,20 +182,20 @@
|
||||
return i - startIdx + n;
|
||||
};
|
||||
inImplicit = function() {
|
||||
var _ref, _ref1;
|
||||
return (_ref = stackTop()) != null ? (_ref1 = _ref[2]) != null ? _ref1.ours : void 0 : void 0;
|
||||
var ref, ref1;
|
||||
return (ref = stackTop()) != null ? (ref1 = ref[2]) != null ? ref1.ours : void 0 : void 0;
|
||||
};
|
||||
inImplicitCall = function() {
|
||||
var _ref;
|
||||
return inImplicit() && ((_ref = stackTop()) != null ? _ref[0] : void 0) === '(';
|
||||
var ref;
|
||||
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '(';
|
||||
};
|
||||
inImplicitObject = function() {
|
||||
var _ref;
|
||||
return inImplicit() && ((_ref = stackTop()) != null ? _ref[0] : void 0) === '{';
|
||||
var ref;
|
||||
return inImplicit() && ((ref = stackTop()) != null ? ref[0] : void 0) === '{';
|
||||
};
|
||||
inImplicitControl = function() {
|
||||
var _ref;
|
||||
return inImplicit && ((_ref = stackTop()) != null ? _ref[0] : void 0) === 'CONTROL';
|
||||
var ref;
|
||||
return inImplicit && ((ref = stackTop()) != null ? ref[0] : void 0) === 'CONTROL';
|
||||
};
|
||||
startImplicitCall = function(j) {
|
||||
var idx;
|
||||
@@ -194,11 +212,11 @@
|
||||
};
|
||||
endImplicitCall = function() {
|
||||
stack.pop();
|
||||
tokens.splice(i, 0, generate('CALL_END', ')'));
|
||||
tokens.splice(i, 0, generate('CALL_END', ')', ['', 'end of input', token[2]]));
|
||||
return i += 1;
|
||||
};
|
||||
startImplicitObject = function(j, startsLine) {
|
||||
var idx;
|
||||
var idx, val;
|
||||
if (startsLine == null) {
|
||||
startsLine = true;
|
||||
}
|
||||
@@ -210,7 +228,9 @@
|
||||
ours: true
|
||||
}
|
||||
]);
|
||||
tokens.splice(idx, 0, generate('{', generate(new String('{')), token));
|
||||
val = new String('{');
|
||||
val.generated = true;
|
||||
tokens.splice(idx, 0, generate('{', val, token));
|
||||
if (j == null) {
|
||||
return i += 1;
|
||||
}
|
||||
@@ -241,11 +261,11 @@
|
||||
stack.push([tag, i]);
|
||||
return forward(1);
|
||||
}
|
||||
if (__indexOf.call(EXPRESSION_START, tag) >= 0) {
|
||||
if (indexOf.call(EXPRESSION_START, tag) >= 0) {
|
||||
stack.push([tag, i]);
|
||||
return forward(1);
|
||||
}
|
||||
if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
|
||||
if (indexOf.call(EXPRESSION_END, tag) >= 0) {
|
||||
while (inImplicit()) {
|
||||
if (inImplicitCall()) {
|
||||
endImplicitCall();
|
||||
@@ -255,33 +275,39 @@
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
stack.pop();
|
||||
start = stack.pop();
|
||||
}
|
||||
if ((__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced && !token.stringEnd || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (__indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || __indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((_ref = tokens[i + 1]) != null ? _ref.spaced : void 0) && !((_ref1 = tokens[i + 1]) != null ? _ref1.newLine : void 0))) {
|
||||
if ((indexOf.call(IMPLICIT_FUNC, tag) >= 0 && token.spaced || tag === '?' && i > 0 && !tokens[i - 1].spaced) && (indexOf.call(IMPLICIT_CALL, nextTag) >= 0 || indexOf.call(IMPLICIT_UNSPACED_CALL, nextTag) >= 0 && !((ref = tokens[i + 1]) != null ? ref.spaced : void 0) && !((ref1 = tokens[i + 1]) != null ? ref1.newLine : void 0))) {
|
||||
if (tag === '?') {
|
||||
tag = token[0] = 'FUNC_EXIST';
|
||||
}
|
||||
startImplicitCall(i + 1);
|
||||
return forward(2);
|
||||
}
|
||||
if (__indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.matchTags(i + 1, 'INDENT', null, ':') && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
|
||||
if (indexOf.call(IMPLICIT_FUNC, tag) >= 0 && this.indexOfTag(i + 1, 'INDENT', null, ':') > -1 && !this.findTagsBackwards(i, ['CLASS', 'EXTENDS', 'IF', 'CATCH', 'SWITCH', 'LEADING_WHEN', 'FOR', 'WHILE', 'UNTIL'])) {
|
||||
startImplicitCall(i + 1);
|
||||
stack.push(['INDENT', i + 2]);
|
||||
return forward(3);
|
||||
}
|
||||
if (tag === ':') {
|
||||
if (this.tag(i - 2) === '@') {
|
||||
s = i - 2;
|
||||
} else {
|
||||
s = i - 1;
|
||||
}
|
||||
s = (function() {
|
||||
var ref2;
|
||||
switch (false) {
|
||||
case ref2 = this.tag(i - 1), indexOf.call(EXPRESSION_END, ref2) < 0:
|
||||
return start[1];
|
||||
case this.tag(i - 2) !== '@':
|
||||
return i - 2;
|
||||
default:
|
||||
return i - 1;
|
||||
}
|
||||
}).call(this);
|
||||
while (this.tag(s - 2) === 'HERECOMMENT') {
|
||||
s -= 2;
|
||||
}
|
||||
this.insideForDeclaration = nextTag === 'FOR';
|
||||
startsLine = s === 0 || (_ref2 = this.tag(s - 1), __indexOf.call(LINEBREAKS, _ref2) >= 0) || tokens[s - 1].newLine;
|
||||
startsLine = s === 0 || (ref2 = this.tag(s - 1), indexOf.call(LINEBREAKS, ref2) >= 0) || tokens[s - 1].newLine;
|
||||
if (stackTop()) {
|
||||
_ref3 = stackTop(), stackTag = _ref3[0], stackIdx = _ref3[1];
|
||||
ref3 = stackTop(), stackTag = ref3[0], stackIdx = ref3[1];
|
||||
if ((stackTag === '{' || stackTag === 'INDENT' && this.tag(stackIdx - 1) === '{') && (startsLine || this.tag(s - 1) === ',' || this.tag(s - 1) === '{')) {
|
||||
return forward(1);
|
||||
}
|
||||
@@ -289,18 +315,21 @@
|
||||
startImplicitObject(s, !!startsLine);
|
||||
return forward(2);
|
||||
}
|
||||
if (inImplicitObject() && __indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
if (inImplicitObject() && indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
stackTop()[2].sameLine = false;
|
||||
}
|
||||
newLine = prevTag === 'OUTDENT' || prevToken.newLine;
|
||||
if (__indexOf.call(IMPLICIT_END, tag) >= 0 || __indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
|
||||
if (indexOf.call(IMPLICIT_END, tag) >= 0 || indexOf.call(CALL_CLOSERS, tag) >= 0 && newLine) {
|
||||
while (inImplicit()) {
|
||||
_ref4 = stackTop(), stackTag = _ref4[0], stackIdx = _ref4[1], (_ref5 = _ref4[2], sameLine = _ref5.sameLine, startsLine = _ref5.startsLine);
|
||||
ref4 = stackTop(), stackTag = ref4[0], stackIdx = ref4[1], (ref5 = ref4[2], sameLine = ref5.sameLine, startsLine = ref5.startsLine);
|
||||
if (inImplicitCall() && prevTag !== ',') {
|
||||
endImplicitCall();
|
||||
} else if (inImplicitObject() && !this.insideForDeclaration && sameLine && tag !== 'TERMINATOR' && prevTag !== ':' && endImplicitObject()) {
|
||||
|
||||
} else if (inImplicitObject() && !this.insideForDeclaration && sameLine && tag !== 'TERMINATOR' && prevTag !== ':') {
|
||||
endImplicitObject();
|
||||
} else if (inImplicitObject() && tag === 'TERMINATOR' && prevTag !== ',' && !(startsLine && this.looksObjectish(i + 1))) {
|
||||
if (nextTag === 'HERECOMMENT') {
|
||||
return forward(1);
|
||||
}
|
||||
endImplicitObject();
|
||||
} else {
|
||||
break;
|
||||
@@ -319,16 +348,16 @@
|
||||
|
||||
Rewriter.prototype.addLocationDataToGeneratedTokens = function() {
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var column, line, nextLocation, prevLocation, _ref, _ref1;
|
||||
var column, line, nextLocation, prevLocation, ref, ref1;
|
||||
if (token[2]) {
|
||||
return 1;
|
||||
}
|
||||
if (!(token.generated || token.explicit)) {
|
||||
return 1;
|
||||
}
|
||||
if (token[0] === '{' && (nextLocation = (_ref = tokens[i + 1]) != null ? _ref[2] : void 0)) {
|
||||
if (token[0] === '{' && (nextLocation = (ref = tokens[i + 1]) != null ? ref[2] : void 0)) {
|
||||
line = nextLocation.first_line, column = nextLocation.first_column;
|
||||
} else if (prevLocation = (_ref1 = tokens[i - 1]) != null ? _ref1[2] : void 0) {
|
||||
} else if (prevLocation = (ref1 = tokens[i - 1]) != null ? ref1[2] : void 0) {
|
||||
line = prevLocation.last_line, column = prevLocation.last_column;
|
||||
} else {
|
||||
line = column = 0;
|
||||
@@ -347,37 +376,37 @@
|
||||
var action, condition, indent, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
condition = function(token, i) {
|
||||
var _ref, _ref1, _ref2, _ref3;
|
||||
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'TERMINATOR' && (_ref1 = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((_ref2 = token[0]) === 'CATCH' || _ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (_ref3 = token[0], __indexOf.call(CALL_CLOSERS, _ref3) >= 0) && this.tokens[i - 1].newLine;
|
||||
var ref, ref1, ref2, ref3;
|
||||
return token[1] !== ';' && (ref = token[0], indexOf.call(SINGLE_CLOSERS, ref) >= 0) && !(token[0] === 'TERMINATOR' && (ref1 = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((ref2 = token[0]) === 'CATCH' || ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (ref3 = token[0], indexOf.call(CALL_CLOSERS, ref3) >= 0) && this.tokens[i - 1].newLine;
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
};
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var j, tag, _i, _ref, _ref1, _ref2;
|
||||
var j, k, ref, ref1, ref2, tag;
|
||||
tag = token[0];
|
||||
if (tag === 'TERMINATOR') {
|
||||
if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
|
||||
tokens.splice.apply(tokens, [i, 1].concat(__slice.call(this.indentation())));
|
||||
tokens.splice.apply(tokens, [i, 1].concat(slice.call(this.indentation())));
|
||||
return 1;
|
||||
}
|
||||
if (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0) {
|
||||
if (ref = this.tag(i + 1), indexOf.call(EXPRESSION_CLOSE, ref) >= 0) {
|
||||
tokens.splice(i, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (tag === 'CATCH') {
|
||||
for (j = _i = 1; _i <= 2; j = ++_i) {
|
||||
if (!((_ref1 = this.tag(i + j)) === 'OUTDENT' || _ref1 === 'TERMINATOR' || _ref1 === 'FINALLY')) {
|
||||
for (j = k = 1; k <= 2; j = ++k) {
|
||||
if (!((ref1 = this.tag(i + j)) === 'OUTDENT' || ref1 === 'TERMINATOR' || ref1 === 'FINALLY')) {
|
||||
continue;
|
||||
}
|
||||
tokens.splice.apply(tokens, [i + j, 0].concat(__slice.call(this.indentation())));
|
||||
tokens.splice.apply(tokens, [i + j, 0].concat(slice.call(this.indentation())));
|
||||
return 2 + j;
|
||||
}
|
||||
}
|
||||
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
if (indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
_ref2 = this.indentation(tokens[i]), indent = _ref2[0], outdent = _ref2[1];
|
||||
ref2 = this.indentation(tokens[i]), indent = ref2[0], outdent = ref2[1];
|
||||
if (starter === 'THEN') {
|
||||
indent.fromThen = true;
|
||||
}
|
||||
@@ -399,7 +428,7 @@
|
||||
var prevTag, tag;
|
||||
tag = token[0];
|
||||
prevTag = this.tokens[i - 1][0];
|
||||
return tag === 'TERMINATOR' || (tag === 'INDENT' && __indexOf.call(SINGLE_LINERS, prevTag) < 0);
|
||||
return tag === 'TERMINATOR' || (tag === 'INDENT' && indexOf.call(SINGLE_LINERS, prevTag) < 0);
|
||||
};
|
||||
action = function(token, i) {
|
||||
if (token[0] !== 'INDENT' || (token.generated && !token.fromThen)) {
|
||||
@@ -432,15 +461,15 @@
|
||||
Rewriter.prototype.generate = generate;
|
||||
|
||||
Rewriter.prototype.tag = function(i) {
|
||||
var _ref;
|
||||
return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
|
||||
var ref;
|
||||
return (ref = this.tokens[i]) != null ? ref[0] : void 0;
|
||||
};
|
||||
|
||||
return Rewriter;
|
||||
|
||||
})();
|
||||
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
|
||||
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END'], ['STRING_START', 'STRING_END'], ['REGEX_START', 'REGEX_END']];
|
||||
|
||||
exports.INVERSES = INVERSES = {};
|
||||
|
||||
@@ -448,8 +477,8 @@
|
||||
|
||||
EXPRESSION_END = [];
|
||||
|
||||
for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
|
||||
_ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
|
||||
for (k = 0, len = BALANCED_PAIRS.length; k < len; k++) {
|
||||
ref = BALANCED_PAIRS[k], left = ref[0], rite = ref[1];
|
||||
EXPRESSION_START.push(INVERSES[rite] = left);
|
||||
EXPRESSION_END.push(INVERSES[left] = rite);
|
||||
}
|
||||
@@ -458,7 +487,7 @@
|
||||
|
||||
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
|
||||
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'STRING_START', 'JS', 'REGEX', 'REGEX_START', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'NULL', 'UNDEFINED', 'UNARY', 'YIELD', 'UNARY_MATH', 'SUPER', 'THROW', '@', '->', '=>', '[', '(', '{', '--', '++'];
|
||||
|
||||
IMPLICIT_UNSPACED_CALL = ['+', '-'];
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var Scope, extend, last, _ref;
|
||||
|
||||
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
|
||||
var Scope,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
exports.Scope = Scope = (function() {
|
||||
Scope.root = null;
|
||||
|
||||
function Scope(parent, expressions, method) {
|
||||
function Scope(parent, expressions, method, referencedVars) {
|
||||
var ref, ref1;
|
||||
this.parent = parent;
|
||||
this.expressions = expressions;
|
||||
this.method = method;
|
||||
this.referencedVars = referencedVars;
|
||||
this.variables = [
|
||||
{
|
||||
name: 'arguments',
|
||||
@@ -19,8 +18,9 @@
|
||||
];
|
||||
this.positions = {};
|
||||
if (!this.parent) {
|
||||
Scope.root = this;
|
||||
this.utilities = {};
|
||||
}
|
||||
this.root = (ref = (ref1 = this.parent) != null ? ref1.root : void 0) != null ? ref : this;
|
||||
}
|
||||
|
||||
Scope.prototype.add = function(name, type, immediate) {
|
||||
@@ -38,8 +38,8 @@
|
||||
};
|
||||
|
||||
Scope.prototype.namedMethod = function() {
|
||||
var _ref1;
|
||||
if (((_ref1 = this.method) != null ? _ref1.name : void 0) || !this.parent) {
|
||||
var ref;
|
||||
if (((ref = this.method) != null ? ref.name : void 0) || !this.parent) {
|
||||
return this.method;
|
||||
}
|
||||
return this.parent.namedMethod();
|
||||
@@ -61,23 +61,26 @@
|
||||
};
|
||||
|
||||
Scope.prototype.check = function(name) {
|
||||
var _ref1;
|
||||
return !!(this.type(name) || ((_ref1 = this.parent) != null ? _ref1.check(name) : void 0));
|
||||
var ref;
|
||||
return !!(this.type(name) || ((ref = this.parent) != null ? ref.check(name) : void 0));
|
||||
};
|
||||
|
||||
Scope.prototype.temporary = function(name, index) {
|
||||
if (name.length > 1) {
|
||||
return '_' + name + (index > 1 ? index - 1 : '');
|
||||
Scope.prototype.temporary = function(name, index, single) {
|
||||
if (single == null) {
|
||||
single = false;
|
||||
}
|
||||
if (single) {
|
||||
return (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
|
||||
} else {
|
||||
return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
|
||||
return name + (index || '');
|
||||
}
|
||||
};
|
||||
|
||||
Scope.prototype.type = function(name) {
|
||||
var v, _i, _len, _ref1;
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
var i, len, ref, v;
|
||||
ref = this.variables;
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
v = ref[i];
|
||||
if (v.name === name) {
|
||||
return v.type;
|
||||
}
|
||||
@@ -85,16 +88,20 @@
|
||||
return null;
|
||||
};
|
||||
|
||||
Scope.prototype.freeVariable = function(name, reserve) {
|
||||
var index, temp;
|
||||
if (reserve == null) {
|
||||
reserve = true;
|
||||
Scope.prototype.freeVariable = function(name, options) {
|
||||
var index, ref, temp;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
index = 0;
|
||||
while (this.check((temp = this.temporary(name, index)))) {
|
||||
while (true) {
|
||||
temp = this.temporary(name, index, options.single);
|
||||
if (!(this.check(temp) || indexOf.call(this.root.referencedVars, temp) >= 0)) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (reserve) {
|
||||
if ((ref = options.reserve) != null ? ref : true) {
|
||||
this.add(temp, 'var', true);
|
||||
}
|
||||
return temp;
|
||||
@@ -113,30 +120,32 @@
|
||||
};
|
||||
|
||||
Scope.prototype.declaredVariables = function() {
|
||||
var realVars, tempVars, v, _i, _len, _ref1;
|
||||
realVars = [];
|
||||
tempVars = [];
|
||||
_ref1 = this.variables;
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
if (v.type === 'var') {
|
||||
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
|
||||
var v;
|
||||
return ((function() {
|
||||
var i, len, ref, results;
|
||||
ref = this.variables;
|
||||
results = [];
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
v = ref[i];
|
||||
if (v.type === 'var') {
|
||||
results.push(v.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
return realVars.sort().concat(tempVars.sort());
|
||||
return results;
|
||||
}).call(this)).sort();
|
||||
};
|
||||
|
||||
Scope.prototype.assignedVariables = function() {
|
||||
var v, _i, _len, _ref1, _results;
|
||||
_ref1 = this.variables;
|
||||
_results = [];
|
||||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||||
v = _ref1[_i];
|
||||
var i, len, ref, results, v;
|
||||
ref = this.variables;
|
||||
results = [];
|
||||
for (i = 0, len = ref.length; i < len; i++) {
|
||||
v = ref[i];
|
||||
if (v.type.assigned) {
|
||||
_results.push("" + v.name + " = " + v.type.value);
|
||||
results.push(v.name + " = " + v.type.value);
|
||||
}
|
||||
}
|
||||
return _results;
|
||||
return results;
|
||||
};
|
||||
|
||||
return Scope;
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
// Generated by CoffeeScript 1.8.0
|
||||
// Generated by CoffeeScript 1.9.1
|
||||
(function() {
|
||||
var LineMap, SourceMap;
|
||||
|
||||
LineMap = (function() {
|
||||
function LineMap(line) {
|
||||
this.line = line;
|
||||
function LineMap(line1) {
|
||||
this.line = line1;
|
||||
this.columns = [];
|
||||
}
|
||||
|
||||
LineMap.prototype.add = function(column, _arg, options) {
|
||||
LineMap.prototype.add = function(column, arg, options) {
|
||||
var sourceColumn, sourceLine;
|
||||
sourceLine = _arg[0], sourceColumn = _arg[1];
|
||||
sourceLine = arg[0], sourceColumn = arg[1];
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
@@ -45,18 +45,18 @@
|
||||
}
|
||||
|
||||
SourceMap.prototype.add = function(sourceLocation, generatedLocation, options) {
|
||||
var column, line, lineMap, _base;
|
||||
var base, column, line, lineMap;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
line = generatedLocation[0], column = generatedLocation[1];
|
||||
lineMap = ((_base = this.lines)[line] || (_base[line] = new LineMap(line)));
|
||||
lineMap = ((base = this.lines)[line] || (base[line] = new LineMap(line)));
|
||||
return lineMap.add(column, sourceLocation, options);
|
||||
};
|
||||
|
||||
SourceMap.prototype.sourceLocation = function(_arg) {
|
||||
SourceMap.prototype.sourceLocation = function(arg) {
|
||||
var column, line, lineMap;
|
||||
line = _arg[0], column = _arg[1];
|
||||
line = arg[0], column = arg[1];
|
||||
while (!((lineMap = this.lines[line]) || (line <= 0))) {
|
||||
line--;
|
||||
}
|
||||
@@ -64,7 +64,7 @@
|
||||
};
|
||||
|
||||
SourceMap.prototype.generate = function(options, code) {
|
||||
var buffer, lastColumn, lastSourceColumn, lastSourceLine, lineMap, lineNumber, mapping, needComma, v3, writingline, _i, _j, _len, _len1, _ref, _ref1;
|
||||
var buffer, i, j, lastColumn, lastSourceColumn, lastSourceLine, len, len1, lineMap, lineNumber, mapping, needComma, ref, ref1, v3, writingline;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
@@ -77,13 +77,13 @@
|
||||
lastSourceColumn = 0;
|
||||
needComma = false;
|
||||
buffer = "";
|
||||
_ref = this.lines;
|
||||
for (lineNumber = _i = 0, _len = _ref.length; _i < _len; lineNumber = ++_i) {
|
||||
lineMap = _ref[lineNumber];
|
||||
ref = this.lines;
|
||||
for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
|
||||
lineMap = ref[lineNumber];
|
||||
if (lineMap) {
|
||||
_ref1 = lineMap.columns;
|
||||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||||
mapping = _ref1[_j];
|
||||
ref1 = lineMap.columns;
|
||||
for (j = 0, len1 = ref1.length; j < len1; j++) {
|
||||
mapping = ref1[j];
|
||||
if (!(mapping)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
10
package.json
10
package.json
@@ -8,7 +8,7 @@
|
||||
"compiler"
|
||||
],
|
||||
"author": "Jeremy Ashkenas",
|
||||
"version": "1.8.0",
|
||||
"version": "1.9.1",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
@@ -23,7 +23,8 @@
|
||||
},
|
||||
"preferGlobal": true,
|
||||
"scripts": {
|
||||
"test": "node ./bin/cake test"
|
||||
"test": "node ./bin/cake test",
|
||||
"test-harmony": "node --harmony ./bin/cake test"
|
||||
},
|
||||
"homepage": "http://coffeescript.org",
|
||||
"bugs": "https://github.com/jashkenas/coffeescript/issues",
|
||||
@@ -36,9 +37,6 @@
|
||||
"jison": ">=0.2.0",
|
||||
"highlight.js": "~8.0.0",
|
||||
"underscore": "~1.5.2",
|
||||
"docco": "~0.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"mkdirp": "~0.3.5"
|
||||
"docco": "~0.7.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ helpers = require './helpers'
|
||||
SourceMap = require './sourcemap'
|
||||
|
||||
# The current CoffeeScript version number.
|
||||
exports.VERSION = '1.8.0'
|
||||
exports.VERSION = '1.9.1'
|
||||
|
||||
exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md']
|
||||
|
||||
@@ -44,7 +44,15 @@ exports.compile = compile = withPrettyErrors (code, options) ->
|
||||
if options.sourceMap
|
||||
map = new SourceMap
|
||||
|
||||
fragments = parser.parse(lexer.tokenize code, options).compileToFragments options
|
||||
tokens = lexer.tokenize code, options
|
||||
|
||||
# Pass a list of referenced variables, so that generated variables won't get
|
||||
# the same name.
|
||||
options.referencedVars = (
|
||||
token[1] for token in tokens when token.variable
|
||||
)
|
||||
|
||||
fragments = parser.parse(tokens).compileToFragments options
|
||||
|
||||
currentLine = 0
|
||||
currentLine += 1 if options.header
|
||||
@@ -124,13 +132,17 @@ exports.run = (code, options = {}) ->
|
||||
# The CoffeeScript REPL uses this to run the input.
|
||||
exports.eval = (code, options = {}) ->
|
||||
return unless code = code.trim()
|
||||
Script = vm.Script
|
||||
if Script
|
||||
createContext = vm.Script.createContext ? vm.createContext
|
||||
|
||||
isContext = vm.isContext ? (ctx) ->
|
||||
options.sandbox instanceof createContext().constructor
|
||||
|
||||
if createContext
|
||||
if options.sandbox?
|
||||
if options.sandbox instanceof Script.createContext().constructor
|
||||
if isContext options.sandbox
|
||||
sandbox = options.sandbox
|
||||
else
|
||||
sandbox = Script.createContext()
|
||||
sandbox = createContext()
|
||||
sandbox[k] = v for own k, v of options.sandbox
|
||||
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox
|
||||
else
|
||||
@@ -188,16 +200,17 @@ lexer = new Lexer
|
||||
# directly as a "Jison lexer".
|
||||
parser.lexer =
|
||||
lex: ->
|
||||
token = @tokens[@pos++]
|
||||
token = parser.tokens[@pos++]
|
||||
if token
|
||||
[tag, @yytext, @yylloc] = token
|
||||
@errorToken = token.origin or token
|
||||
parser.errorToken = token.origin or token
|
||||
@yylineno = @yylloc.first_line
|
||||
else
|
||||
tag = ''
|
||||
|
||||
tag
|
||||
setInput: (@tokens) ->
|
||||
setInput: (tokens) ->
|
||||
parser.tokens = tokens
|
||||
@pos = 0
|
||||
upcomingInput: ->
|
||||
""
|
||||
@@ -209,15 +222,18 @@ parser.yy.parseError = (message, {token}) ->
|
||||
# Disregard Jison's message, it contains redundant line numer information.
|
||||
# Disregard the token, we take its value directly from the lexer in case
|
||||
# the error is caused by a generated token which might refer to its origin.
|
||||
{errorToken, tokens} = parser.lexer
|
||||
{errorToken, tokens} = parser
|
||||
[errorTag, errorText, errorLoc] = errorToken
|
||||
|
||||
errorText = if errorToken is tokens[tokens.length - 1]
|
||||
'end of input'
|
||||
else if errorTag in ['INDENT', 'OUTDENT']
|
||||
'indentation'
|
||||
else
|
||||
helpers.nameWhitespaceCharacter errorText
|
||||
errorText = switch
|
||||
when errorToken is tokens[tokens.length - 1]
|
||||
'end of input'
|
||||
when errorTag in ['INDENT', 'OUTDENT']
|
||||
'indentation'
|
||||
when errorTag in ['IDENTIFIER', 'NUMBER', 'STRING', 'STRING_START', 'REGEX', 'REGEX_START']
|
||||
errorTag.replace(/_START$/, '').toLowerCase()
|
||||
else
|
||||
helpers.nameWhitespaceCharacter errorText
|
||||
|
||||
# The second argument has a `loc` property, which should have the location
|
||||
# data for this token. Unfortunately, Jison seems to send an outdated `loc`
|
||||
@@ -303,4 +319,3 @@ Error.prepareStackTrace = (err, stack) ->
|
||||
" at #{formatSourcePosition frame, getSourceMapping}"
|
||||
|
||||
"#{err.toString()}\n#{frames.join '\n'}\n"
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ path = require 'path'
|
||||
helpers = require './helpers'
|
||||
optparse = require './optparse'
|
||||
CoffeeScript = require './coffee-script'
|
||||
mkdirp = require 'mkdirp'
|
||||
{spawn, exec} = require 'child_process'
|
||||
{EventEmitter} = require 'events'
|
||||
|
||||
@@ -59,6 +58,7 @@ sourceCode = []
|
||||
notSources = {}
|
||||
watchedDirs = {}
|
||||
optionParser = null
|
||||
jsToSources = {}
|
||||
|
||||
# Run `coffee` by parsing passed options and determining what action to take.
|
||||
# Many flags cause us to divert before compiling anything. Flags passed after
|
||||
@@ -330,6 +330,20 @@ outputPath = (source, base, extension=".js") ->
|
||||
dir = path.join opts.output, path.relative base, srcDir
|
||||
path.join dir, basename + extension
|
||||
|
||||
# Recursively mkdir, like `mkdir -p`.
|
||||
mkdirp = (dir, fn) ->
|
||||
mode = 0o777 & ~process.umask()
|
||||
|
||||
do mkdirs = (p = dir, fn) ->
|
||||
fs.exists p, (exists) ->
|
||||
if exists
|
||||
fn()
|
||||
else
|
||||
mkdirs path.dirname(p), ->
|
||||
fs.mkdir p, mode, (err) ->
|
||||
return fn err if err
|
||||
fn()
|
||||
|
||||
# Write out a JavaScript source file with the compiled code. By default, files
|
||||
# are written out in `cwd` as `.js` files with the same name, but the output
|
||||
# directory can be customized with `--output`.
|
||||
@@ -339,6 +353,12 @@ outputPath = (source, base, extension=".js") ->
|
||||
writeJs = (base, sourcePath, js, jsPath, generatedSourceMap = null) ->
|
||||
sourceMapPath = outputPath sourcePath, base, ".js.map"
|
||||
jsDir = path.dirname jsPath
|
||||
if jsPath of jsToSources
|
||||
printLine "Error: The two following source files have the same output file:"
|
||||
printLine " " + jsToSources[jsPath]
|
||||
printLine " " + sourcePath
|
||||
process.exit 1
|
||||
jsToSources[jsPath] = sourcePath
|
||||
compile = ->
|
||||
if opts.compile
|
||||
js = ' ' if js.length <= 0
|
||||
|
||||
@@ -132,7 +132,17 @@ grammar =
|
||||
# they can also serve as keys in object literals.
|
||||
AlphaNumeric: [
|
||||
o 'NUMBER', -> new Literal $1
|
||||
o 'String'
|
||||
]
|
||||
|
||||
String: [
|
||||
o 'STRING', -> new Literal $1
|
||||
o 'STRING_START Body STRING_END', -> new Parens $2
|
||||
]
|
||||
|
||||
Regex: [
|
||||
o 'REGEX', -> new Literal $1
|
||||
o 'REGEX_START Invocation REGEX_END', -> $2
|
||||
]
|
||||
|
||||
# All of our immediate values. Generally these can be passed straight
|
||||
@@ -140,7 +150,7 @@ grammar =
|
||||
Literal: [
|
||||
o 'AlphaNumeric'
|
||||
o 'JS', -> new Literal $1
|
||||
o 'REGEX', -> new Literal $1
|
||||
o 'Regex'
|
||||
o 'DEBUGGER', -> new Literal $1
|
||||
o 'UNDEFINED', -> new Undefined
|
||||
o 'NULL', -> new Null
|
||||
@@ -451,7 +461,8 @@ grammar =
|
||||
]
|
||||
|
||||
ForBody: [
|
||||
o 'FOR Range', -> source: LOC(2) new Value($2)
|
||||
o 'FOR Range', -> source: (LOC(2) new Value($2))
|
||||
o 'FOR Range BY Expression', -> source: (LOC(2) new Value($2)), step: $4
|
||||
o 'ForStart ForSource', -> $2.own = $1.own; $2.name = $1[0]; $2.index = $1[1]; $2
|
||||
]
|
||||
|
||||
@@ -536,6 +547,9 @@ grammar =
|
||||
o 'UNARY_MATH Expression', -> new Op $1 , $2
|
||||
o '- Expression', (-> new Op '-', $2), prec: 'UNARY_MATH'
|
||||
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY_MATH'
|
||||
o 'YIELD Statement', -> new Op $1 , $2
|
||||
o 'YIELD Expression', -> new Op $1 , $2
|
||||
o 'YIELD FROM Expression', -> new Op $1.concat($2) , $3
|
||||
|
||||
o '-- SimpleAssignable', -> new Op '--', $2
|
||||
o '++ SimpleAssignable', -> new Op '++', $2
|
||||
@@ -595,6 +609,7 @@ operators = [
|
||||
['left', 'COMPARE']
|
||||
['left', 'LOGIC']
|
||||
['nonassoc', 'INDENT', 'OUTDENT']
|
||||
['right', 'YIELD']
|
||||
['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS']
|
||||
['right', 'FORIN', 'FOROF', 'BY', 'WHEN']
|
||||
['right', 'IF', 'ELSE', 'FOR', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS']
|
||||
|
||||
@@ -62,9 +62,6 @@ exports.del = (obj, key) ->
|
||||
delete obj[key]
|
||||
val
|
||||
|
||||
# Gets the last item of an array(-like) object.
|
||||
exports.last = last = (array, back) -> array[array.length - (back or 0) - 1]
|
||||
|
||||
# Typical Array::some
|
||||
exports.some = Array::some ? (fn) ->
|
||||
return true for e in this when fn e
|
||||
|
||||
684
src/lexer.coffee
684
src/lexer.coffee
@@ -12,7 +12,7 @@
|
||||
{Rewriter, INVERSES} = require './rewriter'
|
||||
|
||||
# Import the helpers we need.
|
||||
{count, starts, compact, last, repeat, invertLiterate,
|
||||
{count, starts, compact, repeat, invertLiterate,
|
||||
locationDataToString, throwSyntaxError} = require './helpers'
|
||||
|
||||
# The Lexer Class
|
||||
@@ -32,8 +32,7 @@ exports.Lexer = class Lexer
|
||||
# Each tokenizing method is responsible for returning the number of characters
|
||||
# it has consumed.
|
||||
#
|
||||
# Before returning the token stream, run it through the [Rewriter](rewriter.html)
|
||||
# unless explicitly asked not to.
|
||||
# Before returning the token stream, run it through the [Rewriter](rewriter.html).
|
||||
tokenize: (code, opts = {}) ->
|
||||
@literate = opts.literate # Are we lexing literate CoffeeScript?
|
||||
@indent = 0 # The current indentation level.
|
||||
@@ -60,7 +59,6 @@ exports.Lexer = class Lexer
|
||||
@commentToken() or
|
||||
@whitespaceToken() or
|
||||
@lineToken() or
|
||||
@heredocToken() or
|
||||
@stringToken() or
|
||||
@numberToken() or
|
||||
@regexToken() or
|
||||
@@ -72,8 +70,10 @@ exports.Lexer = class Lexer
|
||||
|
||||
i += consumed
|
||||
|
||||
return {@tokens, index: i} if opts.untilBalanced and @ends.length is 0
|
||||
|
||||
@closeIndentation()
|
||||
@error "missing #{tag}" if tag = @ends.pop()
|
||||
@error "missing #{end.tag}", end.origin[2] if end = @ends.pop()
|
||||
return @tokens if opts.rewrite is off
|
||||
(new Rewriter).rewrite @tokens
|
||||
|
||||
@@ -109,8 +109,12 @@ exports.Lexer = class Lexer
|
||||
if id is 'own' and @tag() is 'FOR'
|
||||
@token 'OWN', id
|
||||
return id.length
|
||||
forcedIdentifier = colon or
|
||||
(prev = last @tokens) and (prev[0] in ['.', '?.', '::', '?::'] or
|
||||
if id is 'from' and @tag() is 'YIELD'
|
||||
@token 'FROM', id
|
||||
return id.length
|
||||
[..., prev] = @tokens
|
||||
forcedIdentifier = colon or prev? and
|
||||
(prev[0] in ['.', '?.', '::', '?::'] or
|
||||
not prev.spaced and prev[0] is '@')
|
||||
tag = 'IDENTIFIER'
|
||||
|
||||
@@ -140,7 +144,7 @@ exports.Lexer = class Lexer
|
||||
id = new String id
|
||||
id.reserved = yes
|
||||
else if id in RESERVED
|
||||
@error "reserved word \"#{id}\""
|
||||
@error "reserved word '#{id}'", length: id.length
|
||||
|
||||
unless forcedIdentifier
|
||||
id = COFFEE_ALIAS_MAP[id] if id in COFFEE_ALIASES
|
||||
@@ -153,6 +157,7 @@ exports.Lexer = class Lexer
|
||||
else tag
|
||||
|
||||
tagToken = @token tag, id, 0, idLength
|
||||
tagToken.variable = not forcedIdentifier
|
||||
if poppedToken
|
||||
[tagToken[2].first_line, tagToken[2].first_column] =
|
||||
[poppedToken[2].first_line, poppedToken[2].first_column]
|
||||
@@ -167,15 +172,16 @@ exports.Lexer = class Lexer
|
||||
numberToken: ->
|
||||
return 0 unless match = NUMBER.exec @chunk
|
||||
number = match[0]
|
||||
if /^0[BOX]/.test number
|
||||
@error "radix prefix '#{number}' must be lowercase"
|
||||
else if /E/.test(number) and not /^0x/.test number
|
||||
@error "exponential notation '#{number}' must be indicated with a lowercase 'e'"
|
||||
else if /^0\d*[89]/.test number
|
||||
@error "decimal literal '#{number}' must not be prefixed with '0'"
|
||||
else if /^0\d+/.test number
|
||||
@error "octal literal '#{number}' must be prefixed with '0o'"
|
||||
lexedLength = number.length
|
||||
if /^0[BOX]/.test number
|
||||
@error "radix prefix in '#{number}' must be lowercase", offset: 1
|
||||
else if /E/.test(number) and not /^0x/.test number
|
||||
@error "exponential notation in '#{number}' must be indicated with a lowercase 'e'",
|
||||
offset: number.indexOf('E')
|
||||
else if /^0\d*[89]/.test number
|
||||
@error "decimal literal '#{number}' must not be prefixed with '0'", length: lexedLength
|
||||
else if /^0\d+/.test number
|
||||
@error "octal literal '#{number}' must be prefixed with '0o'", length: lexedLength
|
||||
if octalLiteral = /^0o([0-7]+)/.exec number
|
||||
number = '0x' + parseInt(octalLiteral[1], 8).toString 16
|
||||
if binaryLiteral = /^0b([01]+)/.exec number
|
||||
@@ -183,49 +189,60 @@ exports.Lexer = class Lexer
|
||||
@token 'NUMBER', number, 0, lexedLength
|
||||
lexedLength
|
||||
|
||||
# Matches strings, including multi-line strings. Ensures that quotation marks
|
||||
# are balanced within the string's contents, and within nested interpolations.
|
||||
# Matches strings, including multi-line strings, as well as heredocs, with or without
|
||||
# interpolation.
|
||||
stringToken: ->
|
||||
switch quote = @chunk.charAt 0
|
||||
when "'" then [string] = SIMPLESTR.exec(@chunk) || []
|
||||
when '"' then string = @balancedString @chunk, '"'
|
||||
return 0 unless string
|
||||
inner = string[1...-1]
|
||||
trimmed = @removeNewlines inner
|
||||
if quote is '"' and 0 < string.indexOf '#{', 1
|
||||
numBreak = pos = 0
|
||||
innerLen = inner.length
|
||||
numBreak++ while inner.charAt(pos++) is '\n' and pos < innerLen
|
||||
@interpolateString trimmed, strOffset: 1 + numBreak, lexedLength: string.length
|
||||
else
|
||||
@token 'STRING', quote + @escapeLines(trimmed) + quote, 0, string.length
|
||||
if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string
|
||||
@error "octal escape sequences #{string} are not allowed"
|
||||
string.length
|
||||
[quote] = STRING_START.exec(@chunk) || []
|
||||
return 0 unless quote
|
||||
regex = switch quote
|
||||
when "'" then STRING_SINGLE
|
||||
when '"' then STRING_DOUBLE
|
||||
when "'''" then HEREDOC_SINGLE
|
||||
when '"""' then HEREDOC_DOUBLE
|
||||
heredoc = quote.length is 3
|
||||
|
||||
# Matches heredocs, adjusting indentation to the correct level, as heredocs
|
||||
# preserve whitespace, but ignore indentation to the left.
|
||||
heredocToken: ->
|
||||
return 0 unless match = HEREDOC.exec @chunk
|
||||
heredoc = match[0]
|
||||
quote = heredoc.charAt 0
|
||||
doc = @sanitizeHeredoc match[2], quote: quote, indent: null
|
||||
if quote is '"' and 0 <= doc.indexOf '#{'
|
||||
strOffset = if match[2].charAt(0) is '\n' then 4 else 3
|
||||
@interpolateString doc, heredoc: yes, strOffset: strOffset, lexedLength: heredoc.length
|
||||
{tokens, index: end} = @matchWithInterpolations regex, quote
|
||||
$ = tokens.length - 1
|
||||
|
||||
delimiter = quote[0]
|
||||
if heredoc
|
||||
# Find the smallest indentation. It will be removed from all lines later.
|
||||
indent = null
|
||||
doc = (token[1] for token, i in tokens when token[0] is 'NEOSTRING').join '#{}'
|
||||
while match = HEREDOC_INDENT.exec doc
|
||||
attempt = match[1]
|
||||
indent = attempt if indent is null or 0 < attempt.length < indent.length
|
||||
indentRegex = /// ^#{indent} ///gm if indent
|
||||
@mergeInterpolationTokens tokens, {delimiter}, (value, i) =>
|
||||
value = @formatString value
|
||||
value = value.replace LEADING_BLANK_LINE, '' if i is 0
|
||||
value = value.replace TRAILING_BLANK_LINE, '' if i is $
|
||||
value = value.replace indentRegex, '' if indentRegex
|
||||
value
|
||||
else
|
||||
@token 'STRING', @makeString(doc, quote, yes), 0, heredoc.length
|
||||
heredoc.length
|
||||
@mergeInterpolationTokens tokens, {delimiter}, (value, i) =>
|
||||
value = @formatString value
|
||||
value = value.replace SIMPLE_STRING_OMIT, (match, offset) ->
|
||||
if (i is 0 and offset is 0) or
|
||||
(i is $ and offset + match.length is value.length)
|
||||
''
|
||||
else
|
||||
' '
|
||||
value
|
||||
|
||||
end
|
||||
|
||||
# Matches and consumes comments.
|
||||
commentToken: ->
|
||||
return 0 unless match = @chunk.match COMMENT
|
||||
[comment, here] = match
|
||||
if here
|
||||
@token 'HERECOMMENT',
|
||||
(@sanitizeHeredoc here,
|
||||
herecomment: true, indent: repeat ' ', @indent),
|
||||
0, comment.length
|
||||
if match = HERECOMMENT_ILLEGAL.exec comment
|
||||
@error "block comments cannot contain #{match[0]}",
|
||||
offset: match.index, length: match[0].length
|
||||
if here.indexOf('\n') >= 0
|
||||
here = here.replace /// \n #{repeat ' ', @indent} ///g, '\n'
|
||||
@token 'HERECOMMENT', here, 0, comment.length
|
||||
comment.length
|
||||
|
||||
# Matches JavaScript interpolated directly into the source via backticks.
|
||||
@@ -234,70 +251,51 @@ exports.Lexer = class Lexer
|
||||
@token 'JS', (script = match[0])[1...-1], 0, script.length
|
||||
script.length
|
||||
|
||||
# Matches regular expression literals. Lexing regular expressions is difficult
|
||||
# to distinguish from division, so we borrow some basic heuristics from
|
||||
# JavaScript and Ruby.
|
||||
# Matches regular expression literals, as well as multiline extended ones.
|
||||
# Lexing regular expressions is difficult to distinguish from division, so we
|
||||
# borrow some basic heuristics from JavaScript and Ruby.
|
||||
regexToken: ->
|
||||
return 0 if @chunk.charAt(0) isnt '/'
|
||||
return length if length = @heregexToken()
|
||||
|
||||
prev = last @tokens
|
||||
return 0 if prev and (prev[0] in (if prev.spaced then NOT_REGEX else NOT_SPACED_REGEX))
|
||||
return 0 unless match = REGEX.exec @chunk
|
||||
[match, regex, flags] = match
|
||||
# Avoid conflicts with floor division operator.
|
||||
return 0 if regex is '//'
|
||||
if regex[..1] is '/*' then @error 'regular expressions cannot begin with `*`'
|
||||
@token 'REGEX', "#{regex}#{flags}", 0, match.length
|
||||
match.length
|
||||
|
||||
# Matches multiline extended regular expressions.
|
||||
heregexToken: ->
|
||||
return 0 unless match = HEREGEX.exec @chunk
|
||||
[heregex, body, flags] = match
|
||||
if 0 > body.indexOf '#{'
|
||||
re = @escapeLines body.replace(HEREGEX_OMIT, '$1$2').replace(/\//g, '\\/'), yes
|
||||
if re.match /^\*/ then @error 'regular expressions cannot begin with `*`'
|
||||
@token 'REGEX', "/#{ re or '(?:)' }/#{flags}", 0, heregex.length
|
||||
return heregex.length
|
||||
@token 'IDENTIFIER', 'RegExp', 0, 0
|
||||
@token 'CALL_START', '(', 0, 0
|
||||
tokens = []
|
||||
for token in @interpolateString(body, regex: yes, strOffset: 3)
|
||||
[tag, value] = token
|
||||
if tag is 'TOKENS'
|
||||
tokens.push value...
|
||||
else if tag is 'NEOSTRING'
|
||||
continue unless value = value.replace HEREGEX_OMIT, '$1$2'
|
||||
# Convert NEOSTRING into STRING
|
||||
value = value.replace /\\/g, '\\\\'
|
||||
token[0] = 'STRING'
|
||||
token[1] = @makeString(value, '"', yes)
|
||||
tokens.push token
|
||||
switch
|
||||
when match = REGEX_ILLEGAL.exec @chunk
|
||||
@error "regular expressions cannot begin with #{match[2]}",
|
||||
offset: match.index + match[1].length
|
||||
when match = @matchWithInterpolations HEREGEX, '///'
|
||||
{tokens, index} = match
|
||||
when match = REGEX.exec @chunk
|
||||
[regex, body, closed] = match
|
||||
@validateEscapes body, isRegex: yes, offsetInChunk: 1
|
||||
index = regex.length
|
||||
[..., prev] = @tokens
|
||||
if prev
|
||||
if prev.spaced and prev[0] in CALLABLE
|
||||
return 0 if not closed or POSSIBLY_DIVISION.test regex
|
||||
else if prev[0] in NOT_REGEX
|
||||
return 0
|
||||
@error 'missing / (unclosed regex)' unless closed
|
||||
else
|
||||
@error "Unexpected #{tag}"
|
||||
return 0
|
||||
|
||||
prev = last @tokens
|
||||
plusToken = ['+', '+']
|
||||
plusToken[2] = prev[2] # Copy location data
|
||||
tokens.push plusToken
|
||||
[flags] = REGEX_FLAGS.exec @chunk[index..]
|
||||
end = index + flags.length
|
||||
origin = @makeToken 'REGEX', null, 0, end
|
||||
switch
|
||||
when not VALID_FLAGS.test flags
|
||||
@error "invalid regular expression flags #{flags}", offset: index, length: flags.length
|
||||
when regex or tokens.length is 1
|
||||
body ?= @formatHeregex tokens[0][1]
|
||||
@token 'REGEX', "#{@makeDelimitedLiteral body, delimiter: '/'}#{flags}", 0, end, origin
|
||||
else
|
||||
@token 'REGEX_START', '(', 0, 0, origin
|
||||
@token 'IDENTIFIER', 'RegExp', 0, 0
|
||||
@token 'CALL_START', '(', 0, 0
|
||||
@mergeInterpolationTokens tokens, {delimiter: '"', double: yes}, @formatHeregex
|
||||
if flags
|
||||
@token ',', ',', index, 0
|
||||
@token 'STRING', '"' + flags + '"', index, flags.length
|
||||
@token ')', ')', end, 0
|
||||
@token 'REGEX_END', ')', end, 0
|
||||
|
||||
# Remove the extra "+"
|
||||
tokens.pop()
|
||||
|
||||
unless tokens[0]?[0] is 'STRING'
|
||||
@token 'STRING', '""', 0, 0
|
||||
@token '+', '+', 0, 0
|
||||
@tokens.push tokens...
|
||||
|
||||
if flags
|
||||
# Find the flags in the heregex
|
||||
flagsOffset = heregex.lastIndexOf flags
|
||||
@token ',', ',', flagsOffset, 0
|
||||
@token 'STRING', '"' + flags + '"', flagsOffset, flags.length
|
||||
|
||||
@token ')', ')', heregex.length-1, 0
|
||||
heregex.length
|
||||
end
|
||||
|
||||
# Matches newlines, indents, and outdents, and determines which is which.
|
||||
# If we can detect that the current line is continued onto the the next line,
|
||||
@@ -330,11 +328,11 @@ exports.Lexer = class Lexer
|
||||
diff = size - @indent + @outdebt
|
||||
@token 'INDENT', diff, indent.length - size, size
|
||||
@indents.push diff
|
||||
@ends.push 'OUTDENT'
|
||||
@ends.push {tag: 'OUTDENT'}
|
||||
@outdebt = @indebt = 0
|
||||
@indent = size
|
||||
else if size < @baseIndent
|
||||
@error 'missing indentation', indent.length
|
||||
@error 'missing indentation', offset: indent.length
|
||||
else
|
||||
@indebt = 0
|
||||
@outdentToken @indent - size, noNewlines, indent.length
|
||||
@@ -376,7 +374,7 @@ exports.Lexer = class Lexer
|
||||
whitespaceToken: ->
|
||||
return 0 unless (match = WHITESPACE.exec @chunk) or
|
||||
(nline = @chunk.charAt(0) is '\n')
|
||||
prev = last @tokens
|
||||
[..., prev] = @tokens
|
||||
prev[if match then 'spaced' else 'newLine'] = true if prev
|
||||
if match then match[0].length else 0
|
||||
|
||||
@@ -404,10 +402,10 @@ exports.Lexer = class Lexer
|
||||
else
|
||||
value = @chunk.charAt 0
|
||||
tag = value
|
||||
prev = last @tokens
|
||||
[..., prev] = @tokens
|
||||
if value is '=' and prev
|
||||
if not prev[1].reserved and prev[1] in JS_FORBIDDEN
|
||||
@error "reserved word \"#{@value()}\" can't be assigned"
|
||||
@error "reserved word '#{prev[1]}' can't be assigned", prev[2]
|
||||
if prev[1] in ['||', '&&']
|
||||
prev[0] = 'COMPOUND_ASSIGN'
|
||||
prev[1] += '='
|
||||
@@ -430,31 +428,16 @@ exports.Lexer = class Lexer
|
||||
tag = 'INDEX_START'
|
||||
switch prev[0]
|
||||
when '?' then prev[0] = 'INDEX_SOAK'
|
||||
token = @makeToken tag, value
|
||||
switch value
|
||||
when '(', '{', '[' then @ends.push INVERSES[value]
|
||||
when '(', '{', '[' then @ends.push {tag: INVERSES[value], origin: token}
|
||||
when ')', '}', ']' then @pair value
|
||||
@token tag, value
|
||||
@tokens.push token
|
||||
value.length
|
||||
|
||||
# Token Manipulators
|
||||
# ------------------
|
||||
|
||||
# Sanitize a heredoc or herecomment by
|
||||
# erasing all external indentation on the left-hand side.
|
||||
sanitizeHeredoc: (doc, options) ->
|
||||
{indent, herecomment} = options
|
||||
if herecomment
|
||||
if HEREDOC_ILLEGAL.test doc
|
||||
@error "block comment cannot contain \"*/\", starting"
|
||||
return doc if doc.indexOf('\n') < 0
|
||||
else
|
||||
while match = HEREDOC_INDENT.exec doc
|
||||
attempt = match[1]
|
||||
indent = attempt if indent is null or 0 < attempt.length < indent.length
|
||||
doc = doc.replace /// \n #{indent} ///g, '\n' if indent
|
||||
doc = doc.replace /^\n/, '' unless herecomment
|
||||
doc
|
||||
|
||||
# A source of ambiguity in our grammar used to be parameter lists in function
|
||||
# definitions versus argument lists in function calls. Walk backwards, tagging
|
||||
# parameters specially in order to make things easier for the parser.
|
||||
@@ -480,145 +463,149 @@ exports.Lexer = class Lexer
|
||||
closeIndentation: ->
|
||||
@outdentToken @indent
|
||||
|
||||
# Matches a balanced group such as a single or double-quoted string. Pass in
|
||||
# a series of delimiters, all of which must be nested correctly within the
|
||||
# contents of the string. This method allows us to have strings within
|
||||
# interpolations within strings, ad infinitum.
|
||||
balancedString: (str, end) ->
|
||||
continueCount = 0
|
||||
stack = [end]
|
||||
for i in [1...str.length]
|
||||
if continueCount
|
||||
--continueCount
|
||||
continue
|
||||
switch letter = str.charAt i
|
||||
when '\\'
|
||||
++continueCount
|
||||
continue
|
||||
when end
|
||||
stack.pop()
|
||||
unless stack.length
|
||||
return str[0..i]
|
||||
end = stack[stack.length - 1]
|
||||
continue
|
||||
if end is '}' and letter in ['"', "'"]
|
||||
stack.push end = letter
|
||||
else if end is '}' and letter is '/' and match = (HEREGEX.exec(str[i..]) or REGEX.exec(str[i..]))
|
||||
continueCount += match[0].length - 1
|
||||
else if end is '}' and letter is '{'
|
||||
stack.push end = '}'
|
||||
else if end is '"' and prev is '#' and letter is '{'
|
||||
stack.push end = '}'
|
||||
prev = letter
|
||||
@error "missing #{ stack.pop() }, starting"
|
||||
|
||||
# Expand variables and expressions inside double-quoted strings using
|
||||
# Ruby-like notation for substitution of arbitrary expressions.
|
||||
# Match the contents of a delimited token and expand variables and expressions
|
||||
# inside it using Ruby-like notation for substitution of arbitrary
|
||||
# expressions.
|
||||
#
|
||||
# "Hello #{name.capitalize()}."
|
||||
#
|
||||
# If it encounters an interpolation, this method will recursively create a
|
||||
# new Lexer, tokenize the interpolated contents, and merge them into the
|
||||
# token stream.
|
||||
# If it encounters an interpolation, this method will recursively create a new
|
||||
# Lexer and tokenize until the `{` of `#{` is balanced with a `}`.
|
||||
#
|
||||
# - `str` is the start of the string contents (IE with the " or """ stripped
|
||||
# off.)
|
||||
# - `options.offsetInChunk` is the start of the interpolated string in the
|
||||
# current chunk, including the " or """, etc... If not provided, this is
|
||||
# assumed to be 0. `options.lexedLength` is the length of the
|
||||
# interpolated string, including both the start and end quotes. Both of these
|
||||
# values are ignored if `options.regex` is true.
|
||||
# - `options.strOffset` is the offset of str, relative to the start of the
|
||||
# current chunk.
|
||||
interpolateString: (str, options = {}) ->
|
||||
{heredoc, regex, offsetInChunk, strOffset, lexedLength} = options
|
||||
offsetInChunk ||= 0
|
||||
strOffset ||= 0
|
||||
lexedLength ||= str.length
|
||||
|
||||
# Parse the string.
|
||||
# - `regex` matches the contents of a token (but not `delimiter`, and not
|
||||
# `#{` if interpolations are desired).
|
||||
# - `delimiter` is the delimiter of the token. Examples are `'`, `"`, `'''`,
|
||||
# `"""` and `///`.
|
||||
#
|
||||
# This method allows us to have strings within interpolations within strings,
|
||||
# ad infinitum.
|
||||
matchWithInterpolations: (regex, delimiter) ->
|
||||
tokens = []
|
||||
pi = 0
|
||||
i = -1
|
||||
while letter = str.charAt i += 1
|
||||
if letter is '\\'
|
||||
i += 1
|
||||
continue
|
||||
unless letter is '#' and str.charAt(i+1) is '{' and
|
||||
(expr = @balancedString str[i + 1..], '}')
|
||||
continue
|
||||
# NEOSTRING is a fake token. This will be converted to a string below.
|
||||
tokens.push @makeToken('NEOSTRING', str[pi...i], strOffset + pi) if pi < i
|
||||
unless errorToken
|
||||
errorToken = @makeToken '', 'string interpolation', offsetInChunk + i + 1, 2
|
||||
inner = expr[1...-1]
|
||||
if inner.length
|
||||
[line, column] = @getLineAndColumnFromChunk(strOffset + i + 2)
|
||||
nested = new Lexer().tokenize inner, line: line, column: column, rewrite: off
|
||||
popped = nested.pop()
|
||||
popped = nested.shift() if nested[0]?[0] is 'TERMINATOR'
|
||||
if len = nested.length
|
||||
if len > 1
|
||||
nested.unshift @makeToken '(', '(', strOffset + i + 1, 0
|
||||
nested.push @makeToken ')', ')', strOffset + i + 1 + inner.length, 0
|
||||
# Push a fake 'TOKENS' token, which will get turned into real tokens below.
|
||||
tokens.push ['TOKENS', nested]
|
||||
i += expr.length
|
||||
pi = i + 1
|
||||
tokens.push @makeToken('NEOSTRING', str[pi..], strOffset + pi) if i > pi < str.length
|
||||
offsetInChunk = delimiter.length
|
||||
return null unless @chunk[...offsetInChunk] is delimiter
|
||||
str = @chunk[offsetInChunk..]
|
||||
loop
|
||||
[strPart] = regex.exec str
|
||||
|
||||
# If regex, then return now and let the regex code deal with all these fake tokens
|
||||
return tokens if regex
|
||||
@validateEscapes strPart, {isRegex: delimiter.charAt(0) is '/', offsetInChunk}
|
||||
|
||||
# If we didn't find any tokens, then just return an empty string.
|
||||
return @token 'STRING', '""', offsetInChunk, lexedLength unless tokens.length
|
||||
# Push a fake 'NEOSTRING' token, which will get turned into a real string later.
|
||||
tokens.push @makeToken 'NEOSTRING', strPart, offsetInChunk
|
||||
|
||||
# If the first token is not a string, add a fake empty string to the beginning.
|
||||
tokens.unshift @makeToken('NEOSTRING', '', offsetInChunk) unless tokens[0][0] is 'NEOSTRING'
|
||||
str = str[strPart.length..]
|
||||
offsetInChunk += strPart.length
|
||||
|
||||
if interpolated = tokens.length > 1
|
||||
@token '(', '(', offsetInChunk, 0, errorToken
|
||||
break unless str[...2] is '#{'
|
||||
|
||||
# Push all the tokens
|
||||
# The `1`s are to remove the `#` in `#{`.
|
||||
[line, column] = @getLineAndColumnFromChunk offsetInChunk + 1
|
||||
{tokens: nested, index} =
|
||||
new Lexer().tokenize str[1..], line: line, column: column, untilBalanced: on
|
||||
# Skip the trailing `}`.
|
||||
index += 1
|
||||
|
||||
# Turn the leading and trailing `{` and `}` into parentheses. Unnecessary
|
||||
# parentheses will be removed later.
|
||||
[open, ..., close] = nested
|
||||
open[0] = open[1] = '('
|
||||
close[0] = close[1] = ')'
|
||||
close.origin = ['', 'end of interpolation', close[2]]
|
||||
|
||||
# Remove leading 'TERMINATOR' (if any).
|
||||
nested.splice 1, 1 if nested[1]?[0] is 'TERMINATOR'
|
||||
|
||||
# Push a fake 'TOKENS' token, which will get turned into real tokens later.
|
||||
tokens.push ['TOKENS', nested]
|
||||
|
||||
str = str[index..]
|
||||
offsetInChunk += index
|
||||
|
||||
unless str[...delimiter.length] is delimiter
|
||||
@error "missing #{delimiter}", length: delimiter.length
|
||||
|
||||
[firstToken, ..., lastToken] = tokens
|
||||
firstToken[2].first_column -= delimiter.length
|
||||
lastToken[2].last_column += delimiter.length
|
||||
lastToken[2].last_column -= 1 if lastToken[1].length is 0
|
||||
|
||||
{tokens, index: offsetInChunk + delimiter.length}
|
||||
|
||||
# Merge the array `tokens` of the fake token types 'TOKENS' and 'NEOSTRING'
|
||||
# (as returned by `matchWithInterpolations`) into the token stream. The value
|
||||
# of 'NEOSTRING's are converted using `fn` and turned into strings using
|
||||
# `options` first.
|
||||
mergeInterpolationTokens: (tokens, options, fn) ->
|
||||
if tokens.length > 1
|
||||
lparen = @token 'STRING_START', '(', 0, 0
|
||||
|
||||
firstIndex = @tokens.length
|
||||
for token, i in tokens
|
||||
[tag, value] = token
|
||||
if i
|
||||
switch tag
|
||||
when 'TOKENS'
|
||||
# Optimize out empty interpolations (an empty pair of parentheses).
|
||||
continue if value.length is 2
|
||||
# Push all the tokens in the fake 'TOKENS' token. These already have
|
||||
# sane location data.
|
||||
locationToken = value[0]
|
||||
tokensToPush = value
|
||||
when 'NEOSTRING'
|
||||
# Convert 'NEOSTRING' into 'STRING'.
|
||||
converted = fn token[1], i
|
||||
# Optimize out empty strings. We ensure that the tokens stream always
|
||||
# starts with a string token, though, to make sure that the result
|
||||
# really is a string.
|
||||
if converted.length is 0
|
||||
if i is 0
|
||||
firstEmptyStringIndex = @tokens.length
|
||||
else
|
||||
continue
|
||||
# However, there is one case where we can optimize away a starting
|
||||
# empty string.
|
||||
if i is 2 and firstEmptyStringIndex?
|
||||
@tokens.splice firstEmptyStringIndex, 2 # Remove empty string and the plus.
|
||||
token[0] = 'STRING'
|
||||
token[1] = @makeDelimitedLiteral converted, options
|
||||
locationToken = token
|
||||
tokensToPush = [token]
|
||||
if @tokens.length > firstIndex
|
||||
# Create a 0-length "+" token.
|
||||
plusToken = @token '+', '+' if i
|
||||
locationToken = if tag == 'TOKENS' then value[0] else token
|
||||
plusToken = @token '+', '+'
|
||||
plusToken[2] =
|
||||
first_line: locationToken[2].first_line
|
||||
first_line: locationToken[2].first_line
|
||||
first_column: locationToken[2].first_column
|
||||
last_line: locationToken[2].first_line
|
||||
last_column: locationToken[2].first_column
|
||||
if tag is 'TOKENS'
|
||||
# Push all the tokens in the fake 'TOKENS' token. These already have
|
||||
# sane location data.
|
||||
@tokens.push value...
|
||||
else if tag is 'NEOSTRING'
|
||||
# Convert NEOSTRING into STRING
|
||||
token[0] = 'STRING'
|
||||
token[1] = @makeString value, '"', heredoc
|
||||
@tokens.push token
|
||||
else
|
||||
@error "Unexpected #{tag}"
|
||||
if interpolated
|
||||
rparen = @makeToken ')', ')', offsetInChunk + lexedLength, 0
|
||||
rparen.stringEnd = true
|
||||
@tokens.push rparen
|
||||
tokens
|
||||
last_line: locationToken[2].first_line
|
||||
last_column: locationToken[2].first_column
|
||||
@tokens.push tokensToPush...
|
||||
|
||||
if lparen
|
||||
[..., lastToken] = tokens
|
||||
lparen.origin = ['STRING', null,
|
||||
first_line: lparen[2].first_line
|
||||
first_column: lparen[2].first_column
|
||||
last_line: lastToken[2].last_line
|
||||
last_column: lastToken[2].last_column
|
||||
]
|
||||
rparen = @token 'STRING_END', ')'
|
||||
rparen[2] =
|
||||
first_line: lastToken[2].last_line
|
||||
first_column: lastToken[2].last_column
|
||||
last_line: lastToken[2].last_line
|
||||
last_column: lastToken[2].last_column
|
||||
|
||||
# Pairs up a closing token, ensuring that all listed pairs of tokens are
|
||||
# correctly balanced throughout the course of the token stream.
|
||||
pair: (tag) ->
|
||||
unless tag is wanted = last @ends
|
||||
[..., prev] = @ends
|
||||
unless tag is wanted = prev?.tag
|
||||
@error "unmatched #{tag}" unless 'OUTDENT' is wanted
|
||||
# Auto-close INDENT to support syntax like this:
|
||||
#
|
||||
# el.click((event) ->
|
||||
# el.hide())
|
||||
#
|
||||
@outdentToken last(@indents), true
|
||||
[..., lastIndent] = @indents
|
||||
@outdentToken lastIndent, true
|
||||
return @pair tag
|
||||
@ends.pop()
|
||||
|
||||
@@ -641,8 +628,8 @@ exports.Lexer = class Lexer
|
||||
|
||||
column = @chunkColumn
|
||||
if lineCount > 0
|
||||
lines = string.split '\n'
|
||||
column = last(lines).length
|
||||
[..., lastLine] = string.split '\n'
|
||||
column = lastLine.length
|
||||
else
|
||||
column += string.length
|
||||
|
||||
@@ -677,50 +664,76 @@ exports.Lexer = class Lexer
|
||||
@tokens.push token
|
||||
token
|
||||
|
||||
# Peek at a tag in the current token stream.
|
||||
tag: (index, tag) ->
|
||||
(tok = last @tokens, index) and if tag then tok[0] = tag else tok[0]
|
||||
# Peek at the last tag in the token stream.
|
||||
tag: ->
|
||||
[..., token] = @tokens
|
||||
token?[0]
|
||||
|
||||
# Peek at a value in the current token stream.
|
||||
value: (index, val) ->
|
||||
(tok = last @tokens, index) and if val then tok[1] = val else tok[1]
|
||||
# Peek at the last value in the token stream.
|
||||
value: ->
|
||||
[..., token] = @tokens
|
||||
token?[1]
|
||||
|
||||
# Are we in the midst of an unfinished expression?
|
||||
unfinished: ->
|
||||
LINE_CONTINUER.test(@chunk) or
|
||||
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-',
|
||||
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', 'YIELD',
|
||||
'**', 'SHIFT', 'RELATION', 'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
|
||||
|
||||
# Remove newlines from beginning and (non escaped) from end of string literals.
|
||||
removeNewlines: (str) ->
|
||||
str.replace(/^\s*\n\s*/, '')
|
||||
.replace(/([^\\]|\\\\)\s*\n\s*$/, '$1')
|
||||
formatString: (str) ->
|
||||
str.replace STRING_OMIT, '$1'
|
||||
|
||||
# Converts newlines for string literals.
|
||||
escapeLines: (str, heredoc) ->
|
||||
# Ignore escaped backslashes and remove escaped newlines
|
||||
str = str.replace /\\[^\S\n]*(\n|\\)\s*/g, (escaped, character) ->
|
||||
if character is '\n' then '' else escaped
|
||||
if heredoc
|
||||
str.replace MULTILINER, '\\n'
|
||||
else
|
||||
str.replace /\s*\n\s*/g, ' '
|
||||
formatHeregex: (str) ->
|
||||
str.replace HEREGEX_OMIT, '$1$2'
|
||||
|
||||
# Constructs a string token by escaping quotes and newlines.
|
||||
makeString: (body, quote, heredoc) ->
|
||||
return quote + quote unless body
|
||||
# Ignore escaped backslashes and unescape quotes
|
||||
body = body.replace /// \\( #{quote} | \\ ) ///g, (match, contents) ->
|
||||
if contents is quote then contents else match
|
||||
body = body.replace /// #{quote} ///g, '\\$&'
|
||||
quote + @escapeLines(body, heredoc) + quote
|
||||
# Validates escapes in strings and regexes.
|
||||
validateEscapes: (str, options = {}) ->
|
||||
match = INVALID_ESCAPE.exec str
|
||||
return unless match
|
||||
[[], before, octal, hex, unicode] = match
|
||||
return if options.isRegex and octal and octal.charAt(0) isnt '0'
|
||||
message =
|
||||
if octal
|
||||
"octal escape sequences are not allowed"
|
||||
else
|
||||
"invalid escape sequence"
|
||||
invalidEscape = "\\#{octal or hex or unicode}"
|
||||
@error "#{message} #{invalidEscape}",
|
||||
offset: (options.offsetInChunk ? 0) + match.index + before.length
|
||||
length: invalidEscape.length
|
||||
|
||||
# Throws a compiler error on the current position.
|
||||
error: (message, offset = 0) ->
|
||||
# TODO: Are there some cases we could improve the error line number by
|
||||
# passing the offset in the chunk where the error happened?
|
||||
[first_line, first_column] = @getLineAndColumnFromChunk offset
|
||||
throwSyntaxError message, {first_line, first_column}
|
||||
# Constructs a string or regex by escaping certain characters.
|
||||
makeDelimitedLiteral: (body, options = {}) ->
|
||||
body = '(?:)' if body is '' and options.delimiter is '/'
|
||||
regex = ///
|
||||
(\\\\) # escaped backslash
|
||||
| (\\0(?=[1-7])) # nul character mistaken as octal escape
|
||||
| \\?(#{options.delimiter}) # (possibly escaped) delimiter
|
||||
| \\?(?: (\n)|(\r)|(\u2028)|(\u2029) ) # (possibly escaped) newlines
|
||||
| (\\.) # other escapes
|
||||
///g
|
||||
body = body.replace regex, (match, backslash, nul, delimiter, lf, cr, ls, ps, other) -> switch
|
||||
# Ignore escaped backslashes.
|
||||
when backslash then (if options.double then backslash + backslash else backslash)
|
||||
when nul then '\\x00'
|
||||
when delimiter then "\\#{delimiter}"
|
||||
when lf then '\\n'
|
||||
when cr then '\\r'
|
||||
when ls then '\\u2028'
|
||||
when ps then '\\u2029'
|
||||
when other then (if options.double then "\\#{other}" else other)
|
||||
"#{options.delimiter}#{body}#{options.delimiter}"
|
||||
|
||||
# Throws an error at either a given offset from the current chunk or at the
|
||||
# location of a token (`token[2]`).
|
||||
error: (message, options = {}) ->
|
||||
location =
|
||||
if 'first_line' of options
|
||||
options
|
||||
else
|
||||
[first_line, first_column] = @getLineAndColumnFromChunk options.offset ? 0
|
||||
{first_line, first_column, last_column: first_column + (options.length ? 1) - 1}
|
||||
throwSyntaxError message, location
|
||||
|
||||
# Constants
|
||||
# ---------
|
||||
@@ -729,7 +742,7 @@ exports.Lexer = class Lexer
|
||||
JS_KEYWORDS = [
|
||||
'true', 'false', 'null', 'this'
|
||||
'new', 'delete', 'typeof', 'in', 'instanceof'
|
||||
'return', 'throw', 'break', 'continue', 'debugger'
|
||||
'return', 'throw', 'break', 'continue', 'debugger', 'yield'
|
||||
'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally'
|
||||
'class', 'extends', 'super'
|
||||
]
|
||||
@@ -756,12 +769,11 @@ COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat COFFEE_ALIASES
|
||||
# to avoid having a JavaScript error at runtime.
|
||||
RESERVED = [
|
||||
'case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum'
|
||||
'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind'
|
||||
'__indexOf', 'implements', 'interface', 'package', 'private', 'protected'
|
||||
'public', 'static', 'yield'
|
||||
'export', 'import', 'native', 'implements', 'interface', 'package', 'private'
|
||||
'protected', 'public', 'static'
|
||||
]
|
||||
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval']
|
||||
STRICT_PROSCRIBED = ['arguments', 'eval', 'yield*']
|
||||
|
||||
# The superset of both JavaScript keywords and reserved words, none of which may
|
||||
# be used as identifiers or properties.
|
||||
@@ -775,7 +787,8 @@ BOM = 65279
|
||||
|
||||
# Token matching regexes.
|
||||
IDENTIFIER = /// ^
|
||||
( [$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]* )
|
||||
(?!\d)
|
||||
( (?: (?!\s)[$\w\x7f-\uffff] )+ )
|
||||
( [^\n\S]* : (?!:) )? # Is this a property name?
|
||||
///
|
||||
|
||||
@@ -786,8 +799,6 @@ NUMBER = ///
|
||||
^ \d*\.?\d+ (?:e[+-]?\d+)? # decimal
|
||||
///i
|
||||
|
||||
HEREDOC = /// ^ ("""|''') ((?: \\[\s\S] | [^\\] )*?) (?:\n[^\n\S]*)? \1 ///
|
||||
|
||||
OPERATOR = /// ^ (
|
||||
?: [-=]> # function
|
||||
| [-+*/%<>&|^!?=]= # compound assign / compare
|
||||
@@ -806,43 +817,67 @@ CODE = /^[-=]>/
|
||||
|
||||
MULTI_DENT = /^(?:\n[^\n\S]*)+/
|
||||
|
||||
SIMPLESTR = /^'[^\\']*(?:\\[\s\S][^\\']*)*'/
|
||||
|
||||
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/
|
||||
|
||||
# String-matching-regexes.
|
||||
STRING_START = /^(?:'''|"""|'|")/
|
||||
|
||||
STRING_SINGLE = /// ^(?: [^\\'] | \\[\s\S] )* ///
|
||||
STRING_DOUBLE = /// ^(?: [^\\"#] | \\[\s\S] | \#(?!\{) )* ///
|
||||
HEREDOC_SINGLE = /// ^(?: [^\\'] | \\[\s\S] | '(?!'') )* ///
|
||||
HEREDOC_DOUBLE = /// ^(?: [^\\"#] | \\[\s\S] | "(?!"") | \#(?!\{) )* ///
|
||||
|
||||
STRING_OMIT = ///
|
||||
((?:\\\\)+) # consume (and preserve) an even number of backslashes
|
||||
| \\[^\S\n]*\n\s* # remove escaped newlines
|
||||
///g
|
||||
SIMPLE_STRING_OMIT = /\s*\n\s*/g
|
||||
HEREDOC_INDENT = /\n+([^\n\S]*)(?=\S)/g
|
||||
|
||||
# Regex-matching-regexes.
|
||||
REGEX = /// ^
|
||||
(/ (?! [\s=] ) # disallow leading whitespace or equals signs
|
||||
[^ [ / \n \\ ]* # every other thing
|
||||
(?:
|
||||
(?: \\[\s\S] # anything escaped
|
||||
| \[ # character class
|
||||
[^ \] \n \\ ]*
|
||||
(?: \\[\s\S] [^ \] \n \\ ]* )*
|
||||
]
|
||||
) [^ [ / \n \\ ]*
|
||||
)*
|
||||
/) ([imgy]{0,4}) (?!\w)
|
||||
/ (?!/) ((
|
||||
?: [^ [ / \n \\ ] # every other thing
|
||||
| \\[^\n] # anything but newlines escaped
|
||||
| \[ # character class
|
||||
(?: \\[^\n] | [^ \] \n \\ ] )*
|
||||
]
|
||||
)*) (/)?
|
||||
///
|
||||
|
||||
HEREGEX = /// ^ /{3} ((?:\\?[\s\S])+?) /{3} ([imgy]{0,4}) (?!\w) ///
|
||||
REGEX_FLAGS = /^\w*/
|
||||
VALID_FLAGS = /^(?!.*(.).*\1)[imgy]*$/
|
||||
|
||||
HEREGEX = /// ^(?: [^\\/#] | \\[\s\S] | /(?!//) | \#(?!\{) )* ///
|
||||
|
||||
HEREGEX_OMIT = ///
|
||||
((?:\\\\)+) # consume (and preserve) an even number of backslashes
|
||||
| \\(\s|/) # preserve escaped whitespace and "de-escape" slashes
|
||||
| \\(\s) # preserve escaped whitespace
|
||||
| \s+(?:#.*)? # remove whitespace and comments
|
||||
///g
|
||||
|
||||
# Token cleaning regexes.
|
||||
MULTILINER = /\n/g
|
||||
REGEX_ILLEGAL = /// ^ ( / | /{3}\s*) (\*) ///
|
||||
|
||||
HEREDOC_INDENT = /\n+([^\n\S]*)/g
|
||||
POSSIBLY_DIVISION = /// ^ /=?\s ///
|
||||
|
||||
HEREDOC_ILLEGAL = /\*\//
|
||||
# Other regexes.
|
||||
HERECOMMENT_ILLEGAL = /\*\//
|
||||
|
||||
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?![.\d]) | :: ) ///
|
||||
LINE_CONTINUER = /// ^ \s* (?: , | \??\.(?![.\d]) | :: ) ///
|
||||
|
||||
TRAILING_SPACES = /\s+$/
|
||||
INVALID_ESCAPE = ///
|
||||
( (?:^|[^\\]) (?:\\\\)* ) # make sure the escape isn’t escaped
|
||||
\\ (
|
||||
?: (0[0-7]|[1-7]) # octal escape
|
||||
| (x(?![\da-fA-F]{2}).{0,2}) # hex escape
|
||||
| (u(?![\da-fA-F]{4}).{0,4}) # unicode escape
|
||||
)
|
||||
///
|
||||
|
||||
LEADING_BLANK_LINE = /^[^\n\S]*\n/
|
||||
TRAILING_BLANK_LINE = /\n[^\n\S]*$/
|
||||
|
||||
TRAILING_SPACES = /\s+$/
|
||||
|
||||
# Compound assignment tokens.
|
||||
COMPOUND_ASSIGN = [
|
||||
@@ -873,23 +908,20 @@ RELATION = ['IN', 'OF', 'INSTANCEOF']
|
||||
# Boolean tokens.
|
||||
BOOL = ['TRUE', 'FALSE']
|
||||
|
||||
# Tokens which a regular expression will never immediately follow, but which
|
||||
# a division operator might.
|
||||
#
|
||||
# See: http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
|
||||
#
|
||||
# Our list is shorter, due to sans-parentheses method calls.
|
||||
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', 'NULL', 'UNDEFINED', '++', '--']
|
||||
|
||||
# If the previous token is not spaced, there are more preceding tokens that
|
||||
# force a division parse:
|
||||
NOT_SPACED_REGEX = NOT_REGEX.concat ')', '}', 'THIS', 'IDENTIFIER', 'STRING', ']'
|
||||
|
||||
# Tokens which could legitimately be invoked or indexed. An opening
|
||||
# parentheses or bracket following these tokens will be recorded as the start
|
||||
# of a function invocation or indexing operation.
|
||||
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER']
|
||||
INDEXABLE = CALLABLE.concat 'NUMBER', 'BOOL', 'NULL', 'UNDEFINED'
|
||||
CALLABLE = ['IDENTIFIER', ')', ']', '?', '@', 'THIS', 'SUPER']
|
||||
INDEXABLE = CALLABLE.concat [
|
||||
'NUMBER', 'STRING', 'STRING_END', 'REGEX', 'REGEX_END'
|
||||
'BOOL', 'NULL', 'UNDEFINED', '}', '::'
|
||||
]
|
||||
|
||||
# Tokens which a regular expression will never immediately follow (except spaced
|
||||
# CALLABLEs in some cases), but which a division operator can.
|
||||
#
|
||||
# See: http://www-archive.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
|
||||
NOT_REGEX = INDEXABLE.concat ['++', '--']
|
||||
|
||||
# Tokens that, when immediately preceding a `WHEN`, indicate that the `WHEN`
|
||||
# occurs at the start of a line. We disambiguate these from trailing whens to
|
||||
|
||||
285
src/nodes.coffee
285
src/nodes.coffee
@@ -9,7 +9,7 @@ Error.stackTraceLimit = Infinity
|
||||
{RESERVED, STRICT_PROSCRIBED} = require './lexer'
|
||||
|
||||
# Import the helpers we plan to use.
|
||||
{compact, flatten, extend, merge, del, starts, ends, last, some,
|
||||
{compact, flatten, extend, merge, del, starts, ends, some,
|
||||
addLocationDataFn, locationDataToString, throwSyntaxError} = require './helpers'
|
||||
|
||||
# Functions required by parser
|
||||
@@ -89,7 +89,11 @@ exports.Base = class Base
|
||||
else
|
||||
meth = 'call'
|
||||
func = new Value func, [new Access new Literal meth]
|
||||
(new Call func, args).compileNode o
|
||||
parts = (new Call func, args).compileNode o
|
||||
if func.isGenerator
|
||||
parts.unshift @makeCode "(yield* "
|
||||
parts.push @makeCode ")"
|
||||
parts
|
||||
|
||||
# If the code generation wishes to use the result of a complex expression
|
||||
# in multiple places, ensure that the expression is only ever evaluated once,
|
||||
@@ -98,14 +102,15 @@ exports.Base = class Base
|
||||
# If `level` is passed, then returns `[val, ref]`, where `val` is the compiled value, and `ref`
|
||||
# is the compiled reference. If `level` is not passed, this returns `[val, ref]` where
|
||||
# the two values are raw nodes which have not been compiled.
|
||||
cache: (o, level, reused) ->
|
||||
unless @isComplex()
|
||||
ref = if level then @compileToFragments o, level else this
|
||||
[ref, ref]
|
||||
else
|
||||
ref = new Literal reused or o.scope.freeVariable 'ref'
|
||||
cache: (o, level, isComplex) ->
|
||||
complex = if isComplex? then isComplex this else @isComplex()
|
||||
if complex
|
||||
ref = new Literal o.scope.freeVariable 'ref'
|
||||
sub = new Assign ref, this
|
||||
if level then [sub.compileToFragments(o, level), [@makeCode(ref.value)]] else [sub, ref]
|
||||
else
|
||||
ref = if level then @compileToFragments o, level else this
|
||||
[ref, ref]
|
||||
|
||||
cacheToCodeFragments: (cacheValues) ->
|
||||
[fragmentsToText(cacheValues[0]), fragmentsToText(cacheValues[1])]
|
||||
@@ -316,7 +321,7 @@ exports.Block = class Block extends Base
|
||||
o.indent = if o.bare then '' else TAB
|
||||
o.level = LEVEL_TOP
|
||||
@spaced = yes
|
||||
o.scope = new Scope null, this, null
|
||||
o.scope = new Scope null, this, null, o.referencedVars ? []
|
||||
# Mark given local variables in the root scope as parameters so they don't
|
||||
# end up being declared on this block.
|
||||
o.scope.parameter name for name in o.locals or []
|
||||
@@ -448,14 +453,15 @@ exports.Return = class Return extends Base
|
||||
|
||||
compileNode: (o) ->
|
||||
answer = []
|
||||
exprIsYieldReturn = @expression?.isYieldReturn?()
|
||||
# TODO: If we call expression.compile() here twice, we'll sometimes get back different results!
|
||||
answer.push @makeCode @tab + "return#{if @expression then " " else ""}"
|
||||
unless exprIsYieldReturn
|
||||
answer.push @makeCode @tab + "return#{if @expression then " " else ""}"
|
||||
if @expression
|
||||
answer = answer.concat @expression.compileToFragments o, LEVEL_PAREN
|
||||
answer.push @makeCode ";"
|
||||
answer.push @makeCode ";" unless exprIsYieldReturn
|
||||
return answer
|
||||
|
||||
|
||||
#### Value
|
||||
|
||||
# A value, variable or literal or parenthesized, indexed or dotted into,
|
||||
@@ -506,10 +512,11 @@ exports.Value = class Value extends Base
|
||||
(@base instanceof Obj) and (not onlyGenerated or @base.generated)
|
||||
|
||||
isSplice: ->
|
||||
last(@properties) instanceof Slice
|
||||
[..., lastProp] = @properties
|
||||
lastProp instanceof Slice
|
||||
|
||||
looksStatic: (className) ->
|
||||
@base.value is className and @properties.length and
|
||||
@base.value is className and @properties.length is 1 and
|
||||
@properties[0].name?.value isnt 'prototype'
|
||||
|
||||
# The value can be unwrapped as its inner node, if there are no attached
|
||||
@@ -521,7 +528,7 @@ exports.Value = class Value extends Base
|
||||
# We cache them separately for compiling complex expressions.
|
||||
# `a()[b()] ?= c` -> `(_base = a())[_name = b()] ? _base[_name] = c`
|
||||
cacheReference: (o) ->
|
||||
name = last @properties
|
||||
[..., name] = @properties
|
||||
if @properties.length < 2 and not @base.isComplex() and not name?.isComplex()
|
||||
return [this, this] # `a` `a.b`
|
||||
base = new Value @base, @properties[...-1]
|
||||
@@ -577,7 +584,7 @@ exports.Comment = class Comment extends Base
|
||||
makeReturn: THIS
|
||||
|
||||
compileNode: (o, level) ->
|
||||
comment = @comment.replace /^(\s*)#/gm, "$1 *"
|
||||
comment = @comment.replace /^(\s*)# /gm, "$1 * "
|
||||
code = "/*#{multident comment, @tab}#{if '\n' in comment then "\n#{@tab}" else ''} */"
|
||||
code = o.indent + code if (level or o.level) is LEVEL_TOP
|
||||
[@makeCode("\n"), @makeCode(code)]
|
||||
@@ -610,10 +617,21 @@ exports.Call = class Call extends Base
|
||||
superReference: (o) ->
|
||||
method = o.scope.namedMethod()
|
||||
if method?.klass
|
||||
accesses = [new Access(new Literal '__super__')]
|
||||
{klass, name, variable} = method
|
||||
if klass.isComplex()
|
||||
bref = new Literal o.scope.parent.freeVariable 'base'
|
||||
base = new Value new Parens new Assign bref, klass
|
||||
variable.base = base
|
||||
variable.properties.splice 0, klass.properties.length
|
||||
if name.isComplex() or (name instanceof Index and name.index.isAssignable())
|
||||
nref = new Literal o.scope.parent.freeVariable 'name'
|
||||
name = new Index new Assign nref, name.index
|
||||
variable.properties.pop()
|
||||
variable.properties.push name
|
||||
accesses = [new Access new Literal '__super__']
|
||||
accesses.push new Access new Literal 'constructor' if method.static
|
||||
accesses.push new Access new Literal method.name
|
||||
(new Value (new Literal method.klass), accesses).compile o
|
||||
accesses.push if nref? then new Index nref else name
|
||||
(new Value bref ? klass, accesses).compile o
|
||||
else if method?.ctor
|
||||
"#{method.name}.__super__.constructor"
|
||||
else
|
||||
@@ -733,7 +751,7 @@ exports.Extends = class Extends extends Base
|
||||
|
||||
# Hooks one constructor into another's prototype chain.
|
||||
compileToFragments: (o) ->
|
||||
new Call(new Value(new Literal utility 'extends'), [@child, @parent]).compileToFragments o
|
||||
new Call(new Value(new Literal utility 'extend', o), [@child, @parent]).compileToFragments o
|
||||
|
||||
#### Access
|
||||
|
||||
@@ -790,9 +808,10 @@ exports.Range = class Range extends Base
|
||||
# But only if they need to be cached to avoid double evaluation.
|
||||
compileVariables: (o) ->
|
||||
o = merge o, top: true
|
||||
[@fromC, @fromVar] = @cacheToCodeFragments @from.cache o, LEVEL_LIST
|
||||
[@toC, @toVar] = @cacheToCodeFragments @to.cache o, LEVEL_LIST
|
||||
[@step, @stepVar] = @cacheToCodeFragments step.cache o, LEVEL_LIST if step = del o, 'step'
|
||||
isComplex = del o, 'isComplex'
|
||||
[@fromC, @fromVar] = @cacheToCodeFragments @from.cache o, LEVEL_LIST, isComplex
|
||||
[@toC, @toVar] = @cacheToCodeFragments @to.cache o, LEVEL_LIST, isComplex
|
||||
[@step, @stepVar] = @cacheToCodeFragments step.cache o, LEVEL_LIST, isComplex if step = del o, 'step'
|
||||
[@fromNum, @toNum] = [@fromVar.match(NUMBER), @toVar.match(NUMBER)]
|
||||
@stepNum = @stepVar.match(NUMBER) if @stepVar
|
||||
|
||||
@@ -850,7 +869,7 @@ exports.Range = class Range extends Base
|
||||
range.pop() if @exclusive
|
||||
return [@makeCode "[#{ range.join(', ') }]"]
|
||||
idt = @tab + TAB
|
||||
i = o.scope.freeVariable 'i'
|
||||
i = o.scope.freeVariable 'i', single: true
|
||||
result = o.scope.freeVariable 'results'
|
||||
pre = "\n#{idt}#{result} = [];"
|
||||
if @fromNum and @toNum
|
||||
@@ -908,35 +927,54 @@ exports.Obj = class Obj extends Base
|
||||
|
||||
compileNode: (o) ->
|
||||
props = @properties
|
||||
return [@makeCode(if @front then '({})' else '{}')] unless props.length
|
||||
if @generated
|
||||
for node in props when node instanceof Value
|
||||
node.error 'cannot have an implicit value in an implicit object'
|
||||
break for prop, dynamicIndex in props when (prop.variable or prop).base instanceof Parens
|
||||
hasDynamic = dynamicIndex < props.length
|
||||
idt = o.indent += TAB
|
||||
lastNoncom = @lastNonComment @properties
|
||||
answer = []
|
||||
if hasDynamic
|
||||
oref = o.scope.freeVariable 'obj'
|
||||
answer.push @makeCode "(\n#{idt}#{oref} = "
|
||||
answer.push @makeCode "{#{if props.length is 0 or dynamicIndex is 0 then '}' else '\n'}"
|
||||
for prop, i in props
|
||||
join = if i is props.length - 1
|
||||
if i is dynamicIndex
|
||||
answer.push @makeCode "\n#{idt}}" unless i is 0
|
||||
answer.push @makeCode ',\n'
|
||||
join = if i is props.length - 1 or i is dynamicIndex - 1
|
||||
''
|
||||
else if prop is lastNoncom or prop instanceof Comment
|
||||
'\n'
|
||||
else
|
||||
',\n'
|
||||
indent = if prop instanceof Comment then '' else idt
|
||||
indent += TAB if hasDynamic and i < dynamicIndex
|
||||
if prop instanceof Assign and prop.variable instanceof Value and prop.variable.hasProperties()
|
||||
prop.variable.error 'Invalid object key'
|
||||
if prop instanceof Value and prop.this
|
||||
prop = new Assign prop.properties[0].name, prop, 'object'
|
||||
if prop not instanceof Comment
|
||||
if prop not instanceof Assign
|
||||
prop = new Assign prop, prop, 'object'
|
||||
(prop.variable.base or prop.variable).asKey = yes
|
||||
if i < dynamicIndex
|
||||
if prop not instanceof Assign
|
||||
prop = new Assign prop, prop, 'object'
|
||||
(prop.variable.base or prop.variable).asKey = yes
|
||||
else
|
||||
if prop instanceof Assign
|
||||
key = prop.variable
|
||||
value = prop.value
|
||||
else
|
||||
[key, value] = prop.base.cache o
|
||||
prop = new Assign (new Value (new Literal oref), [new Access key]), value
|
||||
if indent then answer.push @makeCode indent
|
||||
answer.push prop.compileToFragments(o, LEVEL_TOP)...
|
||||
if join then answer.push @makeCode join
|
||||
answer.unshift @makeCode "{#{ props.length and '\n' }"
|
||||
answer.push @makeCode "#{ props.length and '\n' + @tab }}"
|
||||
if @front then @wrapInBraces answer else answer
|
||||
if hasDynamic
|
||||
answer.push @makeCode ",\n#{idt}#{oref}\n#{@tab})"
|
||||
else
|
||||
answer.push @makeCode "\n#{@tab}}" unless props.length is 0
|
||||
if @front and not hasDynamic then @wrapInBraces answer else answer
|
||||
|
||||
assigns: (name) ->
|
||||
for prop in @properties when prop.assigns name then return yes
|
||||
@@ -990,7 +1028,8 @@ exports.Class = class Class extends Base
|
||||
# Figure out the appropriate name for the constructor function of this class.
|
||||
determineName: ->
|
||||
return null unless @variable
|
||||
decl = if tail = last @variable.properties
|
||||
[..., tail] = @variable.properties
|
||||
decl = if tail
|
||||
tail instanceof Access and tail.name.value
|
||||
else
|
||||
@variable.base.value
|
||||
@@ -1006,7 +1045,6 @@ exports.Class = class Class extends Base
|
||||
if node instanceof Literal and node.value is 'this'
|
||||
node.value = name
|
||||
else if node instanceof Code
|
||||
node.klass = name
|
||||
node.context = name if node.bound
|
||||
|
||||
# Ensure that all functions bound to the instance are proxied in the
|
||||
@@ -1014,7 +1052,7 @@ exports.Class = class Class extends Base
|
||||
addBoundFunctions: (o) ->
|
||||
for bvar in @boundFuncs
|
||||
lhs = (new Value (new Literal "this"), [new Access bvar]).compile o
|
||||
@ctor.body.unshift new Literal "#{lhs} = #{utility 'bind'}(#{lhs}, this)"
|
||||
@ctor.body.unshift new Literal "#{lhs} = #{utility 'bind', o}(#{lhs}, this)"
|
||||
return
|
||||
|
||||
# Merge the properties from a top-level object as prototypal properties
|
||||
@@ -1040,7 +1078,8 @@ exports.Class = class Class extends Base
|
||||
if assign.variable.this
|
||||
func.static = yes
|
||||
else
|
||||
assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), new Access base])
|
||||
acc = if base.isComplex() then new Index base else new Access base
|
||||
assign.variable = new Value(new Literal(name), [(new Access new Literal 'prototype'), acc])
|
||||
if func instanceof Code and func.bound
|
||||
@boundFuncs.push base
|
||||
func.bound = no
|
||||
@@ -1113,7 +1152,7 @@ exports.Class = class Class extends Base
|
||||
@body.expressions.push lname
|
||||
|
||||
if @parent
|
||||
superClass = new Literal o.classScope.freeVariable 'super', no
|
||||
superClass = new Literal o.classScope.freeVariable 'superClass', reserve: no
|
||||
@body.expressions.unshift new Extends lname, superClass
|
||||
func.params.push new Param superClass
|
||||
args.push @parent
|
||||
@@ -1157,21 +1196,28 @@ exports.Assign = class Assign extends Base
|
||||
return @compileSplice o if @variable.isSplice()
|
||||
return @compileConditional o if @context in ['||=', '&&=', '?=']
|
||||
return @compileSpecialMath o if @context in ['**=', '//=', '%%=']
|
||||
compiledName = @variable.compileToFragments o, LEVEL_LIST
|
||||
name = fragmentsToText compiledName
|
||||
if @value instanceof Code
|
||||
if @value.static
|
||||
@value.klass = @variable.base
|
||||
@value.name = @variable.properties[0]
|
||||
@value.variable = @variable
|
||||
else if @variable.properties?.length >= 2
|
||||
[properties..., prototype, name] = @variable.properties
|
||||
if prototype.name?.value is 'prototype'
|
||||
@value.klass = new Value @variable.base, properties
|
||||
@value.name = name
|
||||
@value.variable = @variable
|
||||
unless @context
|
||||
varBase = @variable.unwrapAll()
|
||||
unless varBase.isAssignable()
|
||||
@variable.error "\"#{@variable.compile o}\" cannot be assigned"
|
||||
unless varBase.hasProperties?()
|
||||
if @param
|
||||
o.scope.add name, 'var'
|
||||
o.scope.add varBase.value, 'var'
|
||||
else
|
||||
o.scope.find name
|
||||
if @value instanceof Code and match = METHOD_DEF.exec name
|
||||
@value.klass = match[1] if match[2]
|
||||
@value.name = match[3] ? match[4] ? match[5]
|
||||
o.scope.find varBase.value
|
||||
val = @value.compileToFragments o, LEVEL_LIST
|
||||
compiledName = @variable.compileToFragments o, LEVEL_LIST
|
||||
return (compiledName.concat @makeCode(": "), val) if @context is 'object'
|
||||
answer = compiledName.concat @makeCode(" #{ @context or '=' } "), val
|
||||
if o.level <= LEVEL_LIST then answer else @wrapInBraces answer
|
||||
@@ -1228,9 +1274,9 @@ exports.Assign = class Assign extends Base
|
||||
if not expandedIdx and obj instanceof Splat
|
||||
name = obj.name.unwrap().value
|
||||
obj = obj.unwrap()
|
||||
val = "#{olen} <= #{vvarText}.length ? #{ utility 'slice' }.call(#{vvarText}, #{i}"
|
||||
val = "#{olen} <= #{vvarText}.length ? #{ utility 'slice', o }.call(#{vvarText}, #{i}"
|
||||
if rest = olen - i - 1
|
||||
ivar = o.scope.freeVariable 'i'
|
||||
ivar = o.scope.freeVariable 'i', single: true
|
||||
val += ", #{ivar} = #{vvarText}.length - #{rest}) : (#{ivar} = #{i}, [])"
|
||||
else
|
||||
val += ") : []"
|
||||
@@ -1241,7 +1287,7 @@ exports.Assign = class Assign extends Base
|
||||
if rest is 1
|
||||
expandedIdx = "#{vvarText}.length - 1"
|
||||
else
|
||||
ivar = o.scope.freeVariable 'i'
|
||||
ivar = o.scope.freeVariable 'i', single: true
|
||||
val = new Literal "#{ivar} = #{vvarText}.length - #{rest}"
|
||||
expandedIdx = "#{ivar}++"
|
||||
assigns.push val.compileToFragments o, LEVEL_LIST
|
||||
@@ -1315,9 +1361,11 @@ exports.Assign = class Assign extends Base
|
||||
# has no *children* -- they're within the inner scope.
|
||||
exports.Code = class Code extends Base
|
||||
constructor: (params, body, tag) ->
|
||||
@params = params or []
|
||||
@body = body or new Block
|
||||
@bound = tag is 'boundfunc'
|
||||
@params = params or []
|
||||
@body = body or new Block
|
||||
@bound = tag is 'boundfunc'
|
||||
@isGenerator = !!@body.contains (node) ->
|
||||
node instanceof Op and node.operator in ['yield', 'yield*']
|
||||
|
||||
children: ['params', 'body']
|
||||
|
||||
@@ -1355,9 +1403,8 @@ exports.Code = class Code extends Base
|
||||
for param in @params when param not instanceof Expansion
|
||||
o.scope.parameter param.asReference o
|
||||
for param in @params when param.splat or param instanceof Expansion
|
||||
for {name: p} in @params when param not instanceof Expansion
|
||||
if p.this then p = p.properties[0].name
|
||||
if p.value then o.scope.add p.value, 'var', yes
|
||||
for p in @params when p not instanceof Expansion and p.name.value
|
||||
o.scope.add p.name.value, 'var', yes
|
||||
splats = new Assign new Value(new Arr(p.asReference o for p in @params)),
|
||||
new Value new Literal 'arguments'
|
||||
break
|
||||
@@ -1381,12 +1428,13 @@ exports.Code = class Code extends Base
|
||||
o.scope.parameter fragmentsToText params[i]
|
||||
uniqs = []
|
||||
@eachParamName (name, node) ->
|
||||
node.error "multiple parameters named '#{name}'" if name in uniqs
|
||||
node.error "multiple parameters named #{name}" if name in uniqs
|
||||
uniqs.push name
|
||||
@body.makeReturn() unless wasEmpty or @noReturn
|
||||
code = 'function'
|
||||
code += ' ' + @name if @ctor
|
||||
code += '('
|
||||
code = 'function'
|
||||
code += '*' if @isGenerator
|
||||
code += ' ' + @name if @ctor
|
||||
code += '('
|
||||
answer = [@makeCode(code)]
|
||||
for p, i in params
|
||||
if i then answer.push @makeCode ", "
|
||||
@@ -1425,9 +1473,9 @@ exports.Param = class Param extends Base
|
||||
return @reference if @reference
|
||||
node = @name
|
||||
if node.this
|
||||
node = node.properties[0].name
|
||||
if node.value.reserved
|
||||
node = new Literal o.scope.freeVariable node.value
|
||||
name = node.properties[0].name.value
|
||||
name = "_#{name}" if name.reserved
|
||||
node = new Literal o.scope.freeVariable name
|
||||
else if node.isComplex()
|
||||
node = new Literal o.scope.freeVariable 'arg'
|
||||
node = new Value node
|
||||
@@ -1445,9 +1493,7 @@ exports.Param = class Param extends Base
|
||||
# `name` is the name of the parameter and `node` is the AST node corresponding
|
||||
# to that name.
|
||||
eachName: (iterator, name = @name)->
|
||||
atParam = (obj) ->
|
||||
node = obj.properties[0].name
|
||||
iterator node.value, node unless node.value.reserved
|
||||
atParam = (obj) -> iterator "@#{obj.properties[0].name.value}", obj
|
||||
# * simple literals `foo`
|
||||
return iterator name.value, name if name instanceof Literal
|
||||
# * at-params `@foo`
|
||||
@@ -1504,12 +1550,12 @@ exports.Splat = class Splat extends Base
|
||||
node = list[0]
|
||||
fragments = node.compileToFragments o, LEVEL_LIST
|
||||
return fragments if apply
|
||||
return [].concat node.makeCode("#{ utility 'slice' }.call("), fragments, node.makeCode(")")
|
||||
return [].concat node.makeCode("#{ utility 'slice', o }.call("), fragments, node.makeCode(")")
|
||||
args = list[index..]
|
||||
for node, i in args
|
||||
compiledNode = node.compileToFragments o, LEVEL_LIST
|
||||
args[i] = if node instanceof Splat
|
||||
then [].concat node.makeCode("#{ utility 'slice' }.call("), compiledNode, node.makeCode(")")
|
||||
then [].concat node.makeCode("#{ utility 'slice', o }.call("), compiledNode, node.makeCode(")")
|
||||
else [].concat node.makeCode("["), compiledNode, node.makeCode("]")
|
||||
if index is 0
|
||||
node = list[0]
|
||||
@@ -1518,7 +1564,8 @@ exports.Splat = class Splat extends Base
|
||||
base = (node.compileToFragments o, LEVEL_LIST for node in list[...index])
|
||||
base = list[0].joinFragmentArrays base, ', '
|
||||
concatPart = list[index].joinFragmentArrays args, ', '
|
||||
[].concat list[0].makeCode("["), base, list[index].makeCode("].concat("), concatPart, (last list).makeCode(")")
|
||||
[..., last] = list
|
||||
[].concat list[0].makeCode("["), base, list[index].makeCode("].concat("), concatPart, last.makeCode(")")
|
||||
|
||||
#### Expansion
|
||||
|
||||
@@ -1612,9 +1659,10 @@ exports.Op = class Op extends Base
|
||||
|
||||
# The map of conversions from CoffeeScript to JavaScript symbols.
|
||||
CONVERSIONS =
|
||||
'==': '==='
|
||||
'!=': '!=='
|
||||
'of': 'in'
|
||||
'==': '==='
|
||||
'!=': '!=='
|
||||
'of': 'in'
|
||||
'yieldfrom': 'yield*'
|
||||
|
||||
# The map of invertible operators.
|
||||
INVERSIONS =
|
||||
@@ -1625,11 +1673,18 @@ exports.Op = class Op extends Base
|
||||
|
||||
isSimpleNumber: NO
|
||||
|
||||
isYield: ->
|
||||
@operator in ['yield', 'yield*']
|
||||
|
||||
isYieldReturn: ->
|
||||
@isYield() and @first instanceof Return
|
||||
|
||||
isUnary: ->
|
||||
not @second
|
||||
|
||||
isComplex: ->
|
||||
not (@isUnary() and @operator in ['+', '-']) or @first.isComplex()
|
||||
not (@isUnary() and @operator in ['+', '-'] and
|
||||
@first instanceof Value and @first.isSimpleNumber())
|
||||
|
||||
# Am I capable of
|
||||
# [Python-style comparison chaining](http://docs.python.org/reference/expressions.html#notin)?
|
||||
@@ -1691,6 +1746,7 @@ exports.Op = class Op extends Base
|
||||
@error 'delete operand may not be argument or var'
|
||||
if @operator in ['--', '++'] and @first.unwrapAll().value in STRICT_PROSCRIBED
|
||||
@error "cannot increment/decrement \"#{@first.unwrapAll().value}\""
|
||||
return @compileYield o if @isYield()
|
||||
return @compileUnary o if @isUnary()
|
||||
return @compileChain o if isChain
|
||||
switch @operator
|
||||
@@ -1745,6 +1801,22 @@ exports.Op = class Op extends Base
|
||||
parts.reverse() if @flip
|
||||
@joinFragmentArrays parts, ''
|
||||
|
||||
compileYield: (o) ->
|
||||
parts = []
|
||||
op = @operator
|
||||
if not o.scope.parent?
|
||||
@error 'yield statements must occur within a function generator.'
|
||||
if 'expression' in Object.keys(@first) and not (@first instanceof Throw)
|
||||
if @isYieldReturn()
|
||||
parts.push @first.compileToFragments o, LEVEL_TOP
|
||||
else if @first.expression?
|
||||
parts.push @first.expression.compileToFragments o, LEVEL_OP
|
||||
else
|
||||
parts.push [@makeCode "(#{op} "]
|
||||
parts.push @first.compileToFragments o, LEVEL_OP
|
||||
parts.push [@makeCode ")"]
|
||||
@joinFragmentArrays parts, ''
|
||||
|
||||
compilePower: (o) ->
|
||||
# Make a Math.pow call
|
||||
pow = new Value new Literal('Math'), [new Access new Literal 'pow']
|
||||
@@ -1756,7 +1828,7 @@ exports.Op = class Op extends Base
|
||||
new Call(floor, [div]).compileToFragments o
|
||||
|
||||
compileModulo: (o) ->
|
||||
mod = new Value new Literal utility 'modulo'
|
||||
mod = new Value new Literal utility 'modulo', o
|
||||
new Call(mod, [@first, @second]).compileToFragments o
|
||||
|
||||
toString: (idt) ->
|
||||
@@ -1790,7 +1862,7 @@ exports.In = class In extends Base
|
||||
|
||||
compileLoopTest: (o) ->
|
||||
[sub, ref] = @object.cache o, LEVEL_LIST
|
||||
fragments = [].concat @makeCode(utility('indexOf') + ".call("), @array.compileToFragments(o, LEVEL_LIST),
|
||||
fragments = [].concat @makeCode(utility('indexOf', o) + ".call("), @array.compileToFragments(o, LEVEL_LIST),
|
||||
@makeCode(", "), ref, @makeCode(") " + if @negated then '< 0' else '>= 0')
|
||||
return fragments if fragmentsToText(sub) is fragmentsToText(ref)
|
||||
fragments = sub.concat @makeCode(', '), fragments
|
||||
@@ -1935,29 +2007,30 @@ exports.For = class For extends While
|
||||
# comprehensions. Some of the generated code can be shared in common, and
|
||||
# some cannot.
|
||||
compileNode: (o) ->
|
||||
body = Block.wrap [@body]
|
||||
lastJumps = last(body.expressions)?.jumps()
|
||||
@returns = no if lastJumps and lastJumps instanceof Return
|
||||
source = if @range then @source.base else @source
|
||||
scope = o.scope
|
||||
name = @name and (@name.compile o, LEVEL_LIST) if not @pattern
|
||||
index = @index and (@index.compile o, LEVEL_LIST)
|
||||
body = Block.wrap [@body]
|
||||
[..., last] = body.expressions
|
||||
@returns = no if last?.jumps() instanceof Return
|
||||
source = if @range then @source.base else @source
|
||||
scope = o.scope
|
||||
name = @name and (@name.compile o, LEVEL_LIST) if not @pattern
|
||||
index = @index and (@index.compile o, LEVEL_LIST)
|
||||
scope.find(name) if name and not @pattern
|
||||
scope.find(index) if index
|
||||
rvar = scope.freeVariable 'results' if @returns
|
||||
ivar = (@object and index) or scope.freeVariable 'i'
|
||||
kvar = (@range and name) or index or ivar
|
||||
kvarAssign = if kvar isnt ivar then "#{kvar} = " else ""
|
||||
rvar = scope.freeVariable 'results' if @returns
|
||||
ivar = (@object and index) or scope.freeVariable 'i', single: true
|
||||
kvar = (@range and name) or index or ivar
|
||||
kvarAssign = if kvar isnt ivar then "#{kvar} = " else ""
|
||||
if @step and not @range
|
||||
[step, stepVar] = @cacheToCodeFragments @step.cache o, LEVEL_LIST
|
||||
[step, stepVar] = @cacheToCodeFragments @step.cache o, LEVEL_LIST, isComplexOrAssignable
|
||||
stepNum = stepVar.match NUMBER
|
||||
name = ivar if @pattern
|
||||
varPart = ''
|
||||
guardPart = ''
|
||||
defPart = ''
|
||||
idt1 = @tab + TAB
|
||||
name = ivar if @pattern
|
||||
varPart = ''
|
||||
guardPart = ''
|
||||
defPart = ''
|
||||
idt1 = @tab + TAB
|
||||
if @range
|
||||
forPartFragments = source.compileToFragments merge(o, {index: ivar, name, @step})
|
||||
forPartFragments = source.compileToFragments merge o,
|
||||
{index: ivar, name, @step, isComplex: isComplexOrAssignable}
|
||||
else
|
||||
svar = @source.compile o, LEVEL_LIST
|
||||
if (name or @own) and not IDENTIFIER.test svar
|
||||
@@ -1999,7 +2072,7 @@ exports.For = class For extends While
|
||||
varPart = "\n#{idt1}#{namePart};" if namePart
|
||||
if @object
|
||||
forPartFragments = [@makeCode("#{kvar} in #{svar}")]
|
||||
guardPart = "\n#{idt1}if (!#{utility 'hasProp'}.call(#{svar}, #{kvar})) continue;" if @own
|
||||
guardPart = "\n#{idt1}if (!#{utility 'hasProp', o}.call(#{svar}, #{kvar})) continue;" if @own
|
||||
bodyFragments = body.compileToFragments merge(o, indent: idt1), LEVEL_TOP
|
||||
if bodyFragments and (bodyFragments.length > 0)
|
||||
bodyFragments = [].concat @makeCode("\n"), bodyFragments, @makeCode("\n")
|
||||
@@ -2158,10 +2231,10 @@ UTILITIES =
|
||||
|
||||
# Correctly set up a prototype chain for inheritance, including a reference
|
||||
# to the superclass for `super()` calls, and copies of any static properties.
|
||||
extends: -> "
|
||||
extend: (o) -> "
|
||||
function(child, parent) {
|
||||
for (var key in parent) {
|
||||
if (#{utility 'hasProp'}.call(parent, key)) child[key] = parent[key];
|
||||
if (#{utility 'hasProp', o}.call(parent, key)) child[key] = parent[key];
|
||||
}
|
||||
function ctor() {
|
||||
this.constructor = child;
|
||||
@@ -2212,8 +2285,7 @@ LEVEL_ACCESS = 6 # ...[0]
|
||||
# Tabs are two spaces for pretty printing.
|
||||
TAB = ' '
|
||||
|
||||
IDENTIFIER_STR = "[$A-Za-z_\\x7f-\\uffff][$\\w\\x7f-\\uffff]*"
|
||||
IDENTIFIER = /// ^ #{IDENTIFIER_STR} $ ///
|
||||
IDENTIFIER = /// ^ (?!\d) [$\w\x7f-\uffff]+ $ ///
|
||||
SIMPLENUM = /^[+-]?\d+$/
|
||||
HEXNUM = /^[+-]?0x[\da-f]+/i
|
||||
NUMBER = ///^[+-]?(?:
|
||||
@@ -2221,15 +2293,6 @@ NUMBER = ///^[+-]?(?:
|
||||
\d*\.?\d+ (?:e[+-]?\d+)? # decimal
|
||||
)$///i
|
||||
|
||||
METHOD_DEF = /// ^
|
||||
(#{IDENTIFIER_STR})
|
||||
(\.prototype)?
|
||||
(?: \.(#{IDENTIFIER_STR})
|
||||
| \[("(?:[^\\"\r\n]|\\.)*"|'(?:[^\\'\r\n]|\\.)*')\]
|
||||
| \[(0x[\da-fA-F]+ | \d*\.?\d+ (?:[eE][+-]?\d+)?)\]
|
||||
)
|
||||
$ ///
|
||||
|
||||
# Is a literal value a string/regex?
|
||||
IS_STRING = /^['"]/
|
||||
IS_REGEX = /^\//
|
||||
@@ -2238,10 +2301,14 @@ IS_REGEX = /^\//
|
||||
# ----------------
|
||||
|
||||
# Helper for ensuring that utility functions are assigned at the top level.
|
||||
utility = (name) ->
|
||||
ref = "__#{name}"
|
||||
Scope.root.assign ref, UTILITIES[name]()
|
||||
ref
|
||||
utility = (name, o) ->
|
||||
{root} = o.scope
|
||||
if name of root.utilities
|
||||
root.utilities[name]
|
||||
else
|
||||
ref = root.freeVariable name
|
||||
root.assign ref, UTILITIES[name] o
|
||||
root.utilities[name] = ref
|
||||
|
||||
multident = (code, tab) ->
|
||||
code = code.replace /\n/g, '$&' + tab
|
||||
@@ -2265,6 +2332,8 @@ isLiteralThis = (node) ->
|
||||
(node instanceof Code and node.bound) or
|
||||
(node instanceof Call and node.isSuper)
|
||||
|
||||
isComplexOrAssignable = (node) -> node.isComplex() or node.isAssignable?()
|
||||
|
||||
# Unfold a node's child if soak, then tuck the node under created `If`
|
||||
unfoldSoak = (o, parent, name) ->
|
||||
return unless ifn = parent[name].unfoldSoak o
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user